summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornsouch <nsouch@FreeBSD.org>2000-01-14 00:18:06 +0000
committernsouch <nsouch@FreeBSD.org>2000-01-14 00:18:06 +0000
commit59fc142474158cbbfbae06872a4e3efaa40e777f (patch)
tree3dd5303c8a8a1e20337965402c872462f141a217
parent83719ce7419aa6d99e02f397ba20a42d7406963b (diff)
downloadFreeBSD-src-59fc142474158cbbfbae06872a4e3efaa40e777f.zip
FreeBSD-src-59fc142474158cbbfbae06872a4e3efaa40e777f.tar.gz
Port of ppbus standalone framework to the newbus system.
Note1: the correct interrupt level is invoked correctly for each driver. For this purpose, drivers request the bus before being able to call BUS_SETUP_INTR and BUS_TEARDOWN_INTR call is forced by the ppbus core when drivers release it. Thus, when BUS_SETUP_INTR is called at ppbus driver level, ppbus checks that the caller owns the bus and stores the interrupt handler cookie (in order to unregister it later). Printing is impossible while plip link is up is still TRUE. vpo (ZIP driver) and lpt are make in such a way that using the ZIP and printing concurrently is permitted is also TRUE. Note2: specific chipset detection is not done by default. PPC_PROBE_CHIPSET is now needed to force chipset detection. If set, the flags 0x40 still avoid detection at boot. Port of the pcf(4) driver to the newbus system (was previously directly connected to the rootbus and attached by a bogus pcf_isa_probe function).
-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