summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/conf/NOTES2
-rw-r--r--sys/conf/files14
-rw-r--r--sys/conf/options.i3861
-rw-r--r--sys/dev/pcf/pcf.c140
-rw-r--r--sys/dev/ppbus/if_plip.c281
-rw-r--r--sys/dev/ppbus/immio.c146
-rw-r--r--sys/dev/ppbus/lpbb.c162
-rw-r--r--sys/dev/ppbus/lpt.c351
-rw-r--r--sys/dev/ppbus/ppb_1284.c325
-rw-r--r--sys/dev/ppbus/ppb_1284.h24
-rw-r--r--sys/dev/ppbus/ppb_base.c137
-rw-r--r--sys/dev/ppbus/ppb_msq.c51
-rw-r--r--sys/dev/ppbus/ppb_msq.h16
-rw-r--r--sys/dev/ppbus/ppbconf.c429
-rw-r--r--sys/dev/ppbus/ppbconf.h231
-rw-r--r--sys/dev/ppbus/ppbio.h83
-rw-r--r--sys/dev/ppbus/ppbus_if.m92
-rw-r--r--sys/dev/ppbus/ppi.c248
-rw-r--r--sys/dev/ppbus/pps.c144
-rw-r--r--sys/dev/ppbus/vpo.c117
-rw-r--r--sys/dev/ppbus/vpoio.c170
-rw-r--r--sys/dev/ppbus/vpoio.h6
-rw-r--r--sys/dev/ppc/ppc.c818
-rw-r--r--sys/dev/ppc/ppcreg.h29
-rw-r--r--sys/i386/conf/LINT2
-rw-r--r--sys/i386/conf/NOTES2
-rw-r--r--sys/i386/isa/isa_compat.h10
-rw-r--r--sys/i386/isa/pcf.c140
-rw-r--r--sys/i386/isa/ppc.c818
-rw-r--r--sys/i386/isa/ppcreg.h29
-rw-r--r--sys/isa/ppc.c818
-rw-r--r--sys/isa/ppcreg.h29
32 files changed, 3343 insertions, 2522 deletions
diff --git a/sys/conf/NOTES b/sys/conf/NOTES
index a651ccb..3a284bd 100644
--- a/sys/conf/NOTES
+++ b/sys/conf/NOTES
@@ -2131,6 +2131,8 @@ pseudo-device "i4bisppp" 4
# ppc ISA-bus parallel port interfaces.
#
+options PPC_PROBE_CHIPSET # Enable chipset specific detection
+ # (see flags in ppc(4))
options DEBUG_1284 # IEEE1284 signaling protocol debug
options PERIPH_1284 # Makes your computer act as a IEEE1284
# compliant peripheral
diff --git a/sys/conf/files b/sys/conf/files
index 5545f8b..69bfdbd 100644
--- a/sys/conf/files
+++ b/sys/conf/files
@@ -209,6 +209,20 @@ dev/pdq/pdq.c optional fea
dev/pdq/pdq_ifsubr.c optional fea
dev/pdq/pdq.c optional fpa
dev/pdq/pdq_ifsubr.c optional fpa
+ppbus_if.o optional ppbus \
+ dependency "ppbus_if.c ppbus_if.h" \
+ compile-with "${NORMAL_C}" \
+ no-implicit-rule local
+ppbus_if.c optional ppbus \
+ dependency "$S/kern/makedevops.pl $S/dev/ppbus/ppbus_if.m" \
+ compile-with "perl5 $S/kern/makedevops.pl -c $S/dev/ppbus/ppbus_if.m" \
+ no-obj no-implicit-rule before-depend local \
+ clean "ppbus_if.c"
+ppbus_if.h optional ppbus \
+ dependency "$S/kern/makedevops.pl $S/dev/ppbus/ppbus_if.m" \
+ compile-with "perl5 $S/kern/makedevops.pl -h $S/dev/ppbus/ppbus_if.m" \
+ no-obj no-implicit-rule before-depend \
+ clean "ppbus_if.h"
dev/ppbus/immio.c optional vpo
dev/ppbus/if_plip.c optional plip
dev/ppbus/lpbb.c optional lpbb
diff --git a/sys/conf/options.i386 b/sys/conf/options.i386
index 1bd8511..8ef1aee 100644
--- a/sys/conf/options.i386
+++ b/sys/conf/options.i386
@@ -6,6 +6,7 @@ USER_LDT
MATH_EMULATE opt_math_emulate.h
GPL_MATH_EMULATE opt_math_emulate.h
PMAP_SHPGPERPROC opt_pmap.h
+PPC_PROBE_CHIPSET opt_ppc.h
PPC_DEBUG opt_ppc.h
SHOW_BUSYBUFS
PANIC_REBOOT_WAIT_TIME opt_panic.h
diff --git a/sys/dev/pcf/pcf.c b/sys/dev/pcf/pcf.c
index 1aeb7e6..e37823e 100644
--- a/sys/dev/pcf/pcf.c
+++ b/sys/dev/pcf/pcf.c
@@ -34,12 +34,20 @@
#include <sys/malloc.h>
#include <machine/clock.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <isa/isareg.h>
+#include <isa/isavar.h>
#include <i386/isa/isa_device.h>
#include <dev/iicbus/iiconf.h>
#include "iicbus_if.h"
+#define IO_PCFSIZE 2
+
#define TIMEOUT 9999 /* XXX */
/* Status bits of S1 register (read only) */
@@ -71,37 +79,23 @@
struct pcf_softc {
int pcf_base; /* isa port */
+ int pcf_flags;
u_char pcf_addr; /* interface I2C address */
int pcf_slave_mode; /* receiver or transmitter */
int pcf_started; /* 1 if start condition sent */
device_t iicbus; /* the corresponding iicbus */
-};
-
-struct pcf_isa_softc {
-
- int pcf_unit; /* unit of the isa device */
- int pcf_base; /* isa port */
- int pcf_irq; /* isa irq or null if polled */
-
- unsigned int pcf_flags; /* boot flags */
-};
-
-#define MAXPCF 2
-
-static struct pcf_isa_softc *pcfdata[MAXPCF];
-static int npcf = 0;
-
-static int pcfprobe_isa(struct isa_device *);
-static int pcfattach_isa(struct isa_device *);
-struct isa_driver pcfdriver = {
- pcfprobe_isa, pcfattach_isa, "pcf"
+ int rid_irq, rid_ioport;
+ struct resource *res_irq, *res_ioport;
+ void *intr_cookie;
};
static int pcf_probe(device_t);
static int pcf_attach(device_t);
+static void pcfintr(void *arg);
+
static int pcf_print_child(device_t, device_t);
static int pcf_repeated_start(device_t, u_char, int);
@@ -109,7 +103,6 @@ static int pcf_start(device_t, u_char, int);
static int pcf_stop(device_t);
static int pcf_write(device_t, char *, int, int *, int);
static int pcf_read(device_t, char *, int, int *, int, int);
-static ointhand2_t pcfintr;
static int pcf_rst_card(device_t, u_char, u_char, u_char *);
static device_method_t pcf_methods[] = {
@@ -143,72 +136,68 @@ static devclass_t pcf_devclass;
#define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev))
static int
-pcfprobe_isa(struct isa_device *dvp)
+pcf_probe(device_t pcfdev)
{
- device_t pcfdev;
- struct pcf_isa_softc *pcf;
-
- if (npcf >= MAXPCF)
- return (0);
-
- if ((pcf = (struct pcf_isa_softc *)malloc(sizeof(struct pcf_isa_softc),
- M_DEVBUF, M_NOWAIT)) == NULL)
- return (0);
-
- pcf->pcf_base = dvp->id_iobase; /* XXX should be ivars */
- pcf->pcf_unit = dvp->id_unit;
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
+ device_t parent = device_get_parent(pcfdev);
- if (!(dvp->id_flags & IIC_POLLED))
- pcf->pcf_irq = (dvp->id_irq);
+ device_set_desc(pcfdev, "PCF8584 I2C bus controller");
- pcfdata[npcf++] = pcf;
+ pcf = DEVTOSOFTC(pcfdev);
+ bzero(pcf, sizeof(struct pcf_softc));
- /* XXX add the pcf device to the root_bus until isa bus exists */
- pcfdev = device_add_child(root_bus, "pcf", pcf->pcf_unit);
+ pcf->rid_irq = pcf->rid_ioport = 0;
+ pcf->res_irq = pcf->res_ioport = 0;
- if (!pcfdev)
+ /* IO port is mandatory */
+ pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT,
+ &pcf->rid_ioport, 0ul, ~0ul,
+ IO_PCFSIZE, RF_ACTIVE);
+ if (pcf->res_ioport == 0) {
+ device_printf(pcfdev, "cannot reserve I/O port range\n");
goto error;
+ }
+ BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &pcf->pcf_base);
- return (1);
-
-error:
- free(pcf, M_DEVBUF);
- return (0);
-}
-
-static int
-pcfattach_isa(struct isa_device *isdp)
-{
- isdp->id_ointr = pcfintr;
- return (1); /* ok */
-}
+ pcf->pcf_flags = device_get_flags(pcfdev);
-static int
-pcf_probe(device_t pcfdev)
-{
- struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
- int unit = device_get_unit(pcfdev);
-
- /* retrieve base address from isa initialization
- *
- * XXX should use ivars with isabus
- */
- pcf->pcf_base = pcfdata[unit]->pcf_base;
+ if (!(pcf->pcf_flags & IIC_POLLED)) {
+ pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if (pcf->res_irq == 0) {
+ device_printf(pcfdev, "can't reserve irq, polled mode.\n");
+ pcf->pcf_flags |= IIC_POLLED;
+ }
+ }
/* reset the chip */
pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);
- /* XXX try do detect chipset */
-
- device_set_desc(pcfdev, "PCF8584 I2C bus controller");
-
return (0);
+error:
+ if (pcf->res_ioport != 0) {
+ bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
+ pcf->res_ioport);
+ bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
+ pcf->res_ioport);
+ }
+ return (ENXIO);
}
static int
pcf_attach(device_t pcfdev)
{
- struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
+ device_t parent = device_get_parent(pcfdev);
+ int error = 0;
+
+ if (pcf->res_irq) {
+ /* default to the tty mask for registration */ /* XXX */
+ error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq, INTR_TYPE_NET,
+ pcfintr, pcfdev, &pcf->intr_cookie);
+ if (error)
+ return (error);
+ }
pcf->iicbus = iicbus_alloc_bus(pcfdev);
@@ -392,10 +381,10 @@ error:
}
static void
-pcfintr(unit)
+pcfintr(void *arg)
{
- struct pcf_softc *pcf =
- (struct pcf_softc *)devclass_get_softc(pcf_devclass, unit);
+ device_t pcfdev = (device_t)arg;
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
char data, status, addr;
char error = 0;
@@ -403,14 +392,13 @@ pcfintr(unit)
status = PCF_GET_S1(pcf);
if (status & PIN) {
- printf("pcf%d: spurious interrupt, status=0x%x\n", unit,
- status & 0xff);
+ device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff);
goto error;
}
if (status & LAB)
- printf("pcf%d: bus arbitration lost!\n", unit);
+ device_printf(pcfdev, "bus arbitration lost!\n");
if (status & BER) {
error = IIC_EBUSERR;
@@ -643,4 +631,4 @@ error:
return (error);
}
-DRIVER_MODULE(pcf, root, pcf_driver, pcf_devclass, 0, 0);
+DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0);
diff --git a/sys/dev/ppbus/if_plip.c b/sys/dev/ppbus/if_plip.c
index f2085e4..033889e 100644
--- a/sys/dev/ppbus/if_plip.c
+++ b/sys/dev/ppbus/if_plip.c
@@ -77,15 +77,28 @@
/*
* Update for ppbus, PLIP support only - Nicolas Souchu
*/
+#include "plip.h"
+
+#if NPLIP > 0
+
+#include "opt_plip.h"
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
#include <sys/mbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+#include <machine/clock.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
#include <net/if.h>
#include <net/if_types.h>
#include <net/netisr.h>
@@ -96,8 +109,8 @@
#include <net/bpf.h>
#include <dev/ppbus/ppbconf.h>
-
-#include "opt_plip.h"
+#include "ppbus_if.h"
+#include <dev/ppbus/ppbio.h>
#ifndef LPMTU /* MTU for the lp# interfaces */
#define LPMTU 1500
@@ -135,20 +148,15 @@ static int volatile lptflag = 1;
static int volatile lptflag = 0;
#endif
-struct lpt_softc {
+struct lp_data {
unsigned short lp_unit;
- struct ppb_device lp_dev;
-
struct ifnet sc_if;
u_char *sc_ifbuf;
int sc_iferrs;
-};
-
-static int nlp = 0;
-#define MAXPLIP 8 /* XXX not much better! */
-static struct lpt_softc *lpdata[MAXPLIP];
+ struct resource *res_irq;
+};
/* Tables for the lp# interface */
static u_char *txmith;
@@ -162,87 +170,87 @@ static u_char *ctxmith;
#define ctrecvl (ctxmith+(3*LPIPTBLSIZE))
/* Functions for the lp# interface */
-static struct ppb_device *lpprobe(struct ppb_data *);
-static int lpattach(struct ppb_device *);
+static int lp_probe(device_t dev);
+static int lp_attach(device_t dev);
static int lpinittables(void);
static int lpioctl(struct ifnet *, u_long, caddr_t);
static int lpoutput(struct ifnet *, struct mbuf *, struct sockaddr *,
struct rtentry *);
-static void lpintr(int);
+static void lp_intr(void *);
-/*
- * Make ourselves visible as a ppbus driver
- */
+#define DEVTOSOFTC(dev) \
+ ((struct lp_data *)device_get_softc(dev))
+#define UNITOSOFTC(unit) \
+ ((struct lp_data *)devclass_get_softc(lp_devclass, (unit)))
+#define UNITODEVICE(unit) \
+ (devclass_get_device(lp_devclass, (unit)))
-static struct ppb_driver lpdriver = {
- lpprobe, lpattach, "lp"
+static devclass_t lp_devclass;
+
+static device_method_t lp_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, lp_probe),
+ DEVMETHOD(device_attach, lp_attach),
+
+ { 0, 0 }
};
-DATA_SET(ppbdriver_set, lpdriver);
+static driver_t lp_driver = {
+ "plip",
+ lp_methods,
+ sizeof(struct lp_data),
+};
/*
* lpprobe()
*/
-static struct ppb_device *
-lpprobe(struct ppb_data *ppb)
+static int
+lp_probe(device_t dev)
{
- struct lpt_softc *lp;
+ device_t ppbus = device_get_parent(dev);
+ struct lp_data *lp;
+ int irq, zero = 0;
+
+ lp = DEVTOSOFTC(dev);
+ bzero(lp, sizeof(struct lp_data));
+
+ /* retrieve the ppbus irq */
+ BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq);
/* if we haven't interrupts, the probe fails */
- if (!ppb->ppb_link->id_irq) {
- printf("plip: not an interrupt driven port, failed.\n");
- return (0);
+ if (irq == -1) {
+ device_printf(dev, "not an interrupt driven port, failed.\n");
+ return (ENXIO);
}
- lp = (struct lpt_softc *) malloc(sizeof(struct lpt_softc),
- M_TEMP, M_NOWAIT);
- if (!lp) {
- printf("lp: cannot malloc!\n");
- return (0);
+ /* reserve the interrupt resource, expecting irq is available to continue */
+ lp->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &zero, irq, irq, 1,
+ RF_SHAREABLE);
+ if (lp->res_irq == 0) {
+ device_printf(dev, "cannot reserve interrupt, failed.\n");
+ return (ENXIO);
}
- bzero(lp, sizeof(struct lpt_softc));
-
- lpdata[nlp] = lp;
/*
* lp dependent initialisation.
*/
- lp->lp_unit = nlp;
-
- if (bootverbose)
- printf("plip: irq %d\n", ppb->ppb_link->id_irq);
-
- /*
- * ppbus dependent initialisation.
- */
- lp->lp_dev.id_unit = lp->lp_unit;
- lp->lp_dev.name = lpdriver.name;
- lp->lp_dev.ppb = ppb;
- lp->lp_dev.intr = lpintr;
+ lp->lp_unit = device_get_unit(dev);
- /* Ok, go to next device on next probe */
- nlp ++;
+ device_set_desc(dev, "PLIP network interface");
- return (&lp->lp_dev);
+ return (0);
}
static int
-lpattach (struct ppb_device *dev)
+lp_attach (device_t dev)
{
- int unit = dev->id_unit;
- struct lpt_softc *sc = lpdata[unit];
- struct ifnet *ifp = &sc->sc_if;
+ struct lp_data *lp = DEVTOSOFTC(dev);
+ struct ifnet *ifp = &lp->sc_if;
- /*
- * Report ourselves
- */
- printf("plip%d: <PLIP network interface> on ppbus %d\n",
- dev->id_unit, dev->ppb->ppb_link->adapter_unit);
-
- ifp->if_softc = sc;
+ ifp->if_softc = lp;
ifp->if_name = "lp";
- ifp->if_unit = unit;
+ ifp->if_unit = device_get_unit(dev);
ifp->if_mtu = LPMTU;
ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
ifp->if_ioctl = lpioctl;
@@ -255,7 +263,7 @@ lpattach (struct ppb_device *dev)
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
- return (1);
+ return (0);
}
/*
* Build the translation tables for the LPIP (BSD unix) protocol.
@@ -303,10 +311,13 @@ lpinittables (void)
static int
lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
{
- struct lpt_softc *sc = lpdata[ifp->if_unit];
+ device_t dev = UNITODEVICE(ifp->if_unit);
+ device_t ppbus = device_get_parent(dev);
+ struct lp_data *sc = DEVTOSOFTC(dev);
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
u_char *ptr;
+ void *ih;
int error;
switch (cmd) {
@@ -322,11 +333,11 @@ lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
case SIOCSIFFLAGS:
if ((!(ifp->if_flags & IFF_UP)) && (ifp->if_flags & IFF_RUNNING)) {
- ppb_wctr(&sc->lp_dev, 0x00);
+ ppb_wctr(ppbus, 0x00);
ifp->if_flags &= ~IFF_RUNNING;
/* IFF_UP is not set, try to release the bus anyway */
- ppb_release_bus(&sc->lp_dev);
+ ppb_release_bus(ppbus, dev);
break;
}
if (((ifp->if_flags & IFF_UP)) && (!(ifp->if_flags & IFF_RUNNING))) {
@@ -334,26 +345,33 @@ lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
/* XXX
* Should the request be interruptible?
*/
- if ((error = ppb_request_bus(&sc->lp_dev, PPB_WAIT|PPB_INTR)))
+ if ((error = ppb_request_bus(ppbus, dev, PPB_WAIT|PPB_INTR)))
return (error);
/* Now IFF_UP means that we own the bus */
- ppb_set_mode(&sc->lp_dev, PPB_COMPATIBLE);
+ ppb_set_mode(ppbus, PPB_COMPATIBLE);
if (lpinittables()) {
- ppb_release_bus(&sc->lp_dev);
+ ppb_release_bus(ppbus, dev);
return ENOBUFS;
}
sc->sc_ifbuf = malloc(sc->sc_if.if_mtu + MLPIPHDRLEN,
M_DEVBUF, M_WAITOK);
if (!sc->sc_ifbuf) {
- ppb_release_bus(&sc->lp_dev);
+ ppb_release_bus(ppbus, dev);
return ENOBUFS;
}
- ppb_wctr(&sc->lp_dev, IRQENABLE);
+ /* attach our interrupt handler, later detached when the bus is released */
+ if ((error = BUS_SETUP_INTR(ppbus, dev, sc->res_irq,
+ INTR_TYPE_NET, lp_intr, dev, &ih))) {
+ ppb_release_bus(ppbus, dev);
+ return (error);
+ }
+
+ ppb_wctr(ppbus, IRQENABLE);
ifp->if_flags |= IFF_RUNNING;
}
break;
@@ -404,15 +422,15 @@ lpioctl (struct ifnet *ifp, u_long cmd, caddr_t data)
}
static __inline int
-clpoutbyte (u_char byte, int spin, struct ppb_device *dev)
+clpoutbyte (u_char byte, int spin, device_t ppbus)
{
- ppb_wdtr(dev, ctxmitl[byte]);
- while (ppb_rstr(dev) & CLPIP_SHAKE)
+ ppb_wdtr(ppbus, ctxmitl[byte]);
+ while (ppb_rstr(ppbus) & CLPIP_SHAKE)
if (--spin == 0) {
return 1;
}
- ppb_wdtr(dev, ctxmith[byte]);
- while (!(ppb_rstr(dev) & CLPIP_SHAKE))
+ ppb_wdtr(ppbus, ctxmith[byte]);
+ while (!(ppb_rstr(ppbus) & CLPIP_SHAKE))
if (--spin == 0) {
return 1;
}
@@ -420,23 +438,23 @@ clpoutbyte (u_char byte, int spin, struct ppb_device *dev)
}
static __inline int
-clpinbyte (int spin, struct ppb_device *dev)
+clpinbyte (int spin, device_t ppbus)
{
u_char c, cl;
- while((ppb_rstr(dev) & CLPIP_SHAKE))
+ while((ppb_rstr(ppbus) & CLPIP_SHAKE))
if(!--spin) {
return -1;
}
- cl = ppb_rstr(dev);
- ppb_wdtr(dev, 0x10);
+ cl = ppb_rstr(ppbus);
+ ppb_wdtr(ppbus, 0x10);
- while(!(ppb_rstr(dev) & CLPIP_SHAKE))
+ while(!(ppb_rstr(ppbus) & CLPIP_SHAKE))
if(!--spin) {
return -1;
}
- c = ppb_rstr(dev);
- ppb_wdtr(dev, 0x00);
+ c = ppb_rstr(ppbus);
+ ppb_wdtr(ppbus, 0x00);
return (ctrecvl[cl] | ctrecvh[c]);
}
@@ -460,9 +478,11 @@ lptap(struct ifnet *ifp, struct mbuf *m)
}
static void
-lpintr (int unit)
+lp_intr (void *arg)
{
- struct lpt_softc *sc = lpdata[unit];
+ device_t dev = (device_t)arg;
+ device_t ppbus = device_get_parent(dev);
+ struct lp_data *sc = DEVTOSOFTC(dev);
int len, s, j;
u_char *bp;
u_char c, cl;
@@ -473,14 +493,14 @@ lpintr (int unit)
if (sc->sc_if.if_flags & IFF_LINK0) {
/* Ack. the request */
- ppb_wdtr(&sc->lp_dev, 0x01);
+ ppb_wdtr(ppbus, 0x01);
/* Get the packet length */
- j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
+ j = clpinbyte(LPMAXSPIN2, ppbus);
if (j == -1)
goto err;
len = j;
- j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
+ j = clpinbyte(LPMAXSPIN2, ppbus);
if (j == -1)
goto err;
len = len + (j << 8);
@@ -490,14 +510,14 @@ lpintr (int unit)
bp = sc->sc_ifbuf;
while (len--) {
- j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
+ j = clpinbyte(LPMAXSPIN2, ppbus);
if (j == -1) {
goto err;
}
*bp++ = j;
}
/* Get and ignore checksum */
- j = clpinbyte(LPMAXSPIN2, &sc->lp_dev);
+ j = clpinbyte(LPMAXSPIN2, ppbus);
if (j == -1) {
goto err;
}
@@ -525,27 +545,27 @@ lpintr (int unit)
}
goto done;
}
- while ((ppb_rstr(&sc->lp_dev) & LPIP_SHAKE)) {
+ while ((ppb_rstr(ppbus) & LPIP_SHAKE)) {
len = sc->sc_if.if_mtu + LPIPHDRLEN;
bp = sc->sc_ifbuf;
while (len--) {
- cl = ppb_rstr(&sc->lp_dev);
- ppb_wdtr(&sc->lp_dev, 8);
+ cl = ppb_rstr(ppbus);
+ ppb_wdtr(ppbus, 8);
j = LPMAXSPIN2;
- while((ppb_rstr(&sc->lp_dev) & LPIP_SHAKE))
+ while((ppb_rstr(ppbus) & LPIP_SHAKE))
if(!--j) goto err;
- c = ppb_rstr(&sc->lp_dev);
- ppb_wdtr(&sc->lp_dev, 0);
+ c = ppb_rstr(ppbus);
+ ppb_wdtr(ppbus, 0);
*bp++= trecvh[cl] | trecvl[c];
j = LPMAXSPIN2;
- while (!((cl=ppb_rstr(&sc->lp_dev)) & LPIP_SHAKE)) {
+ while (!((cl=ppb_rstr(ppbus)) & LPIP_SHAKE)) {
if (cl != c &&
- (((cl = ppb_rstr(&sc->lp_dev)) ^ 0xb8) & 0xf8) ==
+ (((cl = ppb_rstr(ppbus)) ^ 0xb8) & 0xf8) ==
(c & 0xf8))
goto end;
if (!--j) goto err;
@@ -578,7 +598,7 @@ lpintr (int unit)
goto done;
err:
- ppb_wdtr(&sc->lp_dev, 0);
+ ppb_wdtr(ppbus, 0);
lprintf("R");
sc->sc_if.if_ierrors++;
sc->sc_iferrs++;
@@ -588,8 +608,8 @@ lpintr (int unit)
* so stop wasting our time
*/
if (sc->sc_iferrs > LPMAXERRS) {
- printf("lp%d: Too many errors, Going off-line.\n", unit);
- ppb_wctr(&sc->lp_dev, 0x00);
+ printf("lp%d: Too many errors, Going off-line.\n", device_get_unit(dev));
+ ppb_wctr(ppbus, 0x00);
sc->sc_if.if_flags &= ~IFF_RUNNING;
sc->sc_iferrs=0;
}
@@ -600,14 +620,14 @@ lpintr (int unit)
}
static __inline int
-lpoutbyte (u_char byte, int spin, struct ppb_device *dev)
+lpoutbyte (u_char byte, int spin, device_t ppbus)
{
- ppb_wdtr(dev, txmith[byte]);
- while (!(ppb_rstr(dev) & LPIP_SHAKE))
+ ppb_wdtr(ppbus, txmith[byte]);
+ while (!(ppb_rstr(ppbus) & LPIP_SHAKE))
if (--spin == 0)
return 1;
- ppb_wdtr(dev, txmitl[byte]);
- while (ppb_rstr(dev) & LPIP_SHAKE)
+ ppb_wdtr(ppbus, txmitl[byte]);
+ while (ppb_rstr(ppbus) & LPIP_SHAKE)
if (--spin == 0)
return 1;
return 0;
@@ -617,7 +637,8 @@ static int
lpoutput (struct ifnet *ifp, struct mbuf *m,
struct sockaddr *dst, struct rtentry *rt)
{
- struct lpt_softc *sc = lpdata[ifp->if_unit];
+ device_t dev = UNITODEVICE(ifp->if_unit);
+ device_t ppbus = device_get_parent(dev);
int s, err;
struct mbuf *mm;
u_char *cp = "\0\0";
@@ -634,19 +655,19 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
s = splhigh();
/* Suspend (on laptops) or receive-errors might have taken us offline */
- ppb_wctr(&sc->lp_dev, IRQENABLE);
+ ppb_wctr(ppbus, IRQENABLE);
if (ifp->if_flags & IFF_LINK0) {
- if (!(ppb_rstr(&sc->lp_dev) & CLPIP_SHAKE)) {
+ if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
lprintf("&");
- lpintr(ifp->if_unit);
+ lp_intr(dev);
}
/* Alert other end to pending packet */
spin = LPMAXSPIN1;
- ppb_wdtr(&sc->lp_dev, 0x08);
- while ((ppb_rstr(&sc->lp_dev) & 0x08) == 0)
+ ppb_wdtr(ppbus, 0x08);
+ while ((ppb_rstr(ppbus) & 0x08) == 0)
if (--spin == 0) {
goto nend;
}
@@ -659,21 +680,21 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
for (mm = m; mm; mm = mm->m_next) {
count += mm->m_len;
}
- if (clpoutbyte(count & 0xFF, LPMAXSPIN1, &sc->lp_dev))
+ if (clpoutbyte(count & 0xFF, LPMAXSPIN1, ppbus))
goto nend;
- if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, &sc->lp_dev))
+ if (clpoutbyte((count >> 8) & 0xFF, LPMAXSPIN1, ppbus))
goto nend;
/* Send dummy ethernet header */
for (i = 0; i < 12; i++) {
- if (clpoutbyte(i, LPMAXSPIN1, &sc->lp_dev))
+ if (clpoutbyte(i, LPMAXSPIN1, ppbus))
goto nend;
chksum += i;
}
- if (clpoutbyte(0x08, LPMAXSPIN1, &sc->lp_dev))
+ if (clpoutbyte(0x08, LPMAXSPIN1, ppbus))
goto nend;
- if (clpoutbyte(0x00, LPMAXSPIN1, &sc->lp_dev))
+ if (clpoutbyte(0x00, LPMAXSPIN1, ppbus))
goto nend;
chksum += 0x08 + 0x00; /* Add into checksum */
@@ -683,17 +704,17 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
len = mm->m_len;
while (len--) {
chksum += *cp;
- if (clpoutbyte(*cp++, LPMAXSPIN2, &sc->lp_dev))
+ if (clpoutbyte(*cp++, LPMAXSPIN2, ppbus))
goto nend;
}
} while ((mm = mm->m_next));
/* Send checksum */
- if (clpoutbyte(chksum, LPMAXSPIN2, &sc->lp_dev))
+ if (clpoutbyte(chksum, LPMAXSPIN2, ppbus))
goto nend;
/* Go quiescent */
- ppb_wdtr(&sc->lp_dev, 0);
+ ppb_wdtr(ppbus, 0);
err = 0; /* No errors */
@@ -710,22 +731,22 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
m_freem(m);
- if (!(ppb_rstr(&sc->lp_dev) & CLPIP_SHAKE)) {
+ if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
lprintf("^");
- lpintr(ifp->if_unit);
+ lp_intr(dev);
}
(void) splx(s);
return 0;
}
- if (ppb_rstr(&sc->lp_dev) & LPIP_SHAKE) {
+ if (ppb_rstr(ppbus) & LPIP_SHAKE) {
lprintf("&");
- lpintr(ifp->if_unit);
+ lp_intr(dev);
}
- if (lpoutbyte(0x08, LPMAXSPIN1, &sc->lp_dev))
+ if (lpoutbyte(0x08, LPMAXSPIN1, ppbus))
goto end;
- if (lpoutbyte(0x00, LPMAXSPIN2, &sc->lp_dev))
+ if (lpoutbyte(0x00, LPMAXSPIN2, ppbus))
goto end;
mm = m;
@@ -733,7 +754,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
cp = mtod(mm,u_char *);
len = mm->m_len;
while (len--)
- if (lpoutbyte(*cp++, LPMAXSPIN2, &sc->lp_dev))
+ if (lpoutbyte(*cp++, LPMAXSPIN2, ppbus))
goto end;
} while ((mm = mm->m_next));
@@ -741,7 +762,7 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
end:
--cp;
- ppb_wdtr(&sc->lp_dev, txmitl[*cp] ^ 0x17);
+ ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17);
if (err) { /* if we didn't timeout... */
ifp->if_oerrors++;
@@ -755,11 +776,15 @@ lpoutput (struct ifnet *ifp, struct mbuf *m,
m_freem(m);
- if (ppb_rstr(&sc->lp_dev) & LPIP_SHAKE) {
+ if (ppb_rstr(ppbus) & LPIP_SHAKE) {
lprintf("^");
- lpintr(ifp->if_unit);
+ lp_intr(dev);
}
(void) splx(s);
return 0;
}
+
+DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, 0, 0);
+
+#endif /* NPLIP > 0 */
diff --git a/sys/dev/ppbus/immio.c b/sys/dev/ppbus/immio.c
index e10f9a1..30d9117 100644
--- a/sys/dev/ppbus/immio.c
+++ b/sys/dev/ppbus/immio.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -36,6 +36,8 @@
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/buf.h>
@@ -49,11 +51,14 @@
#include "opt_vpo.h"
+#include <dev/ppbus/ppbio.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <dev/ppbus/vpoio.h>
#include <dev/ppbus/ppb_1284.h>
+#include "ppbus_if.h"
+
#define VP0_SELTMO 5000 /* select timeout */
#define VP0_FAST_SPINTMO 500000 /* wait status timeout */
#define VP0_LOW_SPINTMO 5000000 /* wait status timeout */
@@ -275,6 +280,7 @@ imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus)
{
DECLARE_CPP_MICROSEQ;
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
char s1, s2, s3;
int ret;
@@ -286,7 +292,7 @@ imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus)
CPP_S2, (void *)&s2, CPP_S3, (void *)&s3,
CPP_PARAM, 0x30);
- ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, cpp_microseq, &ret);
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x38)) {
if (bootverbose)
@@ -297,7 +303,7 @@ imm_disconnect(struct vpoio_data *vpo, int *connected, int release_bus)
}
if (release_bus)
- return (ppb_release_bus(&vpo->vpo_dev));
+ return (ppb_release_bus(ppbus, vpo->vpo_dev));
else
return (0);
}
@@ -310,6 +316,7 @@ imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus)
{
DECLARE_CPP_MICROSEQ;
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
char s1, s2, s3;
int error;
int ret;
@@ -319,7 +326,7 @@ imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus)
*disconnected = 0;
if (request_bus)
- if ((error = ppb_request_bus(&vpo->vpo_dev, how)))
+ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, how)))
return (error);
ppb_MS_init_msq(cpp_microseq, 3, CPP_S1, (void *)&s1,
@@ -327,18 +334,18 @@ imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus)
/* select device 0 in compatible mode */
ppb_MS_init_msq(cpp_microseq, 1, CPP_PARAM, 0xe0);
- ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, cpp_microseq, &ret);
/* disconnect all devices */
ppb_MS_init_msq(cpp_microseq, 1, CPP_PARAM, 0x30);
- ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, cpp_microseq, &ret);
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev))
+ if (PPB_IN_EPP_MODE(ppbus))
ppb_MS_init_msq(cpp_microseq, 1, CPP_PARAM, 0x28);
else
ppb_MS_init_msq(cpp_microseq, 1, CPP_PARAM, 0xe0);
- ppb_MS_microseq(&vpo->vpo_dev, cpp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, cpp_microseq, &ret);
if ((s1 != (char)0xb8 || s2 != (char)0x18 || s3 != (char)0x30)) {
if (bootverbose)
@@ -359,9 +366,10 @@ imm_connect(struct vpoio_data *vpo, int how, int *disconnected, int request_bus)
static int
imm_detect(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error;
- if ((error = ppb_request_bus(&vpo->vpo_dev, PPB_DONTWAIT)))
+ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT)))
return (error);
/* disconnect the drive, keep the bus */
@@ -378,7 +386,7 @@ imm_detect(struct vpoio_data *vpo)
}
/* send SCSI reset signal */
- ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, NULL);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, NULL);
/* release the bus now */
imm_disconnect(vpo, &error, 1);
@@ -396,7 +404,7 @@ imm_detect(struct vpoio_data *vpo)
return (0);
error:
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
return (VP0_EINITFAILED);
}
@@ -406,12 +414,13 @@ error:
static int
imm_outstr(struct vpoio_data *vpo, char *buffer, int size)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev))
- ppb_reset_epp_timeout(&vpo->vpo_dev);
+ if (PPB_IN_EPP_MODE(ppbus))
+ ppb_reset_epp_timeout(ppbus);
- ppb_MS_exec(&vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer,
+ ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
return (error);
@@ -423,12 +432,13 @@ imm_outstr(struct vpoio_data *vpo, char *buffer, int size)
static int
imm_instr(struct vpoio_data *vpo, char *buffer, int size)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev))
- ppb_reset_epp_timeout(&vpo->vpo_dev);
+ if (PPB_IN_EPP_MODE(ppbus))
+ ppb_reset_epp_timeout(ppbus);
- ppb_MS_exec(&vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer,
+ ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
return (error);
@@ -438,13 +448,14 @@ static char
imm_select(struct vpoio_data *vpo, int initiator, int target)
{
DECLARE_SELECT_MICROSEQUENCE;
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int ret;
/* initialize the select microsequence */
ppb_MS_init_msq(select_microseq, 1,
SELECT_TARGET, 1 << initiator | 1 << target);
- ppb_MS_microseq(&vpo->vpo_dev, select_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret);
return (ret);
}
@@ -459,15 +470,15 @@ imm_select(struct vpoio_data *vpo, int initiator, int target)
static char
imm_wait(struct vpoio_data *vpo, int tmo)
{
-
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
register int k;
register char r;
- ppb_wctr(&vpo->vpo_dev, 0xc);
+ ppb_wctr(ppbus, 0xc);
/* XXX should be ported to microseq */
k = 0;
- while (!((r = ppb_rstr(&vpo->vpo_dev)) & 0x80) && (k++ < tmo))
+ while (!((r = ppb_rstr(ppbus)) & 0x80) && (k++ < tmo))
DELAY(1);
/*
@@ -477,7 +488,7 @@ imm_wait(struct vpoio_data *vpo, int tmo)
* 0xa8 = ZIP+ wants command
* 0xb8 = end of transfer, ZIP+ is sending status
*/
- ppb_wctr(&vpo->vpo_dev, 0x4);
+ ppb_wctr(ppbus, 0x4);
if (k < tmo)
return (r & 0xb8);
@@ -488,26 +499,28 @@ static int
imm_negociate(struct vpoio_data *vpo)
{
DECLARE_NEGOCIATE_MICROSEQ;
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int negociate_mode;
int ret;
- if (PPB_IN_NIBBLE_MODE(&vpo->vpo_dev))
+ if (PPB_IN_NIBBLE_MODE(ppbus))
negociate_mode = 0;
- else if (PPB_IN_PS2_MODE(&vpo->vpo_dev))
+ else if (PPB_IN_PS2_MODE(ppbus))
negociate_mode = 1;
else
return (0);
#if 0 /* XXX use standalone code not to depend on ppb_1284 code yet */
- ret = ppb_1284_negociate(&vpo->vpo_dev, negociate_mode);
+ ret = ppb_1284_negociate(ppbus, negociate_mode);
if (ret)
return (VP0_ENEGOCIATE);
#endif
- ppb_MS_init_msq(negociate_microseq, 1, NEGOCIATED_MODE, negociate_mode);
+ ppb_MS_init_msq(negociate_microseq, 1,
+ NEGOCIATED_MODE, negociate_mode);
- ppb_MS_microseq(&vpo->vpo_dev, negociate_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, negociate_microseq, &ret);
return (ret);
}
@@ -518,21 +531,20 @@ imm_negociate(struct vpoio_data *vpo)
* Low level probe of vpo device
*
*/
-struct ppb_device *
-imm_probe(struct ppb_data *ppb, struct vpoio_data *vpo)
+int
+imm_probe(device_t dev, struct vpoio_data *vpo)
{
+ int error;
/* ppbus dependent initialisation */
- vpo->vpo_dev.id_unit = vpo->vpo_unit;
- vpo->vpo_dev.name = "vpo";
- vpo->vpo_dev.ppb = ppb;
+ vpo->vpo_dev = dev;
/* now, try to initialise the drive */
- if (imm_detect(vpo)) {
- return (NULL);
+ if ((error = imm_detect(vpo))) {
+ return (error);
}
- return (&vpo->vpo_dev);
+ return (0);
}
/*
@@ -544,22 +556,17 @@ imm_probe(struct ppb_data *ppb, struct vpoio_data *vpo)
int
imm_attach(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int epp;
/*
- * Report ourselves
- */
- printf("imm%d: <Iomega Matchmaker Parallel to SCSI interface> on ppbus %d\n",
- vpo->vpo_dev.id_unit, vpo->vpo_dev.ppb->ppb_link->adapter_unit);
-
- /*
* Initialize microsequence code
*/
vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc(
sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT);
if (!vpo->vpo_nibble_inbyte_msq)
- return (0);
+ return (ENXIO);
bcopy((void *)nibble_inbyte_submicroseq,
(void *)vpo->vpo_nibble_inbyte_msq,
@@ -570,32 +577,32 @@ imm_attach(struct vpoio_data *vpo)
/*
* Initialize mode dependent in/out microsequences
*/
- ppb_request_bus(&vpo->vpo_dev, PPB_WAIT);
+ ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT);
/* enter NIBBLE mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1) {
+ if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) {
- ppb_MS_GET_init(&vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
- ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
}
/* enter PS2 mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1) {
+ if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
- ppb_MS_GET_init(&vpo->vpo_dev, ps2_inbyte_submicroseq);
- ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
}
- epp = ppb_get_epp_protocol(&vpo->vpo_dev);
+ epp = ppb_get_epp_protocol(ppbus);
/* enter EPP mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) {
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
switch (epp) {
case EPP_1_9:
case EPP_1_7:
- ppb_MS_GET_init(&vpo->vpo_dev, epp17_instr);
- ppb_MS_PUT_init(&vpo->vpo_dev, epp17_outstr);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr);
break;
default:
panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
@@ -604,7 +611,7 @@ imm_attach(struct vpoio_data *vpo)
}
/* try to enter EPP or PS/2 mode, NIBBLE otherwise */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) {
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
switch (epp) {
case EPP_1_9:
printf("imm%d: EPP 1.9 mode\n", vpo->vpo_unit);
@@ -616,25 +623,25 @@ imm_attach(struct vpoio_data *vpo)
panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
epp);
}
- } else if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1)
+ } else if (ppb_set_mode(ppbus, PPB_PS2) != -1)
printf("imm%d: PS2 mode\n", vpo->vpo_unit);
- else if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1)
+ else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1)
printf("imm%d: NIBBLE mode\n", vpo->vpo_unit);
else {
printf("imm%d: can't enter NIBBLE, PS2 or EPP mode\n",
vpo->vpo_unit);
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF);
- return (0);
+ return (ENXIO);
}
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
- return (1);
+ return (0);
}
/*
@@ -644,6 +651,7 @@ imm_attach(struct vpoio_data *vpo)
int
imm_reset_bus(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int disconnected;
/* first, connect to the drive and request the bus */
@@ -652,7 +660,7 @@ imm_reset_bus(struct vpoio_data *vpo)
if (!disconnected) {
/* reset the SCSI bus */
- ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, NULL);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, NULL);
/* then disconnect */
imm_disconnect(vpo, NULL, 1);
@@ -672,7 +680,7 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
int clen, char *buffer, int blen, int *result, int *count,
int *ret)
{
-
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
register char r;
char l, h = 0;
int len, error = 0, not_connected = 0;
@@ -752,7 +760,7 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
error = imm_outstr(vpo, &buffer[*count], len);
} else {
- if (!PPB_IN_EPP_MODE(&vpo->vpo_dev))
+ if (!PPB_IN_EPP_MODE(ppbus))
len = 1;
else
len = (((blen - *count) >= VP0_SECTOR_SIZE)) ?
@@ -769,9 +777,9 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
*count += len;
}
- if ((PPB_IN_NIBBLE_MODE(&vpo->vpo_dev) ||
- PPB_IN_PS2_MODE(&vpo->vpo_dev)) && negociated)
- ppb_MS_microseq(&vpo->vpo_dev, transfer_epilog, NULL);
+ if ((PPB_IN_NIBBLE_MODE(ppbus) ||
+ PPB_IN_PS2_MODE(ppbus)) && negociated)
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, transfer_epilog, NULL);
/*
* Retrieve status ...
@@ -795,9 +803,9 @@ imm_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
*result = ((int) h << 8) | ((int) l & 0xff);
error:
- if ((PPB_IN_NIBBLE_MODE(&vpo->vpo_dev) ||
- PPB_IN_PS2_MODE(&vpo->vpo_dev)) && negociated)
- ppb_MS_microseq(&vpo->vpo_dev, transfer_epilog, NULL);
+ if ((PPB_IN_NIBBLE_MODE(ppbus) ||
+ PPB_IN_PS2_MODE(ppbus)) && negociated)
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, transfer_epilog, NULL);
/* return to printer state, release the ppbus */
imm_disconnect(vpo, NULL, 1);
diff --git a/sys/dev/ppbus/lpbb.c b/sys/dev/ppbus/lpbb.c
index b98f80e2..5b0c75e 100644
--- a/sys/dev/ppbus/lpbb.c
+++ b/sys/dev/ppbus/lpbb.c
@@ -46,19 +46,19 @@
#include <machine/clock.h>
#include <dev/ppbus/ppbconf.h>
+#include "ppbus_if.h"
+#include <dev/ppbus/ppbio.h>
#include <dev/iicbus/iiconf.h>
#include <dev/iicbus/iicbus.h>
#include "iicbb_if.h"
-/* iicbus softc */
struct lpbb_softc {
-
- struct ppb_device lpbb_dev;
+ int dummy;
};
-static int lpbb_detect(struct lpbb_softc *);
+static int lpbb_detect(device_t dev);
static int lpbb_probe(device_t);
static int lpbb_attach(device_t);
@@ -93,38 +93,14 @@ static driver_t lpbb_driver = {
sizeof(struct lpbb_softc),
};
-/*
- * Make ourselves visible as a ppbus driver
- */
-static struct ppb_device *lpbb_ppb_probe(struct ppb_data *ppb);
-static int lpbb_ppb_attach(struct ppb_device *dev);
-
-#define MAXLPBB 8 /* XXX not much better! */
-static struct lpbb_softc *lpbbdata[MAXLPBB];
-static int nlpbb = 0;
-
-#ifdef _KERNEL
-
-static struct ppb_driver lpbbdriver = {
- lpbb_ppb_probe, lpbb_ppb_attach, "lpbb"
-};
-DATA_SET(ppbdriver_set, lpbbdriver);
-
-#endif
-
static int
lpbb_probe(device_t dev)
{
- struct lpbb_softc *sc = lpbbdata[device_get_unit(dev)];
- struct lpbb_softc *scdst = (struct lpbb_softc *)device_get_softc(dev);
-
- /* XXX copy softc. Yet, ppbus device is sc->lpbb_dev, but will be
- * dev->parent when ppbus will be ported to the new bus architecture */
- bcopy(sc, scdst, sizeof(struct lpbb_softc));
+ device_set_desc(dev, "Parallel I2C bit-banging interface");
- device_set_desc(dev, "parallel I2C bit-banging interface");
+ if (!lpbb_detect(dev))
+ return (ENXIO);
- /* probe done by ppbus initialization */
return (0);
}
@@ -147,60 +123,10 @@ lpbb_attach(device_t dev)
return (0);
}
-/*
- * lppbb_ppb_probe()
- */
-static struct ppb_device *
-lpbb_ppb_probe(struct ppb_data *ppb)
-{
- struct lpbb_softc *sc;
-
- sc = (struct lpbb_softc *) malloc(sizeof(struct lpbb_softc),
- M_TEMP, M_NOWAIT);
- if (!sc) {
- printf("lpbb: cannot malloc!\n");
- return (0);
- }
- bzero(sc, sizeof(struct lpbb_softc));
-
- lpbbdata[nlpbb] = sc;
-
- /*
- * ppbus dependent initialisation.
- */
- sc->lpbb_dev.id_unit = nlpbb;
- sc->lpbb_dev.name = lpbbdriver.name;
- sc->lpbb_dev.ppb = ppb;
- sc->lpbb_dev.intr = 0;
-
- if (!lpbb_detect(sc)) {
- free(sc, M_TEMP);
- return (NULL);
- }
-
- /* Ok, go to next device on next probe */
- nlpbb ++;
-
- /* XXX wrong according to new bus architecture. ppbus needs to be
- * ported
- */
- return (&sc->lpbb_dev);
-}
-
-static int
-lpbb_ppb_attach(struct ppb_device *dev)
-{
- /* add the parallel port I2C interface to the bus tree */
- if (!device_add_child(root_bus, "lpbb", dev->id_unit))
- return (0);
-
- return (1);
-}
-
static int
lpbb_callback(device_t dev, int index, caddr_t *data)
{
- struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
+ device_t ppbus = device_get_parent(dev);
int error = 0;
int how;
@@ -208,12 +134,12 @@ lpbb_callback(device_t dev, int index, caddr_t *data)
case IIC_REQUEST_BUS:
/* request the ppbus */
how = *(int *)data;
- error = ppb_request_bus(&sc->lpbb_dev, how);
+ error = ppb_request_bus(ppbus, dev, how);
break;
case IIC_RELEASE_BUS:
/* release the ppbus */
- error = ppb_release_bus(&sc->lpbb_dev);
+ error = ppb_release_bus(ppbus, dev);
break;
default:
@@ -230,49 +156,51 @@ lpbb_callback(device_t dev, int index, caddr_t *data)
#define ALIM 0x20
#define I2CKEY 0x50
-static int getSDA(struct lpbb_softc *sc)
+static int getSDA(device_t ppbus)
{
-if((ppb_rstr(&sc->lpbb_dev)&SDA_in)==SDA_in)
- return 1;
-else
- return 0;
+ if((ppb_rstr(ppbus)&SDA_in)==SDA_in)
+ return 1;
+ else
+ return 0;
}
-static void setSDA(struct lpbb_softc *sc, char val)
+static void setSDA(device_t ppbus, char val)
{
-if(val==0)
- ppb_wdtr(&sc->lpbb_dev, (u_char)SDA_out);
-else
- ppb_wdtr(&sc->lpbb_dev, (u_char)~SDA_out);
+ if(val==0)
+ ppb_wdtr(ppbus, (u_char)SDA_out);
+ else
+ ppb_wdtr(ppbus, (u_char)~SDA_out);
}
-static void setSCL(struct lpbb_softc *sc, unsigned char val)
+static void setSCL(device_t ppbus, unsigned char val)
{
-if(val==0)
- ppb_wctr(&sc->lpbb_dev, (u_char)(ppb_rctr(&sc->lpbb_dev)&~SCL_out));
-else
- ppb_wctr(&sc->lpbb_dev, (u_char)(ppb_rctr(&sc->lpbb_dev)|SCL_out));
+ if(val==0)
+ ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)&~SCL_out));
+ else
+ ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus)|SCL_out));
}
-static int lpbb_detect(struct lpbb_softc *sc)
+static int lpbb_detect(device_t dev)
{
- if (ppb_request_bus(&sc->lpbb_dev, PPB_DONTWAIT)) {
- printf("lpbb: can't allocate ppbus\n");
+ device_t ppbus = device_get_parent(dev);
+
+ if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) {
+ device_printf(dev, "can't allocate ppbus\n");
return (0);
}
/* reset bus */
- setSDA(sc, 1);
- setSCL(sc, 1);
+ setSDA(ppbus, 1);
+ setSCL(ppbus, 1);
- if ((ppb_rstr(&sc->lpbb_dev) & I2CKEY) ||
- ((ppb_rstr(&sc->lpbb_dev) & ALIM) != ALIM)) {
+ if ((ppb_rstr(ppbus) & I2CKEY) ||
+ ((ppb_rstr(ppbus) & ALIM) != ALIM)) {
- ppb_release_bus(&sc->lpbb_dev);
+ ppb_release_bus(ppbus, dev);
return (0);
}
- ppb_release_bus(&sc->lpbb_dev);
+ ppb_release_bus(ppbus, dev);
return (1);
}
@@ -280,11 +208,11 @@ static int lpbb_detect(struct lpbb_softc *sc)
static int
lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
{
- struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
+ device_t ppbus = device_get_parent(dev);
/* reset bus */
- setSDA(sc, 1);
- setSCL(sc, 1);
+ setSDA(ppbus, 1);
+ setSCL(ppbus, 1);
return (IIC_ENOADDR);
}
@@ -292,18 +220,18 @@ lpbb_reset(device_t dev, u_char speed, u_char addr, u_char * oldaddr)
static void
lpbb_setlines(device_t dev, int ctrl, int data)
{
- struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
+ device_t ppbus = device_get_parent(dev);
- setSCL(sc, ctrl);
- setSDA(sc, data);
+ setSCL(ppbus, ctrl);
+ setSDA(ppbus, data);
}
static int
lpbb_getdataline(device_t dev)
{
- struct lpbb_softc *sc = (struct lpbb_softc *)device_get_softc(dev);
+ device_t ppbus = device_get_parent(dev);
- return (getSDA(sc));
+ return (getSDA(ppbus));
}
-DRIVER_MODULE(lpbb, root, lpbb_driver, lpbb_devclass, 0, 0);
+DRIVER_MODULE(lpbb, ppbus, lpbb_driver, lpbb_devclass, 0, 0);
diff --git a/sys/dev/ppbus/lpt.c b/sys/dev/ppbus/lpt.c
index 531ad48..f652a81 100644
--- a/sys/dev/ppbus/lpt.c
+++ b/sys/dev/ppbus/lpt.c
@@ -60,28 +60,37 @@
* Updated for ppbus by Nicolas Souchu
* [Mon Jul 28 1997]
*/
+#include "lpt.h"
+#if NLPT > 0
#ifdef _KERNEL
+#include "opt_lpt.h"
+
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/buf.h>
#include <sys/kernel.h>
#include <sys/uio.h>
#include <sys/syslog.h>
-#include <sys/malloc.h>
#include <machine/clock.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
#include <machine/lpt.h>
#endif
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_1284.h>
#include <dev/ppbus/lpt.h>
-
-#include "opt_lpt.h"
+#include "ppbus_if.h"
+#include <dev/ppbus/ppbio.h>
#ifndef LPT_DEBUG
#define lprintf(args)
@@ -105,9 +114,6 @@ static int volatile lptflag = 1;
#define LPTFLAGS(s) ((s)&0xfc)
struct lpt_data {
- unsigned short lpt_unit;
-
- struct ppb_device lpt_dev;
short sc_state;
/* default case: negative prime, negative ack, handshake strobe,
@@ -132,36 +138,45 @@ struct lpt_data {
#define LP_ENABLE_EXT 0x10 /* we shall use advanced mode when possible */
u_char sc_backoff ; /* time to call lptout() again */
-};
+ struct resource *intr_resource; /* interrupt resource */
+ void *intr_cookie; /* interrupt registration cookie */
-static int nlpt = 0;
-#define MAXLPT 8 /* XXX not much better! */
-static struct lpt_data *lptdata[MAXLPT];
+};
#define LPT_NAME "lpt" /* our official name */
static timeout_t lptout;
-static int lpt_port_test(struct lpt_data *sc, u_char data, u_char mask);
-static int lpt_detect(struct lpt_data *sc);
+static int lpt_port_test(device_t dev, u_char data, u_char mask);
+static int lpt_detect(device_t dev);
-/*
- * Make ourselves visible as a ppbus driver
- */
+#define DEVTOSOFTC(dev) \
+ ((struct lpt_data *)device_get_softc(dev))
+#define UNITOSOFTC(unit) \
+ ((struct lpt_data *)devclass_get_softc(lpt_devclass, (unit)))
+#define UNITODEVICE(unit) \
+ (devclass_get_device(lpt_devclass, (unit)))
-static struct ppb_device *lptprobe(struct ppb_data *ppb);
-static int lptattach(struct ppb_device *dev);
-static void lptintr(int unit);
+static int lpt_probe(device_t dev);
+static int lpt_attach(device_t dev);
-static void lpt_intr(int unit); /* without spls */
+static void lptintr(device_t dev);
+static void lpt_intr(void *arg); /* without spls */
-#ifdef _KERNEL
+static devclass_t lpt_devclass;
+
+static device_method_t lpt_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, lpt_probe),
+ DEVMETHOD(device_attach, lpt_attach),
-static struct ppb_driver lptdriver = {
- lptprobe, lptattach, LPT_NAME
+ { 0, 0 }
};
-DATA_SET(ppbdriver_set, lptdriver);
-#endif
+static driver_t lpt_driver = {
+ "lpt",
+ lpt_methods,
+ sizeof(struct lpt_data),
+};
/* bits for state */
#define OPEN (1<<0) /* device is open */
@@ -184,7 +199,7 @@ DATA_SET(ppbdriver_set, lptdriver);
/* Only used in polling code */
#define LPS_INVERT (LPS_NBSY | LPS_NACK | LPS_SEL | LPS_NERR)
#define LPS_MASK (LPS_NBSY | LPS_NACK | LPS_OUT | LPS_SEL | LPS_NERR)
-#define NOT_READY(lpt) ((ppb_rstr(&(lpt)->lpt_dev)^LPS_INVERT)&LPS_MASK)
+#define NOT_READY(ppbus) ((ppb_rstr(ppbus)^LPS_INVERT)&LPS_MASK)
#define MAX_SLEEP (hz*5) /* Timeout while waiting for device ready */
#define MAX_SPIN 20 /* Max delay for device ready in usecs */
@@ -215,43 +230,49 @@ static struct cdevsw lpt_cdevsw = {
};
static int
-lpt_request_ppbus(struct lpt_data *sc, int how)
+lpt_request_ppbus(device_t dev, int how)
{
+ device_t ppbus = device_get_parent(dev);
+ struct lpt_data *sc = DEVTOSOFTC(dev);
int error;
if (sc->sc_state & HAVEBUS)
return (0);
/* we have the bus only if the request succeded */
- if ((error = ppb_request_bus(&sc->lpt_dev, how)) == 0)
+ if ((error = ppb_request_bus(ppbus, dev, how)) == 0)
sc->sc_state |= HAVEBUS;
return (error);
}
static int
-lpt_release_ppbus(struct lpt_data *sc)
+lpt_release_ppbus(device_t dev)
{
- ppb_release_bus(&sc->lpt_dev);
- sc->sc_state &= ~HAVEBUS;
+ device_t ppbus = device_get_parent(dev);
+ struct lpt_data *sc = DEVTOSOFTC(dev);
+ int error = 0;
- return (0);
+ if ((error = ppb_release_bus(ppbus, dev)) == 0)
+ sc->sc_state &= ~HAVEBUS;
+
+ return (error);
}
/*
* Internal routine to lptprobe to do port tests of one byte value
*/
static int
-lpt_port_test(struct lpt_data *sc, u_char data, u_char mask)
+lpt_port_test(device_t ppbus, u_char data, u_char mask)
{
int temp, timeout;
data = data & mask;
- ppb_wdtr(&sc->lpt_dev, data);
+ ppb_wdtr(ppbus, data);
timeout = 10000;
do {
DELAY(10);
- temp = ppb_rdtr(&sc->lpt_dev) & mask;
+ temp = ppb_rdtr(ppbus) & mask;
}
while (temp != data && --timeout);
lprintf(("out=%x\tin=%x\ttout=%d\n", data, temp, timeout));
@@ -306,8 +327,10 @@ lpt_port_test(struct lpt_data *sc, u_char data, u_char mask)
* Quick exit on fail added.
*/
static int
-lpt_detect(struct lpt_data *sc)
+lpt_detect(device_t dev)
{
+ device_t ppbus = device_get_parent(dev);
+
static u_char testbyte[18] = {
0x55, /* alternating zeros */
0xaa, /* alternating ones */
@@ -320,33 +343,33 @@ lpt_detect(struct lpt_data *sc)
status = 1; /* assume success */
- if ((error = lpt_request_ppbus(sc, PPB_DONTWAIT))) {
+ if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) {
printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
status = 0;
goto end_probe;
}
for (i = 0; i < 18 && status; i++)
- if (!lpt_port_test(sc, testbyte[i], 0xff)) {
+ if (!lpt_port_test(ppbus, testbyte[i], 0xff)) {
status = 0;
goto end_probe;
}
end_probe:
/* write 0's to control and data ports */
- ppb_wdtr(&sc->lpt_dev, 0);
- ppb_wctr(&sc->lpt_dev, 0);
+ ppb_wdtr(ppbus, 0);
+ ppb_wctr(ppbus, 0);
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(dev);
return (status);
}
/*
- * lptprobe()
+ * lpt_probe()
*/
-static struct ppb_device *
-lptprobe(struct ppb_data *ppb)
+static int
+lpt_probe(device_t dev)
{
struct lpt_data *sc;
static int once;
@@ -354,96 +377,81 @@ lptprobe(struct ppb_data *ppb)
if (!once++)
cdevsw_add(&lpt_cdevsw);
- sc = (struct lpt_data *) malloc(sizeof(struct lpt_data),
- M_TEMP, M_NOWAIT);
- if (!sc) {
- printf(LPT_NAME ": cannot malloc!\n");
- return (0);
- }
+ sc = DEVTOSOFTC(dev);
bzero(sc, sizeof(struct lpt_data));
- lptdata[nlpt] = sc;
-
- /*
- * lpt dependent initialisation.
- */
- sc->lpt_unit = nlpt;
-
- /*
- * ppbus dependent initialisation.
- */
- sc->lpt_dev.id_unit = sc->lpt_unit;
- sc->lpt_dev.name = lptdriver.name;
- sc->lpt_dev.ppb = ppb;
- sc->lpt_dev.intr = lptintr;
-
/*
* Now, try to detect the printer.
*/
- if (!lpt_detect(sc)) {
- free(sc, M_TEMP);
- return (0);
- }
+ if (!lpt_detect(dev))
+ return (ENXIO);
- /* Ok, go to next device on next probe */
- nlpt ++;
+ device_set_desc(dev, "Printer");
- return (&sc->lpt_dev);
+ return (0);
}
static int
-lptattach(struct ppb_device *dev)
+lpt_attach(device_t dev)
{
- struct lpt_data *sc = lptdata[dev->id_unit];
+ device_t ppbus = device_get_parent(dev);
+ struct lpt_data *sc = DEVTOSOFTC(dev);
+ int zero = 0, irq, unit = device_get_unit(dev);
int error;
- /*
- * Report ourselves
- */
- printf(LPT_NAME "%d: <generic printer> on ppbus %d\n",
- dev->id_unit, dev->ppb->ppb_link->adapter_unit);
-
sc->sc_primed = 0; /* not primed yet */
- if ((error = lpt_request_ppbus(sc, PPB_DONTWAIT))) {
+ if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) {
printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
return (0);
}
- ppb_wctr(&sc->lpt_dev, LPC_NINIT);
+ ppb_wctr(ppbus, LPC_NINIT);
/* check if we can use interrupt, should be done by ppc stuff */
lprintf(("oldirq %x\n", sc->sc_irq));
- if (ppb_get_irq(&sc->lpt_dev)) {
+
+ /* retrieve the ppbus irq */
+ BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq);
+
+ if (irq > 0) {
+ /* declare our interrupt handler */
+ sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &zero, irq, irq, 1, RF_SHAREABLE);
+ }
+ if (sc->intr_resource) {
sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
- printf(LPT_NAME "%d: Interrupt-driven port\n", dev->id_unit);
+ device_printf(dev, "Interrupt-driven port\n");
} else {
sc->sc_irq = 0;
- lprintf((LPT_NAME "%d: Polled port\n", dev->id_unit));
+ device_printf(dev, "Polled port\n");
}
- lprintf(("irq %x\n", sc->sc_irq));
+ lprintf(("irq %x %x\n", irq, sc->sc_irq));
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(dev);
- make_dev(&lpt_cdevsw, dev->id_unit,
- UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d", dev->id_unit);
- make_dev(&lpt_cdevsw, dev->id_unit | LP_BYPASS,
- UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d.ctl", dev->id_unit);
- return (1);
+ make_dev(&lpt_cdevsw, unit,
+ UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d", unit);
+ make_dev(&lpt_cdevsw, unit | LP_BYPASS,
+ UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d.ctl", unit);
+ return (0);
}
static void
lptout(void *arg)
{
- struct lpt_data *sc = arg;
- int pl;
+ device_t dev = (device_t)arg;
+ struct lpt_data *sc = DEVTOSOFTC(dev);
+#ifdef LPT_DEBUG
+ device_t ppbus = device_get_parent(dev);
+#endif
- lprintf(("T %x ", ppb_rstr(&sc->lpt_dev)));
+ lprintf(("T %x ", ppb_rstr(ppbus)));
if (sc->sc_state & OPEN) {
sc->sc_backoff++;
if (sc->sc_backoff > hz/LPTOUTMAX)
sc->sc_backoff = sc->sc_backoff > hz/LPTOUTMAX;
- timeout(lptout, (caddr_t)sc, sc->sc_backoff);
+ timeout(lptout, (caddr_t)dev, sc->sc_backoff);
} else
sc->sc_state &= ~TOUT;
@@ -451,15 +459,13 @@ lptout(void *arg)
sc->sc_state &= ~EERROR;
/*
- * Avoid possible hangs do to missed interrupts
+ * Avoid possible hangs due to missed interrupts
*/
if (sc->sc_xfercnt) {
- pl = spltty();
- lpt_intr(sc->lpt_unit);
- splx(pl);
+ lptintr(dev);
} else {
sc->sc_state &= ~OBUSY;
- wakeup((caddr_t)sc);
+ wakeup((caddr_t)dev);
}
}
@@ -472,17 +478,16 @@ lptout(void *arg)
static int
lptopen(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct lpt_data *sc;
-
int s;
int trys, err;
u_int unit = LPTUNIT(minor(dev));
+ struct lpt_data *sc = UNITOSOFTC(unit);
+ device_t lptdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(lptdev);
- if ((unit >= nlpt))
+ if (!sc)
return (ENXIO);
- sc = lptdata[unit];
-
if (sc->sc_state) {
lprintf((LPT_NAME ": still open %x\n", sc->sc_state));
return(EBUSY);
@@ -498,13 +503,17 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
}
/* request the ppbus only if we don't have it already */
- if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
+ if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) {
+ /* give it a chance to try later */
+ sc->sc_state = 0;
return (err);
+ }
s = spltty();
lprintf((LPT_NAME " flags 0x%x\n", sc->sc_flags));
- /* set IRQ status according to ENABLE_IRQ flag */
+ /* set IRQ status according to ENABLE_IRQ flag
+ */
if (sc->sc_irq & LP_ENABLE_IRQ)
sc->sc_irq |= LP_USE_IRQ;
else
@@ -513,13 +522,13 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
/* init printer */
if ((sc->sc_flags & LP_NO_PRIME) == 0) {
if((sc->sc_flags & LP_PRIMEOPEN) || sc->sc_primed == 0) {
- ppb_wctr(&sc->lpt_dev, 0);
+ ppb_wctr(ppbus, 0);
sc->sc_primed++;
DELAY(500);
}
}
- ppb_wctr(&sc->lpt_dev, LPC_SEL|LPC_NINIT);
+ ppb_wctr(ppbus, LPC_SEL|LPC_NINIT);
/* wait till ready (printer running diagnostics) */
trys = 0;
@@ -528,24 +537,24 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
if (trys++ >= LPINITRDY*4) {
splx(s);
sc->sc_state = 0;
- lprintf(("status %x\n", ppb_rstr(&sc->lpt_dev)));
+ lprintf(("status %x\n", ppb_rstr(ppbus)));
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(lptdev);
return (EBUSY);
}
/* wait 1/4 second, give up if we get a signal */
- if (tsleep((caddr_t)sc, LPPRI|PCATCH, "lptinit", hz/4) !=
+ if (tsleep((caddr_t)lptdev, LPPRI|PCATCH, "lptinit", hz/4) !=
EWOULDBLOCK) {
sc->sc_state = 0;
splx(s);
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(lptdev);
return (EBUSY);
}
/* is printer online and ready for output */
- } while ((ppb_rstr(&sc->lpt_dev) &
+ } while ((ppb_rstr(ppbus) &
(LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
(LPS_SEL|LPS_NBSY|LPS_NERR));
@@ -557,7 +566,7 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
if (sc->sc_irq & LP_USE_IRQ)
sc->sc_control |= LPC_ENA;
- ppb_wctr(&sc->lpt_dev, sc->sc_control);
+ ppb_wctr(ppbus, sc->sc_control);
sc->sc_state = OPEN;
sc->sc_inbuf = geteblk(BUFSIZE);
@@ -566,13 +575,13 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
splx(s);
/* release the ppbus */
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(lptdev);
/* only use timeout if using interrupt */
lprintf(("irq %x\n", sc->sc_irq));
if (sc->sc_irq & LP_USE_IRQ) {
sc->sc_state |= TOUT;
- timeout(lptout, (caddr_t)sc,
+ timeout(lptout, (caddr_t)lptdev,
(sc->sc_backoff = hz/LPTOUTINITIAL));
}
@@ -589,34 +598,39 @@ lptopen(dev_t dev, int flags, int fmt, struct proc *p)
static int
lptclose(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
+ u_int unit = LPTUNIT(minor(dev));
+ struct lpt_data *sc = UNITOSOFTC(unit);
+ device_t lptdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(lptdev);
int err;
if(sc->sc_flags & LP_BYPASS)
goto end_close;
- if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
+ if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0)
return (err);
sc->sc_state &= ~OPEN;
/* if the last write was interrupted, don't complete it */
if((!(sc->sc_state & INTERRUPTED)) && (sc->sc_irq & LP_USE_IRQ))
- while ((ppb_rstr(&sc->lpt_dev) &
+ while ((ppb_rstr(ppbus) &
(LPS_SEL|LPS_OUT|LPS_NBSY|LPS_NERR)) !=
(LPS_SEL|LPS_NBSY|LPS_NERR) || sc->sc_xfercnt)
/* wait 1/4 second, give up if we get a signal */
- if (tsleep((caddr_t)sc, LPPRI|PCATCH,
+ if (tsleep((caddr_t)lptdev, LPPRI|PCATCH,
"lpclose", hz) != EWOULDBLOCK)
break;
- ppb_wctr(&sc->lpt_dev, LPC_NINIT);
+ ppb_wctr(ppbus, LPC_NINIT);
brelse(sc->sc_inbuf);
brelse(sc->sc_statbuf);
end_close:
- /* release the bus anyway */
- lpt_release_ppbus(sc);
+ /* release the bus anyway
+ * unregistration of interrupt forced by release
+ */
+ lpt_release_ppbus(lptdev);
sc->sc_state = 0;
sc->sc_xfercnt = 0;
@@ -633,8 +647,10 @@ end_close:
* This code is only used when we are polling the port
*/
static int
-lpt_pushbytes(struct lpt_data *sc)
+lpt_pushbytes(device_t dev)
{
+ struct lpt_data *sc = DEVTOSOFTC(dev);
+ device_t ppbus = device_get_parent(dev);
int spin, err, tic;
char ch;
@@ -651,11 +667,11 @@ lpt_pushbytes(struct lpt_data *sc)
* Loop 20 usecs testing BUSY bit, then sleep
* for exponentially increasing timeout. (vak)
*/
- for (spin = 0; NOT_READY(sc) && spin < MAX_SPIN; ++spin)
+ for (spin = 0; NOT_READY(ppbus) && spin < MAX_SPIN; ++spin)
DELAY(1); /* XXX delay is NOT this accurate! */
if (spin >= MAX_SPIN) {
tic = 0;
- while (NOT_READY(sc)) {
+ while (NOT_READY(ppbus)) {
/*
* Now sleep, every cycle a
* little longer ..
@@ -666,7 +682,7 @@ lpt_pushbytes(struct lpt_data *sc)
*/
if (tic > MAX_SLEEP)
tic = MAX_SLEEP;
- err = tsleep((caddr_t)sc, LPPRI,
+ err = tsleep((caddr_t)dev, LPPRI,
LPT_NAME "poll", tic);
if (err != EWOULDBLOCK) {
return (err);
@@ -675,10 +691,10 @@ lpt_pushbytes(struct lpt_data *sc)
}
/* output data */
- ppb_wdtr(&sc->lpt_dev, ch);
+ ppb_wdtr(ppbus, ch);
/* strobe */
- ppb_wctr(&sc->lpt_dev, sc->sc_control|LPC_STB);
- ppb_wctr(&sc->lpt_dev, sc->sc_control);
+ ppb_wctr(ppbus, sc->sc_control|LPC_STB);
+ ppb_wctr(ppbus, sc->sc_control);
}
return(0);
@@ -691,16 +707,19 @@ lpt_pushbytes(struct lpt_data *sc)
static int
lptread(dev_t dev, struct uio *uio, int ioflag)
{
- struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
+ u_int unit = LPTUNIT(minor(dev));
+ struct lpt_data *sc = UNITOSOFTC(unit);
+ device_t lptdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(lptdev);
int error = 0, len;
- if ((error = ppb_1284_negociate(&sc->lpt_dev, PPB_NIBBLE, 0)))
+ if ((error = ppb_1284_negociate(ppbus, PPB_NIBBLE, 0)))
return (error);
/* read data in an other buffer, read/write may be simultaneous */
len = 0;
while (uio->uio_resid) {
- if ((error = ppb_1284_read(&sc->lpt_dev, PPB_NIBBLE,
+ if ((error = ppb_1284_read(ppbus, PPB_NIBBLE,
sc->sc_statbuf->b_data, min(BUFSTATSIZE,
uio->uio_resid), &len))) {
goto error;
@@ -714,7 +733,7 @@ lptread(dev_t dev, struct uio *uio, int ioflag)
}
error:
- ppb_1284_terminate(&sc->lpt_dev);
+ ppb_1284_terminate(ppbus);
return (error);
}
@@ -729,9 +748,11 @@ static int
lptwrite(dev_t dev, struct uio *uio, int ioflag)
{
register unsigned n;
- int pl, err;
+ int err;
u_int unit = LPTUNIT(minor(dev));
- struct lpt_data *sc = lptdata[LPTUNIT(minor(dev))];
+ struct lpt_data *sc = UNITOSOFTC(unit);
+ device_t lptdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(lptdev);
if(sc->sc_flags & LP_BYPASS) {
/* we can't do writes in bypass mode */
@@ -739,9 +760,22 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
}
/* request the ppbus only if we don't have it already */
- if ((err = lpt_request_ppbus(sc, PPB_WAIT|PPB_INTR)) != 0)
+ /* XXX interrupt registration?! */
+ if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0)
return (err);
+ /* if interrupts are working, register the handler */
+ if (sc->sc_irq & LP_USE_IRQ) {
+ /* register our interrupt handler */
+ err = BUS_SETUP_INTR(ppbus, lptdev, sc->intr_resource,
+ INTR_TYPE_TTY, lpt_intr, lptdev,
+ &sc->intr_cookie);
+ if (err) {
+ device_printf(lptdev, "handler registration failed, polled mode.\n");
+ sc->sc_irq &= ~LP_USE_IRQ;
+ }
+ }
+
sc->sc_state &= ~INTERRUPTED;
while ((n = min(BUFSIZE, uio->uio_resid)) != 0) {
sc->sc_cp = sc->sc_inbuf->b_data ;
@@ -750,8 +784,8 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
if (sc->sc_irq & LP_ENABLE_EXT) {
/* try any extended mode */
- err = ppb_write(&sc->lpt_dev, sc->sc_cp,
- sc->sc_xfercnt, 0);
+ err = ppb_write(ppbus, sc->sc_cp,
+ sc->sc_xfercnt, 0);
switch (err) {
case 0:
/* if not all data was sent, we could rely
@@ -774,13 +808,11 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
/* give it one */
if ((sc->sc_state & OBUSY) == 0){
lprintf(("\nC %d. ", sc->sc_xfercnt));
- pl = spltty();
- lpt_intr(sc->lpt_unit);
- (void) splx(pl);
+ lptintr(lptdev);
}
lprintf(("W "));
if (sc->sc_state & OBUSY)
- if ((err = tsleep((caddr_t)sc,
+ if ((err = tsleep((caddr_t)lptdev,
LPPRI|PCATCH, LPT_NAME "write", 0))) {
sc->sc_state |= INTERRUPTED;
return(err);
@@ -791,7 +823,7 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
if(!(sc->sc_irq & LP_USE_IRQ) && (sc->sc_xfercnt)) {
lprintf(("p"));
- err = lpt_pushbytes(sc);
+ err = lpt_pushbytes(lptdev);
if (err)
return(err);
@@ -799,7 +831,7 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
}
/* we have not been interrupted, release the ppbus */
- lpt_release_ppbus(sc);
+ lpt_release_ppbus(lptdev);
return(0);
}
@@ -812,9 +844,11 @@ lptwrite(dev_t dev, struct uio *uio, int ioflag)
*/
static void
-lpt_intr(int unit)
+lpt_intr(void *arg)
{
- struct lpt_data *sc = lptdata[unit];
+ device_t lptdev = (device_t)arg;
+ device_t ppbus = device_get_parent(lptdev);
+ struct lpt_data *sc = DEVTOSOFTC(lptdev);
int sts;
int i;
@@ -829,7 +863,7 @@ lpt_intr(int unit)
* to see if the printer will become ready ``really soon now''.
*/
for (i = 0; i < 100 &&
- ((sts=ppb_rstr(&sc->lpt_dev)) & RDY_MASK) != LP_READY; i++) ;
+ ((sts=ppb_rstr(ppbus)) & RDY_MASK) != LP_READY; i++) ;
if ((sts & RDY_MASK) == LP_READY) {
sc->sc_state = (sc->sc_state | OBUSY) & ~EERROR;
@@ -838,10 +872,10 @@ lpt_intr(int unit)
if (sc->sc_xfercnt) {
/* send char */
/*lprintf(("%x ", *sc->sc_cp)); */
- ppb_wdtr(&sc->lpt_dev, *sc->sc_cp++) ;
- ppb_wctr(&sc->lpt_dev, sc->sc_control|LPC_STB);
+ ppb_wdtr(ppbus, *sc->sc_cp++) ;
+ ppb_wctr(ppbus, sc->sc_control|LPC_STB);
/* DELAY(X) */
- ppb_wctr(&sc->lpt_dev, sc->sc_control);
+ ppb_wctr(ppbus, sc->sc_control);
/* any more data for printer */
if(--(sc->sc_xfercnt) > 0) return;
@@ -867,12 +901,12 @@ lpt_intr(int unit)
}
static void
-lptintr(int unit)
+lptintr(device_t dev)
{
/* call the interrupt at required spl level */
int s = spltty();
- lpt_intr(unit);
+ lpt_intr(dev);
splx(s);
return;
@@ -882,12 +916,10 @@ static int
lptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
int error = 0;
- struct lpt_data *sc;
u_int unit = LPTUNIT(minor(dev));
+ struct lpt_data *sc = UNITOSOFTC(unit);
u_char old_sc_irq; /* old printer IRQ status */
- sc = lptdata[unit];
-
switch (cmd) {
case LPT_IRQ :
if(sc->sc_irq & LP_HAS_IRQ) {
@@ -939,3 +971,8 @@ lptioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
return(error);
}
+
+DRIVER_MODULE(lpt, ppbus, lpt_driver, lpt_devclass, 0, 0);
+
+#endif
+
diff --git a/sys/dev/ppbus/ppb_1284.c b/sys/dev/ppbus/ppb_1284.c
index 3022174..2040874 100644
--- a/sys/dev/ppbus/ppb_1284.c
+++ b/sys/dev/ppbus/ppb_1284.c
@@ -35,27 +35,34 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/bus.h>
#include <machine/clock.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_1284.h>
+#include "ppbus_if.h"
+
+#include <dev/ppbus/ppbio.h>
+
+#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
+
/*
* do_1284_wait()
*
* Wait for the peripherial up to 40ms
*/
static int
-do_1284_wait(struct ppb_device *dev, char mask, char status)
+do_1284_wait(device_t bus, char mask, char status)
{
- return (ppb_poll_device(dev, 4, mask, status, PPB_NOINTR | PPB_POLL));
+ return (ppb_poll_bus(bus, 4, mask, status, PPB_NOINTR | PPB_POLL));
}
static int
-do_peripheral_wait(struct ppb_device *dev, char mask, char status)
+do_peripheral_wait(device_t bus, char mask, char status)
{
- return (ppb_poll_device(dev, 100, mask, status, PPB_NOINTR | PPB_POLL));
+ return (ppb_poll_bus(bus, 100, mask, status, PPB_NOINTR | PPB_POLL));
}
#define nibble2char(s) (((s & ~nACK) >> 3) | (~s & nBUSY) >> 4)
@@ -66,10 +73,12 @@ do_peripheral_wait(struct ppb_device *dev, char mask, char status)
* Unconditionaly reset the error field
*/
static int
-ppb_1284_reset_error(struct ppb_device *dev, int state)
+ppb_1284_reset_error(device_t bus, int state)
{
- dev->ppb->error = PPB_NO_ERROR;
- dev->ppb->state = state;
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+
+ ppb->error = PPB_NO_ERROR;
+ ppb->state = state;
return (0);
}
@@ -80,9 +89,9 @@ ppb_1284_reset_error(struct ppb_device *dev, int state)
* Get IEEE1284 state
*/
static int
-ppb_1284_get_state(struct ppb_device *dev)
+ppb_1284_get_state(device_t bus)
{
- return (dev->ppb->state);
+ return (DEVTOSOFTC(bus)->state);
}
/*
@@ -91,32 +100,36 @@ ppb_1284_get_state(struct ppb_device *dev)
* Change IEEE1284 state if no error occured
*/
static int
-ppb_1284_set_state(struct ppb_device *dev, int state)
+ppb_1284_set_state(device_t bus, int state)
{
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+
/* call ppb_1284_reset_error() if you absolutly want to change
* the state from PPB_ERROR to another */
- if ((dev->ppb->state != PPB_ERROR) &&
- (dev->ppb->error == PPB_NO_ERROR)) {
- dev->ppb->state = state;
- dev->ppb->error = PPB_NO_ERROR;
+ if ((ppb->state != PPB_ERROR) &&
+ (ppb->error == PPB_NO_ERROR)) {
+ ppb->state = state;
+ ppb->error = PPB_NO_ERROR;
}
return (0);
}
static int
-ppb_1284_set_error(struct ppb_device *dev, int error, int event)
+ppb_1284_set_error(device_t bus, int error, int event)
{
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+
/* do not accumulate errors */
- if ((dev->ppb->error == PPB_NO_ERROR) &&
- (dev->ppb->state != PPB_ERROR)) {
- dev->ppb->error = error;
- dev->ppb->state = PPB_ERROR;
+ if ((ppb->error == PPB_NO_ERROR) &&
+ (ppb->state != PPB_ERROR)) {
+ ppb->error = error;
+ ppb->state = PPB_ERROR;
}
#ifdef DEBUG_1284
printf("ppb1284: error=%d status=0x%x event=%d\n", error,
- ppb_rstr(dev) & 0xff, event);
+ ppb_rstr(bus) & 0xff, event);
#endif
return (0);
@@ -174,54 +187,54 @@ ppb_request_mode(int mode, int options)
* Negociate the peripheral side
*/
int
-ppb_peripheral_negociate(struct ppb_device *dev, int mode, int options)
+ppb_peripheral_negociate(device_t bus, int mode, int options)
{
int spin, request_mode, error = 0;
char r;
- ppb_set_mode(dev, PPB_COMPATIBLE);
- ppb_1284_set_state(dev, PPB_PERIPHERAL_NEGOCIATION);
+ ppb_set_mode(bus, PPB_COMPATIBLE);
+ ppb_1284_set_state(bus, PPB_PERIPHERAL_NEGOCIATION);
/* compute ext. value */
request_mode = ppb_request_mode(mode, options);
/* wait host */
spin = 10;
- while (spin-- && (ppb_rstr(dev) & nBUSY))
+ while (spin-- && (ppb_rstr(bus) & nBUSY))
DELAY(1);
/* check termination */
- if (!(ppb_rstr(dev) & SELECT) || !spin) {
+ if (!(ppb_rstr(bus) & SELECT) || !spin) {
error = ENODEV;
goto error;
}
/* Event 4 - read ext. value */
- r = ppb_rdtr(dev);
+ r = ppb_rdtr(bus);
/* nibble mode is not supported */
if ((r == (char)request_mode) ||
(r == NIBBLE_1284_NORMAL)) {
/* Event 5 - restore direction bit, no data avail */
- ppb_wctr(dev, (STROBE | nINIT) & ~(SELECTIN));
+ ppb_wctr(bus, (STROBE | nINIT) & ~(SELECTIN));
DELAY(1);
/* Event 6 */
- ppb_wctr(dev, (nINIT) & ~(SELECTIN | STROBE));
+ ppb_wctr(bus, (nINIT) & ~(SELECTIN | STROBE));
if (r == NIBBLE_1284_NORMAL) {
#ifdef DEBUG_1284
printf("R");
#endif
- ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4);
+ ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);
error = EINVAL;
goto error;
} else {
- ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE);
+ ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE);
switch (r) {
case BYTE_1284_NORMAL:
- ppb_set_mode(dev, PPB_BYTE);
+ ppb_set_mode(bus, PPB_BYTE);
break;
default:
break;
@@ -233,12 +246,12 @@ ppb_peripheral_negociate(struct ppb_device *dev, int mode, int options)
}
} else {
/* Event 5 - mode not supported */
- ppb_wctr(dev, SELECTIN);
+ ppb_wctr(bus, SELECTIN);
DELAY(1);
/* Event 6 */
- ppb_wctr(dev, (SELECTIN) & ~(STROBE | nINIT));
- ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 4);
+ ppb_wctr(bus, (SELECTIN) & ~(STROBE | nINIT));
+ ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 4);
#ifdef DEBUG_1284
printf("r");
@@ -250,7 +263,7 @@ ppb_peripheral_negociate(struct ppb_device *dev, int mode, int options)
return (0);
error:
- ppb_peripheral_terminate(dev, PPB_WAIT);
+ ppb_peripheral_terminate(bus, PPB_WAIT);
return (error);
}
@@ -262,7 +275,7 @@ error:
* Always return 0 in compatible mode
*/
int
-ppb_peripheral_terminate(struct ppb_device *dev, int how)
+ppb_peripheral_terminate(device_t bus, int how)
{
int error = 0;
@@ -270,38 +283,38 @@ ppb_peripheral_terminate(struct ppb_device *dev, int how)
printf("t");
#endif
- ppb_1284_set_state(dev, PPB_PERIPHERAL_TERMINATION);
+ ppb_1284_set_state(bus, PPB_PERIPHERAL_TERMINATION);
/* Event 22 - wait up to host response time (1s) */
- if ((error = do_peripheral_wait(dev, SELECT | nBUSY, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 22);
+ if ((error = do_peripheral_wait(bus, SELECT | nBUSY, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 22);
goto error;
}
/* Event 24 */
- ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
+ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
/* Event 25 - wait up to host response time (1s) */
- if ((error = do_peripheral_wait(dev, nBUSY, nBUSY))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 25);
+ if ((error = do_peripheral_wait(bus, nBUSY, nBUSY))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 25);
goto error;
}
/* Event 26 */
- ppb_wctr(dev, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));
+ ppb_wctr(bus, (SELECTIN | nINIT | STROBE) & ~(AUTOFEED));
DELAY(1);
/* Event 27 */
- ppb_wctr(dev, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED));
+ ppb_wctr(bus, (SELECTIN | nINIT) & ~(STROBE | AUTOFEED));
/* Event 28 - wait up to host response time (1s) */
- if ((error = do_peripheral_wait(dev, nBUSY, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 28);
+ if ((error = do_peripheral_wait(bus, nBUSY, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 28);
goto error;
}
error:
- ppb_set_mode(dev, PPB_COMPATIBLE);
- ppb_1284_set_state(dev, PPB_FORWARD_IDLE);
+ ppb_set_mode(bus, PPB_COMPATIBLE);
+ ppb_1284_set_state(bus, PPB_FORWARD_IDLE);
return (0);
}
@@ -312,19 +325,19 @@ error:
* Write 1 byte in BYTE mode
*/
static int
-byte_peripheral_outbyte(struct ppb_device *dev, char *buffer, int last)
+byte_peripheral_outbyte(device_t bus, char *buffer, int last)
{
int error = 0;
/* Event 7 */
- if ((error = do_1284_wait(dev, nBUSY, nBUSY))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 7);
+ if ((error = do_1284_wait(bus, nBUSY, nBUSY))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 7);
goto error;
}
/* check termination */
- if (!(ppb_rstr(dev) & SELECT)) {
- ppb_peripheral_terminate(dev, PPB_WAIT);
+ if (!(ppb_rstr(bus) & SELECT)) {
+ ppb_peripheral_terminate(bus, PPB_WAIT);
goto error;
}
@@ -332,35 +345,35 @@ byte_peripheral_outbyte(struct ppb_device *dev, char *buffer, int last)
#ifdef DEBUG_1284
printf("B");
#endif
- ppb_wdtr(dev, *buffer);
+ ppb_wdtr(bus, *buffer);
/* Event 9 */
- ppb_wctr(dev, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN));
+ ppb_wctr(bus, (AUTOFEED | STROBE) & ~(nINIT | SELECTIN));
/* Event 10 - wait data read */
- if ((error = do_peripheral_wait(dev, nBUSY, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 16);
+ if ((error = do_peripheral_wait(bus, nBUSY, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 16);
goto error;
}
/* Event 11 */
if (!last) {
- ppb_wctr(dev, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN));
+ ppb_wctr(bus, (AUTOFEED) & ~(nINIT | STROBE | SELECTIN));
} else {
- ppb_wctr(dev, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED));
+ ppb_wctr(bus, (nINIT) & ~(STROBE | SELECTIN | AUTOFEED));
}
#if 0
/* Event 16 - wait strobe */
- if ((error = do_peripheral_wait(dev, nACK | nBUSY, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 16);
+ if ((error = do_peripheral_wait(bus, nACK | nBUSY, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 16);
goto error;
}
#endif
/* check termination */
- if (!(ppb_rstr(dev) & SELECT)) {
- ppb_peripheral_terminate(dev, PPB_WAIT);
+ if (!(ppb_rstr(bus) & SELECT)) {
+ ppb_peripheral_terminate(bus, PPB_WAIT);
goto error;
}
@@ -374,12 +387,12 @@ error:
* Write n bytes in BYTE mode
*/
int
-byte_peripheral_write(struct ppb_device *dev, char *buffer, int len, int *sent)
+byte_peripheral_write(device_t bus, char *buffer, int len, int *sent)
{
int error = 0, i;
char r;
- ppb_1284_set_state(dev, PPB_PERIPHERAL_TRANSFER);
+ ppb_1284_set_state(bus, PPB_PERIPHERAL_TRANSFER);
/* wait forever, the remote host is master and should initiate
* termination
@@ -388,14 +401,14 @@ byte_peripheral_write(struct ppb_device *dev, char *buffer, int len, int *sent)
/* force remote nFAULT low to release the remote waiting
* process, if any
*/
- r = ppb_rctr(dev);
- ppb_wctr(dev, r & ~nINIT);
+ r = ppb_rctr(bus);
+ ppb_wctr(bus, r & ~nINIT);
#ifdef DEBUG_1284
printf("y");
#endif
/* Event 7 */
- error = ppb_poll_device(dev, PPB_FOREVER, nBUSY, nBUSY,
+ error = ppb_poll_bus(bus, PPB_FOREVER, nBUSY, nBUSY,
PPB_INTR);
if (error && error != EWOULDBLOCK)
@@ -404,12 +417,12 @@ byte_peripheral_write(struct ppb_device *dev, char *buffer, int len, int *sent)
#ifdef DEBUG_1284
printf("b");
#endif
- if ((error = byte_peripheral_outbyte(dev, buffer+i, (i == len-1))))
+ if ((error = byte_peripheral_outbyte(bus, buffer+i, (i == len-1))))
goto error;
}
error:
if (!error)
- ppb_1284_set_state(dev, PPB_PERIPHERAL_IDLE);
+ ppb_1284_set_state(bus, PPB_PERIPHERAL_IDLE);
*sent = i;
return (error);
@@ -421,35 +434,35 @@ error:
* Read 1 byte in BYTE mode
*/
int
-byte_1284_inbyte(struct ppb_device *dev, char *buffer)
+byte_1284_inbyte(device_t bus, char *buffer)
{
int error = 0;
/* Event 7 - ready to take data (nAUTO low) */
- ppb_wctr(dev, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
+ ppb_wctr(bus, (PCD | nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
/* Event 9 - peripheral set nAck low */
- if ((error = do_1284_wait(dev, nACK, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 9);
+ if ((error = do_1284_wait(bus, nACK, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 9);
goto error;
}
/* read the byte */
- *buffer = ppb_rdtr(dev);
+ *buffer = ppb_rdtr(bus);
/* Event 10 - data received, can't accept more */
- ppb_wctr(dev, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
+ ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
/* Event 11 - peripheral ack */
- if ((error = do_1284_wait(dev, nACK, nACK))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 11);
+ if ((error = do_1284_wait(bus, nACK, nACK))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 11);
goto error;
}
/* Event 16 - strobe */
- ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
+ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
DELAY(3);
- ppb_wctr(dev, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
+ ppb_wctr(bus, (nINIT) & ~(AUTOFEED | STROBE | SELECTIN));
error:
return (error);
@@ -461,7 +474,7 @@ error:
* Read 1 byte in NIBBLE mode
*/
int
-nibble_1284_inbyte(struct ppb_device *dev, char *buffer)
+nibble_1284_inbyte(device_t bus, char *buffer)
{
char nibble[2];
int i, error;
@@ -469,25 +482,25 @@ nibble_1284_inbyte(struct ppb_device *dev, char *buffer)
for (i = 0; i < 2; i++) {
/* Event 7 - ready to take data (nAUTO low) */
- ppb_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
+ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
/* Event 8 - peripheral writes the first nibble */
/* Event 9 - peripheral set nAck low */
- if ((error = do_1284_wait(dev, nACK, 0))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 9);
+ if ((error = do_1284_wait(bus, nACK, 0))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 9);
goto error;
}
/* read nibble */
- nibble[i] = ppb_rstr(dev);
+ nibble[i] = ppb_rstr(bus);
/* Event 10 - ack, nibble received */
- ppb_wctr(dev, nINIT & ~(AUTOFEED | STROBE | SELECTIN));
+ ppb_wctr(bus, nINIT & ~(AUTOFEED | STROBE | SELECTIN));
/* Event 11 - wait ack from peripherial */
- if ((error = do_1284_wait(dev, nACK, nACK))) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 11);
+ if ((error = do_1284_wait(bus, nACK, nACK))) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 11);
goto error;
}
}
@@ -505,7 +518,7 @@ error:
* Read in IEEE1284 NIBBLE/BYTE mode
*/
int
-spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read)
+spp_1284_read(device_t bus, int mode, char *buffer, int max, int *read)
{
int error = 0, len = 0;
int terminate_after_transfer = 1;
@@ -513,11 +526,11 @@ spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read
*read = len = 0;
- state = ppb_1284_get_state(dev);
+ state = ppb_1284_get_state(bus);
switch (state) {
case PPB_FORWARD_IDLE:
- if ((error = ppb_1284_negociate(dev, mode, 0)))
+ if ((error = ppb_1284_negociate(bus, mode, 0)))
return (error);
break;
@@ -526,15 +539,15 @@ spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read
break;
default:
- ppb_1284_terminate(dev);
- if ((error = ppb_1284_negociate(dev, mode, 0)))
+ ppb_1284_terminate(bus);
+ if ((error = ppb_1284_negociate(bus, mode, 0)))
return (error);
break;
}
- while ((len < max) && !(ppb_rstr(dev) & (nFAULT))) {
+ while ((len < max) && !(ppb_rstr(bus) & (nFAULT))) {
- ppb_1284_set_state(dev, PPB_REVERSE_TRANSFER);
+ ppb_1284_set_state(bus, PPB_REVERSE_TRANSFER);
#ifdef DEBUG_1284
printf("B");
@@ -543,11 +556,11 @@ spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read
switch (mode) {
case PPB_NIBBLE:
/* read a byte, error means no more data */
- if (nibble_1284_inbyte(dev, buffer+len))
+ if (nibble_1284_inbyte(bus, buffer+len))
goto end_while;
break;
case PPB_BYTE:
- if (byte_1284_inbyte(dev, buffer+len))
+ if (byte_1284_inbyte(bus, buffer+len))
goto end_while;
break;
default:
@@ -559,12 +572,12 @@ spp_1284_read(struct ppb_device *dev, int mode, char *buffer, int max, int *read
end_while:
if (!error)
- ppb_1284_set_state(dev, PPB_REVERSE_IDLE);
+ ppb_1284_set_state(bus, PPB_REVERSE_IDLE);
*read = len;
if (terminate_after_transfer || error)
- ppb_1284_terminate(dev);
+ ppb_1284_terminate(bus);
return (error);
}
@@ -574,7 +587,7 @@ end_while:
*
*/
int
-ppb_1284_read_id(struct ppb_device *dev, int mode, char *buffer,
+ppb_1284_read_id(device_t bus, int mode, char *buffer,
int max, int *read)
{
int error = 0;
@@ -585,20 +598,20 @@ ppb_1284_read_id(struct ppb_device *dev, int mode, char *buffer,
switch (mode) {
case PPB_NIBBLE:
case PPB_ECP:
- if ((error = ppb_1284_negociate(dev, PPB_NIBBLE, PPB_REQUEST_ID)))
+ if ((error = ppb_1284_negociate(bus, PPB_NIBBLE, PPB_REQUEST_ID)))
return (error);
- error = spp_1284_read(dev, PPB_NIBBLE, buffer, max, read);
+ error = spp_1284_read(bus, PPB_NIBBLE, buffer, max, read);
break;
case PPB_BYTE:
- if ((error = ppb_1284_negociate(dev, PPB_BYTE, PPB_REQUEST_ID)))
+ if ((error = ppb_1284_negociate(bus, PPB_BYTE, PPB_REQUEST_ID)))
return (error);
- error = spp_1284_read(dev, PPB_BYTE, buffer, max, read);
+ error = spp_1284_read(bus, PPB_BYTE, buffer, max, read);
break;
default:
panic("%s: unsupported mode %d\n", __FUNCTION__, mode);
}
- ppb_1284_terminate(dev);
+ ppb_1284_terminate(bus);
return (error);
}
@@ -608,7 +621,7 @@ ppb_1284_read_id(struct ppb_device *dev, int mode, char *buffer,
* IEEE1284 read
*/
int
-ppb_1284_read(struct ppb_device *dev, int mode, char *buffer,
+ppb_1284_read(device_t bus, int mode, char *buffer,
int max, int *read)
{
int error = 0;
@@ -616,7 +629,7 @@ ppb_1284_read(struct ppb_device *dev, int mode, char *buffer,
switch (mode) {
case PPB_NIBBLE:
case PPB_BYTE:
- error = spp_1284_read(dev, mode, buffer, max, read);
+ error = spp_1284_read(bus, mode, buffer, max, read);
break;
default:
return (EINVAL);
@@ -635,7 +648,7 @@ ppb_1284_read(struct ppb_device *dev, int mode, char *buffer,
* After negociation, nFAULT is low if data is available
*/
int
-ppb_1284_negociate(struct ppb_device *dev, int mode, int options)
+ppb_1284_negociate(device_t bus, int mode, int options)
{
int error;
int request_mode;
@@ -644,77 +657,77 @@ ppb_1284_negociate(struct ppb_device *dev, int mode, int options)
printf("n");
#endif
- if (ppb_1284_get_state(dev) >= PPB_PERIPHERAL_NEGOCIATION)
- ppb_peripheral_terminate(dev, PPB_WAIT);
+ if (ppb_1284_get_state(bus) >= PPB_PERIPHERAL_NEGOCIATION)
+ ppb_peripheral_terminate(bus, PPB_WAIT);
- if (ppb_1284_get_state(dev) != PPB_FORWARD_IDLE)
- ppb_1284_terminate(dev);
+ if (ppb_1284_get_state(bus) != PPB_FORWARD_IDLE)
+ ppb_1284_terminate(bus);
#ifdef DEBUG_1284
printf("%d", mode);
#endif
/* ensure the host is in compatible mode */
- ppb_set_mode(dev, PPB_COMPATIBLE);
+ ppb_set_mode(bus, PPB_COMPATIBLE);
/* reset error to catch the actual negociation error */
- ppb_1284_reset_error(dev, PPB_FORWARD_IDLE);
+ ppb_1284_reset_error(bus, PPB_FORWARD_IDLE);
/* calculate ext. value */
request_mode = ppb_request_mode(mode, options);
/* default state */
- ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
+ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
DELAY(1);
/* enter negociation phase */
- ppb_1284_set_state(dev, PPB_NEGOCIATION);
+ ppb_1284_set_state(bus, PPB_NEGOCIATION);
/* Event 0 - put the exten. value on the data lines */
- ppb_wdtr(dev, request_mode);
+ ppb_wdtr(bus, request_mode);
#ifdef PERIPH_1284
/* request remote host attention */
- ppb_wctr(dev, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
+ ppb_wctr(bus, (nINIT | STROBE) & ~(AUTOFEED | SELECTIN));
DELAY(1);
- ppb_wctr(dev, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN));
+ ppb_wctr(bus, (nINIT) & ~(STROBE | AUTOFEED | SELECTIN));
#else
DELAY(1);
#endif /* !PERIPH_1284 */
/* Event 1 - enter IEEE1284 mode */
- ppb_wctr(dev, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
+ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(STROBE | SELECTIN));
#ifdef PERIPH_1284
/* ignore the PError line, wait a bit more, remote host's
* interrupts don't respond fast enough */
- if (ppb_poll_device(dev, 40, nACK | SELECT | nFAULT,
+ if (ppb_poll_bus(bus, 40, nACK | SELECT | nFAULT,
SELECT | nFAULT, PPB_NOINTR | PPB_POLL)) {
- ppb_1284_set_error(dev, PPB_NOT_IEEE1284, 2);
+ ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
error = ENODEV;
goto error;
}
#else
/* Event 2 - trying IEEE1284 dialog */
- if (do_1284_wait(dev, nACK | PERROR | SELECT | nFAULT,
+ if (do_1284_wait(bus, nACK | PERROR | SELECT | nFAULT,
PERROR | SELECT | nFAULT)) {
- ppb_1284_set_error(dev, PPB_NOT_IEEE1284, 2);
+ ppb_1284_set_error(bus, PPB_NOT_IEEE1284, 2);
error = ENODEV;
goto error;
}
#endif /* !PERIPH_1284 */
/* Event 3 - latch the ext. value to the peripheral */
- ppb_wctr(dev, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
+ ppb_wctr(bus, (nINIT | STROBE | AUTOFEED) & ~SELECTIN);
DELAY(1);
/* Event 4 - IEEE1284 device recognized */
- ppb_wctr(dev, nINIT & ~(SELECTIN | AUTOFEED | STROBE));
+ ppb_wctr(bus, nINIT & ~(SELECTIN | AUTOFEED | STROBE));
/* Event 6 - waiting for status lines */
- if (do_1284_wait(dev, nACK, nACK)) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 6);
+ if (do_1284_wait(bus, nACK, nACK)) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 6);
error = EBUSY;
goto error;
}
@@ -724,19 +737,19 @@ ppb_1284_negociate(struct ppb_device *dev, int mode, int options)
if (options & PPB_EXTENSIBILITY_LINK) {
/* XXX not fully supported yet */
- ppb_1284_terminate(dev);
+ ppb_1284_terminate(bus);
return (0);
}
if (request_mode == NIBBLE_1284_NORMAL) {
- if (do_1284_wait(dev, nACK | SELECT, nACK)) {
- ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 7);
+ if (do_1284_wait(bus, nACK | SELECT, nACK)) {
+ ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
error = ENODEV;
goto error;
}
} else {
- if (do_1284_wait(dev, nACK | SELECT, SELECT | nACK)) {
- ppb_1284_set_error(dev, PPB_MODE_UNSUPPORTED, 7);
+ if (do_1284_wait(bus, nACK | SELECT, SELECT | nACK)) {
+ ppb_1284_set_error(bus, PPB_MODE_UNSUPPORTED, 7);
error = ENODEV;
goto error;
}
@@ -746,46 +759,46 @@ ppb_1284_negociate(struct ppb_device *dev, int mode, int options)
case PPB_NIBBLE:
case PPB_PS2:
/* enter reverse idle phase */
- ppb_1284_set_state(dev, PPB_REVERSE_IDLE);
+ ppb_1284_set_state(bus, PPB_REVERSE_IDLE);
break;
case PPB_ECP:
/* negociation ok, now setup the communication */
- ppb_1284_set_state(dev, PPB_SETUP);
- ppb_wctr(dev, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE));
+ ppb_1284_set_state(bus, PPB_SETUP);
+ ppb_wctr(bus, (nINIT | AUTOFEED) & ~(SELECTIN | STROBE));
#ifdef PERIPH_1284
/* ignore PError line */
- if (do_1284_wait(dev, nACK | SELECT | nBUSY,
+ if (do_1284_wait(bus, nACK | SELECT | nBUSY,
nACK | SELECT | nBUSY)) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 30);
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
error = ENODEV;
goto error;
}
#else
- if (do_1284_wait(dev, nACK | SELECT | PERROR | nBUSY,
+ if (do_1284_wait(bus, nACK | SELECT | PERROR | nBUSY,
nACK | SELECT | PERROR | nBUSY)) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 30);
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 30);
error = ENODEV;
goto error;
}
#endif /* !PERIPH_1284 */
/* ok, the host enters the ForwardIdle state */
- ppb_1284_set_state(dev, PPB_ECP_FORWARD_IDLE);
+ ppb_1284_set_state(bus, PPB_ECP_FORWARD_IDLE);
break;
case PPB_EPP:
- ppb_1284_set_state(dev, PPB_EPP_IDLE);
+ ppb_1284_set_state(bus, PPB_EPP_IDLE);
break;
default:
panic("%s: unknown mode (%d)!", __FUNCTION__, mode);
}
- ppb_set_mode(dev, mode);
+ ppb_set_mode(bus, mode);
return (0);
error:
- ppb_1284_terminate(dev);
+ ppb_1284_terminate(bus);
return (error);
}
@@ -797,7 +810,7 @@ error:
* is _always_ in compatible mode after ppb_1284_terminate()
*/
int
-ppb_1284_terminate(struct ppb_device *dev)
+ppb_1284_terminate(device_t bus)
{
#ifdef DEBUG_1284
@@ -806,40 +819,40 @@ ppb_1284_terminate(struct ppb_device *dev)
/* do not reset error here to keep the error that
* may occured before the ppb_1284_terminate() call */
- ppb_1284_set_state(dev, PPB_TERMINATION);
+ ppb_1284_set_state(bus, PPB_TERMINATION);
#ifdef PERIPH_1284
/* request remote host attention */
- ppb_wctr(dev, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED));
+ ppb_wctr(bus, (nINIT | STROBE | SELECTIN) & ~(AUTOFEED));
DELAY(1);
#endif /* PERIPH_1284 */
/* Event 22 - set nSelectin low and nAutoFeed high */
- ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
+ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
/* Event 24 - waiting for peripheral, Xflag ignored */
- if (do_1284_wait(dev, nACK | nBUSY | nFAULT, nFAULT)) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 24);
+ if (do_1284_wait(bus, nACK | nBUSY | nFAULT, nFAULT)) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 24);
goto error;
}
/* Event 25 - set nAutoFd low */
- ppb_wctr(dev, (nINIT | SELECTIN | AUTOFEED) & ~STROBE);
+ ppb_wctr(bus, (nINIT | SELECTIN | AUTOFEED) & ~STROBE);
/* Event 26 - compatible mode status is set */
/* Event 27 - peripheral set nAck high */
- if (do_1284_wait(dev, nACK, nACK)) {
- ppb_1284_set_error(dev, PPB_TIMEOUT, 27);
+ if (do_1284_wait(bus, nACK, nACK)) {
+ ppb_1284_set_error(bus, PPB_TIMEOUT, 27);
}
/* Event 28 - end termination, return to idle phase */
- ppb_wctr(dev, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
+ ppb_wctr(bus, (nINIT | SELECTIN) & ~(STROBE | AUTOFEED));
error:
/* return to compatible mode */
- ppb_set_mode(dev, PPB_COMPATIBLE);
- ppb_1284_set_state(dev, PPB_FORWARD_IDLE);
+ ppb_set_mode(bus, PPB_COMPATIBLE);
+ ppb_1284_set_state(bus, PPB_FORWARD_IDLE);
return (0);
}
diff --git a/sys/dev/ppbus/ppb_1284.h b/sys/dev/ppbus/ppb_1284.h
index f975c26..de1f270 100644
--- a/sys/dev/ppbus/ppb_1284.h
+++ b/sys/dev/ppbus/ppb_1284.h
@@ -108,17 +108,17 @@
#define PPB_PERIPHERAL_TRANSFER 13
#define PPB_PERIPHERAL_TERMINATION 14
-extern int nibble_1284_inbyte(struct ppb_device *, char *);
-extern int byte_1284_inbyte(struct ppb_device *, char *);
-extern int spp_1284_read(struct ppb_device *, int, char *, int, int *);
-
-extern int ppb_1284_negociate(struct ppb_device *, int, int);
-extern int ppb_1284_terminate(struct ppb_device *);
-extern int ppb_1284_read_id(struct ppb_device *, int, char *, int, int *);
-extern int ppb_1284_read(struct ppb_device *, int, char *, int, int *);
-
-extern int ppb_peripheral_terminate(struct ppb_device *, int);
-extern int ppb_peripheral_negociate(struct ppb_device *, int, int);
-extern int byte_peripheral_write(struct ppb_device *, char *, int, int *);
+extern int nibble_1284_inbyte(device_t, char *);
+extern int byte_1284_inbyte(device_t, char *);
+extern int spp_1284_read(device_t, int, char *, int, int *);
+
+extern int ppb_1284_negociate(device_t, int, int);
+extern int ppb_1284_terminate(device_t);
+extern int ppb_1284_read_id(device_t, int, char *, int, int *);
+extern int ppb_1284_read(device_t, int, char *, int, int *);
+
+extern int ppb_peripheral_terminate(device_t, int);
+extern int ppb_peripheral_negociate(device_t, int, int);
+extern int byte_peripheral_write(device_t, char *, int, int *);
#endif
diff --git a/sys/dev/ppbus/ppb_base.c b/sys/dev/ppbus/ppb_base.c
index 250999b..c2f1d9b 100644
--- a/sys/dev/ppbus/ppb_base.c
+++ b/sys/dev/ppbus/ppb_base.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -29,49 +29,29 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
+
#include <machine/clock.h>
#include <dev/ppbus/ppbconf.h>
+
+#include "ppbus_if.h"
+#include <dev/ppbus/ppbio.h>
+
+#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
+
/*
- * ppb_intr()
+ * ppb_poll_bus()
*
- * Function called by ppcintr() when an intr occurs.
- */
-void
-ppb_intr(struct ppb_link *pl)
-{
- struct ppb_data *ppb = pl->ppbus;
-
- /*
- * Call chipset dependent code.
- * Should be filled at chipset initialisation if needed.
- */
- if (pl->adapter->intr_handler)
- (*pl->adapter->intr_handler)(pl->adapter_unit);
-
- /*
- * Call upper handler iff the bus is owned by a device and
- * this device has specified an interrupt handler.
- */
- if (ppb->ppb_owner && ppb->ppb_owner->intr)
- (*ppb->ppb_owner->intr)(ppb->ppb_owner->id_unit);
- if (ppb->ppb_owner && ppb->ppb_owner->bintr)
- (*ppb->ppb_owner->bintr)(ppb->ppb_owner);
-
- return;
-}
-
-/*
- * ppb_poll_device()
- *
- * Polls the device
+ * Polls the bus
*
* max is a delay in 10-milliseconds
*/
int
-ppb_poll_device(struct ppb_device *dev, int max,
- char mask, char status, int how)
+ppb_poll_bus(device_t bus, int max,
+ char mask, char status, int how)
{
int i, j, error;
char r;
@@ -79,7 +59,7 @@ ppb_poll_device(struct ppb_device *dev, int max,
/* try at least up to 10ms */
for (j = 0; j < ((how & PPB_POLL) ? max : 1); j++) {
for (i = 0; i < 10000; i++) {
- r = ppb_rstr(dev);
+ r = ppb_rstr(bus);
DELAY(1);
if ((r & mask) == status)
return (0);
@@ -88,19 +68,19 @@ ppb_poll_device(struct ppb_device *dev, int max,
if (!(how & PPB_POLL)) {
for (i = 0; max == PPB_FOREVER || i < max-1; i++) {
- if ((ppb_rstr(dev) & mask) == status)
+ if ((ppb_rstr(bus) & mask) == status)
return (0);
switch (how) {
case PPB_NOINTR:
/* wait 10 ms */
- tsleep((caddr_t)dev, PPBPRI, "ppbpoll", hz/100);
+ tsleep((caddr_t)bus, PPBPRI, "ppbpoll", hz/100);
break;
case PPB_INTR:
default:
/* wait 10 ms */
- if (((error = tsleep((caddr_t)dev, PPBPRI | PCATCH,
+ if (((error = tsleep((caddr_t)bus, PPBPRI | PCATCH,
"ppbpoll", hz/100)) != EWOULDBLOCK) != 0) {
return (error);
}
@@ -113,22 +93,48 @@ ppb_poll_device(struct ppb_device *dev, int max,
}
/*
- * ppb_set_mode()
+ * ppb_get_epp_protocol()
*
- * Set the operating mode of the chipset
+ * Return the chipset EPP protocol
*/
int
-ppb_set_mode(struct ppb_device *dev, int mode)
+ppb_get_epp_protocol(device_t bus)
{
- struct ppb_data *ppb = dev->ppb;
- int old_mode = ppb_get_mode(dev);
+ uintptr_t protocol;
+
+ BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_EPP_PROTO, &protocol);
- if ((*ppb->ppb_link->adapter->setmode)(
- ppb->ppb_link->adapter_unit, mode))
- return (-1);
+ return (protocol);
+}
+
+/*
+ * ppb_get_mode()
+ *
+ */
+int
+ppb_get_mode(device_t bus)
+{
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
/* XXX yet device mode = ppbus mode = chipset mode */
- dev->mode = ppb->mode = (mode & PPB_MASK);
+ return (ppb->mode);
+}
+
+/*
+ * ppb_set_mode()
+ *
+ * Set the operating mode of the chipset, return the previous mode
+ */
+int
+ppb_set_mode(device_t bus, int mode)
+{
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+ int old_mode = ppb_get_mode(bus);
+
+ if (!PPBUS_SETMODE(device_get_parent(bus), mode)) {
+ /* XXX yet device mode = ppbus mode = chipset mode */
+ ppb->mode = (mode & PPB_MASK);
+ }
return (old_mode);
}
@@ -139,12 +145,9 @@ ppb_set_mode(struct ppb_device *dev, int mode)
* Write charaters to the port
*/
int
-ppb_write(struct ppb_device *dev, char *buf, int len, int how)
+ppb_write(device_t bus, char *buf, int len, int how)
{
- struct ppb_data *ppb = dev->ppb;
-
- return (ppb->ppb_link->adapter->write(ppb->ppb_link->adapter_unit,
- buf, len, how));
+ return (PPBUS_WRITE(device_get_parent(bus), buf, len, how));
}
/*
@@ -153,16 +156,9 @@ ppb_write(struct ppb_device *dev, char *buf, int len, int how)
* Reset the EPP timeout bit in the status register
*/
int
-ppb_reset_epp_timeout(struct ppb_device *dev)
+ppb_reset_epp_timeout(device_t bus)
{
- struct ppb_data *ppb = dev->ppb;
-
- if (ppb->ppb_owner != dev)
- return (EACCES);
-
- (*ppb->ppb_link->adapter->reset_epp_timeout)(ppb->ppb_link->adapter_unit);
-
- return (0);
+ return(PPBUS_RESET_EPP(device_get_parent(bus)));
}
/*
@@ -171,16 +167,9 @@ ppb_reset_epp_timeout(struct ppb_device *dev)
* Wait for the ECP FIFO to be empty
*/
int
-ppb_ecp_sync(struct ppb_device *dev)
+ppb_ecp_sync(device_t bus)
{
- struct ppb_data *ppb = dev->ppb;
-
- if (ppb->ppb_owner != dev)
- return (EACCES);
-
- (*ppb->ppb_link->adapter->ecp_sync)(ppb->ppb_link->adapter_unit);
-
- return (0);
+ return (PPBUS_ECP_SYNC(device_get_parent(bus)));
}
/*
@@ -189,15 +178,11 @@ ppb_ecp_sync(struct ppb_device *dev)
* Read the status register and update the status info
*/
int
-ppb_get_status(struct ppb_device *dev, struct ppb_status *status)
+ppb_get_status(device_t bus, struct ppb_status *status)
{
- struct ppb_data *ppb = dev->ppb;
register char r;
- if (ppb->ppb_owner != dev)
- return (EACCES);
-
- r = status->status = ppb_rstr(dev);
+ r = status->status = ppb_rstr(bus);
status->timeout = r & TIMEOUT;
status->error = !(r & nFAULT);
diff --git a/sys/dev/ppbus/ppb_msq.c b/sys/dev/ppbus/ppb_msq.c
index a98b254..074dd07 100644
--- a/sys/dev/ppbus/ppb_msq.c
+++ b/sys/dev/ppbus/ppb_msq.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -31,10 +31,13 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/bus.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
+#include "ppbus_if.h"
+
/* msq index (see PPB_MAX_XFER)
* These are device modes
*/
@@ -49,18 +52,18 @@
* Device mode to submsq conversion
*/
static struct ppb_xfer *
-mode2xfer(struct ppb_device *dev, int opcode)
+mode2xfer(device_t bus, struct ppb_device *ppbdev, int opcode)
{
int index, epp;
struct ppb_xfer *table;
switch (opcode) {
case MS_OP_GET:
- table = dev->get_xfer;
+ table = ppbdev->get_xfer;
break;
case MS_OP_PUT:
- table = dev->put_xfer;
+ table = ppbdev->put_xfer;
break;
default:
@@ -68,7 +71,7 @@ mode2xfer(struct ppb_device *dev, int opcode)
}
/* retrieve the device operating mode */
- switch (ppb_get_mode(dev)) {
+ switch (ppb_get_mode(bus)) {
case PPB_COMPATIBLE:
index = COMPAT_MSQ;
break;
@@ -79,7 +82,7 @@ mode2xfer(struct ppb_device *dev, int opcode)
index = PS2_MSQ;
break;
case PPB_EPP:
- switch ((epp = ppb_get_epp_protocol(dev))) {
+ switch ((epp = ppb_get_epp_protocol(bus))) {
case EPP_1_7:
index = EPP17_MSQ;
break;
@@ -95,7 +98,7 @@ mode2xfer(struct ppb_device *dev, int opcode)
index = ECP_MSQ;
break;
default:
- panic("%s: unknown mode (%d)", __FUNCTION__, dev->mode);
+ panic("%s: unknown mode (%d)", __FUNCTION__, ppbdev->mode);
}
return (&table[index]);
@@ -108,9 +111,10 @@ mode2xfer(struct ppb_device *dev, int opcode)
*
*/
int
-ppb_MS_init(struct ppb_device *dev, struct ppb_microseq *loop, int opcode)
+ppb_MS_init(device_t bus, device_t dev, struct ppb_microseq *loop, int opcode)
{
- struct ppb_xfer *xfer = mode2xfer(dev, opcode);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
+ struct ppb_xfer *xfer = mode2xfer(bus, ppbdev, opcode);
xfer->loop = loop;
@@ -124,7 +128,7 @@ ppb_MS_init(struct ppb_device *dev, struct ppb_microseq *loop, int opcode)
*
*/
int
-ppb_MS_exec(struct ppb_device *dev, int opcode, union ppb_insarg param1,
+ppb_MS_exec(device_t bus, device_t dev, int opcode, union ppb_insarg param1,
union ppb_insarg param2, union ppb_insarg param3, int *ret)
{
struct ppb_microseq msq[] = {
@@ -139,7 +143,7 @@ ppb_MS_exec(struct ppb_device *dev, int opcode, union ppb_insarg param1,
msq[0].arg[2] = param3;
/* execute the microseq */
- return (ppb_MS_microseq(dev, msq, ret));
+ return (ppb_MS_microseq(bus, dev, msq, ret));
}
/*
@@ -149,7 +153,7 @@ ppb_MS_exec(struct ppb_device *dev, int opcode, union ppb_insarg param1,
*
*/
int
-ppb_MS_loop(struct ppb_device *dev, struct ppb_microseq *prolog,
+ppb_MS_loop(device_t bus, device_t dev, struct ppb_microseq *prolog,
struct ppb_microseq *body, struct ppb_microseq *epilog,
int iter, int *ret)
{
@@ -172,7 +176,7 @@ ppb_MS_loop(struct ppb_device *dev, struct ppb_microseq *prolog,
loop_microseq[4].arg[0].p = (void *)epilog;
/* execute the loop */
- return (ppb_MS_microseq(dev, loop_microseq, ret));
+ return (ppb_MS_microseq(bus, dev, loop_microseq, ret));
}
/*
@@ -242,9 +246,11 @@ ppb_MS_init_msq(struct ppb_microseq *msq, int nbparam, ...)
* level to avoid function call overhead between ppbus and the adapter
*/
int
-ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
+ppb_MS_microseq(device_t bus, device_t dev, struct ppb_microseq *msq, int *ret)
{
- struct ppb_data *ppb = dev->ppb;
+ struct ppb_data *ppb = (struct ppb_data *)device_get_softc(bus);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
+
struct ppb_microseq *mi; /* current microinstruction */
int error;
@@ -269,13 +275,13 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
case MS_OP_GET:
/* attempt to choose the best mode for the device */
- xfer = mode2xfer(dev, mi->opcode);
+ xfer = mode2xfer(bus, ppbdev, mi->opcode);
/* figure out if we should use ieee1284 code */
if (!xfer->loop) {
if (mi->opcode == MS_OP_PUT) {
- if ((error = ppb->ppb_link->adapter->write(
- ppb->ppb_link->adapter_unit,
+ if ((error = PPBUS_WRITE(
+ device_get_parent(bus),
(char *)mi->arg[0].p,
mi->arg[1].i, 0)))
goto error;
@@ -291,7 +297,7 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
initxfer[1].arg[0].i = mi->arg[1].i;
/* initialize transfer */
- ppb_MS_microseq(dev, initxfer, &error);
+ ppb_MS_microseq(bus, dev, initxfer, &error);
if (error)
goto error;
@@ -299,7 +305,7 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
/* the xfer microsequence should not contain any
* MS_OP_PUT or MS_OP_GET!
*/
- ppb_MS_microseq(dev, xfer->loop, &error);
+ ppb_MS_microseq(bus, dev, xfer->loop, &error);
if (error)
goto error;
@@ -318,9 +324,8 @@ ppb_MS_microseq(struct ppb_device *dev, struct ppb_microseq *msq, int *ret)
* faster. This is the default if the microinstr
* is unknown here
*/
- if ((error = ppb->ppb_link->adapter->exec_microseq(
- ppb->ppb_link->adapter_unit,
- &mi)))
+ if ((error = PPBUS_EXEC_MICROSEQ(
+ device_get_parent(bus), &mi)))
goto error;
break;
}
diff --git a/sys/dev/ppbus/ppb_msq.h b/sys/dev/ppbus/ppb_msq.h
index 25b55fd..64d16d895 100644
--- a/sys/dev/ppbus/ppb_msq.h
+++ b/sys/dev/ppbus/ppb_msq.h
@@ -158,12 +158,13 @@
* Function abstraction level
*/
-#define ppb_MS_GET_init(dev,body) ppb_MS_init(dev, body, MS_OP_GET)
+#define ppb_MS_GET_init(bus,dev,body) ppb_MS_init(bus, dev, body, MS_OP_GET)
-#define ppb_MS_PUT_init(dev,body) ppb_MS_init(dev, body, MS_OP_PUT)
+#define ppb_MS_PUT_init(bus,dev,body) ppb_MS_init(bus, dev, body, MS_OP_PUT)
extern int ppb_MS_init(
- struct ppb_device *, /* ppbus device */
+ device_t, /* ppbus bus */
+ device_t, /* ppbus device */
struct ppb_microseq *, /* loop msq to assign */
int opcode /* MS_OP_GET, MS_OP_PUT */
);
@@ -175,7 +176,8 @@ extern int ppb_MS_init_msq(
);
extern int ppb_MS_exec(
- struct ppb_device *, /* ppbus device */
+ device_t, /* ppbus bus */
+ device_t, /* ppbus device */
int, /* microseq opcode */
union ppb_insarg, /* param1 */
union ppb_insarg, /* param2 */
@@ -184,7 +186,8 @@ extern int ppb_MS_exec(
);
extern int ppb_MS_loop(
- struct ppb_device *, /* ppbus device */
+ device_t, /* ppbus bus */
+ device_t, /* ppbus device */
struct ppb_microseq *, /* prologue msq of loop */
struct ppb_microseq *, /* body msq of loop */
struct ppb_microseq *, /* epilogue msq of loop */
@@ -193,7 +196,8 @@ extern int ppb_MS_loop(
);
extern int ppb_MS_microseq(
- struct ppb_device *, /* ppbus device */
+ device_t, /* ppbus bus */
+ device_t, /* ppbus device */
struct ppb_microseq *, /* msq to execute */
int * /* returned value */
);
diff --git a/sys/dev/ppbus/ppbconf.c b/sys/dev/ppbus/ppbconf.c
index f98fcf2..2d7aa1a 100644
--- a/sys/dev/ppbus/ppbconf.c
+++ b/sys/dev/ppbus/ppbconf.c
@@ -26,61 +26,154 @@
* $FreeBSD$
*
*/
+#include "opt_ppb_1284.h"
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/linker_set.h>
+#include <sys/kernel.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/malloc.h>
-#include <vm/vm.h>
-#include <vm/pmap.h>
-
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_1284.h>
-#include "opt_ppb_1284.h"
+#include "ppbus_if.h"
+
+#define DEVTOSOFTC(dev) ((struct ppb_data *)device_get_softc(dev))
+
+MALLOC_DEFINE(M_PPBUSDEV, "ppbusdev", "Parallel Port bus device");
-static LIST_HEAD(, ppb_data) ppbdata; /* list of existing ppbus */
+static devclass_t ppbus_devclass;
/*
- * Add a null driver so that the linker set always exists.
+ * Device methods
*/
-
-static struct ppb_driver nulldriver = {
- NULL, NULL, "null"
+static int ppbus_probe(device_t);
+static int ppbus_attach(device_t);
+static void ppbus_print_child(device_t bus, device_t dev);
+static int ppbus_read_ivar(device_t, device_t, int, uintptr_t *);
+static int ppbus_write_ivar(device_t, device_t, int, u_long);
+static int ppbus_setup_intr(device_t, device_t, struct resource *, int,
+ void (*)(void *), void *, void **);
+static int ppbus_teardown_intr(device_t, device_t, struct resource *, void *);
+
+static device_method_t ppbus_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppbus_probe),
+ DEVMETHOD(device_attach, ppbus_attach),
+
+ /* bus interface */
+ DEVMETHOD(bus_print_child, ppbus_print_child),
+ DEVMETHOD(bus_read_ivar, ppbus_read_ivar),
+ DEVMETHOD(bus_write_ivar, ppbus_write_ivar),
+ DEVMETHOD(bus_setup_intr, ppbus_setup_intr),
+ DEVMETHOD(bus_teardown_intr, ppbus_teardown_intr),
+ DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource),
+
+ { 0, 0 }
};
-DATA_SET(ppbdriver_set, nulldriver);
+static driver_t ppbus_driver = {
+ "ppbus",
+ ppbus_methods,
+ sizeof(struct ppb_data),
+ };
+
+static void
+ppbus_print_child(device_t bus, device_t dev)
+{
+ struct ppb_device *ppbdev;
+
+ bus_print_child_header(bus, dev);
+
+ ppbdev = (struct ppb_device *)device_get_ivars(dev);
+
+ if (ppbdev->flags != 0)
+ printf(" flags 0x%x", ppbdev->flags);
+
+ printf(" on %s%d\n", device_get_name(bus), device_get_unit(bus));
+
+ return;
+}
+
+static int
+ppbus_probe(device_t dev)
+{
+ device_set_desc(dev, "Parallel port bus");
+
+ return (0);
+}
/*
- * ppb_alloc_bus()
+ * ppb_add_device()
*
- * Allocate area to store the ppbus description.
+ * Add a ppbus device, allocate/initialize the ivars
*/
-struct ppb_data *
-ppb_alloc_bus(void)
+static void
+ppbus_add_device(device_t dev, const char *name, int unit)
{
- struct ppb_data *ppb;
- static int ppbdata_initted = 0; /* done-init flag */
-
- ppb = (struct ppb_data *) malloc(sizeof(struct ppb_data),
- M_TEMP, M_NOWAIT);
+ struct ppb_device *ppbdev;
+ device_t child;
+
+ /* allocate ivars for the new ppbus child */
+ ppbdev = malloc(sizeof(struct ppb_device), M_PPBUSDEV, M_NOWAIT);
+ if (!ppbdev)
+ return;
+ bzero(ppbdev, sizeof *ppbdev);
+
+ /* initialize the ivars */
+ ppbdev->name = name;
+
+ /* add the device as a child to the ppbus bus with the allocated
+ * ivars */
+ child = device_add_child(dev, name, unit);
+ device_set_ivars(child, ppbdev);
- /*
- * Add the new parallel port bus to the list of existing ppbus.
- */
- if (ppb) {
- bzero(ppb, sizeof(struct ppb_data));
+ return;
+}
- if (!ppbdata_initted) { /* list not initialised */
- LIST_INIT(&ppbdata);
- ppbdata_initted = 1;
- }
- LIST_INSERT_HEAD(&ppbdata, ppb, ppb_chain);
- } else {
- printf("ppb_alloc_bus: cannot malloc!\n");
+static int
+ppbus_read_ivar(device_t bus, device_t dev, int index, uintptr_t* val)
+ {
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
+
+ switch (index) {
+ case PPBUS_IVAR_MODE:
+ /* XXX yet device mode = ppbus mode = chipset mode */
+ *val = (u_long)ppb_get_mode(bus);
+ ppbdev->mode = (u_short)*val;
+ break;
+ case PPBUS_IVAR_AVM:
+ *val = (u_long)ppbdev->avm;
+ break;
+ case PPBUS_IVAR_IRQ:
+ BUS_READ_IVAR(device_get_parent(bus), bus, PPC_IVAR_IRQ, val);
+ break;
+ default:
+ return (ENOENT);
}
- return(ppb);
+
+ return (0);
}
+
+static int
+ppbus_write_ivar(device_t bus, device_t dev, int index, u_long val)
+{
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
+
+ switch (index) {
+ case PPBUS_IVAR_MODE:
+ /* XXX yet device mode = ppbus mode = chipset mode */
+ ppb_set_mode(bus,val);
+ ppbdev->mode = ppb_get_mode(bus);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+ }
#define PPB_PNP_PRINTER 0
#define PPB_PNP_MODEM 1
@@ -151,17 +244,17 @@ search_token(char *str, int slen, char *token)
* Returns the class id. of the peripherial, -1 otherwise
*/
static int
-ppb_pnp_detect(struct ppb_data *ppb, struct ppb_device *pnpdev)
+ppb_pnp_detect(device_t bus)
{
char *token, *class = 0;
int i, len, error;
int class_id = -1;
char str[PPB_PnP_STRING_SIZE+1];
+ int unit = device_get_unit(bus);
- printf("Probing for PnP devices on ppbus%d:\n",
- ppb->ppb_link->adapter_unit);
+ printf("Probing for PnP devices on ppbus%d:\n", unit);
- if ((error = ppb_1284_read_id(pnpdev, PPB_NIBBLE, str,
+ if ((error = ppb_1284_read_id(bus, PPB_NIBBLE, str,
PPB_PnP_STRING_SIZE, &len)))
goto end_detect;
@@ -178,10 +271,10 @@ ppb_pnp_detect(struct ppb_data *ppb, struct ppb_device *pnpdev)
if ((token = search_token(str, len, "MFG")) != NULL ||
(token = search_token(str, len, "MANUFACTURER")) != NULL)
- printf("ppbus%d: <%s", ppb->ppb_link->adapter_unit,
+ printf("ppbus%d: <%s", unit,
search_token(token, UNKNOWN_LENGTH, ":") + 1);
else
- printf("ppbus%d: <unknown", ppb->ppb_link->adapter_unit);
+ printf("ppbus%d: <unknown", unit);
if ((token = search_token(str, len, "MDL")) != NULL ||
(token = search_token(str, len, "MODEL")) != NULL)
@@ -233,21 +326,11 @@ end_detect:
* Scan the ppbus for IEEE1284 compliant devices
*/
static int
-ppb_scan_bus(struct ppb_data *ppb)
+ppb_scan_bus(device_t bus)
{
- struct ppb_device pnpdev; /* temporary device to perform I/O */
+ struct ppb_data * ppb = (struct ppb_data *)device_get_softc(bus);
int error = 0;
-
- /* initialize the pnpdev structure for future use */
- bzero(&pnpdev, sizeof(pnpdev));
- pnpdev.ppb = ppb;
-
- if ((error = ppb_request_bus(&pnpdev, PPB_DONTWAIT))) {
- if (bootverbose)
- printf("ppb: cannot allocate ppbus!\n");
-
- return (error);
- }
+ int unit = device_get_unit(bus);
/* try all IEEE1284 modes, for one device only
*
@@ -255,207 +338,175 @@ ppb_scan_bus(struct ppb_data *ppb)
* daisy chained devices
*/
- error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, PPB_REQUEST_ID);
+ error = ppb_1284_negociate(bus, PPB_NIBBLE, PPB_REQUEST_ID);
if ((ppb->state == PPB_ERROR) && (ppb->error == PPB_NOT_IEEE1284))
goto end_scan;
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
- printf("ppb%d: IEEE1284 device found ", ppb->ppb_link->adapter_unit);
+ printf("ppbus%d: IEEE1284 device found ", unit);
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE, 0))) {
+ if (!(error = ppb_1284_negociate(bus, PPB_NIBBLE, 0))) {
printf("/NIBBLE");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2, 0))) {
+ if (!(error = ppb_1284_negociate(bus, PPB_PS2, 0))) {
printf("/PS2");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, 0))) {
+ if (!(error = ppb_1284_negociate(bus, PPB_ECP, 0))) {
printf("/ECP");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP, PPB_USE_RLE))) {
+ if (!(error = ppb_1284_negociate(bus, PPB_ECP, PPB_USE_RLE))) {
printf("/ECP_RLE");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_EPP, 0))) {
+ if (!(error = ppb_1284_negociate(bus, PPB_EPP, 0))) {
printf("/EPP");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
/* try more IEEE1284 modes */
if (bootverbose) {
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_NIBBLE,
+ if (!(error = ppb_1284_negociate(bus, PPB_NIBBLE,
PPB_REQUEST_ID))) {
printf("/NIBBLE_ID");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_PS2,
+ if (!(error = ppb_1284_negociate(bus, PPB_PS2,
PPB_REQUEST_ID))) {
printf("/PS2_ID");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP,
+ if (!(error = ppb_1284_negociate(bus, PPB_ECP,
PPB_REQUEST_ID))) {
printf("/ECP_ID");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_ECP,
+ if (!(error = ppb_1284_negociate(bus, PPB_ECP,
PPB_REQUEST_ID | PPB_USE_RLE))) {
printf("/ECP_RLE_ID");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
- if (!(error = ppb_1284_negociate(&pnpdev, PPB_COMPATIBLE,
+ if (!(error = ppb_1284_negociate(bus, PPB_COMPATIBLE,
PPB_EXTENSIBILITY_LINK))) {
printf("/Extensibility Link");
- ppb_1284_terminate(&pnpdev);
+ ppb_1284_terminate(bus);
}
}
printf("\n");
/* detect PnP devices */
- ppb->class_id = ppb_pnp_detect(ppb, &pnpdev);
-
- ppb_release_bus(&pnpdev);
+ ppb->class_id = ppb_pnp_detect(bus);
return (0);
end_scan:
- ppb_release_bus(&pnpdev);
return (error);
}
#endif /* !DONTPROBE_1284 */
-/*
- * ppb_attachdevs()
- *
- * Called by ppcattach(), this function probes the ppbus and
- * attaches found devices.
- */
-int
-ppb_attachdevs(struct ppb_data *ppb)
+static int
+ppbus_attach(device_t dev)
{
- struct ppb_device *dev;
- struct ppb_driver **p_drvpp, *p_drvp;
+ int i;
+ int unit, disabled;
+ char *name;
- LIST_INIT(&ppb->ppb_devs); /* initialise device/driver list */
- p_drvpp = (struct ppb_driver **)ppbdriver_set.ls_items;
-
-#ifndef DONTPROBE_1284
- /* detect IEEE1284 compliant devices */
- ppb_scan_bus(ppb);
-#endif /* !DONTPROBE_1284 */
-
/*
- * Blindly try all probes here. Later we should look at
- * the parallel-port PnP standard, and intelligently seek
- * drivers based on configuration first.
+ * Add all devices configured to be attached to ppbus0.
*/
- while ((p_drvp = *p_drvpp++) != NULL) {
- if (p_drvp->probe && (dev = (p_drvp->probe(ppb))) != NULL) {
- /*
- * Add the device to the list of probed devices.
- */
- LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain);
-
- /* Call the device's attach routine */
- (void)p_drvp->attach(dev);
- }
+ for (i = resource_query_string(-1, "at", "ppbus0");
+ i != -1;
+ i = resource_query_string(i, "at", "ppbus0")) {
+ unit = resource_query_unit(i);
+ name = resource_query_name(i);
+ if (resource_int_value(name, unit, "disabled", &disabled) == 0) {
+ if (disabled)
+ continue;
+ }
+ ppbus_add_device(dev, name, unit);
}
- return (0);
-}
-
-/*
- * ppb_next_bus()
- *
- * Return the next bus in ppbus queue
- */
-struct ppb_data *
-ppb_next_bus(struct ppb_data *ppb)
-{
- if (ppb == NULL)
- return (ppbdata.lh_first);
-
- return (ppb->ppb_chain.le_next);
-}
+ /*
+ * and ppbus?
+ */
+ for (i = resource_query_string(-1, "at", "ppbus");
+ i != -1;
+ i = resource_query_string(i, "at", "ppbus")) {
+ unit = resource_query_unit(i);
+ name = resource_query_name(i);
+ if (resource_int_value(name, unit, "disabled", &disabled) == 0) {
+ if (disabled)
+ continue;
+ }
+ ppbus_add_device(dev, name, unit);
+ }
-/*
- * ppb_lookup_bus()
- *
- * Get ppb_data structure pointer according to the base address of the ppbus
- */
-struct ppb_data *
-ppb_lookup_bus(int base_port)
-{
- struct ppb_data *ppb;
+#ifndef DONTPROBE_1284
+ /* detect IEEE1284 compliant devices */
+ ppb_scan_bus(dev);
+#endif /* !DONTPROBE_1284 */
- for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next)
- if (ppb->ppb_link->base == base_port)
- break;
+ /* launch attachement of the added children */
+ bus_generic_attach(dev);
- return (ppb);
+ return 0;
}
-/*
- * ppb_lookup_link()
- *
- * Get ppb_data structure pointer according to the unit value
- * of the corresponding link structure
- */
-struct ppb_data *
-ppb_lookup_link(int unit)
+static int
+ppbus_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
+ void (*ihand)(void *), void *arg, void **cookiep)
{
- struct ppb_data *ppb;
+ int error;
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(child);
- for (ppb = ppbdata.lh_first; ppb; ppb = ppb->ppb_chain.le_next)
- if (ppb->ppb_link->adapter_unit == unit)
- break;
+ /* a device driver must own the bus to register an interrupt */
+ if (ppb->ppb_owner != child)
+ return (EINVAL);
- return (ppb);
-}
-
-/*
- * ppb_attach_device()
- *
- * Called by loadable kernel modules to add a device
- */
-int
-ppb_attach_device(struct ppb_device *dev)
-{
- struct ppb_data *ppb = dev->ppb;
+ if ((error = BUS_SETUP_INTR(device_get_parent(bus), child, r, flags,
+ ihand, arg, cookiep)))
+ return (error);
- /* add the device to the list of probed devices */
- LIST_INSERT_HEAD(&ppb->ppb_devs, dev, chain);
+ /* store the resource and the cookie for eventually forcing
+ * handler unregistration
+ */
+ ppbdev->intr_cookie = *cookiep;
+ ppbdev->intr_resource = r;
return (0);
}
-/*
- * ppb_remove_device()
- *
- * Called by loadable kernel modules to remove a device
- */
-void
-ppb_remove_device(struct ppb_device *dev)
+static int
+ppbus_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
{
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(child);
+
+ /* a device driver must own the bus to unregister an interrupt */
+ if ((ppb->ppb_owner != child) || (ppbdev->intr_cookie != ih) ||
+ (ppbdev->intr_resource != r))
+ return (EINVAL);
- /* remove the device from the list of probed devices */
- LIST_REMOVE(dev, chain);
+ ppbdev->intr_cookie = 0;
+ ppbdev->intr_resource = 0;
- return;
+ /* pass unregistration to the upper layer */
+ return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, ih));
}
/*
@@ -466,10 +517,11 @@ ppb_remove_device(struct ppb_device *dev)
* how : PPB_WAIT or PPB_DONTWAIT
*/
int
-ppb_request_bus(struct ppb_device *dev, int how)
+ppb_request_bus(device_t bus, device_t dev, int how)
{
int s, error = 0;
- struct ppb_data *ppb = dev->ppb;
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
while (!error) {
s = splhigh();
@@ -499,8 +551,8 @@ ppb_request_bus(struct ppb_device *dev, int how)
* drivers that do not set there operating mode
* during attachement
*/
- if (dev->ctx.valid)
- ppb_set_mode(dev, dev->ctx.mode);
+ if (ppbdev->ctx.valid)
+ ppb_set_mode(bus, ppbdev->ctx.mode);
splx(s);
return (0);
@@ -516,10 +568,17 @@ ppb_request_bus(struct ppb_device *dev, int how)
* Release the device allocated with ppb_request_dev()
*/
int
-ppb_release_bus(struct ppb_device *dev)
+ppb_release_bus(device_t bus, device_t dev)
{
- int s;
- struct ppb_data *ppb = dev->ppb;
+ int s, error;
+ struct ppb_data *ppb = DEVTOSOFTC(bus);
+ struct ppb_device *ppbdev = (struct ppb_device *)device_get_ivars(dev);
+
+ if (ppbdev->intr_resource != 0)
+ /* force interrupt handler unregistration when the ppbus is released */
+ if ((error = BUS_TEARDOWN_INTR(bus, dev, ppbdev->intr_resource,
+ ppbdev->intr_cookie)))
+ return (error);
s = splhigh();
if (ppb->ppb_owner != dev) {
@@ -531,13 +590,15 @@ ppb_release_bus(struct ppb_device *dev)
splx(s);
/* save the context of the device */
- dev->ctx.mode = ppb_get_mode(dev);
+ ppbdev->ctx.mode = ppb_get_mode(bus);
/* ok, now the context of the device is valid */
- dev->ctx.valid = 1;
+ ppbdev->ctx.valid = 1;
/* wakeup waiting processes */
wakeup(ppb);
return (0);
}
+
+DRIVER_MODULE(ppbus, ppc, ppbus_driver, ppbus_devclass, 0, 0);
diff --git a/sys/dev/ppbus/ppbconf.h b/sys/dev/ppbus/ppbconf.h
index 4160f0c..93fc886 100644
--- a/sys/dev/ppbus/ppbconf.h
+++ b/sys/dev/ppbus/ppbconf.h
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -55,9 +55,9 @@
#define PPB_OPTIONS_MASK 0xf0
#define PPB_IS_EPP(mode) (mode & PPB_EPP)
-#define PPB_IN_EPP_MODE(dev) (PPB_IS_EPP (ppb_get_mode (dev)))
-#define PPB_IN_NIBBLE_MODE(dev) (ppb_get_mode (dev) & PPB_NIBBLE)
-#define PPB_IN_PS2_MODE(dev) (ppb_get_mode (dev) & PPB_PS2)
+#define PPB_IN_EPP_MODE(bus) (PPB_IS_EPP (ppb_get_mode (bus)))
+#define PPB_IN_NIBBLE_MODE(bus) (ppb_get_mode (bus) & PPB_NIBBLE)
+#define PPB_IN_PS2_MODE(bus) (ppb_get_mode (bus) & PPB_PS2)
#define n(flags) (~(flags) & (flags))
@@ -101,6 +101,28 @@ struct ppb_status {
unsigned int busy:1;
};
+/* Parallel port bus I/O opcodes */
+#define PPB_OUTSB_EPP 1
+#define PPB_OUTSW_EPP 2
+#define PPB_OUTSL_EPP 3
+#define PPB_INSB_EPP 4
+#define PPB_INSW_EPP 5
+#define PPB_INSL_EPP 6
+#define PPB_RDTR 7
+#define PPB_RSTR 8
+#define PPB_RCTR 9
+#define PPB_REPP_A 10
+#define PPB_REPP_D 11
+#define PPB_RECR 12
+#define PPB_RFIFO 13
+#define PPB_WDTR 14
+#define PPB_WSTR 15
+#define PPB_WCTR 16
+#define PPB_WEPP_A 17
+#define PPB_WEPP_D 18
+#define PPB_WECR 19
+#define PPB_WFIFO 20
+
/*
* How tsleep() is called in ppb_request_bus().
*/
@@ -152,14 +174,23 @@ struct ppb_context {
struct microseq *curmsq; /* currently executed microseqence */
};
+/*
+ * List of IVARS available to ppb device drivers
+ */
+#define PPBUS_IVAR_MODE 0
+#define PPBUS_IVAR_AVM 1
+#define PPBUS_IVAR_IRQ 2
+
+/* other fields are reserved to the ppbus internals */
+
struct ppb_device {
- int id_unit; /* unit of the device */
- char *name; /* name of the device */
+ const char *name; /* name of the device */
ushort mode; /* current mode of the device */
ushort avm; /* available IEEE1284 modes of
* the device */
+ uint flags; /* flags */
struct ppb_context ctx; /* context of the device */
@@ -172,76 +203,21 @@ struct ppb_device {
* IEEE1284 code is used */
struct ppb_xfer
put_xfer[PPB_MAX_XFER];
-
- void (*intr)(int); /* interrupt handler */
- void (*bintr)(struct ppb_device *); /* interrupt handler */
+
+ struct resource *intr_resource;
+ void *intr_cookie;
void *drv1, *drv2; /* drivers private data */
-
- struct ppb_data *ppb; /* link to the ppbus */
-
- LIST_ENTRY(ppb_device) chain; /* list of devices on the bus */
};
-/*
- * Parallel Port Bus Adapter structure.
- */
-struct ppb_adapter {
-
- void (*intr_handler)(int);
- void (*reset_epp_timeout)(int);
- void (*ecp_sync)(int);
-
- int (*exec_microseq)(int, struct ppb_microseq **);
-
- int (*setmode)(int, int);
- int (*read)(int, char *, int, int);
- int (*write)(int, char *, int, int);
-
- void (*outsb_epp)(int, char *, int);
- void (*outsw_epp)(int, char *, int);
- void (*outsl_epp)(int, char *, int);
- void (*insb_epp)(int, char *, int);
- void (*insw_epp)(int, char *, int);
- void (*insl_epp)(int, char *, int);
-
- u_char (*r_dtr)(int);
- u_char (*r_str)(int);
- u_char (*r_ctr)(int);
- u_char (*r_epp_A)(int);
- u_char (*r_epp_D)(int);
- u_char (*r_ecr)(int);
- u_char (*r_fifo)(int);
-
- void (*w_dtr)(int, char);
- void (*w_str)(int, char);
- void (*w_ctr)(int, char);
- void (*w_epp_A)(int, char);
- void (*w_epp_D)(int, char);
- void (*w_ecr)(int, char);
- void (*w_fifo)(int, char);
-};
-
-/*
- * ppb_link structure.
- */
-struct ppb_link {
-
- int adapter_unit; /* unit of the adapter */
- int base; /* base address of the port */
- int id_irq; /* != 0 if irq enabled */
- int accum; /* microseq accum */
- char *ptr; /* current buffer pointer */
-
+/* EPP standards */
#define EPP_1_9 0x0 /* default */
#define EPP_1_7 0x1
-
- int epp_protocol; /* EPP protocol: 0=1.9, 1=1.7 */
-
- struct ppb_adapter *adapter; /* link to the ppc adapter */
- struct ppb_data *ppbus; /* link to the ppbus */
-};
-
+
+/* Parallel Port Chipset IVARS */ /* elsewhere XXX */
+#define PPC_IVAR_EPP_PROTO 0
+#define PPC_IVAR_IRQ 1
+
/*
* Maximum size of the PnP info string
*/
@@ -263,113 +239,36 @@ struct ppb_data {
#define PPB_PnP_SCANNER 8
#define PPB_PnP_DIGICAM 9
#define PPB_PnP_UNKNOWN 10
- int class_id; /* not a PnP device if class_id < 0 */
-
- int state; /* current IEEE1284 state */
- int error; /* last IEEE1284 error */
+ int class_id; /* not a PnP device if class_id < 0 */
- ushort mode; /* IEEE 1284-1994 mode
- * NIBBLE, PS2, EPP or ECP */
+ int state; /* current IEEE1284 state */
+ int error; /* last IEEE1284 error */
- struct ppb_link *ppb_link; /* link to the adapter */
- struct ppb_device *ppb_owner; /* device which owns the bus */
- LIST_HEAD(, ppb_device) ppb_devs; /* list of devices on the bus */
- LIST_ENTRY(ppb_data) ppb_chain; /* list of busses */
-};
+ int mode; /* IEEE 1284-1994 mode
+ * NIBBLE, PS2, EPP or ECP */
-/*
- * Parallel Port Bus driver structure.
- */
-struct ppb_driver
-{
- struct ppb_device *(*probe)(struct ppb_data *ppb);
- int (*attach)(struct ppb_device *pdp);
- char *name;
+ void *ppb_owner; /* device which owns the bus */
};
-extern struct linker_set ppbdriver_set;
-
-extern struct ppb_data *ppb_alloc_bus(void);
-extern struct ppb_data *ppb_next_bus(struct ppb_data *);
-extern struct ppb_data *ppb_lookup_bus(int);
-extern struct ppb_data *ppb_lookup_link(int);
+extern int ppb_attach_device(device_t);
+extern int ppb_request_bus(device_t, device_t, int);
+extern int ppb_release_bus(device_t, device_t);
-extern int ppb_attach_device(struct ppb_device *);
-extern void ppb_remove_device(struct ppb_device *);
-extern int ppb_attachdevs(struct ppb_data *);
-
-extern int ppb_request_bus(struct ppb_device *, int);
-extern int ppb_release_bus(struct ppb_device *);
-
-extern void ppb_intr(struct ppb_link *);
-
-extern int ppb_poll_device(struct ppb_device *, int, char, char, int);
-
-extern int ppb_reset_epp_timeout(struct ppb_device *);
-extern int ppb_ecp_sync(struct ppb_device *);
-extern int ppb_get_status(struct ppb_device *, struct ppb_status *);
-
-extern int ppb_set_mode(struct ppb_device *, int);
-extern int ppb_write(struct ppb_device *, char *, int, int);
+/* bus related functions */
+extern int ppb_get_status(device_t, struct ppb_status *);
+extern int ppb_poll_bus(device_t, int, char, char, int);
+extern int ppb_reset_epp_timeout(device_t);
+extern int ppb_ecp_sync(device_t);
+extern int ppb_get_epp_protocol(device_t);
+extern int ppb_set_mode(device_t, int); /* returns old mode */
+extern int ppb_get_mode(device_t); /* returns current mode */
+extern int ppb_write(device_t, char *, int, int);
/*
* These are defined as macros for speedup.
- */
#define ppb_get_base_addr(dev) ((dev)->ppb->ppb_link->base)
#define ppb_get_epp_protocol(dev) ((dev)->ppb->ppb_link->epp_protocol)
#define ppb_get_irq(dev) ((dev)->ppb->ppb_link->id_irq)
-
-#define ppb_get_mode(dev) ((dev)->mode)
-
-/* This set of function access only to the EPP _data_ registers
- * in 8, 16 and 32 bit modes */
-#define ppb_outsb_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->outsb_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-#define ppb_outsw_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->outsw_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-#define ppb_outsl_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->outsl_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-#define ppb_insb_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->insb_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-#define ppb_insw_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->insw_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-#define ppb_insl_epp(dev,buf,cnt) \
- (*(dev)->ppb->ppb_link->adapter->insl_epp) \
- ((dev)->ppb->ppb_link->adapter_unit, buf, cnt)
-
-#define ppb_repp_A(dev) (*(dev)->ppb->ppb_link->adapter->r_epp_A) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_repp_D(dev) (*(dev)->ppb->ppb_link->adapter->r_epp_D) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_recr(dev) (*(dev)->ppb->ppb_link->adapter->r_ecr) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_rfifo(dev) (*(dev)->ppb->ppb_link->adapter->r_fifo) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_wepp_A(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_epp_A) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-#define ppb_wepp_D(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_epp_D) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-#define ppb_wecr(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_ecr) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-#define ppb_wfifo(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_fifo) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-
-#define ppb_rdtr(dev) (*(dev)->ppb->ppb_link->adapter->r_dtr) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_rstr(dev) (*(dev)->ppb->ppb_link->adapter->r_str) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_rctr(dev) (*(dev)->ppb->ppb_link->adapter->r_ctr) \
- ((dev)->ppb->ppb_link->adapter_unit)
-#define ppb_wdtr(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_dtr) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-#define ppb_wstr(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_str) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
-#define ppb_wctr(dev,byte) (*(dev)->ppb->ppb_link->adapter->w_ctr) \
- ((dev)->ppb->ppb_link->adapter_unit, byte)
+ */
#endif
diff --git a/sys/dev/ppbus/ppbio.h b/sys/dev/ppbus/ppbio.h
new file mode 100644
index 0000000..2794edd
--- /dev/null
+++ b/sys/dev/ppbus/ppbio.h
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 1999 Nicolas Souchu
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ */
+
+#ifndef __PPBIO_H
+#define __PPBIO_H
+
+/*
+ * Set of ppbus i/o routines callable from ppbus device drivers
+ */
+
+#define ppb_outsb_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_OUTSB_EPP, buf, cnt, 0))
+#define ppb_outsw_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_OUTSW_EPP, buf, cnt, 0))
+#define ppb_outsl_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_OUTSL_EPP, buf, cnt, 0))
+
+#define ppb_insb_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_INSB_EPP, buf, cnt, 0))
+#define ppb_insw_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_INSW_EPP, buf, cnt, 0))
+#define ppb_insl_epp(dev,buf,cnt) \
+ (PPBUS_IO(device_get_parent(dev), PPB_INSL_EPP, buf, cnt, 0))
+
+#define ppb_repp_A(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_REPP_A, 0, 0, 0))
+#define ppb_repp_D(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_REPP_D, 0, 0, 0))
+#define ppb_recr(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_RECR, 0, 0, 0))
+#define ppb_rfifo(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_RFIFO, 0, 0, 0))
+
+#define ppb_wepp_A(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WEPP_A, 0, 0, byte))
+#define ppb_wepp_D(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WEPP_D, 0, 0, byte))
+#define ppb_wecr(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WECR, 0, 0, byte))
+#define ppb_wfifo(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WFIFO, 0, 0, byte))
+
+#define ppb_rdtr(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_RDTR, 0, 0, 0))
+#define ppb_rstr(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_RSTR, 0, 0, 0))
+#define ppb_rctr(dev) \
+ (PPBUS_IO(device_get_parent(dev), PPB_RCTR, 0, 0, 0))
+
+#define ppb_wdtr(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WDTR, 0, 0, byte))
+#define ppb_wstr(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WSTR, 0, 0, byte))
+#define ppb_wctr(dev,byte) \
+ (PPBUS_IO(device_get_parent(dev), PPB_WCTR, 0, 0, byte))
+
+#endif
diff --git a/sys/dev/ppbus/ppbus_if.m b/sys/dev/ppbus/ppbus_if.m
new file mode 100644
index 0000000..00af081
--- /dev/null
+++ b/sys/dev/ppbus/ppbus_if.m
@@ -0,0 +1,92 @@
+#
+# Copyright (c) 1999 Nicolas Souchu
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <dev/ppbus/ppbconf.h>
+
+INTERFACE ppbus;
+
+#
+# Do low level i/o operations
+#
+METHOD u_char io {
+ device_t dev;
+ int opcode;
+ u_char *addr;
+ int cnt;
+ u_char byte;
+};
+
+#
+# Execution of a microsequence
+#
+METHOD int exec_microseq {
+ device_t dev;
+ struct ppb_microseq **ppb_microseq;
+};
+
+#
+# Reset EPP timeout
+#
+METHOD int reset_epp {
+ device_t dev;
+}
+
+#
+# Set chipset mode
+#
+METHOD int setmode {
+ device_t dev;
+ int mode;
+}
+
+#
+# Synchronize ECP FIFO
+#
+METHOD int ecp_sync {
+ device_t dev;
+}
+
+#
+# Do chipset dependent low level read
+#
+METHOD int read {
+ device_t dev;
+ char *buf;
+ int len;
+ int how;
+}
+
+#
+# Do chipset dependent low level write
+#
+METHOD int write {
+ device_t dev;
+ char *buf;
+ int len;
+ int how;
+}
diff --git a/sys/dev/ppbus/ppi.c b/sys/dev/ppbus/ppi.c
index c610e7f..bd0a638 100644
--- a/sys/dev/ppbus/ppi.c
+++ b/sys/dev/ppbus/ppi.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu, Michael Smith
+ * Copyright (c) 1997, 1998, 1999 Nicolas Souchu, Michael Smith
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,27 +30,35 @@
#if NPPI > 0
+#include "opt_ppb_1284.h"
+
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/uio.h>
-#include <sys/malloc.h>
#include <sys/fcntl.h>
#include <machine/clock.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
-#include "opt_ppb_1284.h"
-
#ifdef PERIPH_1284
#include <dev/ppbus/ppb_1284.h>
#endif
#include <dev/ppbus/ppi.h>
+#include "ppbus_if.h"
+
+#include <dev/ppbus/ppbio.h>
+
#define BUFSIZE 512
struct ppi_data {
@@ -64,25 +72,36 @@ struct ppi_data {
int ppi_mode; /* IEEE1284 mode */
char ppi_buffer[BUFSIZE];
- struct ppb_device ppi_dev;
+ struct resource *intr_resource; /* interrupt resource */
+ void *intr_cookie; /* interrupt registration cookie */
};
-#define MAXPPI 8 /* XXX not much better! */
-static int nppi = 0;
-static struct ppi_data *ppidata[MAXPPI];
+#define DEVTOSOFTC(dev) \
+ ((struct ppi_data *)device_get_softc(dev))
+#define UNITOSOFTC(unit) \
+ ((struct ppi_data *)devclass_get_softc(ppi_devclass, (unit)))
+#define UNITODEVICE(unit) \
+ (devclass_get_device(ppi_devclass, (unit)))
-/*
- * Make ourselves visible as a ppbus driver
- */
+static int ppi_probe(device_t);
+static int ppi_attach(device_t);
+static void ppiintr(void *arg);
+
+static devclass_t ppi_devclass;
-static struct ppb_device *ppiprobe(struct ppb_data *ppb);
-static int ppiattach(struct ppb_device *dev);
-static void ppiintr(int unit);
+static device_method_t ppi_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppi_probe),
+ DEVMETHOD(device_attach, ppi_attach),
-static struct ppb_driver ppidriver = {
- ppiprobe, ppiattach, "ppi"
+ { 0, 0 }
+};
+
+static driver_t ppi_driver = {
+ "ppi",
+ ppi_methods,
+ sizeof(struct ppi_data),
};
-DATA_SET(ppbdriver_set, ppidriver);
static d_open_t ppiopen;
static d_close_t ppiclose;
@@ -111,23 +130,25 @@ static struct cdevsw ppi_cdevsw = {
#ifdef PERIPH_1284
static void
-ppi_enable_intr(struct ppi_data *ppi)
+ppi_enable_intr(device_t ppidev)
{
char r;
+ device_t ppbus = device_get_parent(ppidev);
- r = ppb_rctr(&ppi->ppi_dev);
- ppb_wctr(&ppi->ppi_dev, r | IRQENABLE);
+ r = ppb_rctr(ppbus);
+ ppb_wctr(ppbus, r | IRQENABLE);
return;
}
static void
-ppi_disable_intr(struct ppi_data *ppi)
+ppi_disable_intr(device_t ppidev)
{
char r;
+ device_t ppbus = device_get_parent(ppidev);
- r = ppb_rctr(&ppi->ppi_dev);
- ppb_wctr(&ppi->ppi_dev, r & ~IRQENABLE);
+ r = ppb_rctr(ppbus);
+ ppb_wctr(ppbus, r & ~IRQENABLE);
return;
}
@@ -135,55 +156,48 @@ ppi_disable_intr(struct ppi_data *ppi)
#endif /* PERIPH_1284 */
/*
- * ppiprobe()
+ * ppi_probe()
*/
-static struct ppb_device *
-ppiprobe(struct ppb_data *ppb)
+static int
+ppi_probe(device_t dev)
{
struct ppi_data *ppi;
static int once;
+ /* probe is always ok */
+ device_set_desc(dev, "Parallel I/O");
+
if (!once++)
cdevsw_add(&ppi_cdevsw);
- ppi = (struct ppi_data *) malloc(sizeof(struct ppi_data),
- M_TEMP, M_NOWAIT);
- if (!ppi) {
- printf("ppi: cannot malloc!\n");
- return 0;
- }
+ ppi = DEVTOSOFTC(dev);
bzero(ppi, sizeof(struct ppi_data));
- ppidata[nppi] = ppi;
-
- /*
- * ppi dependent initialisation.
- */
- ppi->ppi_unit = nppi;
-
- /*
- * ppbus dependent initialisation.
- */
- ppi->ppi_dev.id_unit = ppi->ppi_unit;
- ppi->ppi_dev.ppb = ppb;
- ppi->ppi_dev.intr = ppiintr;
-
- /* Ok, go to next device on next probe */
- nppi ++;
-
- return &ppi->ppi_dev;
+ return (0);
}
+/*
+ * ppi_attach()
+ */
static int
-ppiattach(struct ppb_device *dev)
+ppi_attach(device_t dev)
{
- /*
- * Report ourselves
- */
- printf("ppi%d: <generic parallel i/o> on ppbus %d\n",
- dev->id_unit, dev->ppb->ppb_link->adapter_unit);
+ uintptr_t irq;
+ int zero = 0;
+ struct ppi_data *ppi = DEVTOSOFTC(dev);
+
+ /* retrive the irq */
+ BUS_READ_IVAR(device_get_parent(dev), dev, PPBUS_IVAR_IRQ, &irq);
- return (1);
+ /* declare our interrupt handler */
+ ppi->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &zero, irq, irq, 1, RF_ACTIVE);
+
+ make_dev(&ppi_cdevsw, device_get_unit(dev), /* XXX cleanup */
+ UID_ROOT, GID_WHEEL,
+ 0600, "ppi%d", device_get_unit(dev));
+
+ return (0);
}
/*
@@ -199,20 +213,22 @@ ppiattach(struct ppb_device *dev)
*
*/
static void
-ppiintr(int unit)
+ppiintr(void *arg)
{
#ifdef PERIPH_1284
- struct ppi_data *ppi = ppidata[unit];
+ device_t ppidev = (device_t)arg;
+ device_t ppbus = device_get_parent(ppidev);
+ struct ppi_data *ppi = DEVTOSOFTC(ppidev);
- ppi_disable_intr(ppi);
+ ppi_disable_intr(ppidev);
- switch (ppi->ppi_dev.ppb->state) {
+ switch (ppb_1284_get_state(ppbus)) {
/* accept IEEE1284 negociation then wakeup an waiting process to
* continue negociation at process level */
case PPB_FORWARD_IDLE:
/* Event 1 */
- if ((ppb_rstr(&ppi->ppi_dev) & (SELECT | nBUSY)) ==
+ if ((ppb_rstr(ppbus) & (SELECT | nBUSY)) ==
(SELECT | nBUSY)) {
/* IEEE1284 negociation */
#ifdef DEBUG_1284
@@ -220,15 +236,15 @@ ppiintr(int unit)
#endif
/* Event 2 - prepare for reading the ext. value */
- ppb_wctr(&ppi->ppi_dev, (PCD | STROBE | nINIT) & ~SELECTIN);
+ ppb_wctr(ppbus, (PCD | STROBE | nINIT) & ~SELECTIN);
- ppi->ppi_dev.ppb->state = PPB_NEGOCIATION;
+ ppb_1284_set_state(ppbus, PPB_NEGOCIATION);
} else {
#ifdef DEBUG_1284
- printf("0x%x", ppb_rstr(&ppi->ppi_dev));
+ printf("0x%x", ppb_rstr(ppbus));
#endif
- ppb_peripheral_terminate(&ppi->ppi_dev, PPB_DONTWAIT);
+ ppb_peripheral_terminate(ppbus, PPB_DONTWAIT);
break;
}
@@ -242,14 +258,14 @@ ppiintr(int unit)
break;
default:
#ifdef DEBUG_1284
- printf("?%d", ppi->ppi_dev.ppb->state);
+ printf("?%d", ppb_1284_get_state(ppbus);
#endif
- ppi->ppi_dev.ppb->state = PPB_FORWARD_IDLE;
- ppb_set_mode(&ppi->ppi_dev, PPB_COMPATIBLE);
+ ppb_1284_set_state(ppbus, PPB_FORWARD_IDLE);
+ ppb_set_mode(ppbus, PPB_COMPATIBLE);
break;
}
- ppi_enable_intr(ppi);
+ ppi_enable_intr(ppidev);
#endif /* PERIPH_1284 */
return;
@@ -259,19 +275,25 @@ static int
ppiopen(dev_t dev, int flags, int fmt, struct proc *p)
{
u_int unit = minor(dev);
- struct ppi_data *ppi = ppidata[unit];
+ struct ppi_data *ppi = UNITOSOFTC(unit);
+ device_t ppidev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppidev);
int res;
- if (unit >= nppi)
+ if (!ppi)
return (ENXIO);
if (!(ppi->ppi_flags & HAVE_PPBUS)) {
- if ((res = ppb_request_bus(&ppi->ppi_dev,
+ if ((res = ppb_request_bus(ppbus, ppidev,
(flags & O_NONBLOCK) ? PPB_DONTWAIT :
(PPB_WAIT | PPB_INTR))))
return (res);
ppi->ppi_flags |= HAVE_PPBUS;
+
+ /* register our interrupt handler */
+ BUS_SETUP_INTR(device_get_parent(ppidev), ppidev, ppi->intr_resource,
+ INTR_TYPE_TTY, ppiintr, dev, &ppi->intr_cookie);
}
ppi->ppi_count += 1;
@@ -282,26 +304,30 @@ static int
ppiclose(dev_t dev, int flags, int fmt, struct proc *p)
{
u_int unit = minor(dev);
- struct ppi_data *ppi = ppidata[unit];
+ struct ppi_data *ppi = UNITOSOFTC(unit);
+ device_t ppidev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppidev);
ppi->ppi_count --;
if (!ppi->ppi_count) {
#ifdef PERIPH_1284
- switch (ppi->ppi_dev.ppb->state) {
+ switch (ppb_1284_get_state(ppbus)) {
case PPB_PERIPHERAL_IDLE:
- ppb_peripheral_terminate(&ppi->ppi_dev, 0);
+ ppb_peripheral_terminate(ppbus, 0);
break;
case PPB_REVERSE_IDLE:
case PPB_EPP_IDLE:
case PPB_ECP_FORWARD_IDLE:
default:
- ppb_1284_terminate(&ppi->ppi_dev);
+ ppb_1284_terminate(ppbus);
break;
}
#endif /* PERIPH_1284 */
- ppb_release_bus(&ppi->ppi_dev);
+ /* unregistration of interrupt forced by release */
+ ppb_release_bus(ppbus, ppidev);
+
ppi->ppi_flags &= ~HAVE_PPBUS;
}
@@ -321,19 +347,21 @@ ppiread(dev_t dev, struct uio *uio, int ioflag)
{
#ifdef PERIPH_1284
u_int unit = minor(dev);
- struct ppi_data *ppi = ppidata[unit];
+ struct ppi_data *ppi = UNITOSOFTC(unit);
+ device_t ppidev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppidev);
int len, error = 0;
- switch (ppi->ppi_dev.ppb->state) {
+ switch (ppb_1284_get_state(ppbus)) {
case PPB_PERIPHERAL_IDLE:
- ppb_peripheral_terminate(&ppi->ppi_dev, 0);
+ ppb_peripheral_terminate(ppbus, 0);
/* fall throught */
case PPB_FORWARD_IDLE:
/* if can't negociate NIBBLE mode then try BYTE mode,
* the peripheral may be a computer
*/
- if ((ppb_1284_negociate(&ppi->ppi_dev,
+ if ((ppb_1284_negociate(ppbus,
ppi->ppi_mode = PPB_NIBBLE, 0))) {
/* XXX Wait 2 seconds to let the remote host some
@@ -341,7 +369,7 @@ ppiread(dev_t dev, struct uio *uio, int ioflag)
*/
tsleep(ppi, PPBPRI, "ppiread", 2*hz);
- if ((error = ppb_1284_negociate(&ppi->ppi_dev,
+ if ((error = ppb_1284_negociate(ppbus,
ppi->ppi_mode = PPB_BYTE, 0)))
return (error);
}
@@ -360,7 +388,7 @@ ppiread(dev_t dev, struct uio *uio, int ioflag)
/* read data */
len = 0;
while (uio->uio_resid) {
- if ((error = ppb_1284_read(&ppi->ppi_dev, ppi->ppi_mode,
+ if ((error = ppb_1284_read(ppbus, ppi->ppi_mode,
ppi->ppi_buffer, min(BUFSIZE, uio->uio_resid),
&len))) {
goto error;
@@ -403,8 +431,9 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
{
#ifdef PERIPH_1284
u_int unit = minor(dev);
- struct ppi_data *ppi = ppidata[unit];
- struct ppb_data *ppb = ppi->ppi_dev.ppb;
+ struct ppi_data *ppi = UNITOSOFTC(unit);
+ device_t ppidev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppidev);
int len, error = 0, sent;
#if 0
@@ -419,7 +448,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
};
/* negociate ECP mode */
- if (ppb_1284_negociate(&ppi->ppi_dev, PPB_ECP, 0)) {
+ if (ppb_1284_negociate(ppbus, PPB_ECP, 0)) {
printf("ppiwrite: ECP negociation failed\n");
}
@@ -428,7 +457,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
ppb_MS_init_msq(msq, 2, ADDRESS, ppi->ppi_buffer, LENGTH, len);
- error = ppb_MS_microseq(&ppi->ppi_dev, msq, &ret);
+ error = ppb_MS_microseq(ppbus, msq, &ret);
}
#endif
@@ -436,7 +465,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
* wait for the appropriate state
*/
if (ppb->state < PPB_PERIPHERAL_NEGOCIATION)
- ppb_1284_terminate(&ppi->ppi_dev);
+ ppb_1284_terminate(ppbus);
while (ppb->state != PPB_PERIPHERAL_IDLE) {
/* XXX should check a variable before sleeping */
@@ -444,7 +473,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
printf("s");
#endif
- ppi_enable_intr(ppi);
+ ppi_enable_intr(ppidev);
/* sleep until IEEE1284 negociation starts */
error = tsleep(ppi, PCATCH | PPBPRI, "ppiwrite", 0);
@@ -452,7 +481,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
switch (error) {
case 0:
/* negociate peripheral side with BYTE mode */
- ppb_peripheral_negociate(&ppi->ppi_dev, PPB_BYTE, 0);
+ ppb_peripheral_negociate(ppbus, PPB_BYTE, 0);
break;
case EWOULDBLOCK:
break;
@@ -467,7 +496,7 @@ ppiwrite(dev_t dev, struct uio *uio, int ioflag)
/* negociation done, write bytes to master host */
while ((len = min(uio->uio_resid, BUFSIZE)) != 0) {
uiomove(ppi->ppi_buffer, len, uio);
- if ((error = byte_peripheral_write(&ppi->ppi_dev,
+ if ((error = byte_peripheral_write(ppbus,
ppi->ppi_buffer, len, &sent)))
goto error;
#ifdef DEBUG_1284
@@ -488,55 +517,54 @@ static int
ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
u_int unit = minor(dev);
- struct ppi_data *ppi = ppidata[unit];
+ device_t ppidev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppidev);
int error = 0;
u_int8_t *val = (u_int8_t *)data;
switch (cmd) {
case PPIGDATA: /* get data register */
- *val = ppb_rdtr(&ppi->ppi_dev);
+ *val = ppb_rdtr(ppbus);
break;
case PPIGSTATUS: /* get status bits */
- *val = ppb_rstr(&ppi->ppi_dev);
+ *val = ppb_rstr(ppbus);
break;
case PPIGCTRL: /* get control bits */
- *val = ppb_rctr(&ppi->ppi_dev);
+ *val = ppb_rctr(ppbus);
break;
case PPIGEPPD: /* get EPP data bits */
- *val = ppb_repp_D(&ppi->ppi_dev);
+ *val = ppb_repp_D(ppbus);
break;
case PPIGECR: /* get ECP bits */
- *val = ppb_recr(&ppi->ppi_dev);
+ *val = ppb_recr(ppbus);
break;
case PPIGFIFO: /* read FIFO */
- *val = ppb_rfifo(&ppi->ppi_dev);
+ *val = ppb_rfifo(ppbus);
break;
-
case PPISDATA: /* set data register */
- ppb_wdtr(&ppi->ppi_dev, *val);
+ ppb_wdtr(ppbus, *val);
break;
case PPISSTATUS: /* set status bits */
- ppb_wstr(&ppi->ppi_dev, *val);
+ ppb_wstr(ppbus, *val);
break;
case PPISCTRL: /* set control bits */
- ppb_wctr(&ppi->ppi_dev, *val);
+ ppb_wctr(ppbus, *val);
break;
case PPISEPPD: /* set EPP data bits */
- ppb_wepp_D(&ppi->ppi_dev, *val);
+ ppb_wepp_D(ppbus, *val);
break;
case PPISECR: /* set ECP bits */
- ppb_wecr(&ppi->ppi_dev, *val);
+ ppb_wecr(ppbus, *val);
break;
case PPISFIFO: /* write FIFO */
- ppb_wfifo(&ppi->ppi_dev, *val);
+ ppb_wfifo(ppbus, *val);
break;
-
case PPIGEPPA: /* get EPP address bits */
- *val = ppb_repp_A(&ppi->ppi_dev);
+ *val = ppb_repp_A(ppbus);
break;
case PPISEPPA: /* set EPP address bits */
- ppb_wepp_A(&ppi->ppi_dev, *val);
+ ppb_wepp_A(ppbus, *val);
break;
default:
error = ENOTTY;
@@ -546,4 +574,6 @@ ppiioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
return (error);
}
+DRIVER_MODULE(ppi, ppbus, ppi_driver, ppi_devclass, 0, 0);
+
#endif /* NPPI */
diff --git a/sys/dev/ppbus/pps.c b/sys/dev/ppbus/pps.c
index 1189c58..9a540dc 100644
--- a/sys/dev/ppbus/pps.c
+++ b/sys/dev/ppbus/pps.c
@@ -18,11 +18,18 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/timepps.h>
#include <sys/malloc.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
#include <dev/ppbus/ppbconf.h>
+#include "ppbus_if.h"
+#include <dev/ppbus/ppbio.h>
#include "pps.h"
#define PPS_NAME "pps" /* our official name */
@@ -31,23 +38,37 @@ struct pps_data {
int pps_open;
struct ppb_device pps_dev;
struct pps_state pps;
+
+ struct resource *intr_resource; /* interrupt resource */
+ void *intr_cookie; /* interrupt registration cookie */
};
-static int npps;
+static int ppsprobe(device_t dev);
+static int ppsattach(device_t dev);
+static void ppsintr(void *arg);
-/*
- * Make ourselves visible as a ppbus driver
- */
+#define DEVTOSOFTC(dev) \
+ ((struct pps_data *)device_get_softc(dev))
+#define UNITOSOFTC(unit) \
+ ((struct pps_data *)devclass_get_softc(pps_devclass, (unit)))
+#define UNITODEVICE(unit) \
+ (devclass_get_device(pps_devclass, (unit)))
-static struct ppb_device *ppsprobe(struct ppb_data *ppb);
-static int ppsattach(struct ppb_device *dev);
-static void ppsintr(struct ppb_device *ppd);
+static devclass_t pps_devclass;
-static struct ppb_driver ppsdriver = {
- ppsprobe, ppsattach, PPS_NAME
+static device_method_t pps_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppsprobe),
+ DEVMETHOD(device_attach, ppsattach),
+
+ { 0, 0 }
};
-DATA_SET(ppbdriver_set, ppsdriver);
+static driver_t pps_driver = {
+ PPS_NAME,
+ pps_methods,
+ sizeof(struct pps_data),
+};
static d_open_t ppsopen;
static d_close_t ppsclose;
@@ -71,71 +92,76 @@ static struct cdevsw pps_cdevsw = {
/* bmaj */ -1
};
-
-static struct ppb_device *
-ppsprobe(struct ppb_data *ppb)
+static int
+ppsprobe(device_t ppsdev)
{
struct pps_data *sc;
static int once;
dev_t dev;
+ int unit;
if (!once++)
cdevsw_add(&pps_cdevsw);
- sc = (struct pps_data *) malloc(sizeof(struct pps_data),
- M_TEMP, M_NOWAIT);
- if (!sc) {
- printf(PPS_NAME ": cannot malloc!\n");
- return (0);
- }
+ sc = DEVTOSOFTC(ppsdev);
bzero(sc, sizeof(struct pps_data));
- dev = make_dev(&pps_cdevsw, npps,
- UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", npps);
+ unit = device_get_unit(ppsdev);
+ dev = make_dev(&pps_cdevsw, unit,
+ UID_ROOT, GID_WHEEL, 0644, PPS_NAME "%d", unit);
- dev->si_drv1 = sc;
-
- sc->pps_dev.id_unit = npps++;
- sc->pps_dev.ppb = ppb;
- sc->pps_dev.name = ppsdriver.name;
- sc->pps_dev.bintr = ppsintr;
- sc->pps_dev.drv1 = sc;
+ device_set_desc(ppsdev, "Pulse per second Timing Interface");
sc->pps.ppscap = PPS_CAPTUREASSERT | PPS_ECHOASSERT;
pps_init(&sc->pps);
- return (&sc->pps_dev);
+ return (0);
}
static int
-ppsattach(struct ppb_device *dev)
+ppsattach(device_t dev)
{
+ struct pps_data *sc = DEVTOSOFTC(dev);
+ device_t ppbus = device_get_parent(dev);
+ int irq, zero = 0;
- /*
- * Report ourselves
- */
- printf(PPS_NAME "%d: <Pulse per second Timing Interface> on ppbus %d\n",
- dev->id_unit, dev->ppb->ppb_link->adapter_unit);
+ /* retrieve the ppbus irq */
+ BUS_READ_IVAR(ppbus, dev, PPBUS_IVAR_IRQ, &irq);
- return (1);
+ if (irq > 0) {
+ /* declare our interrupt handler */
+ sc->intr_resource = bus_alloc_resource(dev, SYS_RES_IRQ,
+ &zero, irq, irq, 1, RF_SHAREABLE);
+ }
+ /* interrupts seem mandatory */
+ if (sc->intr_resource == 0)
+ return (ENXIO);
+
+ return (0);
}
static int
ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct pps_data *sc;
u_int unit = minor(dev);
-
- if ((unit >= npps))
- return (ENXIO);
-
- sc = dev->si_drv1;
+ struct pps_data *sc = UNITOSOFTC(unit);
+ device_t ppsdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppsdev);
+ int error;
if (!sc->pps_open) {
- if (ppb_request_bus(&sc->pps_dev, PPB_WAIT|PPB_INTR))
+ if (ppb_request_bus(ppbus, ppsdev, PPB_WAIT|PPB_INTR))
return (EINTR);
- ppb_wctr(&sc->pps_dev, 0);
- ppb_wctr(&sc->pps_dev, IRQENABLE);
+ /* attach the interrupt handler */
+ if ((error = BUS_SETUP_INTR(ppbus, ppsdev, sc->intr_resource,
+ INTR_TYPE_TTY, ppsintr, ppsdev,
+ &sc->intr_cookie))) {
+ ppb_release_bus(ppbus, ppsdev);
+ return (error);
+ }
+
+ ppb_wctr(ppbus, 0);
+ ppb_wctr(ppbus, IRQENABLE);
sc->pps_open = 1;
}
@@ -145,41 +171,49 @@ ppsopen(dev_t dev, int flags, int fmt, struct proc *p)
static int
ppsclose(dev_t dev, int flags, int fmt, struct proc *p)
{
- struct pps_data *sc = dev->si_drv1;
+ u_int unit = minor(dev);
+ struct pps_data *sc = UNITOSOFTC(unit);
+ device_t ppsdev = UNITODEVICE(unit);
+ device_t ppbus = device_get_parent(ppsdev);
sc->pps.ppsparam.mode = 0; /* PHK ??? */
- ppb_wdtr(&sc->pps_dev, 0);
- ppb_wctr(&sc->pps_dev, 0);
+ ppb_wdtr(ppbus, 0);
+ ppb_wctr(ppbus, 0);
- ppb_release_bus(&sc->pps_dev);
+ /* Note: the interrupt handler is automatically detached */
+ ppb_release_bus(ppbus, ppsdev);
sc->pps_open = 0;
return(0);
}
static void
-ppsintr(struct ppb_device *ppd)
+ppsintr(void *arg)
{
- struct pps_data *sc = ppd->drv1;
+ device_t ppsdev = (device_t)arg;
+ device_t ppbus = device_get_parent(ppsdev);
+ struct pps_data *sc = DEVTOSOFTC(ppsdev);
struct timecounter *tc;
unsigned count;
tc = timecounter;
count = timecounter->tc_get_timecount(tc);
- if (!(ppb_rstr(&sc->pps_dev) & nACK))
+ if (!(ppb_rstr(ppbus) & nACK))
return;
if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
- ppb_wctr(&sc->pps_dev, IRQENABLE | AUTOFEED);
+ ppb_wctr(ppbus, IRQENABLE | AUTOFEED);
pps_event(&sc->pps, tc, count, PPS_CAPTUREASSERT);
if (sc->pps.ppsparam.mode & PPS_ECHOASSERT)
- ppb_wctr(&sc->pps_dev, IRQENABLE);
+ ppb_wctr(ppbus, IRQENABLE);
}
static int
ppsioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct proc *p)
{
- struct pps_data *sc = dev->si_drv1;
+ u_int unit = minor(dev);
+ struct pps_data *sc = UNITOSOFTC(unit);
return (pps_ioctl(cmd, data, &sc->pps));
}
+DRIVER_MODULE(pps, ppbus, pps_driver, pps_devclass, 0, 0);
diff --git a/sys/dev/ppbus/vpo.c b/sys/dev/ppbus/vpo.c
index 23e6058..51ccacf 100644
--- a/sys/dev/ppbus/vpo.c
+++ b/sys/dev/ppbus/vpo.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997, 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,8 +30,8 @@
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/malloc.h>
-#include <sys/buf.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <machine/clock.h>
@@ -56,6 +56,8 @@
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/vpoio.h>
+#include "ppbus_if.h"
+
struct vpo_sense {
struct scsi_sense cmd;
unsigned int stat;
@@ -79,96 +81,84 @@ struct vpo_data {
struct vpoio_data vpo_io; /* interface to low level functions */
};
-/* cam related functions */
-static void vpo_action(struct cam_sim *sim, union ccb *ccb);
-static void vpo_poll(struct cam_sim *sim);
+static int vpo_probe(device_t);
+static int vpo_attach(device_t);
-static int nvpo = 0;
-#define MAXVP0 8 /* XXX not much better! */
-static struct vpo_data *vpodata[MAXVP0];
+#define DEVTOSOFTC(dev) \
+ ((struct vpo_data *)device_get_softc(dev))
-#ifdef _KERNEL
+static devclass_t vpo_devclass;
-/*
- * Make ourselves visible as a ppbus driver
- */
-static struct ppb_device *vpoprobe(struct ppb_data *ppb);
-static int vpoattach(struct ppb_device *dev);
+static device_method_t vpo_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, vpo_probe),
+ DEVMETHOD(device_attach, vpo_attach),
-static struct ppb_driver vpodriver = {
- vpoprobe, vpoattach, "vpo"
+ { 0, 0 }
};
-DATA_SET(ppbdriver_set, vpodriver);
-#endif
+static driver_t vpo_driver = {
+ "vpo",
+ vpo_methods,
+ sizeof(struct vpo_data),
+};
+
+/* cam related functions */
+static void vpo_action(struct cam_sim *sim, union ccb *ccb);
+static void vpo_poll(struct cam_sim *sim);
/*
- * vpoprobe()
- *
- * Called by ppb_attachdevs().
+ * vpo_probe()
*/
-static struct ppb_device *
-vpoprobe(struct ppb_data *ppb)
+static int
+vpo_probe(device_t dev)
{
struct vpo_data *vpo;
- struct ppb_device *dev;
-
- if (nvpo >= MAXVP0) {
- printf("vpo: Too many devices (max %d)\n", MAXVP0);
- return(NULL);
- }
+ int error;
- vpo = (struct vpo_data *)malloc(sizeof(struct vpo_data),
- M_DEVBUF, M_NOWAIT);
- if (!vpo) {
- printf("vpo: cannot malloc!\n");
- return(NULL);
- }
+ vpo = DEVTOSOFTC(dev);
bzero(vpo, sizeof(struct vpo_data));
- vpodata[nvpo] = vpo;
-
/* vpo dependent initialisation */
- vpo->vpo_unit = nvpo;
-
- /* ok, go to next device on next probe */
- nvpo ++;
+ vpo->vpo_unit = device_get_unit(dev);
/* low level probe */
vpoio_set_unit(&vpo->vpo_io, vpo->vpo_unit);
/* check ZIP before ZIP+ or imm_probe() will send controls to
* the printer or whatelse connected to the port */
- if ((dev = vpoio_probe(ppb, &vpo->vpo_io))) {
+ if ((error = vpoio_probe(dev, &vpo->vpo_io)) == 0) {
vpo->vpo_isplus = 0;
- } else if ((dev = imm_probe(ppb, &vpo->vpo_io))) {
+ device_set_desc(dev,
+ "Iomega VPI0 Parallel to SCSI interface");
+ } else if ((error = imm_probe(dev, &vpo->vpo_io)) == 0) {
vpo->vpo_isplus = 1;
+ device_set_desc(dev,
+ "Iomega Matchmaker Parallel to SCSI interface");
} else {
- free(vpo, M_DEVBUF);
- return (NULL);
+ return (error);
}
- return (dev);
+ return (0);
}
/*
- * vpoattach()
- *
- * Called by ppb_attachdevs().
+ * vpo_attach()
*/
static int
-vpoattach(struct ppb_device *dev)
+vpo_attach(device_t dev)
{
- struct vpo_data *vpo = vpodata[dev->id_unit];
+ struct vpo_data *vpo = DEVTOSOFTC(dev);
struct cam_devq *devq;
+ int error;
/* low level attachment */
if (vpo->vpo_isplus) {
- if (!imm_attach(&vpo->vpo_io))
- return (0);
+ if ((error = imm_attach(&vpo->vpo_io)))
+ return (error);
} else {
- if (!vpoio_attach(&vpo->vpo_io))
- return (0);
+ if ((error = vpoio_attach(&vpo->vpo_io)))
+ return (error);
}
/*
@@ -178,18 +168,19 @@ vpoattach(struct ppb_device *dev)
devq = cam_simq_alloc(/*maxopenings*/1);
/* XXX What about low-level detach on error? */
if (devq == NULL)
- return (0);
+ return (ENXIO);
- vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo, dev->id_unit,
+ vpo->sim = cam_sim_alloc(vpo_action, vpo_poll, "vpo", vpo,
+ device_get_unit(dev),
/*untagged*/1, /*tagged*/0, devq);
if (vpo->sim == NULL) {
cam_simq_free(devq);
- return (0);
+ return (ENXIO);
}
if (xpt_bus_register(vpo->sim, /*bus*/0) != CAM_SUCCESS) {
cam_sim_free(vpo->sim, /*free_devq*/TRUE);
- return (0);
+ return (ENXIO);
}
if (xpt_create_path(&vpo->path, /*periph*/NULL,
@@ -197,12 +188,12 @@ vpoattach(struct ppb_device *dev)
CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
xpt_bus_deregister(cam_sim_path(vpo->sim));
cam_sim_free(vpo->sim, /*free_devq*/TRUE);
- return (0);
+ return (ENXIO);
}
/* all went ok */
- return (1);
+ return (0);
}
/*
@@ -445,3 +436,5 @@ vpo_poll(struct cam_sim *sim)
/* The ZIP is actually always polled throw vpo_action() */
return;
}
+
+DRIVER_MODULE(vpo, ppbus, vpo_driver, vpo_devclass, 0, 0);
diff --git a/sys/dev/ppbus/vpoio.c b/sys/dev/ppbus/vpoio.c
index 73e4adb..e5fd445 100644
--- a/sys/dev/ppbus/vpoio.c
+++ b/sys/dev/ppbus/vpoio.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1998 Nicolas Souchu
+ * Copyright (c) 1998, 1999 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,6 +30,8 @@
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/module.h>
+#include <sys/bus.h>
#include <sys/malloc.h>
#include <sys/buf.h>
@@ -43,10 +45,13 @@
#include "opt_vpo.h"
+#include <dev/ppbus/ppbio.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <dev/ppbus/vpoio.h>
+#include "ppbus_if.h"
+
/*
* The driver pools the drive. We may add a timeout queue to avoid
* active polling on nACK. I've tried this but it leads to unreliable
@@ -271,10 +276,11 @@ static struct ppb_microseq in_disk_mode[] = {
static int
vpoio_disconnect(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int ret;
- ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret);
- return (ppb_release_bus(&vpo->vpo_dev));
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
+ return (ppb_release_bus(ppbus, vpo->vpo_dev));
}
/*
@@ -283,10 +289,11 @@ vpoio_disconnect(struct vpoio_data *vpo)
static int
vpoio_connect(struct vpoio_data *vpo, int how)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error;
int ret;
- if ((error = ppb_request_bus(&vpo->vpo_dev, how))) {
+ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, how))) {
#ifdef VP0_DEBUG
printf("%s: can't request bus!\n", __FUNCTION__);
@@ -294,10 +301,10 @@ vpoio_connect(struct vpoio_data *vpo, int how)
return error;
}
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev))
- ppb_MS_microseq(&vpo->vpo_dev, connect_epp_microseq, &ret);
+ if (PPB_IN_EPP_MODE(ppbus))
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret);
else
- ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
return (0);
}
@@ -310,6 +317,7 @@ vpoio_connect(struct vpoio_data *vpo, int how)
static void
vpoio_reset (struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int ret;
struct ppb_microseq reset_microseq[] = {
@@ -324,7 +332,7 @@ vpoio_reset (struct vpoio_data *vpo)
};
ppb_MS_init_msq(reset_microseq, 1, INITIATOR, 1 << VP0_INITIATOR);
- ppb_MS_microseq(&vpo->vpo_dev, reset_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, reset_microseq, &ret);
return;
}
@@ -335,9 +343,10 @@ vpoio_reset (struct vpoio_data *vpo)
static int
vpoio_in_disk_mode(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int ret;
- ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
return (ret);
}
@@ -350,37 +359,38 @@ vpoio_in_disk_mode(struct vpoio_data *vpo)
static int
vpoio_detect(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error, ret;
/* allocate the bus, then apply microsequences */
- if ((error = ppb_request_bus(&vpo->vpo_dev, PPB_DONTWAIT)))
+ if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_DONTWAIT)))
return (error);
- ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev))
- ppb_MS_microseq(&vpo->vpo_dev, connect_epp_microseq, &ret);
+ if (PPB_IN_EPP_MODE(ppbus))
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_epp_microseq, &ret);
else
- ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
- ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
if (!ret) {
/* try spp mode (maybe twice or because previous mode was PS2)
* NIBBLE mode will be restored on next transfers if detection
* succeed
*/
- ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE);
- ppb_MS_microseq(&vpo->vpo_dev, connect_spp_microseq, &ret);
+ ppb_set_mode(ppbus, PPB_NIBBLE);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, connect_spp_microseq, &ret);
- ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
if (!ret) {
if (bootverbose)
printf("vpo%d: can't connect to the drive\n",
vpo->vpo_unit);
/* disconnect and release the bus */
- ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq,
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq,
&ret);
goto error;
}
@@ -389,12 +399,12 @@ vpoio_detect(struct vpoio_data *vpo)
/* send SCSI reset signal */
vpoio_reset(vpo);
- ppb_MS_microseq(&vpo->vpo_dev, disconnect_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, disconnect_microseq, &ret);
/* ensure we are disconnected or daisy chained peripheral
* may cause serious problem to the disk */
- ppb_MS_microseq(&vpo->vpo_dev, in_disk_mode, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, in_disk_mode, &ret);
if (ret) {
if (bootverbose)
printf("vpo%d: can't disconnect from the drive\n",
@@ -402,11 +412,11 @@ vpoio_detect(struct vpoio_data *vpo)
goto error;
}
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
return (0);
error:
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
return (VP0_EINITFAILED);
}
@@ -416,37 +426,35 @@ error:
static int
vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size)
{
-
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
- ppb_MS_exec(&vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer,
+ ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_PUT, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
#if 0
/* XXX EPP 1.9 not implemented with microsequences */
else {
- ppb_reset_epp_timeout(&vpo->vpo_dev);
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_SELIN | H_INIT | H_STROBE);
+ ppb_reset_epp_timeout(ppbus);
+ ppb_wctr(ppbus, H_AUTO | H_SELIN | H_INIT | H_STROBE);
if (((long) buffer | size) & 0x03)
- ppb_outsb_epp(&vpo->vpo_dev,
+ ppb_outsb_epp(ppbus,
buffer, size);
else
- ppb_outsl_epp(&vpo->vpo_dev,
+ ppb_outsl_epp(ppbus,
buffer, size/4);
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
+ if ((ppb_rstr(ppbus) & TIMEOUT)) {
error = VP0_EPPDATA_TIMEOUT;
goto error;
}
- ppb_wctr(&vpo->vpo_dev,
- H_AUTO | H_nSELIN | H_INIT | H_STROBE);
+ ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
}
#endif
- ppb_ecp_sync(&vpo->vpo_dev);
+ ppb_ecp_sync(ppbus);
return (error);
}
@@ -457,36 +465,37 @@ vpoio_outstr(struct vpoio_data *vpo, char *buffer, int size)
static int
vpoio_instr(struct vpoio_data *vpo, char *buffer, int size)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int error = 0;
- ppb_MS_exec(&vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer,
+ ppb_MS_exec(ppbus, vpo->vpo_dev, MS_OP_GET, (union ppb_insarg)buffer,
(union ppb_insarg)size, (union ppb_insarg)MS_UNKNOWN, &error);
#if 0
/* XXX EPP 1.9 not implemented with microsequences */
else {
- ppb_reset_epp_timeout(&vpo->vpo_dev);
- ppb_wctr(&vpo->vpo_dev, PCD |
+ ppb_reset_epp_timeout(ppbus);
+ ppb_wctr(ppbus, PCD |
H_AUTO | H_SELIN | H_INIT | H_STROBE);
if (((long) buffer | size) & 0x03)
- ppb_insb_epp(&vpo->vpo_dev,
+ ppb_insb_epp(ppbus,
buffer, size);
else
- ppb_insl_epp(&vpo->vpo_dev,
+ ppb_insl_epp(ppbus,
buffer, size/4);
- if ((ppb_rstr(&vpo->vpo_dev) & TIMEOUT)) {
+ if ((ppb_rstr(ppbus) & TIMEOUT)) {
error = VP0_EPPDATA_TIMEOUT;
goto error;
}
- ppb_wctr(&vpo->vpo_dev, PCD |
+ ppb_wctr(ppbus, PCD |
H_AUTO | H_nSELIN | H_INIT | H_STROBE);
}
#endif
- ppb_ecp_sync(&vpo->vpo_dev);
+ ppb_ecp_sync(ppbus);
return (error);
}
@@ -494,6 +503,7 @@ vpoio_instr(struct vpoio_data *vpo, char *buffer, int size)
static char
vpoio_select(struct vpoio_data *vpo, int initiator, int target)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int ret;
struct ppb_microseq select_microseq[] = {
@@ -523,7 +533,7 @@ vpoio_select(struct vpoio_data *vpo, int initiator, int target)
SELECT_TARGET, 1 << target,
SELECT_INITIATOR, 1 << initiator);
- ppb_MS_microseq(&vpo->vpo_dev, select_microseq, &ret);
+ ppb_MS_microseq(ppbus, vpo->vpo_dev, select_microseq, &ret);
if (ret)
return (VP0_ESELECT_TIMEOUT);
@@ -541,20 +551,20 @@ vpoio_select(struct vpoio_data *vpo, int initiator, int target)
static char
vpoio_wait(struct vpoio_data *vpo, int tmo)
{
-
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
register int k;
register char r;
#if 0 /* broken */
- if (ppb_poll_device(&vpo->vpo_dev, 150, nBUSY, nBUSY, PPB_INTR))
+ if (ppb_poll_device(ppbus, 150, nBUSY, nBUSY, PPB_INTR))
return (0);
- return (ppb_rstr(&vpo->vpo_dev) & 0xf0);
+ return (ppb_rstr(ppbus) & 0xf0);
#endif
/* XXX should be ported to microseq */
k = 0;
- while (!((r = ppb_rstr(&vpo->vpo_dev)) & nBUSY) && (k++ < tmo))
+ while (!((r = ppb_rstr(ppbus)) & nBUSY) && (k++ < tmo))
;
/*
@@ -576,14 +586,13 @@ vpoio_wait(struct vpoio_data *vpo, int tmo)
* Low level probe of vpo device
*
*/
-struct ppb_device *
-vpoio_probe(struct ppb_data *ppb, struct vpoio_data *vpo)
+int
+vpoio_probe(device_t dev, struct vpoio_data *vpo)
{
+ int error;
/* ppbus dependent initialisation */
- vpo->vpo_dev.id_unit = vpo->vpo_unit;
- vpo->vpo_dev.name = "vpo";
- vpo->vpo_dev.ppb = ppb;
+ vpo->vpo_dev = dev;
/*
* Initialize microsequence code
@@ -591,11 +600,11 @@ vpoio_probe(struct ppb_data *ppb, struct vpoio_data *vpo)
INIT_TRIG_MICROSEQ;
/* now, try to initialise the drive */
- if (vpoio_detect(vpo)) {
- return (NULL);
+ if ((error = vpoio_detect(vpo))) {
+ return (error);
}
- return (&vpo->vpo_dev);
+ return (0);
}
/*
@@ -607,19 +616,14 @@ vpoio_probe(struct ppb_data *ppb, struct vpoio_data *vpo)
int
vpoio_attach(struct vpoio_data *vpo)
{
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
int epp;
- /*
- * Report ourselves
- */
- printf("vpo%d: <Iomega VPI0 Parallel to SCSI interface> on ppbus %d\n",
- vpo->vpo_dev.id_unit, vpo->vpo_dev.ppb->ppb_link->adapter_unit);
-
vpo->vpo_nibble_inbyte_msq = (struct ppb_microseq *)malloc(
sizeof(nibble_inbyte_submicroseq), M_DEVBUF, M_NOWAIT);
if (!vpo->vpo_nibble_inbyte_msq)
- return (0);
+ return (ENXIO);
bcopy((void *)nibble_inbyte_submicroseq,
(void *)vpo->vpo_nibble_inbyte_msq,
@@ -630,36 +634,36 @@ vpoio_attach(struct vpoio_data *vpo)
/*
* Initialize mode dependent in/out microsequences
*/
- ppb_request_bus(&vpo->vpo_dev, PPB_WAIT);
+ ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT);
/* enter NIBBLE mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1) {
+ if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1) {
- ppb_MS_GET_init(&vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, vpo->vpo_nibble_inbyte_msq);
- ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
}
/* enter PS2 mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1) {
+ if (ppb_set_mode(ppbus, PPB_PS2) != -1) {
- ppb_MS_GET_init(&vpo->vpo_dev, ps2_inbyte_submicroseq);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, ps2_inbyte_submicroseq);
- ppb_MS_PUT_init(&vpo->vpo_dev, spp_outbyte_submicroseq);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, spp_outbyte_submicroseq);
}
- epp = ppb_get_epp_protocol(&vpo->vpo_dev);
+ epp = ppb_get_epp_protocol(ppbus);
/* enter EPP mode to configure submsq */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) {
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
switch (epp) {
case EPP_1_9:
/* XXX EPP 1.9 support should be improved */
case EPP_1_7:
- ppb_MS_GET_init(&vpo->vpo_dev, epp17_instr_body);
+ ppb_MS_GET_init(ppbus, vpo->vpo_dev, epp17_instr_body);
- ppb_MS_PUT_init(&vpo->vpo_dev, epp17_outstr_body);
+ ppb_MS_PUT_init(ppbus, vpo->vpo_dev, epp17_outstr_body);
break;
default:
panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
@@ -668,7 +672,7 @@ vpoio_attach(struct vpoio_data *vpo)
}
/* try to enter EPP or PS/2 mode, NIBBLE otherwise */
- if (ppb_set_mode(&vpo->vpo_dev, PPB_EPP) != -1) {
+ if (ppb_set_mode(ppbus, PPB_EPP) != -1) {
switch (epp) {
case EPP_1_9:
printf("vpo%d: EPP 1.9 mode\n", vpo->vpo_unit);
@@ -680,25 +684,25 @@ vpoio_attach(struct vpoio_data *vpo)
panic("%s: unknown EPP protocol (0x%x)", __FUNCTION__,
epp);
}
- } else if (ppb_set_mode(&vpo->vpo_dev, PPB_PS2) != -1)
+ } else if (ppb_set_mode(ppbus, PPB_PS2) != -1)
printf("vpo%d: PS2 mode\n", vpo->vpo_unit);
- else if (ppb_set_mode(&vpo->vpo_dev, PPB_NIBBLE) != -1)
+ else if (ppb_set_mode(ppbus, PPB_NIBBLE) != -1)
printf("vpo%d: NIBBLE mode\n", vpo->vpo_unit);
else {
printf("vpo%d: can't enter NIBBLE, PS2 or EPP mode\n",
vpo->vpo_unit);
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
free(vpo->vpo_nibble_inbyte_msq, M_DEVBUF);
- return (0);
+ return (ENXIO);
}
- ppb_release_bus(&vpo->vpo_dev);
+ ppb_release_bus(ppbus, vpo->vpo_dev);
- return (1);
+ return (0);
}
/*
@@ -739,7 +743,7 @@ vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
int clen, char *buffer, int blen, int *result, int *count,
int *ret)
{
-
+ device_t ppbus = device_get_parent(vpo->vpo_dev);
register char r;
char l, h = 0;
int len, error = 0;
@@ -768,7 +772,7 @@ vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
*
* set H_SELIN low for vpoio_wait().
*/
- ppb_wctr(&vpo->vpo_dev, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
+ ppb_wctr(ppbus, H_AUTO | H_nSELIN | H_INIT | H_STROBE);
for (k = 0; k < clen; k++) {
if (vpoio_wait(vpo, VP0_FAST_SPINTMO) != (char)0xe0) {
@@ -804,7 +808,7 @@ vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
/* if in EPP mode or writing bytes, try to transfer a sector
* otherwise, just send one byte
*/
- if (PPB_IN_EPP_MODE(&vpo->vpo_dev) || r == (char)0xc0)
+ if (PPB_IN_EPP_MODE(ppbus) || r == (char)0xc0)
len = (((blen - *count) >= VP0_SECTOR_SIZE)) ?
VP0_SECTOR_SIZE : 1;
else
diff --git a/sys/dev/ppbus/vpoio.h b/sys/dev/ppbus/vpoio.h
index e007d3e..211ca00 100644
--- a/sys/dev/ppbus/vpoio.h
+++ b/sys/dev/ppbus/vpoio.h
@@ -67,12 +67,12 @@ struct vpoio_data {
/* each device must have its own nibble inbyte microsequence */
struct ppb_microseq *vpo_nibble_inbyte_msq;
- struct ppb_device vpo_dev;
+ device_t vpo_dev;
};
#define vpoio_set_unit(vpo,unit) ((vpo)->vpo_unit = unit)
-struct ppb_device *vpoio_probe(struct ppb_data *ppb, struct vpoio_data *vpo);
+int vpoio_probe(device_t dev, struct vpoio_data *vpo);
int vpoio_attach(struct vpoio_data *vpo);
int vpoio_reset_bus(struct vpoio_data *vpo);
@@ -81,7 +81,7 @@ int vpoio_do_scsi(struct vpoio_data *vpo, int host, int target, char *command,
int clen, char *buffer, int blen, int *result, int *count,
int *ret);
-struct ppb_device *imm_probe(struct ppb_data *ppb, struct vpoio_data *vpo);
+int imm_probe(device_t dev, struct vpoio_data *vpo);
int imm_attach(struct vpoio_data *vpo);
int imm_reset_bus(struct vpoio_data *vpo);
diff --git a/sys/dev/ppc/ppc.c b/sys/dev/ppc/ppc.c
index 436caeb..0ee1eb6 100644
--- a/sys/dev/ppc/ppc.c
+++ b/sys/dev/ppc/ppc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997-2000 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,42 +30,90 @@
#if NPPC > 0
+#include "opt_ppc.h"
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
#include <vm/vm.h>
-#include <vm/vm_param.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 <i386/isa/isa_device.h>
-#include <i386/isa/isa.h>
+#include <isa/isareg.h>
+#include <isa/isavar.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <i386/isa/ppcreg.h>
-#include "opt_ppc.h"
+#include "ppbus_if.h"
#define LOG_PPC(function, ppc, string) \
if (bootverbose) printf("%s: %s\n", function, string)
-static int ppcprobe(struct isa_device *);
-static int ppcattach(struct isa_device *);
-struct isa_driver ppcdriver = {
- ppcprobe, ppcattach, "ppc"
+#define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev))
+
+devclass_t ppc_devclass;
+
+static int ppc_probe(device_t dev);
+static int ppc_attach(device_t dev);
+static int ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val);
+
+static void ppc_reset_epp(device_t);
+static void ppc_ecp_sync(device_t);
+static void ppcintr(void *arg);
+
+static int ppc_exec_microseq(device_t, struct ppb_microseq **);
+static int ppc_setmode(device_t, int);
+
+static int ppc_read(device_t, char *, int, int);
+static int ppc_write(device_t, char *, int, int);
+
+static u_char ppc_io(device_t, int, u_char *, int, u_char);
+
+static int ppc_setup_intr(device_t, device_t, struct resource *, int,
+ void (*)(void *), void *, void **);
+static int ppc_teardown_intr(device_t, device_t, struct resource *, void *);
+
+static device_method_t ppc_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppc_probe),
+ DEVMETHOD(device_attach, ppc_attach),
+
+ /* 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),
};
-
-static struct ppc_data *ppcdata[NPPC];
-static int nppc = 0;
-
-static char *ppc_types[] = {
+
+static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
};
@@ -98,91 +146,13 @@ static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
#define BIOS_MAX_PPC 4
/*
- * All these functions are default actions for IN/OUT operations.
- * They may be redefined if needed.
- */
-static void ppc_outsb_epp(int unit, char *addr, int cnt) {
- outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsw_epp(int unit, char *addr, int cnt) {
- outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsl_epp(int unit, char *addr, int cnt) {
- outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insb_epp(int unit, char *addr, int cnt) {
- insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insw_epp(int unit, char *addr, int cnt) {
- insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insl_epp(int unit, char *addr, int cnt) {
- insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-
-static u_char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); }
-static u_char ppc_rstr(int unit) { return r_str(ppcdata[unit]); }
-static u_char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); }
-static u_char ppc_repp_A(int unit) { return r_epp_A(ppcdata[unit]); }
-static u_char ppc_repp_D(int unit) { return r_epp_D(ppcdata[unit]); }
-static u_char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); }
-static u_char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); }
-
-static void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); }
-static void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); }
-static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
-static void ppc_wepp_A(int unit, char byte) { w_epp_A(ppcdata[unit], byte); }
-static void ppc_wepp_D(int unit, char byte) { w_epp_D(ppcdata[unit], byte); }
-static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
-static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
-
-static void ppc_reset_epp_timeout(int);
-static void ppc_ecp_sync(int);
-static ointhand2_t ppcintr;
-
-static int ppc_exec_microseq(int, struct ppb_microseq **);
-static int ppc_generic_setmode(int, int);
-static int ppc_smclike_setmode(int, int);
-
-static int ppc_read(int, char *, int, int);
-static int ppc_write(int, char *, int, int);
-
-static struct ppb_adapter ppc_smclike_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_smclike_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-static struct ppb_adapter ppc_generic_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_generic_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-/*
* ppc_ecp_sync() XXX
*/
static void
-ppc_ecp_sync(int unit) {
+ppc_ecp_sync(device_t dev) {
- struct ppc_data *ppc = ppcdata[unit];
int i, r;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
if (!(ppc->ppc_avm & PPB_ECP))
return;
@@ -199,7 +169,7 @@ ppc_ecp_sync(int unit) {
}
printf("ppc%d: ECP sync failed as data still " \
- "present in FIFO.\n", unit);
+ "present in FIFO.\n", ppc->ppc_unit);
return;
}
@@ -328,6 +298,121 @@ ppc_detect_port(struct ppc_data *ppc)
}
/*
+ * EPP timeout, according to the PC87332 manual
+ * Semantics of clearing EPP timeout bit.
+ * PC87332 - reading SPP_STR does it...
+ * SMC - write 1 to EPP timeout bit XXX
+ * Others - (?) write 0 to EPP timeout bit
+ */
+static void
+ppc_reset_epp_timeout(struct ppc_data *ppc)
+{
+ register char r;
+
+ r = r_str(ppc);
+ w_str(ppc, r | 0x1);
+ w_str(ppc, r & 0xfe);
+
+ return;
+}
+
+static int
+ppc_check_epp_timeout(struct ppc_data *ppc)
+{
+ ppc_reset_epp_timeout(ppc);
+
+ return (!(r_str(ppc) & TIMEOUT));
+}
+
+/*
+ * Configure current operating mode
+ */
+static int
+ppc_generic_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ return (EINVAL);
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+/*
+ * The ppc driver is free to choose options like FIFO or DMA
+ * if ECP mode is available.
+ *
+ * The 'RAW' option allows the upper drivers to force the ppc mode
+ * even with FIFO, DMA available.
+ */
+static int
+ppc_smclike_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP or EPP mode
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ /* select EPP mode */
+ ecr |= PPC_ECR_EPP;
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+#ifdef PPC_PROBE_CHIPSET
+/*
* ppc_pc873xx_detect
*
* Probe for a Natsemi PC873xx-family part.
@@ -381,11 +466,11 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
outb(idport, PC873_SID);
val = inb(idport + 1);
if ((val & 0xf0) == 0x10) {
- ppc->ppc_type = NS_PC87332;
+ ppc->ppc_model = NS_PC87332;
} else if ((val & 0xf8) == 0x70) {
- ppc->ppc_type = NS_PC87306;
+ ppc->ppc_model = NS_PC87306;
} else if ((val & 0xf8) == 0x50) {
- ppc->ppc_type = NS_PC87334;
+ ppc->ppc_model = NS_PC87334;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
@@ -484,7 +569,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
else
ppc->ppc_epp = EPP_1_7;
- if ((ppc->ppc_type == NS_PC87332) && bootverbose) {
+ if ((ppc->ppc_model == NS_PC87332) && bootverbose) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
if (ptr & PC873_EPPRDIR)
@@ -539,7 +624,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
printf(", EPP1.9");
/* enable automatic direction turnover */
- if (ppc->ppc_type == NS_PC87332) {
+ if (ppc->ppc_model == NS_PC87332) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
ptr &= ~PC873_EPPRDIR;
@@ -581,22 +666,14 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter = &ppc_generic_adapter;
- ppc_generic_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_GENERIC;
+ ppc_generic_setmode(ppc, chipset_mode);
return(chipset_mode);
}
return(-1);
}
-static int
-ppc_check_epp_timeout(struct ppc_data *ppc)
-{
- ppc_reset_epp_timeout(ppc->ppc_unit);
-
- return (!(r_str(ppc) & TIMEOUT));
-}
-
/*
* ppc_smc37c66xgt_detect
*
@@ -661,7 +738,7 @@ config:
if (port_address[(int)r] != ppc->ppc_base)
return (-1);
- ppc->ppc_type = type;
+ ppc->ppc_model = type;
/*
* CR1 and CR4 registers bits 3 and 0/1 for mode configuration
@@ -800,8 +877,8 @@ end_detect:
/* end config mode */
outb(csr, 0xaa);
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
- ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
+ ppc_smclike_setmode(ppc, chipset_mode);
return (chipset_mode);
}
@@ -866,15 +943,15 @@ found:
switch (inb(efdr) & WINB_CHIPID) {
case WINB_W83877F_ID:
- ppc->ppc_type = WINB_W83877F;
+ ppc->ppc_model = WINB_W83877F;
break;
case WINB_W83877AF_ID:
- ppc->ppc_type = WINB_W83877AF;
+ ppc->ppc_model = WINB_W83877AF;
break;
default:
- ppc->ppc_type = WINB_UNKNOWN;
+ ppc->ppc_model = WINB_UNKNOWN;
}
if (bootverbose) {
@@ -898,7 +975,7 @@ found:
printf("ppc%d:", ppc->ppc_unit);
}
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (!chipset_mode) {
/* autodetect mode */
@@ -940,7 +1017,7 @@ found:
case (WINB_PARALLEL | WINB_ECP_EPP):
ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP SPP");
@@ -966,7 +1043,7 @@ found:
if (bootverbose)
printf(" ECP+EPP");
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
} else {
outb(efdr, inb(efdr) | WINB_ECP);
@@ -988,10 +1065,18 @@ found:
/* exit configuration mode */
outb(efer, 0xaa);
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
+#endif
/*
* ppc_generic_detect
@@ -1000,7 +1085,7 @@ static int
ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
{
/* default to generic */
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (bootverbose)
printf("ppc%d:", ppc->ppc_unit);
@@ -1023,8 +1108,8 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (ppc->ppc_avm & PPB_ECP) {
/* SMC like chipset found */
- ppc->ppc_type = SMC_LIKE;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_model = SMC_LIKE;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
@@ -1050,7 +1135,14 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
@@ -1063,6 +1155,7 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
static int
ppc_detect(struct ppc_data *ppc, int chipset_mode) {
+#ifdef PPC_PROBE_CHIPSET
int i, mode;
/* list of supported chipsets */
@@ -1073,6 +1166,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
ppc_generic_detect,
NULL
};
+#endif
/* if can't find the port and mode not forced return error */
if (!ppc_detect_port(ppc) && chipset_mode == 0)
@@ -1081,6 +1175,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
/* assume centronics compatible mode is supported */
ppc->ppc_avm = PPB_COMPATIBLE;
+#ifdef PPC_PROBE_CHIPSET
/* we have to differenciate available chipset modes,
* chipset running modes and IEEE-1284 operating modes
*
@@ -1089,9 +1184,11 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
if (ppc->ppc_flags & 0x40) {
if (bootverbose)
printf("ppc: chipset forced to generic\n");
+#endif
ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
+#ifdef PPC_PROBE_CHIPSET
} else {
for (i=0; chipset_detect[i] != NULL; i++) {
if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
@@ -1100,6 +1197,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
}
}
}
+#endif
/* configure/detect ECP FIFO */
if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80))
@@ -1115,9 +1213,9 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
* Microsequence mechanism is supposed to handle fast I/O operations.
*/
static int
-ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
+ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
struct ppb_microseq *mi;
char cc, *p;
int i, iter, len;
@@ -1326,9 +1424,10 @@ ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
}
static void
-ppcintr(int unit)
+ppcintr(void *arg)
{
- struct ppc_data *ppc = ppcdata[unit];
+ device_t dev = (device_t)arg;
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(dev);
u_char ctr, ecr, str;
str = r_str(ppc);
@@ -1341,8 +1440,6 @@ ppcintr(int unit)
/* don't use ecp mode with IRQENABLE set */
if (ctr & IRQENABLE) {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
return;
}
@@ -1356,8 +1453,7 @@ ppcintr(int unit)
w_ecr(ppc, ecr | PPC_nFAULT_INTR);
ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT;
} else {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
+ /* shall be handled by underlying layers XXX */
return;
}
}
@@ -1397,14 +1493,13 @@ ppcintr(int unit)
/* classic interrupt I/O */
ppc->ppc_irqstat &= ~PPC_IRQ_FIFO;
-
}
return;
}
static int
-ppc_read(int unit, char *buf, int len, int mode)
+ppc_read(device_t dev, char *buf, int len, int mode)
{
return (EINVAL);
}
@@ -1417,9 +1512,9 @@ ppc_read(int unit, char *buf, int len, int mode)
* EINVAL is returned
*/
static int
-ppc_write(int unit, char *buf, int len, int how)
+ppc_write(device_t dev, char *buf, int len, int how)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
char ecr, ecr_sav, ctr, ctr_sav;
int s, error = 0;
int spin;
@@ -1434,7 +1529,7 @@ ppc_write(int unit, char *buf, int len, int how)
/*
* Send buffer with DMA, FIFO and interrupts
*/
- if (ppc->ppc_avm & PPB_ECP) {
+ if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
if (ppc->ppc_dmachan >= 0) {
@@ -1568,231 +1663,334 @@ error:
return (error);
}
-/*
- * Configure current operating mode
- */
-static int
-ppc_generic_setmode(int unit, int mode)
+static void
+ppc_reset_epp(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
+
+ ppc_reset_epp_timeout(ppc);
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
+ return;
+}
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+static int
+ppc_setmode(device_t dev, int mode)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- if (mode & PPB_EPP)
- return (EINVAL);
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ return (ppc_smclike_setmode(ppc, mode));
+ break;
- w_ecr(ppc, ecr);
+ case PPC_TYPE_GENERIC:
+ default:
+ return (ppc_generic_setmode(ppc, mode));
+ break;
}
- ppc->ppc_mode = mode;
-
- return (0);
+ /* not reached */
+ return (ENXIO);
}
-/*
- * The ppc driver is free to choose options like FIFO or DMA
- * if ECP mode is available.
- *
- * The 'RAW' option allows the upper drivers to force the ppc mode
- * even with FIFO, DMA available.
- */
-int
-ppc_smclike_setmode(int unit, int mode)
+static int
+ppc_probe(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
-
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
-
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP or EPP mode
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+ static short next_bios_ppc = 0;
+ struct ppc_data *ppc;
+ device_t parent;
+ int port;
- if (mode & PPB_EPP)
- /* select EPP mode */
- ecr |= PPC_ECR_EPP;
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ device_set_desc(dev, "Parallel port");
- w_ecr(ppc, ecr);
- }
+ /* XXX shall be connected to pnpbios - from Peter Wemm */
+ if (isa_get_logicalid(dev))
+ return ENXIO;
- ppc->ppc_mode = mode;
+ parent = device_get_parent(dev);
- return (0);
-}
-
-/*
- * EPP timeout, according to the PC87332 manual
- * Semantics of clearing EPP timeout bit.
- * PC87332 - reading SPP_STR does it...
- * SMC - write 1 to EPP timeout bit XXX
- * Others - (?) write 0 to EPP timeout bit
- */
-static void
-ppc_reset_epp_timeout(int unit)
-{
- struct ppc_data *ppc = ppcdata[unit];
- register char r;
+ /*
+ * Allocate the ppc_data structure.
+ */
+ ppc = DEVTOSOFTC(dev);
+ bzero(ppc, sizeof(struct ppc_data));
- r = r_str(ppc);
- w_str(ppc, r | 0x1);
- w_str(ppc, r & 0xfe);
+ ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0;
+ ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0;
- return;
-}
-
-static int
-ppcprobe(struct isa_device *dvp)
-{
- static short next_bios_ppc = 0;
- struct ppc_data *ppc;
+ /* retrieve ISA parameters */
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_PORT, &port);
/*
* If port not specified, use bios list.
*/
- if(dvp->id_iobase < 0) {
+ if (port < 0) {
if((next_bios_ppc < BIOS_MAX_PPC) &&
(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
- dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
+ port = *(BIOS_PORTS+next_bios_ppc++);
if (bootverbose)
- printf("ppc: parallel port found at 0x%x\n",
- dvp->id_iobase);
- } else
- return (0);
+ device_printf(dev, "parallel port found at 0x%x\n",
+ port);
+ } else {
+ device_printf(dev, "parallel port not found.\n");
+ return ENXIO;
+ }
}
-
- /*
- * Port was explicitly specified.
- * This allows probing of ports unknown to the BIOS.
- */
-
- /*
- * Allocate the ppc_data structure.
- */
- ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
- if (!ppc) {
- printf("ppc: cannot malloc!\n");
+ ppc->ppc_base = port;
+
+ /* IO port is mandatory */
+ ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &ppc->rid_ioport, port, port,
+ IO_LPTSIZE, RF_ACTIVE);
+ if (ppc->res_ioport == 0) {
+ device_printf(dev, "cannot reserve I/O port range\n");
goto error;
}
- bzero(ppc, sizeof(struct ppc_data));
- ppc->ppc_base = dvp->id_iobase;
- ppc->ppc_unit = dvp->id_unit;
- ppc->ppc_type = GENERIC;
+ ppc->ppc_flags = device_get_flags(dev);
- /* store boot flags */
- ppc->ppc_flags = dvp->id_flags;
+ if (!(ppc->ppc_flags & 0x20)) {
+ ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq,
+ 0ul, ~0ul, 1, RF_SHAREABLE);
+ ppc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &ppc->rid_drq,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ }
- ppc->ppc_mode = PPB_COMPATIBLE;
- ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
+ if (ppc->res_irq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_IRQ, &ppc->ppc_irq);
+ if (ppc->res_drq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_DRQ, &ppc->ppc_dmachan);
- /*
- * XXX Try and detect if interrupts are working
- */
- if (!(dvp->id_flags & 0x20) && dvp->id_irq)
- ppc->ppc_irq = ffs(dvp->id_irq) - 1;
+ ppc->ppc_unit = device_get_unit(dev);
+ ppc->ppc_model = GENERIC;
- ppc->ppc_dmachan = dvp->id_drq;
+ ppc->ppc_mode = PPB_COMPATIBLE;
+ ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;
- ppcdata[ppc->ppc_unit] = ppc;
- nppc ++;
-
- /*
- * Link the Parallel Port Chipset (adapter) to
- * the future ppbus. Default to a generic chipset
- */
- ppc->ppc_link.adapter_unit = ppc->ppc_unit;
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
/*
* Try to detect the chipset and its mode.
*/
- if (ppc_detect(ppc, dvp->id_flags & 0xf))
+ if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
goto error;
- return (IO_LPTSIZE);
+ return (0);
error:
- return (0);
+ if (ppc->res_irq != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
+ ppc->res_irq);
+ }
+ if (ppc->res_ioport != 0) {
+ bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ }
+ if (ppc->res_drq != 0) {
+ bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ }
+ return (ENXIO);
}
static int
-ppcattach(struct isa_device *isdp)
+ppc_attach(device_t dev)
{
- struct ppc_data *ppc = ppcdata[isdp->id_unit];
- struct ppb_data *ppbus;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
- ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
- ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
- ppc_epp_protocol[ppc->ppc_epp] : "");
+ device_t ppbus;
+ device_t parent = device_get_parent(dev);
+ device_printf(dev, "%s chipset (%s) in %s mode%s\n",
+ ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm],
+ ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
+ ppc_epp_protocol[ppc->ppc_epp] : "");
+
if (ppc->ppc_fifo)
- printf("ppc%d: FIFO with %d/%d/%d bytes threshold\n",
- ppc->ppc_unit, ppc->ppc_fifo, ppc->ppc_wthr,
- ppc->ppc_rthr);
+ device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
+ ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);
- isdp->id_ointr = ppcintr;
+ 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);
/*
- * Prepare ppbus data area for upper level code.
+ * Probe the ppbus and attach devices found.
*/
- ppbus = ppb_alloc_bus();
+ device_probe_and_attach(ppbus);
- if (!ppbus)
- return (0);
+ /* register the ppc interrupt handler as default */
+ if (ppc->res_irq) {
+ /* default to the tty mask for registration */ /* XXX */
+ if (BUS_SETUP_INTR(parent, dev, ppc->res_irq, INTR_TYPE_TTY,
+ ppcintr, dev, &ppc->intr_cookie) == 0) {
- ppc->ppc_link.ppbus = ppbus;
- ppbus->ppb_link = &ppc->ppc_link;
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+ }
- if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) {
+ return (0);
+}
- /* acquire the DMA channel forever */
- isa_dma_acquire(ppc->ppc_dmachan);
- isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */
+static u_char
+ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
+ switch (iop) {
+ case PPB_OUTSB_EPP:
+ outsb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSW_EPP:
+ outsw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSL_EPP:
+ outsl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSB_EPP:
+ insb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSW_EPP:
+ insw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSL_EPP:
+ insl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_RDTR:
+ return (r_dtr(ppc));
+ break;
+ case PPB_RSTR:
+ return (r_str(ppc));
+ break;
+ case PPB_RCTR:
+ return (r_ctr(ppc));
+ break;
+ case PPB_REPP_A:
+ return (r_epp_A(ppc));
+ break;
+ case PPB_REPP_D:
+ return (r_epp_D(ppc));
+ break;
+ case PPB_RECR:
+ return (r_ecr(ppc));
+ break;
+ case PPB_RFIFO:
+ return (r_fifo(ppc));
+ break;
+ case PPB_WDTR:
+ w_dtr(ppc, byte);
+ break;
+ case PPB_WSTR:
+ w_str(ppc, byte);
+ break;
+ case PPB_WCTR:
+ w_ctr(ppc, byte);
+ break;
+ case PPB_WEPP_A:
+ w_epp_A(ppc, byte);
+ break;
+ case PPB_WEPP_D:
+ w_epp_D(ppc, byte);
+ break;
+ case PPB_WECR:
+ w_ecr(ppc, byte);
+ break;
+ case PPB_WFIFO:
+ w_fifo(ppc, byte);
+ break;
+ default:
+ panic("%s: unknown I/O operation", __FUNCTION__);
+ break;
}
- /*
- * Probe the ppbus and attach devices found.
- */
- ppb_attachdevs(ppbus);
+ return (0); /* not significative */
+}
- return (1);
+static int
+ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
+{
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus);
+
+ switch (index) {
+ case PPC_IVAR_EPP_PROTO:
+ *val = (u_long)ppc->ppc_epp;
+ break;
+ case PPC_IVAR_IRQ:
+ BUS_READ_IVAR(device_get_parent(bus), bus, ISA_IVAR_IRQ, val);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+/*
+ * Resource is useless here since ppbus devices' interrupt handlers are
+ * multiplexed to the same resource initially allocated by ppc
+ */
+static int
+ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
+ void (*ihand)(void *), void *arg, void **cookiep)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+
+ if (ppc->ppc_registered) {
+ /* XXX refuse registration if DMA is in progress */
+
+ /* first, unregister the default interrupt handler */
+ if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus),
+ bus, ppc->res_irq, ppc->intr_cookie)))
+ return (error);
+
+/* bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */
+/* ppc->res_irq); */
+
+ /* DMA/FIFO operation won't be possible anymore */
+ ppc->ppc_registered = 0;
+ }
+
+ /* pass registration to the upper layer, ignore the incoming resource */
+ return (BUS_SETUP_INTR(device_get_parent(bus), child,
+ r, flags, ihand, arg, cookiep));
+}
+
+/*
+ * When no underlying device has a registered interrupt, register the ppc
+ * layer one
+ */
+static int
+ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+ device_t parent = device_get_parent(bus);
+
+ /* pass unregistration to the upper layer */
+ if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih)))
+ return (error);
+
+ /* default to the tty mask for registration */ /* XXX */
+ if (ppc->ppc_irq &&
+ !(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq,
+ INTR_TYPE_TTY, ppcintr, bus, &ppc->intr_cookie))) {
+
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+
+ return (error);
}
+
+DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0);
#endif
diff --git a/sys/dev/ppc/ppcreg.h b/sys/dev/ppc/ppcreg.h
index faecb97..ec17806 100644
--- a/sys/dev/ppc/ppcreg.h
+++ b/sys/dev/ppc/ppcreg.h
@@ -45,12 +45,19 @@
#define NS_PC87334 10
/*
+ * Parallel Port Chipset Type. SMC versus GENERIC (others)
+ */
+#define PPC_TYPE_SMCLIKE 0
+#define PPC_TYPE_GENERIC 1
+
+/*
* Generic structure to hold parallel port chipset info.
*/
struct ppc_data {
int ppc_unit;
- int ppc_type;
+ int ppc_model; /* chipset model if detected */
+ int ppc_type; /* generic or smclike chipset type */
int ppc_mode; /* chipset current mode */
int ppc_avm; /* chipset available modes */
@@ -83,16 +90,22 @@ struct ppc_data {
short ppc_wthr; /* writeIntrThresold */
short ppc_rthr; /* readIntrThresold */
-#define ppc_base ppc_link.base
-#define ppc_epp ppc_link.epp_protocol
-#define ppc_irq ppc_link.id_irq
-#define ppc_subm ppc_link.submicroseq
-#define ppc_ptr ppc_link.ptr
-#define ppc_accum ppc_link.accum
+ char *ppc_ptr; /* microseq current pointer */
+ int ppc_accum; /* microseq accumulator */
+ int ppc_base; /* parallel port base address */
+ int ppc_epp; /* EPP mode (1.7 or 1.9) */
+ int ppc_irq;
unsigned char ppc_flags;
- struct ppb_link ppc_link;
+ device_t ppbus; /* parallel port chipset corresponding ppbus */
+
+ int rid_irq, rid_drq, rid_ioport;
+ struct resource *res_irq, *res_drq, *res_ioport;
+
+ void *intr_cookie;
+
+ int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
};
/*
diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT
index a651ccb..3a284bd 100644
--- a/sys/i386/conf/LINT
+++ b/sys/i386/conf/LINT
@@ -2131,6 +2131,8 @@ pseudo-device "i4bisppp" 4
# ppc ISA-bus parallel port interfaces.
#
+options PPC_PROBE_CHIPSET # Enable chipset specific detection
+ # (see flags in ppc(4))
options DEBUG_1284 # IEEE1284 signaling protocol debug
options PERIPH_1284 # Makes your computer act as a IEEE1284
# compliant peripheral
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index a651ccb..3a284bd 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -2131,6 +2131,8 @@ pseudo-device "i4bisppp" 4
# ppc ISA-bus parallel port interfaces.
#
+options PPC_PROBE_CHIPSET # Enable chipset specific detection
+ # (see flags in ppc(4))
options DEBUG_1284 # IEEE1284 signaling protocol debug
options PERIPH_1284 # Makes your computer act as a IEEE1284
# compliant peripheral
diff --git a/sys/i386/isa/isa_compat.h b/sys/i386/isa/isa_compat.h
index c504b52..98bf519 100644
--- a/sys/i386/isa/isa_compat.h
+++ b/sys/i386/isa/isa_compat.h
@@ -77,9 +77,7 @@
#include "stl.h"
#include "stli.h"
#include "loran.h"
-#include "pcf.h"
#include "tina.h"
-#include "ppc.h"
#include "fla.h"
struct old_isa_driver {
@@ -138,9 +136,7 @@ extern struct isa_driver ascdriver;
extern struct isa_driver stldriver;
extern struct isa_driver stlidriver;
extern struct isa_driver lorandriver;
-extern struct isa_driver pcfdriver;
extern struct isa_driver tinadriver;
-extern struct isa_driver ppcdriver;
static struct old_isa_driver old_drivers[] = {
@@ -212,9 +208,6 @@ static struct old_isa_driver old_drivers[] = {
#if NLORAN > 0
{ INTR_TYPE_TTY, &lorandriver },
#endif
-#if NPPC > 0
- { INTR_TYPE_TTY, &ppcdriver },
-#endif
/* BIO */
@@ -263,9 +256,6 @@ static struct old_isa_driver old_drivers[] = {
#if NWL > 0
{ INTR_TYPE_NET, &wldriver },
#endif
-#if NPCF > 0
- { INTR_TYPE_NET, &pcfdriver },
-#endif
#if NTINA > 0
{ INTR_TYPE_NET, &tinadriver },
#endif
diff --git a/sys/i386/isa/pcf.c b/sys/i386/isa/pcf.c
index 1aeb7e6..e37823e 100644
--- a/sys/i386/isa/pcf.c
+++ b/sys/i386/isa/pcf.c
@@ -34,12 +34,20 @@
#include <sys/malloc.h>
#include <machine/clock.h>
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <isa/isareg.h>
+#include <isa/isavar.h>
#include <i386/isa/isa_device.h>
#include <dev/iicbus/iiconf.h>
#include "iicbus_if.h"
+#define IO_PCFSIZE 2
+
#define TIMEOUT 9999 /* XXX */
/* Status bits of S1 register (read only) */
@@ -71,37 +79,23 @@
struct pcf_softc {
int pcf_base; /* isa port */
+ int pcf_flags;
u_char pcf_addr; /* interface I2C address */
int pcf_slave_mode; /* receiver or transmitter */
int pcf_started; /* 1 if start condition sent */
device_t iicbus; /* the corresponding iicbus */
-};
-
-struct pcf_isa_softc {
-
- int pcf_unit; /* unit of the isa device */
- int pcf_base; /* isa port */
- int pcf_irq; /* isa irq or null if polled */
-
- unsigned int pcf_flags; /* boot flags */
-};
-
-#define MAXPCF 2
-
-static struct pcf_isa_softc *pcfdata[MAXPCF];
-static int npcf = 0;
-
-static int pcfprobe_isa(struct isa_device *);
-static int pcfattach_isa(struct isa_device *);
-struct isa_driver pcfdriver = {
- pcfprobe_isa, pcfattach_isa, "pcf"
+ int rid_irq, rid_ioport;
+ struct resource *res_irq, *res_ioport;
+ void *intr_cookie;
};
static int pcf_probe(device_t);
static int pcf_attach(device_t);
+static void pcfintr(void *arg);
+
static int pcf_print_child(device_t, device_t);
static int pcf_repeated_start(device_t, u_char, int);
@@ -109,7 +103,6 @@ static int pcf_start(device_t, u_char, int);
static int pcf_stop(device_t);
static int pcf_write(device_t, char *, int, int *, int);
static int pcf_read(device_t, char *, int, int *, int, int);
-static ointhand2_t pcfintr;
static int pcf_rst_card(device_t, u_char, u_char, u_char *);
static device_method_t pcf_methods[] = {
@@ -143,72 +136,68 @@ static devclass_t pcf_devclass;
#define DEVTOSOFTC(dev) ((struct pcf_softc *)device_get_softc(dev))
static int
-pcfprobe_isa(struct isa_device *dvp)
+pcf_probe(device_t pcfdev)
{
- device_t pcfdev;
- struct pcf_isa_softc *pcf;
-
- if (npcf >= MAXPCF)
- return (0);
-
- if ((pcf = (struct pcf_isa_softc *)malloc(sizeof(struct pcf_isa_softc),
- M_DEVBUF, M_NOWAIT)) == NULL)
- return (0);
-
- pcf->pcf_base = dvp->id_iobase; /* XXX should be ivars */
- pcf->pcf_unit = dvp->id_unit;
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
+ device_t parent = device_get_parent(pcfdev);
- if (!(dvp->id_flags & IIC_POLLED))
- pcf->pcf_irq = (dvp->id_irq);
+ device_set_desc(pcfdev, "PCF8584 I2C bus controller");
- pcfdata[npcf++] = pcf;
+ pcf = DEVTOSOFTC(pcfdev);
+ bzero(pcf, sizeof(struct pcf_softc));
- /* XXX add the pcf device to the root_bus until isa bus exists */
- pcfdev = device_add_child(root_bus, "pcf", pcf->pcf_unit);
+ pcf->rid_irq = pcf->rid_ioport = 0;
+ pcf->res_irq = pcf->res_ioport = 0;
- if (!pcfdev)
+ /* IO port is mandatory */
+ pcf->res_ioport = bus_alloc_resource(pcfdev, SYS_RES_IOPORT,
+ &pcf->rid_ioport, 0ul, ~0ul,
+ IO_PCFSIZE, RF_ACTIVE);
+ if (pcf->res_ioport == 0) {
+ device_printf(pcfdev, "cannot reserve I/O port range\n");
goto error;
+ }
+ BUS_READ_IVAR(parent, pcfdev, ISA_IVAR_PORT, &pcf->pcf_base);
- return (1);
-
-error:
- free(pcf, M_DEVBUF);
- return (0);
-}
-
-static int
-pcfattach_isa(struct isa_device *isdp)
-{
- isdp->id_ointr = pcfintr;
- return (1); /* ok */
-}
+ pcf->pcf_flags = device_get_flags(pcfdev);
-static int
-pcf_probe(device_t pcfdev)
-{
- struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
- int unit = device_get_unit(pcfdev);
-
- /* retrieve base address from isa initialization
- *
- * XXX should use ivars with isabus
- */
- pcf->pcf_base = pcfdata[unit]->pcf_base;
+ if (!(pcf->pcf_flags & IIC_POLLED)) {
+ pcf->res_irq = bus_alloc_resource(pcfdev, SYS_RES_IRQ, &pcf->rid_irq,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if (pcf->res_irq == 0) {
+ device_printf(pcfdev, "can't reserve irq, polled mode.\n");
+ pcf->pcf_flags |= IIC_POLLED;
+ }
+ }
/* reset the chip */
pcf_rst_card(pcfdev, IIC_FASTEST, PCF_DEFAULT_ADDR, NULL);
- /* XXX try do detect chipset */
-
- device_set_desc(pcfdev, "PCF8584 I2C bus controller");
-
return (0);
+error:
+ if (pcf->res_ioport != 0) {
+ bus_deactivate_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
+ pcf->res_ioport);
+ bus_release_resource(pcfdev, SYS_RES_IOPORT, pcf->rid_ioport,
+ pcf->res_ioport);
+ }
+ return (ENXIO);
}
static int
pcf_attach(device_t pcfdev)
{
- struct pcf_softc *pcf = (struct pcf_softc *)device_get_softc(pcfdev);
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
+ device_t parent = device_get_parent(pcfdev);
+ int error = 0;
+
+ if (pcf->res_irq) {
+ /* default to the tty mask for registration */ /* XXX */
+ error = BUS_SETUP_INTR(parent, pcfdev, pcf->res_irq, INTR_TYPE_NET,
+ pcfintr, pcfdev, &pcf->intr_cookie);
+ if (error)
+ return (error);
+ }
pcf->iicbus = iicbus_alloc_bus(pcfdev);
@@ -392,10 +381,10 @@ error:
}
static void
-pcfintr(unit)
+pcfintr(void *arg)
{
- struct pcf_softc *pcf =
- (struct pcf_softc *)devclass_get_softc(pcf_devclass, unit);
+ device_t pcfdev = (device_t)arg;
+ struct pcf_softc *pcf = DEVTOSOFTC(pcfdev);
char data, status, addr;
char error = 0;
@@ -403,14 +392,13 @@ pcfintr(unit)
status = PCF_GET_S1(pcf);
if (status & PIN) {
- printf("pcf%d: spurious interrupt, status=0x%x\n", unit,
- status & 0xff);
+ device_printf(pcfdev, "spurious interrupt, status=0x%x\n", status & 0xff);
goto error;
}
if (status & LAB)
- printf("pcf%d: bus arbitration lost!\n", unit);
+ device_printf(pcfdev, "bus arbitration lost!\n");
if (status & BER) {
error = IIC_EBUSERR;
@@ -643,4 +631,4 @@ error:
return (error);
}
-DRIVER_MODULE(pcf, root, pcf_driver, pcf_devclass, 0, 0);
+DRIVER_MODULE(pcf, isa, pcf_driver, pcf_devclass, 0, 0);
diff --git a/sys/i386/isa/ppc.c b/sys/i386/isa/ppc.c
index 436caeb..0ee1eb6 100644
--- a/sys/i386/isa/ppc.c
+++ b/sys/i386/isa/ppc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997-2000 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,42 +30,90 @@
#if NPPC > 0
+#include "opt_ppc.h"
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
#include <vm/vm.h>
-#include <vm/vm_param.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 <i386/isa/isa_device.h>
-#include <i386/isa/isa.h>
+#include <isa/isareg.h>
+#include <isa/isavar.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <i386/isa/ppcreg.h>
-#include "opt_ppc.h"
+#include "ppbus_if.h"
#define LOG_PPC(function, ppc, string) \
if (bootverbose) printf("%s: %s\n", function, string)
-static int ppcprobe(struct isa_device *);
-static int ppcattach(struct isa_device *);
-struct isa_driver ppcdriver = {
- ppcprobe, ppcattach, "ppc"
+#define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev))
+
+devclass_t ppc_devclass;
+
+static int ppc_probe(device_t dev);
+static int ppc_attach(device_t dev);
+static int ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val);
+
+static void ppc_reset_epp(device_t);
+static void ppc_ecp_sync(device_t);
+static void ppcintr(void *arg);
+
+static int ppc_exec_microseq(device_t, struct ppb_microseq **);
+static int ppc_setmode(device_t, int);
+
+static int ppc_read(device_t, char *, int, int);
+static int ppc_write(device_t, char *, int, int);
+
+static u_char ppc_io(device_t, int, u_char *, int, u_char);
+
+static int ppc_setup_intr(device_t, device_t, struct resource *, int,
+ void (*)(void *), void *, void **);
+static int ppc_teardown_intr(device_t, device_t, struct resource *, void *);
+
+static device_method_t ppc_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppc_probe),
+ DEVMETHOD(device_attach, ppc_attach),
+
+ /* 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),
};
-
-static struct ppc_data *ppcdata[NPPC];
-static int nppc = 0;
-
-static char *ppc_types[] = {
+
+static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
};
@@ -98,91 +146,13 @@ static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
#define BIOS_MAX_PPC 4
/*
- * All these functions are default actions for IN/OUT operations.
- * They may be redefined if needed.
- */
-static void ppc_outsb_epp(int unit, char *addr, int cnt) {
- outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsw_epp(int unit, char *addr, int cnt) {
- outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsl_epp(int unit, char *addr, int cnt) {
- outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insb_epp(int unit, char *addr, int cnt) {
- insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insw_epp(int unit, char *addr, int cnt) {
- insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insl_epp(int unit, char *addr, int cnt) {
- insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-
-static u_char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); }
-static u_char ppc_rstr(int unit) { return r_str(ppcdata[unit]); }
-static u_char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); }
-static u_char ppc_repp_A(int unit) { return r_epp_A(ppcdata[unit]); }
-static u_char ppc_repp_D(int unit) { return r_epp_D(ppcdata[unit]); }
-static u_char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); }
-static u_char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); }
-
-static void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); }
-static void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); }
-static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
-static void ppc_wepp_A(int unit, char byte) { w_epp_A(ppcdata[unit], byte); }
-static void ppc_wepp_D(int unit, char byte) { w_epp_D(ppcdata[unit], byte); }
-static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
-static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
-
-static void ppc_reset_epp_timeout(int);
-static void ppc_ecp_sync(int);
-static ointhand2_t ppcintr;
-
-static int ppc_exec_microseq(int, struct ppb_microseq **);
-static int ppc_generic_setmode(int, int);
-static int ppc_smclike_setmode(int, int);
-
-static int ppc_read(int, char *, int, int);
-static int ppc_write(int, char *, int, int);
-
-static struct ppb_adapter ppc_smclike_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_smclike_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-static struct ppb_adapter ppc_generic_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_generic_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-/*
* ppc_ecp_sync() XXX
*/
static void
-ppc_ecp_sync(int unit) {
+ppc_ecp_sync(device_t dev) {
- struct ppc_data *ppc = ppcdata[unit];
int i, r;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
if (!(ppc->ppc_avm & PPB_ECP))
return;
@@ -199,7 +169,7 @@ ppc_ecp_sync(int unit) {
}
printf("ppc%d: ECP sync failed as data still " \
- "present in FIFO.\n", unit);
+ "present in FIFO.\n", ppc->ppc_unit);
return;
}
@@ -328,6 +298,121 @@ ppc_detect_port(struct ppc_data *ppc)
}
/*
+ * EPP timeout, according to the PC87332 manual
+ * Semantics of clearing EPP timeout bit.
+ * PC87332 - reading SPP_STR does it...
+ * SMC - write 1 to EPP timeout bit XXX
+ * Others - (?) write 0 to EPP timeout bit
+ */
+static void
+ppc_reset_epp_timeout(struct ppc_data *ppc)
+{
+ register char r;
+
+ r = r_str(ppc);
+ w_str(ppc, r | 0x1);
+ w_str(ppc, r & 0xfe);
+
+ return;
+}
+
+static int
+ppc_check_epp_timeout(struct ppc_data *ppc)
+{
+ ppc_reset_epp_timeout(ppc);
+
+ return (!(r_str(ppc) & TIMEOUT));
+}
+
+/*
+ * Configure current operating mode
+ */
+static int
+ppc_generic_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ return (EINVAL);
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+/*
+ * The ppc driver is free to choose options like FIFO or DMA
+ * if ECP mode is available.
+ *
+ * The 'RAW' option allows the upper drivers to force the ppc mode
+ * even with FIFO, DMA available.
+ */
+static int
+ppc_smclike_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP or EPP mode
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ /* select EPP mode */
+ ecr |= PPC_ECR_EPP;
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+#ifdef PPC_PROBE_CHIPSET
+/*
* ppc_pc873xx_detect
*
* Probe for a Natsemi PC873xx-family part.
@@ -381,11 +466,11 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
outb(idport, PC873_SID);
val = inb(idport + 1);
if ((val & 0xf0) == 0x10) {
- ppc->ppc_type = NS_PC87332;
+ ppc->ppc_model = NS_PC87332;
} else if ((val & 0xf8) == 0x70) {
- ppc->ppc_type = NS_PC87306;
+ ppc->ppc_model = NS_PC87306;
} else if ((val & 0xf8) == 0x50) {
- ppc->ppc_type = NS_PC87334;
+ ppc->ppc_model = NS_PC87334;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
@@ -484,7 +569,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
else
ppc->ppc_epp = EPP_1_7;
- if ((ppc->ppc_type == NS_PC87332) && bootverbose) {
+ if ((ppc->ppc_model == NS_PC87332) && bootverbose) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
if (ptr & PC873_EPPRDIR)
@@ -539,7 +624,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
printf(", EPP1.9");
/* enable automatic direction turnover */
- if (ppc->ppc_type == NS_PC87332) {
+ if (ppc->ppc_model == NS_PC87332) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
ptr &= ~PC873_EPPRDIR;
@@ -581,22 +666,14 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter = &ppc_generic_adapter;
- ppc_generic_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_GENERIC;
+ ppc_generic_setmode(ppc, chipset_mode);
return(chipset_mode);
}
return(-1);
}
-static int
-ppc_check_epp_timeout(struct ppc_data *ppc)
-{
- ppc_reset_epp_timeout(ppc->ppc_unit);
-
- return (!(r_str(ppc) & TIMEOUT));
-}
-
/*
* ppc_smc37c66xgt_detect
*
@@ -661,7 +738,7 @@ config:
if (port_address[(int)r] != ppc->ppc_base)
return (-1);
- ppc->ppc_type = type;
+ ppc->ppc_model = type;
/*
* CR1 and CR4 registers bits 3 and 0/1 for mode configuration
@@ -800,8 +877,8 @@ end_detect:
/* end config mode */
outb(csr, 0xaa);
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
- ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
+ ppc_smclike_setmode(ppc, chipset_mode);
return (chipset_mode);
}
@@ -866,15 +943,15 @@ found:
switch (inb(efdr) & WINB_CHIPID) {
case WINB_W83877F_ID:
- ppc->ppc_type = WINB_W83877F;
+ ppc->ppc_model = WINB_W83877F;
break;
case WINB_W83877AF_ID:
- ppc->ppc_type = WINB_W83877AF;
+ ppc->ppc_model = WINB_W83877AF;
break;
default:
- ppc->ppc_type = WINB_UNKNOWN;
+ ppc->ppc_model = WINB_UNKNOWN;
}
if (bootverbose) {
@@ -898,7 +975,7 @@ found:
printf("ppc%d:", ppc->ppc_unit);
}
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (!chipset_mode) {
/* autodetect mode */
@@ -940,7 +1017,7 @@ found:
case (WINB_PARALLEL | WINB_ECP_EPP):
ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP SPP");
@@ -966,7 +1043,7 @@ found:
if (bootverbose)
printf(" ECP+EPP");
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
} else {
outb(efdr, inb(efdr) | WINB_ECP);
@@ -988,10 +1065,18 @@ found:
/* exit configuration mode */
outb(efer, 0xaa);
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
+#endif
/*
* ppc_generic_detect
@@ -1000,7 +1085,7 @@ static int
ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
{
/* default to generic */
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (bootverbose)
printf("ppc%d:", ppc->ppc_unit);
@@ -1023,8 +1108,8 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (ppc->ppc_avm & PPB_ECP) {
/* SMC like chipset found */
- ppc->ppc_type = SMC_LIKE;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_model = SMC_LIKE;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
@@ -1050,7 +1135,14 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
@@ -1063,6 +1155,7 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
static int
ppc_detect(struct ppc_data *ppc, int chipset_mode) {
+#ifdef PPC_PROBE_CHIPSET
int i, mode;
/* list of supported chipsets */
@@ -1073,6 +1166,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
ppc_generic_detect,
NULL
};
+#endif
/* if can't find the port and mode not forced return error */
if (!ppc_detect_port(ppc) && chipset_mode == 0)
@@ -1081,6 +1175,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
/* assume centronics compatible mode is supported */
ppc->ppc_avm = PPB_COMPATIBLE;
+#ifdef PPC_PROBE_CHIPSET
/* we have to differenciate available chipset modes,
* chipset running modes and IEEE-1284 operating modes
*
@@ -1089,9 +1184,11 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
if (ppc->ppc_flags & 0x40) {
if (bootverbose)
printf("ppc: chipset forced to generic\n");
+#endif
ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
+#ifdef PPC_PROBE_CHIPSET
} else {
for (i=0; chipset_detect[i] != NULL; i++) {
if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
@@ -1100,6 +1197,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
}
}
}
+#endif
/* configure/detect ECP FIFO */
if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80))
@@ -1115,9 +1213,9 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
* Microsequence mechanism is supposed to handle fast I/O operations.
*/
static int
-ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
+ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
struct ppb_microseq *mi;
char cc, *p;
int i, iter, len;
@@ -1326,9 +1424,10 @@ ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
}
static void
-ppcintr(int unit)
+ppcintr(void *arg)
{
- struct ppc_data *ppc = ppcdata[unit];
+ device_t dev = (device_t)arg;
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(dev);
u_char ctr, ecr, str;
str = r_str(ppc);
@@ -1341,8 +1440,6 @@ ppcintr(int unit)
/* don't use ecp mode with IRQENABLE set */
if (ctr & IRQENABLE) {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
return;
}
@@ -1356,8 +1453,7 @@ ppcintr(int unit)
w_ecr(ppc, ecr | PPC_nFAULT_INTR);
ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT;
} else {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
+ /* shall be handled by underlying layers XXX */
return;
}
}
@@ -1397,14 +1493,13 @@ ppcintr(int unit)
/* classic interrupt I/O */
ppc->ppc_irqstat &= ~PPC_IRQ_FIFO;
-
}
return;
}
static int
-ppc_read(int unit, char *buf, int len, int mode)
+ppc_read(device_t dev, char *buf, int len, int mode)
{
return (EINVAL);
}
@@ -1417,9 +1512,9 @@ ppc_read(int unit, char *buf, int len, int mode)
* EINVAL is returned
*/
static int
-ppc_write(int unit, char *buf, int len, int how)
+ppc_write(device_t dev, char *buf, int len, int how)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
char ecr, ecr_sav, ctr, ctr_sav;
int s, error = 0;
int spin;
@@ -1434,7 +1529,7 @@ ppc_write(int unit, char *buf, int len, int how)
/*
* Send buffer with DMA, FIFO and interrupts
*/
- if (ppc->ppc_avm & PPB_ECP) {
+ if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
if (ppc->ppc_dmachan >= 0) {
@@ -1568,231 +1663,334 @@ error:
return (error);
}
-/*
- * Configure current operating mode
- */
-static int
-ppc_generic_setmode(int unit, int mode)
+static void
+ppc_reset_epp(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
+
+ ppc_reset_epp_timeout(ppc);
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
+ return;
+}
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+static int
+ppc_setmode(device_t dev, int mode)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- if (mode & PPB_EPP)
- return (EINVAL);
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ return (ppc_smclike_setmode(ppc, mode));
+ break;
- w_ecr(ppc, ecr);
+ case PPC_TYPE_GENERIC:
+ default:
+ return (ppc_generic_setmode(ppc, mode));
+ break;
}
- ppc->ppc_mode = mode;
-
- return (0);
+ /* not reached */
+ return (ENXIO);
}
-/*
- * The ppc driver is free to choose options like FIFO or DMA
- * if ECP mode is available.
- *
- * The 'RAW' option allows the upper drivers to force the ppc mode
- * even with FIFO, DMA available.
- */
-int
-ppc_smclike_setmode(int unit, int mode)
+static int
+ppc_probe(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
-
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
-
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP or EPP mode
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+ static short next_bios_ppc = 0;
+ struct ppc_data *ppc;
+ device_t parent;
+ int port;
- if (mode & PPB_EPP)
- /* select EPP mode */
- ecr |= PPC_ECR_EPP;
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ device_set_desc(dev, "Parallel port");
- w_ecr(ppc, ecr);
- }
+ /* XXX shall be connected to pnpbios - from Peter Wemm */
+ if (isa_get_logicalid(dev))
+ return ENXIO;
- ppc->ppc_mode = mode;
+ parent = device_get_parent(dev);
- return (0);
-}
-
-/*
- * EPP timeout, according to the PC87332 manual
- * Semantics of clearing EPP timeout bit.
- * PC87332 - reading SPP_STR does it...
- * SMC - write 1 to EPP timeout bit XXX
- * Others - (?) write 0 to EPP timeout bit
- */
-static void
-ppc_reset_epp_timeout(int unit)
-{
- struct ppc_data *ppc = ppcdata[unit];
- register char r;
+ /*
+ * Allocate the ppc_data structure.
+ */
+ ppc = DEVTOSOFTC(dev);
+ bzero(ppc, sizeof(struct ppc_data));
- r = r_str(ppc);
- w_str(ppc, r | 0x1);
- w_str(ppc, r & 0xfe);
+ ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0;
+ ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0;
- return;
-}
-
-static int
-ppcprobe(struct isa_device *dvp)
-{
- static short next_bios_ppc = 0;
- struct ppc_data *ppc;
+ /* retrieve ISA parameters */
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_PORT, &port);
/*
* If port not specified, use bios list.
*/
- if(dvp->id_iobase < 0) {
+ if (port < 0) {
if((next_bios_ppc < BIOS_MAX_PPC) &&
(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
- dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
+ port = *(BIOS_PORTS+next_bios_ppc++);
if (bootverbose)
- printf("ppc: parallel port found at 0x%x\n",
- dvp->id_iobase);
- } else
- return (0);
+ device_printf(dev, "parallel port found at 0x%x\n",
+ port);
+ } else {
+ device_printf(dev, "parallel port not found.\n");
+ return ENXIO;
+ }
}
-
- /*
- * Port was explicitly specified.
- * This allows probing of ports unknown to the BIOS.
- */
-
- /*
- * Allocate the ppc_data structure.
- */
- ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
- if (!ppc) {
- printf("ppc: cannot malloc!\n");
+ ppc->ppc_base = port;
+
+ /* IO port is mandatory */
+ ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &ppc->rid_ioport, port, port,
+ IO_LPTSIZE, RF_ACTIVE);
+ if (ppc->res_ioport == 0) {
+ device_printf(dev, "cannot reserve I/O port range\n");
goto error;
}
- bzero(ppc, sizeof(struct ppc_data));
- ppc->ppc_base = dvp->id_iobase;
- ppc->ppc_unit = dvp->id_unit;
- ppc->ppc_type = GENERIC;
+ ppc->ppc_flags = device_get_flags(dev);
- /* store boot flags */
- ppc->ppc_flags = dvp->id_flags;
+ if (!(ppc->ppc_flags & 0x20)) {
+ ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq,
+ 0ul, ~0ul, 1, RF_SHAREABLE);
+ ppc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &ppc->rid_drq,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ }
- ppc->ppc_mode = PPB_COMPATIBLE;
- ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
+ if (ppc->res_irq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_IRQ, &ppc->ppc_irq);
+ if (ppc->res_drq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_DRQ, &ppc->ppc_dmachan);
- /*
- * XXX Try and detect if interrupts are working
- */
- if (!(dvp->id_flags & 0x20) && dvp->id_irq)
- ppc->ppc_irq = ffs(dvp->id_irq) - 1;
+ ppc->ppc_unit = device_get_unit(dev);
+ ppc->ppc_model = GENERIC;
- ppc->ppc_dmachan = dvp->id_drq;
+ ppc->ppc_mode = PPB_COMPATIBLE;
+ ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;
- ppcdata[ppc->ppc_unit] = ppc;
- nppc ++;
-
- /*
- * Link the Parallel Port Chipset (adapter) to
- * the future ppbus. Default to a generic chipset
- */
- ppc->ppc_link.adapter_unit = ppc->ppc_unit;
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
/*
* Try to detect the chipset and its mode.
*/
- if (ppc_detect(ppc, dvp->id_flags & 0xf))
+ if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
goto error;
- return (IO_LPTSIZE);
+ return (0);
error:
- return (0);
+ if (ppc->res_irq != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
+ ppc->res_irq);
+ }
+ if (ppc->res_ioport != 0) {
+ bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ }
+ if (ppc->res_drq != 0) {
+ bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ }
+ return (ENXIO);
}
static int
-ppcattach(struct isa_device *isdp)
+ppc_attach(device_t dev)
{
- struct ppc_data *ppc = ppcdata[isdp->id_unit];
- struct ppb_data *ppbus;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
- ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
- ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
- ppc_epp_protocol[ppc->ppc_epp] : "");
+ device_t ppbus;
+ device_t parent = device_get_parent(dev);
+ device_printf(dev, "%s chipset (%s) in %s mode%s\n",
+ ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm],
+ ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
+ ppc_epp_protocol[ppc->ppc_epp] : "");
+
if (ppc->ppc_fifo)
- printf("ppc%d: FIFO with %d/%d/%d bytes threshold\n",
- ppc->ppc_unit, ppc->ppc_fifo, ppc->ppc_wthr,
- ppc->ppc_rthr);
+ device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
+ ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);
- isdp->id_ointr = ppcintr;
+ 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);
/*
- * Prepare ppbus data area for upper level code.
+ * Probe the ppbus and attach devices found.
*/
- ppbus = ppb_alloc_bus();
+ device_probe_and_attach(ppbus);
- if (!ppbus)
- return (0);
+ /* register the ppc interrupt handler as default */
+ if (ppc->res_irq) {
+ /* default to the tty mask for registration */ /* XXX */
+ if (BUS_SETUP_INTR(parent, dev, ppc->res_irq, INTR_TYPE_TTY,
+ ppcintr, dev, &ppc->intr_cookie) == 0) {
- ppc->ppc_link.ppbus = ppbus;
- ppbus->ppb_link = &ppc->ppc_link;
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+ }
- if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) {
+ return (0);
+}
- /* acquire the DMA channel forever */
- isa_dma_acquire(ppc->ppc_dmachan);
- isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */
+static u_char
+ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
+ switch (iop) {
+ case PPB_OUTSB_EPP:
+ outsb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSW_EPP:
+ outsw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSL_EPP:
+ outsl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSB_EPP:
+ insb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSW_EPP:
+ insw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSL_EPP:
+ insl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_RDTR:
+ return (r_dtr(ppc));
+ break;
+ case PPB_RSTR:
+ return (r_str(ppc));
+ break;
+ case PPB_RCTR:
+ return (r_ctr(ppc));
+ break;
+ case PPB_REPP_A:
+ return (r_epp_A(ppc));
+ break;
+ case PPB_REPP_D:
+ return (r_epp_D(ppc));
+ break;
+ case PPB_RECR:
+ return (r_ecr(ppc));
+ break;
+ case PPB_RFIFO:
+ return (r_fifo(ppc));
+ break;
+ case PPB_WDTR:
+ w_dtr(ppc, byte);
+ break;
+ case PPB_WSTR:
+ w_str(ppc, byte);
+ break;
+ case PPB_WCTR:
+ w_ctr(ppc, byte);
+ break;
+ case PPB_WEPP_A:
+ w_epp_A(ppc, byte);
+ break;
+ case PPB_WEPP_D:
+ w_epp_D(ppc, byte);
+ break;
+ case PPB_WECR:
+ w_ecr(ppc, byte);
+ break;
+ case PPB_WFIFO:
+ w_fifo(ppc, byte);
+ break;
+ default:
+ panic("%s: unknown I/O operation", __FUNCTION__);
+ break;
}
- /*
- * Probe the ppbus and attach devices found.
- */
- ppb_attachdevs(ppbus);
+ return (0); /* not significative */
+}
- return (1);
+static int
+ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
+{
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus);
+
+ switch (index) {
+ case PPC_IVAR_EPP_PROTO:
+ *val = (u_long)ppc->ppc_epp;
+ break;
+ case PPC_IVAR_IRQ:
+ BUS_READ_IVAR(device_get_parent(bus), bus, ISA_IVAR_IRQ, val);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+/*
+ * Resource is useless here since ppbus devices' interrupt handlers are
+ * multiplexed to the same resource initially allocated by ppc
+ */
+static int
+ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
+ void (*ihand)(void *), void *arg, void **cookiep)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+
+ if (ppc->ppc_registered) {
+ /* XXX refuse registration if DMA is in progress */
+
+ /* first, unregister the default interrupt handler */
+ if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus),
+ bus, ppc->res_irq, ppc->intr_cookie)))
+ return (error);
+
+/* bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */
+/* ppc->res_irq); */
+
+ /* DMA/FIFO operation won't be possible anymore */
+ ppc->ppc_registered = 0;
+ }
+
+ /* pass registration to the upper layer, ignore the incoming resource */
+ return (BUS_SETUP_INTR(device_get_parent(bus), child,
+ r, flags, ihand, arg, cookiep));
+}
+
+/*
+ * When no underlying device has a registered interrupt, register the ppc
+ * layer one
+ */
+static int
+ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+ device_t parent = device_get_parent(bus);
+
+ /* pass unregistration to the upper layer */
+ if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih)))
+ return (error);
+
+ /* default to the tty mask for registration */ /* XXX */
+ if (ppc->ppc_irq &&
+ !(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq,
+ INTR_TYPE_TTY, ppcintr, bus, &ppc->intr_cookie))) {
+
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+
+ return (error);
}
+
+DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0);
#endif
diff --git a/sys/i386/isa/ppcreg.h b/sys/i386/isa/ppcreg.h
index faecb97..ec17806 100644
--- a/sys/i386/isa/ppcreg.h
+++ b/sys/i386/isa/ppcreg.h
@@ -45,12 +45,19 @@
#define NS_PC87334 10
/*
+ * Parallel Port Chipset Type. SMC versus GENERIC (others)
+ */
+#define PPC_TYPE_SMCLIKE 0
+#define PPC_TYPE_GENERIC 1
+
+/*
* Generic structure to hold parallel port chipset info.
*/
struct ppc_data {
int ppc_unit;
- int ppc_type;
+ int ppc_model; /* chipset model if detected */
+ int ppc_type; /* generic or smclike chipset type */
int ppc_mode; /* chipset current mode */
int ppc_avm; /* chipset available modes */
@@ -83,16 +90,22 @@ struct ppc_data {
short ppc_wthr; /* writeIntrThresold */
short ppc_rthr; /* readIntrThresold */
-#define ppc_base ppc_link.base
-#define ppc_epp ppc_link.epp_protocol
-#define ppc_irq ppc_link.id_irq
-#define ppc_subm ppc_link.submicroseq
-#define ppc_ptr ppc_link.ptr
-#define ppc_accum ppc_link.accum
+ char *ppc_ptr; /* microseq current pointer */
+ int ppc_accum; /* microseq accumulator */
+ int ppc_base; /* parallel port base address */
+ int ppc_epp; /* EPP mode (1.7 or 1.9) */
+ int ppc_irq;
unsigned char ppc_flags;
- struct ppb_link ppc_link;
+ device_t ppbus; /* parallel port chipset corresponding ppbus */
+
+ int rid_irq, rid_drq, rid_ioport;
+ struct resource *res_irq, *res_drq, *res_ioport;
+
+ void *intr_cookie;
+
+ int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
};
/*
diff --git a/sys/isa/ppc.c b/sys/isa/ppc.c
index 436caeb..0ee1eb6 100644
--- a/sys/isa/ppc.c
+++ b/sys/isa/ppc.c
@@ -1,5 +1,5 @@
/*-
- * Copyright (c) 1997, 1998 Nicolas Souchu
+ * Copyright (c) 1997-2000 Nicolas Souchu
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -30,42 +30,90 @@
#if NPPC > 0
+#include "opt_ppc.h"
+
#include <sys/param.h>
#include <sys/systm.h>
-#include <sys/conf.h>
-#include <sys/malloc.h>
#include <sys/kernel.h>
-
-#include <machine/clock.h>
-
+#include <sys/bus.h>
+#include <sys/malloc.h>
+
#include <vm/vm.h>
-#include <vm/vm_param.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 <i386/isa/isa_device.h>
-#include <i386/isa/isa.h>
+#include <isa/isareg.h>
+#include <isa/isavar.h>
#include <dev/ppbus/ppbconf.h>
#include <dev/ppbus/ppb_msq.h>
#include <i386/isa/ppcreg.h>
-#include "opt_ppc.h"
+#include "ppbus_if.h"
#define LOG_PPC(function, ppc, string) \
if (bootverbose) printf("%s: %s\n", function, string)
-static int ppcprobe(struct isa_device *);
-static int ppcattach(struct isa_device *);
-struct isa_driver ppcdriver = {
- ppcprobe, ppcattach, "ppc"
+#define DEVTOSOFTC(dev) ((struct ppc_data *)device_get_softc(dev))
+
+devclass_t ppc_devclass;
+
+static int ppc_probe(device_t dev);
+static int ppc_attach(device_t dev);
+static int ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val);
+
+static void ppc_reset_epp(device_t);
+static void ppc_ecp_sync(device_t);
+static void ppcintr(void *arg);
+
+static int ppc_exec_microseq(device_t, struct ppb_microseq **);
+static int ppc_setmode(device_t, int);
+
+static int ppc_read(device_t, char *, int, int);
+static int ppc_write(device_t, char *, int, int);
+
+static u_char ppc_io(device_t, int, u_char *, int, u_char);
+
+static int ppc_setup_intr(device_t, device_t, struct resource *, int,
+ void (*)(void *), void *, void **);
+static int ppc_teardown_intr(device_t, device_t, struct resource *, void *);
+
+static device_method_t ppc_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, ppc_probe),
+ DEVMETHOD(device_attach, ppc_attach),
+
+ /* 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),
};
-
-static struct ppc_data *ppcdata[NPPC];
-static int nppc = 0;
-
-static char *ppc_types[] = {
+
+static char *ppc_models[] = {
"SMC-like", "SMC FDC37C665GT", "SMC FDC37C666GT", "PC87332", "PC87306",
"82091AA", "Generic", "W83877F", "W83877AF", "Winbond", "PC87334", 0
};
@@ -98,91 +146,13 @@ static char *ppc_epp_protocol[] = { " (EPP 1.9)", " (EPP 1.7)", 0 };
#define BIOS_MAX_PPC 4
/*
- * All these functions are default actions for IN/OUT operations.
- * They may be redefined if needed.
- */
-static void ppc_outsb_epp(int unit, char *addr, int cnt) {
- outsb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsw_epp(int unit, char *addr, int cnt) {
- outsw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_outsl_epp(int unit, char *addr, int cnt) {
- outsl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insb_epp(int unit, char *addr, int cnt) {
- insb(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insw_epp(int unit, char *addr, int cnt) {
- insw(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-static void ppc_insl_epp(int unit, char *addr, int cnt) {
- insl(ppcdata[unit]->ppc_base + PPC_EPP_DATA, addr, cnt); }
-
-static u_char ppc_rdtr(int unit) { return r_dtr(ppcdata[unit]); }
-static u_char ppc_rstr(int unit) { return r_str(ppcdata[unit]); }
-static u_char ppc_rctr(int unit) { return r_ctr(ppcdata[unit]); }
-static u_char ppc_repp_A(int unit) { return r_epp_A(ppcdata[unit]); }
-static u_char ppc_repp_D(int unit) { return r_epp_D(ppcdata[unit]); }
-static u_char ppc_recr(int unit) { return r_ecr(ppcdata[unit]); }
-static u_char ppc_rfifo(int unit) { return r_fifo(ppcdata[unit]); }
-
-static void ppc_wdtr(int unit, char byte) { w_dtr(ppcdata[unit], byte); }
-static void ppc_wstr(int unit, char byte) { w_str(ppcdata[unit], byte); }
-static void ppc_wctr(int unit, char byte) { w_ctr(ppcdata[unit], byte); }
-static void ppc_wepp_A(int unit, char byte) { w_epp_A(ppcdata[unit], byte); }
-static void ppc_wepp_D(int unit, char byte) { w_epp_D(ppcdata[unit], byte); }
-static void ppc_wecr(int unit, char byte) { w_ecr(ppcdata[unit], byte); }
-static void ppc_wfifo(int unit, char byte) { w_fifo(ppcdata[unit], byte); }
-
-static void ppc_reset_epp_timeout(int);
-static void ppc_ecp_sync(int);
-static ointhand2_t ppcintr;
-
-static int ppc_exec_microseq(int, struct ppb_microseq **);
-static int ppc_generic_setmode(int, int);
-static int ppc_smclike_setmode(int, int);
-
-static int ppc_read(int, char *, int, int);
-static int ppc_write(int, char *, int, int);
-
-static struct ppb_adapter ppc_smclike_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_smclike_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-static struct ppb_adapter ppc_generic_adapter = {
-
- 0, /* no intr handler, filled by chipset dependent code */
-
- ppc_reset_epp_timeout, ppc_ecp_sync,
-
- ppc_exec_microseq,
-
- ppc_generic_setmode, ppc_read, ppc_write,
-
- ppc_outsb_epp, ppc_outsw_epp, ppc_outsl_epp,
- ppc_insb_epp, ppc_insw_epp, ppc_insl_epp,
-
- ppc_rdtr, ppc_rstr, ppc_rctr, ppc_repp_A, ppc_repp_D, ppc_recr, ppc_rfifo,
- ppc_wdtr, ppc_wstr, ppc_wctr, ppc_wepp_A, ppc_wepp_D, ppc_wecr, ppc_wfifo
-};
-
-/*
* ppc_ecp_sync() XXX
*/
static void
-ppc_ecp_sync(int unit) {
+ppc_ecp_sync(device_t dev) {
- struct ppc_data *ppc = ppcdata[unit];
int i, r;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
if (!(ppc->ppc_avm & PPB_ECP))
return;
@@ -199,7 +169,7 @@ ppc_ecp_sync(int unit) {
}
printf("ppc%d: ECP sync failed as data still " \
- "present in FIFO.\n", unit);
+ "present in FIFO.\n", ppc->ppc_unit);
return;
}
@@ -328,6 +298,121 @@ ppc_detect_port(struct ppc_data *ppc)
}
/*
+ * EPP timeout, according to the PC87332 manual
+ * Semantics of clearing EPP timeout bit.
+ * PC87332 - reading SPP_STR does it...
+ * SMC - write 1 to EPP timeout bit XXX
+ * Others - (?) write 0 to EPP timeout bit
+ */
+static void
+ppc_reset_epp_timeout(struct ppc_data *ppc)
+{
+ register char r;
+
+ r = r_str(ppc);
+ w_str(ppc, r | 0x1);
+ w_str(ppc, r & 0xfe);
+
+ return;
+}
+
+static int
+ppc_check_epp_timeout(struct ppc_data *ppc)
+{
+ ppc_reset_epp_timeout(ppc);
+
+ return (!(r_str(ppc) & TIMEOUT));
+}
+
+/*
+ * Configure current operating mode
+ */
+static int
+ppc_generic_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ return (EINVAL);
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+/*
+ * The ppc driver is free to choose options like FIFO or DMA
+ * if ECP mode is available.
+ *
+ * The 'RAW' option allows the upper drivers to force the ppc mode
+ * even with FIFO, DMA available.
+ */
+static int
+ppc_smclike_setmode(struct ppc_data *ppc, int mode)
+{
+ u_char ecr = 0;
+
+ /* check if mode is available */
+ if (mode && !(ppc->ppc_avm & mode))
+ return (EINVAL);
+
+ /* if ECP mode, configure ecr register */
+ if (ppc->ppc_avm & PPB_ECP) {
+ /* return to byte mode (keeping direction bit),
+ * no interrupt, no DMA to be able to change to
+ * ECP or EPP mode
+ */
+ w_ecr(ppc, PPC_ECR_RESET);
+ ecr = PPC_DISABLE_INTR;
+
+ if (mode & PPB_EPP)
+ /* select EPP mode */
+ ecr |= PPC_ECR_EPP;
+ else if (mode & PPB_ECP)
+ /* select ECP mode */
+ ecr |= PPC_ECR_ECP;
+ else if (mode & PPB_PS2)
+ /* select PS2 mode with ECP */
+ ecr |= PPC_ECR_PS2;
+ else
+ /* select COMPATIBLE/NIBBLE mode */
+ ecr |= PPC_ECR_STD;
+
+ w_ecr(ppc, ecr);
+ }
+
+ ppc->ppc_mode = mode;
+
+ return (0);
+}
+
+#ifdef PPC_PROBE_CHIPSET
+/*
* ppc_pc873xx_detect
*
* Probe for a Natsemi PC873xx-family part.
@@ -381,11 +466,11 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
outb(idport, PC873_SID);
val = inb(idport + 1);
if ((val & 0xf0) == 0x10) {
- ppc->ppc_type = NS_PC87332;
+ ppc->ppc_model = NS_PC87332;
} else if ((val & 0xf8) == 0x70) {
- ppc->ppc_type = NS_PC87306;
+ ppc->ppc_model = NS_PC87306;
} else if ((val & 0xf8) == 0x50) {
- ppc->ppc_type = NS_PC87334;
+ ppc->ppc_model = NS_PC87334;
} else {
if (bootverbose && (val != 0xff))
printf("PC873xx probe at 0x%x got unknown ID 0x%x\n", idport, val);
@@ -484,7 +569,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
else
ppc->ppc_epp = EPP_1_7;
- if ((ppc->ppc_type == NS_PC87332) && bootverbose) {
+ if ((ppc->ppc_model == NS_PC87332) && bootverbose) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
if (ptr & PC873_EPPRDIR)
@@ -539,7 +624,7 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
printf(", EPP1.9");
/* enable automatic direction turnover */
- if (ppc->ppc_type == NS_PC87332) {
+ if (ppc->ppc_model == NS_PC87332) {
outb(idport, PC873_PTR);
ptr = inb(idport + 1);
ptr &= ~PC873_EPPRDIR;
@@ -581,22 +666,14 @@ ppc_pc873xx_detect(struct ppc_data *ppc, int chipset_mode) /* XXX mode never for
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter = &ppc_generic_adapter;
- ppc_generic_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_GENERIC;
+ ppc_generic_setmode(ppc, chipset_mode);
return(chipset_mode);
}
return(-1);
}
-static int
-ppc_check_epp_timeout(struct ppc_data *ppc)
-{
- ppc_reset_epp_timeout(ppc->ppc_unit);
-
- return (!(r_str(ppc) & TIMEOUT));
-}
-
/*
* ppc_smc37c66xgt_detect
*
@@ -661,7 +738,7 @@ config:
if (port_address[(int)r] != ppc->ppc_base)
return (-1);
- ppc->ppc_type = type;
+ ppc->ppc_model = type;
/*
* CR1 and CR4 registers bits 3 and 0/1 for mode configuration
@@ -800,8 +877,8 @@ end_detect:
/* end config mode */
outb(csr, 0xaa);
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
- ppc_smclike_setmode(ppc->ppc_unit, chipset_mode);
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
+ ppc_smclike_setmode(ppc, chipset_mode);
return (chipset_mode);
}
@@ -866,15 +943,15 @@ found:
switch (inb(efdr) & WINB_CHIPID) {
case WINB_W83877F_ID:
- ppc->ppc_type = WINB_W83877F;
+ ppc->ppc_model = WINB_W83877F;
break;
case WINB_W83877AF_ID:
- ppc->ppc_type = WINB_W83877AF;
+ ppc->ppc_model = WINB_W83877AF;
break;
default:
- ppc->ppc_type = WINB_UNKNOWN;
+ ppc->ppc_model = WINB_UNKNOWN;
}
if (bootverbose) {
@@ -898,7 +975,7 @@ found:
printf("ppc%d:", ppc->ppc_unit);
}
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (!chipset_mode) {
/* autodetect mode */
@@ -940,7 +1017,7 @@ found:
case (WINB_PARALLEL | WINB_ECP_EPP):
ppc->ppc_avm |= PPB_ECP | PPB_EPP | PPB_SPP;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP SPP");
@@ -966,7 +1043,7 @@ found:
if (bootverbose)
printf(" ECP+EPP");
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
} else {
outb(efdr, inb(efdr) | WINB_ECP);
@@ -988,10 +1065,18 @@ found:
/* exit configuration mode */
outb(efer, 0xaa);
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
+#endif
/*
* ppc_generic_detect
@@ -1000,7 +1085,7 @@ static int
ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
{
/* default to generic */
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
if (bootverbose)
printf("ppc%d:", ppc->ppc_unit);
@@ -1023,8 +1108,8 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (ppc->ppc_avm & PPB_ECP) {
/* SMC like chipset found */
- ppc->ppc_type = SMC_LIKE;
- ppc->ppc_link.adapter = &ppc_smclike_adapter;
+ ppc->ppc_model = SMC_LIKE;
+ ppc->ppc_type = PPC_TYPE_SMCLIKE;
if (bootverbose)
printf(" ECP+EPP");
@@ -1050,7 +1135,14 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
if (bootverbose)
printf("\n");
- ppc->ppc_link.adapter->setmode(ppc->ppc_unit, chipset_mode);
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ ppc_smclike_setmode(ppc, chipset_mode);
+ break;
+ default:
+ ppc_generic_setmode(ppc, chipset_mode);
+ break;
+ }
return (chipset_mode);
}
@@ -1063,6 +1155,7 @@ ppc_generic_detect(struct ppc_data *ppc, int chipset_mode)
static int
ppc_detect(struct ppc_data *ppc, int chipset_mode) {
+#ifdef PPC_PROBE_CHIPSET
int i, mode;
/* list of supported chipsets */
@@ -1073,6 +1166,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
ppc_generic_detect,
NULL
};
+#endif
/* if can't find the port and mode not forced return error */
if (!ppc_detect_port(ppc) && chipset_mode == 0)
@@ -1081,6 +1175,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
/* assume centronics compatible mode is supported */
ppc->ppc_avm = PPB_COMPATIBLE;
+#ifdef PPC_PROBE_CHIPSET
/* we have to differenciate available chipset modes,
* chipset running modes and IEEE-1284 operating modes
*
@@ -1089,9 +1184,11 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
if (ppc->ppc_flags & 0x40) {
if (bootverbose)
printf("ppc: chipset forced to generic\n");
+#endif
ppc->ppc_mode = ppc_generic_detect(ppc, chipset_mode);
+#ifdef PPC_PROBE_CHIPSET
} else {
for (i=0; chipset_detect[i] != NULL; i++) {
if ((mode = chipset_detect[i](ppc, chipset_mode)) != -1) {
@@ -1100,6 +1197,7 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
}
}
}
+#endif
/* configure/detect ECP FIFO */
if ((ppc->ppc_avm & PPB_ECP) && !(ppc->ppc_flags & 0x80))
@@ -1115,9 +1213,9 @@ ppc_detect(struct ppc_data *ppc, int chipset_mode) {
* Microsequence mechanism is supposed to handle fast I/O operations.
*/
static int
-ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
+ppc_exec_microseq(device_t dev, struct ppb_microseq **p_msq)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
struct ppb_microseq *mi;
char cc, *p;
int i, iter, len;
@@ -1326,9 +1424,10 @@ ppc_exec_microseq(int unit, struct ppb_microseq **p_msq)
}
static void
-ppcintr(int unit)
+ppcintr(void *arg)
{
- struct ppc_data *ppc = ppcdata[unit];
+ device_t dev = (device_t)arg;
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(dev);
u_char ctr, ecr, str;
str = r_str(ppc);
@@ -1341,8 +1440,6 @@ ppcintr(int unit)
/* don't use ecp mode with IRQENABLE set */
if (ctr & IRQENABLE) {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
return;
}
@@ -1356,8 +1453,7 @@ ppcintr(int unit)
w_ecr(ppc, ecr | PPC_nFAULT_INTR);
ppc->ppc_irqstat &= ~PPC_IRQ_nFAULT;
} else {
- /* call upper code */
- ppb_intr(&ppc->ppc_link);
+ /* shall be handled by underlying layers XXX */
return;
}
}
@@ -1397,14 +1493,13 @@ ppcintr(int unit)
/* classic interrupt I/O */
ppc->ppc_irqstat &= ~PPC_IRQ_FIFO;
-
}
return;
}
static int
-ppc_read(int unit, char *buf, int len, int mode)
+ppc_read(device_t dev, char *buf, int len, int mode)
{
return (EINVAL);
}
@@ -1417,9 +1512,9 @@ ppc_read(int unit, char *buf, int len, int mode)
* EINVAL is returned
*/
static int
-ppc_write(int unit, char *buf, int len, int how)
+ppc_write(device_t dev, char *buf, int len, int how)
{
- struct ppc_data *ppc = ppcdata[unit];
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
char ecr, ecr_sav, ctr, ctr_sav;
int s, error = 0;
int spin;
@@ -1434,7 +1529,7 @@ ppc_write(int unit, char *buf, int len, int how)
/*
* Send buffer with DMA, FIFO and interrupts
*/
- if (ppc->ppc_avm & PPB_ECP) {
+ if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_registered)) {
if (ppc->ppc_dmachan >= 0) {
@@ -1568,231 +1663,334 @@ error:
return (error);
}
-/*
- * Configure current operating mode
- */
-static int
-ppc_generic_setmode(int unit, int mode)
+static void
+ppc_reset_epp(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
+
+ ppc_reset_epp_timeout(ppc);
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
+ return;
+}
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+static int
+ppc_setmode(device_t dev, int mode)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- if (mode & PPB_EPP)
- return (EINVAL);
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ switch (ppc->ppc_type) {
+ case PPC_TYPE_SMCLIKE:
+ return (ppc_smclike_setmode(ppc, mode));
+ break;
- w_ecr(ppc, ecr);
+ case PPC_TYPE_GENERIC:
+ default:
+ return (ppc_generic_setmode(ppc, mode));
+ break;
}
- ppc->ppc_mode = mode;
-
- return (0);
+ /* not reached */
+ return (ENXIO);
}
-/*
- * The ppc driver is free to choose options like FIFO or DMA
- * if ECP mode is available.
- *
- * The 'RAW' option allows the upper drivers to force the ppc mode
- * even with FIFO, DMA available.
- */
-int
-ppc_smclike_setmode(int unit, int mode)
+static int
+ppc_probe(device_t dev)
{
- struct ppc_data *ppc = ppcdata[unit];
- u_char ecr = 0;
-
- /* check if mode is available */
- if (mode && !(ppc->ppc_avm & mode))
- return (EINVAL);
-
- /* if ECP mode, configure ecr register */
- if (ppc->ppc_avm & PPB_ECP) {
- /* return to byte mode (keeping direction bit),
- * no interrupt, no DMA to be able to change to
- * ECP or EPP mode
- */
- w_ecr(ppc, PPC_ECR_RESET);
- ecr = PPC_DISABLE_INTR;
+ static short next_bios_ppc = 0;
+ struct ppc_data *ppc;
+ device_t parent;
+ int port;
- if (mode & PPB_EPP)
- /* select EPP mode */
- ecr |= PPC_ECR_EPP;
- else if (mode & PPB_ECP)
- /* select ECP mode */
- ecr |= PPC_ECR_ECP;
- else if (mode & PPB_PS2)
- /* select PS2 mode with ECP */
- ecr |= PPC_ECR_PS2;
- else
- /* select COMPATIBLE/NIBBLE mode */
- ecr |= PPC_ECR_STD;
+ device_set_desc(dev, "Parallel port");
- w_ecr(ppc, ecr);
- }
+ /* XXX shall be connected to pnpbios - from Peter Wemm */
+ if (isa_get_logicalid(dev))
+ return ENXIO;
- ppc->ppc_mode = mode;
+ parent = device_get_parent(dev);
- return (0);
-}
-
-/*
- * EPP timeout, according to the PC87332 manual
- * Semantics of clearing EPP timeout bit.
- * PC87332 - reading SPP_STR does it...
- * SMC - write 1 to EPP timeout bit XXX
- * Others - (?) write 0 to EPP timeout bit
- */
-static void
-ppc_reset_epp_timeout(int unit)
-{
- struct ppc_data *ppc = ppcdata[unit];
- register char r;
+ /*
+ * Allocate the ppc_data structure.
+ */
+ ppc = DEVTOSOFTC(dev);
+ bzero(ppc, sizeof(struct ppc_data));
- r = r_str(ppc);
- w_str(ppc, r | 0x1);
- w_str(ppc, r & 0xfe);
+ ppc->rid_irq = ppc->rid_drq = ppc->rid_ioport = 0;
+ ppc->res_irq = ppc->res_drq = ppc->res_ioport = 0;
- return;
-}
-
-static int
-ppcprobe(struct isa_device *dvp)
-{
- static short next_bios_ppc = 0;
- struct ppc_data *ppc;
+ /* retrieve ISA parameters */
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_PORT, &port);
/*
* If port not specified, use bios list.
*/
- if(dvp->id_iobase < 0) {
+ if (port < 0) {
if((next_bios_ppc < BIOS_MAX_PPC) &&
(*(BIOS_PORTS+next_bios_ppc) != 0) ) {
- dvp->id_iobase = *(BIOS_PORTS+next_bios_ppc++);
+ port = *(BIOS_PORTS+next_bios_ppc++);
if (bootverbose)
- printf("ppc: parallel port found at 0x%x\n",
- dvp->id_iobase);
- } else
- return (0);
+ device_printf(dev, "parallel port found at 0x%x\n",
+ port);
+ } else {
+ device_printf(dev, "parallel port not found.\n");
+ return ENXIO;
+ }
}
-
- /*
- * Port was explicitly specified.
- * This allows probing of ports unknown to the BIOS.
- */
-
- /*
- * Allocate the ppc_data structure.
- */
- ppc = malloc(sizeof(struct ppc_data), M_DEVBUF, M_NOWAIT);
- if (!ppc) {
- printf("ppc: cannot malloc!\n");
+ ppc->ppc_base = port;
+
+ /* IO port is mandatory */
+ ppc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
+ &ppc->rid_ioport, port, port,
+ IO_LPTSIZE, RF_ACTIVE);
+ if (ppc->res_ioport == 0) {
+ device_printf(dev, "cannot reserve I/O port range\n");
goto error;
}
- bzero(ppc, sizeof(struct ppc_data));
- ppc->ppc_base = dvp->id_iobase;
- ppc->ppc_unit = dvp->id_unit;
- ppc->ppc_type = GENERIC;
+ ppc->ppc_flags = device_get_flags(dev);
- /* store boot flags */
- ppc->ppc_flags = dvp->id_flags;
+ if (!(ppc->ppc_flags & 0x20)) {
+ ppc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &ppc->rid_irq,
+ 0ul, ~0ul, 1, RF_SHAREABLE);
+ ppc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, &ppc->rid_drq,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ }
- ppc->ppc_mode = PPB_COMPATIBLE;
- ppc->ppc_epp = (dvp->id_flags & 0x10) >> 4;
+ if (ppc->res_irq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_IRQ, &ppc->ppc_irq);
+ if (ppc->res_drq)
+ BUS_READ_IVAR(parent, dev, ISA_IVAR_DRQ, &ppc->ppc_dmachan);
- /*
- * XXX Try and detect if interrupts are working
- */
- if (!(dvp->id_flags & 0x20) && dvp->id_irq)
- ppc->ppc_irq = ffs(dvp->id_irq) - 1;
+ ppc->ppc_unit = device_get_unit(dev);
+ ppc->ppc_model = GENERIC;
- ppc->ppc_dmachan = dvp->id_drq;
+ ppc->ppc_mode = PPB_COMPATIBLE;
+ ppc->ppc_epp = (ppc->ppc_flags & 0x10) >> 4;
- ppcdata[ppc->ppc_unit] = ppc;
- nppc ++;
-
- /*
- * Link the Parallel Port Chipset (adapter) to
- * the future ppbus. Default to a generic chipset
- */
- ppc->ppc_link.adapter_unit = ppc->ppc_unit;
- ppc->ppc_link.adapter = &ppc_generic_adapter;
+ ppc->ppc_type = PPC_TYPE_GENERIC;
/*
* Try to detect the chipset and its mode.
*/
- if (ppc_detect(ppc, dvp->id_flags & 0xf))
+ if (ppc_detect(ppc, ppc->ppc_flags & 0xf))
goto error;
- return (IO_LPTSIZE);
+ return (0);
error:
- return (0);
+ if (ppc->res_irq != 0) {
+ bus_release_resource(dev, SYS_RES_IRQ, ppc->rid_irq,
+ ppc->res_irq);
+ }
+ if (ppc->res_ioport != 0) {
+ bus_deactivate_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ bus_release_resource(dev, SYS_RES_IOPORT, ppc->rid_ioport,
+ ppc->res_ioport);
+ }
+ if (ppc->res_drq != 0) {
+ bus_deactivate_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ bus_release_resource(dev, SYS_RES_DRQ, ppc->rid_drq,
+ ppc->res_drq);
+ }
+ return (ENXIO);
}
static int
-ppcattach(struct isa_device *isdp)
+ppc_attach(device_t dev)
{
- struct ppc_data *ppc = ppcdata[isdp->id_unit];
- struct ppb_data *ppbus;
+ struct ppc_data *ppc = DEVTOSOFTC(dev);
- printf("ppc%d: %s chipset (%s) in %s mode%s\n", ppc->ppc_unit,
- ppc_types[ppc->ppc_type], ppc_avms[ppc->ppc_avm],
- ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
- ppc_epp_protocol[ppc->ppc_epp] : "");
+ device_t ppbus;
+ device_t parent = device_get_parent(dev);
+ device_printf(dev, "%s chipset (%s) in %s mode%s\n",
+ ppc_models[ppc->ppc_model], ppc_avms[ppc->ppc_avm],
+ ppc_modes[ppc->ppc_mode], (PPB_IS_EPP(ppc->ppc_mode)) ?
+ ppc_epp_protocol[ppc->ppc_epp] : "");
+
if (ppc->ppc_fifo)
- printf("ppc%d: FIFO with %d/%d/%d bytes threshold\n",
- ppc->ppc_unit, ppc->ppc_fifo, ppc->ppc_wthr,
- ppc->ppc_rthr);
+ device_printf(dev, "FIFO with %d/%d/%d bytes threshold\n",
+ ppc->ppc_fifo, ppc->ppc_wthr, ppc->ppc_rthr);
- isdp->id_ointr = ppcintr;
+ 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);
/*
- * Prepare ppbus data area for upper level code.
+ * Probe the ppbus and attach devices found.
*/
- ppbus = ppb_alloc_bus();
+ device_probe_and_attach(ppbus);
- if (!ppbus)
- return (0);
+ /* register the ppc interrupt handler as default */
+ if (ppc->res_irq) {
+ /* default to the tty mask for registration */ /* XXX */
+ if (BUS_SETUP_INTR(parent, dev, ppc->res_irq, INTR_TYPE_TTY,
+ ppcintr, dev, &ppc->intr_cookie) == 0) {
- ppc->ppc_link.ppbus = ppbus;
- ppbus->ppb_link = &ppc->ppc_link;
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+ }
- if ((ppc->ppc_avm & PPB_ECP) && (ppc->ppc_dmachan > 0)) {
+ return (0);
+}
- /* acquire the DMA channel forever */
- isa_dma_acquire(ppc->ppc_dmachan);
- isa_dmainit(ppc->ppc_dmachan, 1024); /* nlpt.BUFSIZE */
+static u_char
+ppc_io(device_t ppcdev, int iop, u_char *addr, int cnt, u_char byte)
+{
+ struct ppc_data *ppc = DEVTOSOFTC(ppcdev);
+ switch (iop) {
+ case PPB_OUTSB_EPP:
+ outsb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSW_EPP:
+ outsw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_OUTSL_EPP:
+ outsl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSB_EPP:
+ insb(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSW_EPP:
+ insw(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_INSL_EPP:
+ insl(ppc->ppc_base + PPC_EPP_DATA, addr, cnt);
+ break;
+ case PPB_RDTR:
+ return (r_dtr(ppc));
+ break;
+ case PPB_RSTR:
+ return (r_str(ppc));
+ break;
+ case PPB_RCTR:
+ return (r_ctr(ppc));
+ break;
+ case PPB_REPP_A:
+ return (r_epp_A(ppc));
+ break;
+ case PPB_REPP_D:
+ return (r_epp_D(ppc));
+ break;
+ case PPB_RECR:
+ return (r_ecr(ppc));
+ break;
+ case PPB_RFIFO:
+ return (r_fifo(ppc));
+ break;
+ case PPB_WDTR:
+ w_dtr(ppc, byte);
+ break;
+ case PPB_WSTR:
+ w_str(ppc, byte);
+ break;
+ case PPB_WCTR:
+ w_ctr(ppc, byte);
+ break;
+ case PPB_WEPP_A:
+ w_epp_A(ppc, byte);
+ break;
+ case PPB_WEPP_D:
+ w_epp_D(ppc, byte);
+ break;
+ case PPB_WECR:
+ w_ecr(ppc, byte);
+ break;
+ case PPB_WFIFO:
+ w_fifo(ppc, byte);
+ break;
+ default:
+ panic("%s: unknown I/O operation", __FUNCTION__);
+ break;
}
- /*
- * Probe the ppbus and attach devices found.
- */
- ppb_attachdevs(ppbus);
+ return (0); /* not significative */
+}
- return (1);
+static int
+ppc_read_ivar(device_t bus, device_t dev, int index, uintptr_t *val)
+{
+ struct ppc_data *ppc = (struct ppc_data *)device_get_softc(bus);
+
+ switch (index) {
+ case PPC_IVAR_EPP_PROTO:
+ *val = (u_long)ppc->ppc_epp;
+ break;
+ case PPC_IVAR_IRQ:
+ BUS_READ_IVAR(device_get_parent(bus), bus, ISA_IVAR_IRQ, val);
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+/*
+ * Resource is useless here since ppbus devices' interrupt handlers are
+ * multiplexed to the same resource initially allocated by ppc
+ */
+static int
+ppc_setup_intr(device_t bus, device_t child, struct resource *r, int flags,
+ void (*ihand)(void *), void *arg, void **cookiep)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+
+ if (ppc->ppc_registered) {
+ /* XXX refuse registration if DMA is in progress */
+
+ /* first, unregister the default interrupt handler */
+ if ((error = BUS_TEARDOWN_INTR(device_get_parent(bus),
+ bus, ppc->res_irq, ppc->intr_cookie)))
+ return (error);
+
+/* bus_deactivate_resource(bus, SYS_RES_IRQ, ppc->rid_irq, */
+/* ppc->res_irq); */
+
+ /* DMA/FIFO operation won't be possible anymore */
+ ppc->ppc_registered = 0;
+ }
+
+ /* pass registration to the upper layer, ignore the incoming resource */
+ return (BUS_SETUP_INTR(device_get_parent(bus), child,
+ r, flags, ihand, arg, cookiep));
+}
+
+/*
+ * When no underlying device has a registered interrupt, register the ppc
+ * layer one
+ */
+static int
+ppc_teardown_intr(device_t bus, device_t child, struct resource *r, void *ih)
+{
+ int error;
+ struct ppc_data *ppc = DEVTOSOFTC(bus);
+ device_t parent = device_get_parent(bus);
+
+ /* pass unregistration to the upper layer */
+ if ((error = BUS_TEARDOWN_INTR(parent, child, r, ih)))
+ return (error);
+
+ /* default to the tty mask for registration */ /* XXX */
+ if (ppc->ppc_irq &&
+ !(error = BUS_SETUP_INTR(parent, bus, ppc->res_irq,
+ INTR_TYPE_TTY, ppcintr, bus, &ppc->intr_cookie))) {
+
+ /* remember the ppcintr is registered */
+ ppc->ppc_registered = 1;
+ }
+
+ return (error);
}
+
+DRIVER_MODULE(ppc, isa, ppc_driver, ppc_devclass, 0, 0);
#endif
diff --git a/sys/isa/ppcreg.h b/sys/isa/ppcreg.h
index faecb97..ec17806 100644
--- a/sys/isa/ppcreg.h
+++ b/sys/isa/ppcreg.h
@@ -45,12 +45,19 @@
#define NS_PC87334 10
/*
+ * Parallel Port Chipset Type. SMC versus GENERIC (others)
+ */
+#define PPC_TYPE_SMCLIKE 0
+#define PPC_TYPE_GENERIC 1
+
+/*
* Generic structure to hold parallel port chipset info.
*/
struct ppc_data {
int ppc_unit;
- int ppc_type;
+ int ppc_model; /* chipset model if detected */
+ int ppc_type; /* generic or smclike chipset type */
int ppc_mode; /* chipset current mode */
int ppc_avm; /* chipset available modes */
@@ -83,16 +90,22 @@ struct ppc_data {
short ppc_wthr; /* writeIntrThresold */
short ppc_rthr; /* readIntrThresold */
-#define ppc_base ppc_link.base
-#define ppc_epp ppc_link.epp_protocol
-#define ppc_irq ppc_link.id_irq
-#define ppc_subm ppc_link.submicroseq
-#define ppc_ptr ppc_link.ptr
-#define ppc_accum ppc_link.accum
+ char *ppc_ptr; /* microseq current pointer */
+ int ppc_accum; /* microseq accumulator */
+ int ppc_base; /* parallel port base address */
+ int ppc_epp; /* EPP mode (1.7 or 1.9) */
+ int ppc_irq;
unsigned char ppc_flags;
- struct ppb_link ppc_link;
+ device_t ppbus; /* parallel port chipset corresponding ppbus */
+
+ int rid_irq, rid_drq, rid_ioport;
+ struct resource *res_irq, *res_drq, *res_ioport;
+
+ void *intr_cookie;
+
+ int ppc_registered; /* 1 if ppcintr() is the registered interrupt */
};
/*
OpenPOWER on IntegriCloud