summaryrefslogtreecommitdiffstats
path: root/sys/dev/ppc/ppc.c
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2006-04-24 23:31:51 +0000
committermarcel <marcel@FreeBSD.org>2006-04-24 23:31:51 +0000
commitdeb16135f3fca75d654b5678f9f331af783b6d6b (patch)
tree4c14a9bedc4bcdbb3fbd46089cf47c3af3cc2de1 /sys/dev/ppc/ppc.c
parenteefd58df920bd36d125e2f8e0db44d74e8859b3a (diff)
downloadFreeBSD-src-deb16135f3fca75d654b5678f9f331af783b6d6b.zip
FreeBSD-src-deb16135f3fca75d654b5678f9f331af783b6d6b.tar.gz
o Move ISA specific code from ppc.c to ppc_isa.c -- a bus front-
end for isa(4). o Add a seperate bus frontend for acpi(4) and allow ISA DMA for it when ISA is configured in the kernel. This allows acpi(4) attachments in non-ISA configurations, as is possible for ia64. o Add a seperate bus frontend for pci(4) and detect known single port parallel cards. o Merge PC98 specific changes under pc98/cbus into the MI driver. The changes are minor enough for conditional compilation and in this form invites better abstraction. o Have ppc(4) usabled on all platforms, now that ISA specifics are untangled enough.
Diffstat (limited to 'sys/dev/ppc/ppc.c')
-rw-r--r--sys/dev/ppc/ppc.c302
1 files changed, 66 insertions, 236 deletions
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index 7e1ed40..48a9889 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -36,18 +36,16 @@ __FBSDID("$FreeBSD$");
#include <sys/module.h>
#include <sys/bus.h>
#include <sys/malloc.h>
-#include <sys/kdb.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-#include <machine/clock.h>
#include <machine/bus.h>
#include <machine/resource.h>
-#include <machine/vmparam.h>
#include <sys/rman.h>
-#include <isa/isareg.h>
-#include <isa/isavar.h>
+#ifdef __i386__
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/vmparam.h>
+#endif
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
@@ -57,47 +55,23 @@ __FBSDID("$FreeBSD$");
#include "ppbus_if.h"
-static int ppc_isa_probe(device_t dev);
-
static void ppcintr(void *arg);
+#define IO_LPTSIZE_EXTENDED 8 /* "Extended" LPT controllers */
+#define IO_LPTSIZE_NORMAL 4 /* "Normal" LPT controllers */
+
#define LOG_PPC(function, ppc, string) \
if (bootverbose) printf("%s: %s\n", function, string)
+#if defined(__i386__) && defined(PC98)
+#define PC98_IEEE_1284_DISABLE 0x100
+#define PC98_IEEE_1284_PORT 0x140
+#endif
#define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev))
devclass_t ppc_devclass;
-
-static device_method_t ppc_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, ppc_isa_probe),
- DEVMETHOD(device_attach, ppc_attach),
- DEVMETHOD(device_detach, ppc_detach),
-
- /* bus interface */
- DEVMETHOD(bus_read_ivar, ppc_read_ivar),
- DEVMETHOD(bus_setup_intr, ppc_setup_intr),
- DEVMETHOD(bus_teardown_intr, ppc_teardown_intr),
- DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
-
- /* ppbus interface */
- DEVMETHOD(ppbus_io, ppc_io),
- DEVMETHOD(ppbus_exec_microseq, ppc_exec_microseq),
- DEVMETHOD(ppbus_reset_epp, ppc_reset_epp),
- DEVMETHOD(ppbus_setmode, ppc_setmode),
- DEVMETHOD(ppbus_ecp_sync, ppc_ecp_sync),
- DEVMETHOD(ppbus_read, ppc_read),
- DEVMETHOD(ppbus_write, ppc_write),
-
- { 0, 0 }
- };
-
-static driver_t ppc_driver = {
- "ppc",
- ppc_methods,
- sizeof(struct ppc_data),
-};
+const char ppc_driver_name[] = "ppc";
static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
@@ -1593,12 +1567,7 @@ ppcintr(void *arg)
#ifdef PPC_DEBUG
printf("d");
#endif
- isa_dmadone(
- ppc->ppc_dmaflags,
- ppc->ppc_dmaddr,
- ppc->ppc_dmacnt,
- ppc->ppc_dmachan);
-
+ ppc->ppc_dmadone(ppc);
ppc->ppc_dmastat = PPC_DMA_COMPLETE;
/* wakeup the waiting process */
@@ -1620,163 +1589,10 @@ ppc_read(device_t dev, char *buf, int len, int mode)
return (EINVAL);
}
-/*
- * Call this function if you want to send data in any advanced mode
- * of your parallel port: FIFO, DMA
- *
- * If what you want is not possible (no ECP, no DMA...),
- * EINVAL is returned
- */
int
ppc_write(device_t dev, char *buf, int len, int how)
{
- struct ppc_data *ppc = DEVTOSOFTC(dev);
- char ecr, ecr_sav, ctr, ctr_sav;
- int s, error = 0;
- int spin;
-
-#ifdef PPC_DEBUG
- printf("w");
-#endif
-
- ecr_sav = r_ecr(ppc);
- ctr_sav = r_ctr(ppc);
-
- /*
- * Send buffer with DMA, FIFO and interrupts
- */
- if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
-
- if (ppc->ppc_dmachan > 0) {
-
- /* byte mode, no intr, no DMA, dir=0, flush fifo
- */
- ecr = PPC_ECR_STD | PPC_DISABLE_INTR;
- w_ecr(ppc, ecr);
-
- /* disable nAck interrupts */
- ctr = r_ctr(ppc);
- ctr &= ~IRQENABLE;
- w_ctr(ppc, ctr);
-
- ppc->ppc_dmaflags = 0;
- ppc->ppc_dmaddr = (caddr_t)buf;
- ppc->ppc_dmacnt = (u_int)len;
-
- switch (ppc->ppc_mode) {
- case PPB_COMPATIBLE:
- /* compatible mode with FIFO, no intr, DMA, dir=0 */
- ecr = PPC_ECR_FIFO | PPC_DISABLE_INTR | PPC_ENABLE_DMA;
- break;
- case PPB_ECP:
- ecr = PPC_ECR_ECP | PPC_DISABLE_INTR | PPC_ENABLE_DMA;
- break;
- default:
- error = EINVAL;
- goto error;
- }
-
- w_ecr(ppc, ecr);
- ecr = r_ecr(ppc);
-
- /* enter splhigh() not to be preempted
- * by the dma interrupt, we may miss
- * the wakeup otherwise
- */
- s = splhigh();
-
- ppc->ppc_dmastat = PPC_DMA_INIT;
-
- /* enable interrupts */
- ecr &= ~PPC_SERVICE_INTR;
- ppc->ppc_irqstat = PPC_IRQ_DMA;
- w_ecr(ppc, ecr);
-
- isa_dmastart(
- ppc->ppc_dmaflags,
- ppc->ppc_dmaddr,
- ppc->ppc_dmacnt,
- ppc->ppc_dmachan);
-#ifdef PPC_DEBUG
- printf("s%d", ppc->ppc_dmacnt);
-#endif
- ppc->ppc_dmastat = PPC_DMA_STARTED;
-
- /* Wait for the DMA completed interrupt. We hope we won't
- * miss it, otherwise a signal will be necessary to unlock the
- * process.
- */
- do {
- /* release CPU */
- error = tsleep(ppc,
- PPBPRI | PCATCH, "ppcdma", 0);
-
- } while (error == EWOULDBLOCK);
-
- splx(s);
-
- if (error) {
-#ifdef PPC_DEBUG
- printf("i");
-#endif
- /* stop DMA */
- isa_dmadone(
- ppc->ppc_dmaflags, ppc->ppc_dmaddr,
- ppc->ppc_dmacnt, ppc->ppc_dmachan);
-
- /* no dma, no interrupt, flush the fifo */
- w_ecr(ppc, PPC_ECR_RESET);
-
- ppc->ppc_dmastat = PPC_DMA_INTERRUPTED;
- goto error;
- }
-
- /* wait for an empty fifo */
- while (!(r_ecr(ppc) & PPC_FIFO_EMPTY)) {
-
- for (spin=100; spin; spin--)
- if (r_ecr(ppc) & PPC_FIFO_EMPTY)
- goto fifo_empty;
-#ifdef PPC_DEBUG
- printf("Z");
-#endif
- error = tsleep(ppc, PPBPRI | PCATCH, "ppcfifo", hz/100);
- if (error != EWOULDBLOCK) {
-#ifdef PPC_DEBUG
- printf("I");
-#endif
- /* no dma, no interrupt, flush the fifo */
- w_ecr(ppc, PPC_ECR_RESET);
-
- ppc->ppc_dmastat = PPC_DMA_INTERRUPTED;
- error = EINTR;
- goto error;
- }
- }
-
-fifo_empty:
- /* no dma, no interrupt, flush the fifo */
- w_ecr(ppc, PPC_ECR_RESET);
-
- } else
- error = EINVAL; /* XXX we should FIFO and
- * interrupts */
- } else
- error = EINVAL;
-
-error:
-
- /* PDRQ must be kept unasserted until nPDACK is
- * deasserted for a minimum of 350ns (SMC datasheet)
- *
- * Consequence may be a FIFO that never empty
- */
- DELAY(1);
-
- w_ecr(ppc, ecr_sav);
- w_ctr(ppc, ctr_sav);
-
- return (error);
+ return (EINVAL);
}
void
@@ -1809,34 +1625,15 @@ ppc_setmode(device_t dev, int mode)
return (ENXIO);
}
-static struct isa_pnp_id lpc_ids[] = {
- { 0x0004d041, "Standard parallel printer port" }, /* PNP0400 */
- { 0x0104d041, "ECP parallel printer port" }, /* PNP0401 */
- { 0 }
-};
-
-static int
-ppc_isa_probe(device_t dev)
-{
- device_t parent;
- int error;
-
- parent = device_get_parent(dev);
-
- error = ISA_PNP_PROBE(parent, dev, lpc_ids);
- if (error == ENXIO)
- return (ENXIO);
- else if (error != 0) /* XXX shall be set after detection */
- device_set_desc(dev, "Parallel port");
-
- return(ppc_probe(dev));
-}
-
int
-ppc_probe(device_t dev)
+ppc_probe(device_t dev, int rid)
{
#ifdef __i386__
static short next_bios_ppc = 0;
+#ifdef PC98
+ unsigned int pc98_ieee_mode = 0x00;
+ unsigned int tmp;
+#endif
#endif
struct ppc_data *ppc;
int error;
@@ -1848,17 +1645,27 @@ ppc_probe(device_t dev)
ppc = DEVTOSOFTC(dev);
bzero(ppc, sizeof(struct ppc_data));
- ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0;
- ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0;
+ ppc->rid_ioport = rid;
/* retrieve ISA parameters */
- error = bus_get_resource(dev, SYS_RES_IOPORT, 0, &port, NULL);
+ error = bus_get_resource(dev, SYS_RES_IOPORT, rid, &port, NULL);
#ifdef __i386__
/*
* If port not specified, use bios list.
*/
if (error) {
+#ifdef PC98
+ if (next_bios_ppc == 0) {
+ /* Use default IEEE-1284 port of NEC PC-98x1 */
+ port = PC98_IEEE_1284_PORT;
+ next_bios_ppc += 1;
+ if (bootverbose)
+ device_printf(dev,
+ "parallel port found at 0x%x\n",
+ (int) port);
+ }
+#else
if((next_bios_ppc < BIOS_MAX_PPC) &&
(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
port = *(BIOS_PORTS+next_bios_ppc++);
@@ -1869,7 +1676,8 @@ ppc_probe(device_t dev)
device_printf(dev, "parallel port not found.\n");
return ENXIO;
}
- bus_set_resource(dev, SYS_RES_IOPORT, 0, port,
+#endif /* PC98 */
+ bus_set_resource(dev, SYS_RES_IOPORT, rid, port,
IO_LPTSIZE_EXTENDED);
}
#endif
@@ -1878,7 +1686,7 @@ ppc_probe(device_t dev)
* There isn't a bios list on alpha. Put it in the usual place.
*/
if (error) {
- bus_set_resource(dev, SYS_RES_IOPORT, 0, 0x3bc,
+ bus_set_resource(dev, SYS_RES_IOPORT, rid, 0x3bc,
IO_LPTSIZE_NORMAL);
}
#endif
@@ -1937,6 +1745,30 @@ ppc_probe(device_t dev)
ppc->ppc_type = PPC_TYPE_GENERIC;
+#if defined(__i386__) && defined(PC98)
+ /*
+ * IEEE STD 1284 Function Check and Enable
+ * for default IEEE-1284 port of NEC PC-98x1
+ */
+ if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
+ !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
+ tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
+ pc98_ieee_mode = tmp;
+ if ((tmp & 0x10) == 0x10) {
+ outb(ppc->ppc_base + PPC_1284_ENABLE, tmp & ~0x10);
+ tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
+ if ((tmp & 0x10) == 0x10)
+ goto error;
+ } else {
+ outb(ppc->ppc_base + PPC_1284_ENABLE, tmp | 0x10);
+ tmp = inb(ppc->ppc_base + PPC_1284_ENABLE);
+ if ((tmp & 0x10) != 0x10)
+ goto error;
+ }
+ outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode | 0x10);
+ }
+#endif
+
/*
* Try to detect the chipset and its mode.
*/
@@ -1946,6 +1778,12 @@ ppc_probe(device_t dev)
return (0);
error:
+#if defined(__i386__) && defined(PC98)
+ if (ppc->ppc_base == PC98_IEEE_1284_PORT &&
+ !(ppc->ppc_flags & PC98_IEEE_1284_DISABLE)) {
+ outb(ppc->ppc_base + PPC_1284_ENABLE, pc98_ieee_mode);
+ }
+#endif
if (ppc->res_irq != 0) {
bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
ppc->res_irq);
@@ -1981,12 +1819,6 @@ ppc_attach(device_t dev)
device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);
- if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) {
- /* acquire the DMA channel forever */ /* XXX */
- isa_dma_acquire(ppc->ppc_dmachan);
- isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */
- }
-
/* add ppbus as a child of this isa to parallel bridge */
ppbus = device_add_child(dev, "ppbus", -1);
@@ -2192,6 +2024,4 @@ ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
return (error);
}
-DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0);
-DRIVER_MODULE(ppc, acpi, ppc_driver, ppc_devclass, 0, 0);
MODULE_DEPEND(ppc, ppbus, 1, 1, 1);
OpenPOWER on IntegriCloud