svn commit: r189181 - projects/jbuild/sys/dev/ppbus
John Birrell
jb at FreeBSD.org
Sat Feb 28 09:56:26 PST 2009
Author: jb
Date: Sat Feb 28 17:56:25 2009
New Revision: 189181
URL: http://svn.freebsd.org/changeset/base/189181
Log:
MFC
Modified:
projects/jbuild/sys/dev/ppbus/if_plip.c
projects/jbuild/sys/dev/ppbus/immio.c
projects/jbuild/sys/dev/ppbus/lpbb.c
projects/jbuild/sys/dev/ppbus/lpt.c
projects/jbuild/sys/dev/ppbus/pcfclock.c
projects/jbuild/sys/dev/ppbus/ppb_1284.c
projects/jbuild/sys/dev/ppbus/ppb_base.c
projects/jbuild/sys/dev/ppbus/ppb_msq.c
projects/jbuild/sys/dev/ppbus/ppbconf.c
projects/jbuild/sys/dev/ppbus/ppbconf.h
projects/jbuild/sys/dev/ppbus/ppi.c
projects/jbuild/sys/dev/ppbus/pps.c
projects/jbuild/sys/dev/ppbus/vpo.c
projects/jbuild/sys/dev/ppbus/vpoio.c
Modified: projects/jbuild/sys/dev/ppbus/if_plip.c
==============================================================================
--- projects/jbuild/sys/dev/ppbus/if_plip.c Sat Feb 28 17:56:11 2009 (r189180)
+++ projects/jbuild/sys/dev/ppbus/if_plip.c Sat Feb 28 17:56:25 2009 (r189181)
@@ -152,8 +152,12 @@ struct lp_data {
int sc_iferrs;
struct resource *res_irq;
+ void *sc_intr_cookie;
};
+static struct mtx lp_tables_lock;
+MTX_SYSINIT(lp_tables, &lp_tables_lock, "plip tables", MTX_DEF);
+
/* Tables for the lp# interface */
static u_char *txmith;
#define txmitl (txmith + (1 * LPIPTBLSIZE))
@@ -170,13 +174,41 @@ 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 lpstop(struct lp_data *);
static void lp_intr(void *);
+static int lp_module_handler(module_t, int, void *);
#define DEVTOSOFTC(dev) \
((struct lp_data *)device_get_softc(dev))
static devclass_t lp_devclass;
+static int
+lp_module_handler(module_t mod, int what, void *arg)
+{
+
+ switch (what) {
+ case MOD_UNLOAD:
+ mtx_lock(&lp_tables_lock);
+ if (txmith != NULL) {
+ free(txmith, M_DEVBUF);
+ txmith = NULL;
+ }
+ if (ctxmith != NULL) {
+ free(ctxmith, M_DEVBUF);
+ ctxmith = NULL;
+ }
+ mtx_unlock(&lp_tables_lock);
+ break;
+ case MOD_LOAD:
+ case MOD_QUIESCE:
+ break;
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (0);
+}
+
static void
lp_identify(driver_t *driver, device_t parent)
{
@@ -201,7 +233,7 @@ lp_attach(device_t dev)
{
struct lp_data *lp = DEVTOSOFTC(dev);
struct ifnet *ifp;
- int rid = 0;
+ int error, rid = 0;
lp->sc_dev = dev;
@@ -224,8 +256,7 @@ lp_attach(device_t dev)
ifp->if_softc = lp;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
ifp->if_mtu = LPMTU;
- ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST |
- IFF_NEEDSGIANT;
+ ifp->if_flags = IFF_SIMPLEX | IFF_POINTOPOINT | IFF_MULTICAST;
ifp->if_ioctl = lpioctl;
ifp->if_output = lpoutput;
ifp->if_hdrlen = 0;
@@ -235,8 +266,39 @@ lp_attach(device_t dev)
bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
+ /*
+ * Attach our interrupt handler. It is only called while we
+ * own the ppbus.
+ */
+ error = bus_setup_intr(dev, lp->res_irq, INTR_TYPE_NET | INTR_MPSAFE,
+ NULL, lp_intr, lp, &lp->sc_intr_cookie);
+ if (error) {
+ bpfdetach(ifp);
+ if_detach(ifp);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, lp->res_irq);
+ device_printf(dev, "Unable to register interrupt handler\n");
+ return (error);
+ }
+
return (0);
}
+
+static int
+lp_detach(device_t dev)
+{
+ struct lp_data *sc = device_get_softc(dev);
+ device_t ppbus = device_get_parent(dev);
+
+ ppb_lock(ppbus);
+ lpstop(sc);
+ ppb_unlock(ppbus);
+ bpfdetach(sc->sc_ifp);
+ if_detach(sc->sc_ifp);
+ bus_teardown_intr(dev, sc->res_irq, sc->sc_intr_cookie);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->res_irq);
+ return (0);
+}
+
/*
* Build the translation tables for the LPIP (BSD unix) protocol.
* We don't want to calculate these nasties in our tight loop, so we
@@ -247,17 +309,22 @@ lpinittables(void)
{
int i;
+ mtx_lock(&lp_tables_lock);
if (txmith == NULL)
txmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
- if (txmith == NULL)
+ if (txmith == NULL) {
+ mtx_unlock(&lp_tables_lock);
return (1);
+ }
if (ctxmith == NULL)
ctxmith = malloc(4 * LPIPTBLSIZE, M_DEVBUF, M_NOWAIT);
- if (ctxmith == NULL)
+ if (ctxmith == NULL) {
+ mtx_unlock(&lp_tables_lock);
return (1);
+ }
for (i = 0; i < LPIPTBLSIZE; i++) {
ctxmith[i] = (i & 0xF0) >> 4;
@@ -272,10 +339,61 @@ lpinittables(void)
trecvh[i] = ((~i) & 0x80) | ((i & 0x38) << 1);
trecvl[i] = (((~i) & 0x80) >> 4) | ((i & 0x38) >> 3);
}
+ mtx_unlock(&lp_tables_lock);
return (0);
}
+static void
+lpstop(struct lp_data *sc)
+{
+ device_t ppbus = device_get_parent(sc->sc_dev);
+
+ ppb_assert_locked(ppbus);
+ ppb_wctr(ppbus, 0x00);
+ sc->sc_ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
+ free(sc->sc_ifbuf, M_DEVBUF);
+ sc->sc_ifbuf = NULL;
+
+ /* IFF_UP is not set, try to release the bus anyway */
+ ppb_release_bus(ppbus, sc->sc_dev);
+}
+
+static int
+lpinit_locked(struct ifnet *ifp)
+{
+ struct lp_data *sc = ifp->if_softc;
+ device_t dev = sc->sc_dev;
+ device_t ppbus = device_get_parent(dev);
+ int error;
+
+ ppb_assert_locked(ppbus);
+ error = ppb_request_bus(ppbus, dev, PPB_DONTWAIT);
+ if (error)
+ return (error);
+
+ /* Now IFF_UP means that we own the bus */
+ ppb_set_mode(ppbus, PPB_COMPATIBLE);
+
+ if (lpinittables()) {
+ ppb_release_bus(ppbus, dev);
+ return (ENOBUFS);
+ }
+
+ sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN,
+ M_DEVBUF, M_NOWAIT);
+ if (sc->sc_ifbuf == NULL) {
+ ppb_release_bus(ppbus, dev);
+ return (ENOBUFS);
+ }
+
+ ppb_wctr(ppbus, IRQENABLE);
+
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
+ return (0);
+}
+
/*
* Process an ioctl request.
*/
@@ -288,7 +406,6 @@ lpioctl(struct ifnet *ifp, u_long cmd, c
struct ifaddr *ifa = (struct ifaddr *)data;
struct ifreq *ifr = (struct ifreq *)data;
u_char *ptr;
- void *ih;
int error;
switch (cmd) {
@@ -301,67 +418,32 @@ lpioctl(struct ifnet *ifp, u_long cmd, c
ifp->if_flags |= IFF_UP;
/* FALLTHROUGH */
case SIOCSIFFLAGS:
+ error = 0;
+ ppb_lock(ppbus);
if ((!(ifp->if_flags & IFF_UP)) &&
- (ifp->if_drv_flags & IFF_DRV_RUNNING)) {
-
- ppb_wctr(ppbus, 0x00);
- ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
-
- /* IFF_UP is not set, try to release the bus anyway */
- ppb_release_bus(ppbus, dev);
- break;
- }
- if (((ifp->if_flags & IFF_UP)) &&
- (!(ifp->if_drv_flags & IFF_DRV_RUNNING))) {
-
- /* XXX
- * Should the request be interruptible?
- */
- if ((error = ppb_request_bus(ppbus, dev, PPB_WAIT |
- PPB_INTR)))
- return (error);
+ (ifp->if_drv_flags & IFF_DRV_RUNNING))
+ lpstop(sc);
+ else if (((ifp->if_flags & IFF_UP)) &&
+ (!(ifp->if_drv_flags & IFF_DRV_RUNNING)))
+ error = lpinit_locked(ifp);
+ ppb_unlock(ppbus);
+ return (error);
- /* Now IFF_UP means that we own the bus */
- ppb_set_mode(ppbus, PPB_COMPATIBLE);
-
- if (lpinittables()) {
- ppb_release_bus(ppbus, dev);
- return (ENOBUFS);
- }
-
- sc->sc_ifbuf = malloc(sc->sc_ifp->if_mtu + MLPIPHDRLEN,
- M_DEVBUF, M_WAITOK);
- if (sc->sc_ifbuf == NULL) {
- ppb_release_bus(ppbus, dev);
+ case SIOCSIFMTU:
+ ppb_lock(ppbus);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ ptr = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF,
+ M_NOWAIT);
+ if (ptr == NULL) {
+ ppb_unlock(ppbus);
return (ENOBUFS);
}
-
- /*
- * Attach our interrupt handler. It is
- * detached later when the bus is released.
- */
- if ((error = bus_setup_intr(dev, sc->res_irq,
- INTR_TYPE_NET, NULL, lp_intr, dev, &ih))) {
- ppb_release_bus(ppbus, dev);
- return (error);
- }
-
- ppb_wctr(ppbus, IRQENABLE);
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
- }
- break;
-
- case SIOCSIFMTU:
- ptr = sc->sc_ifbuf;
- sc->sc_ifbuf = malloc(ifr->ifr_mtu + MLPIPHDRLEN, M_DEVBUF,
- M_NOWAIT);
- if (sc->sc_ifbuf == NULL) {
+ if (sc->sc_ifbuf)
+ free(sc->sc_ifbuf, M_DEVBUF);
sc->sc_ifbuf = ptr;
- return (ENOBUFS);
}
- if (ptr)
- free(ptr, M_DEVBUF);
sc->sc_ifp->if_mtu = ifr->ifr_mtu;
+ ppb_unlock(ppbus);
break;
case SIOCGIFMTU:
@@ -417,14 +499,14 @@ clpinbyte(int spin, device_t ppbus)
{
u_char c, cl;
- while((ppb_rstr(ppbus) & CLPIP_SHAKE))
+ while ((ppb_rstr(ppbus) & CLPIP_SHAKE))
if (!--spin) {
return (-1);
}
cl = ppb_rstr(ppbus);
ppb_wdtr(ppbus, 0x10);
- while(!(ppb_rstr(ppbus) & CLPIP_SHAKE))
+ while (!(ppb_rstr(ppbus) & CLPIP_SHAKE))
if (!--spin) {
return (-1);
}
@@ -445,16 +527,14 @@ lptap(struct ifnet *ifp, struct mbuf *m)
static void
lp_intr(void *arg)
{
- device_t dev = (device_t)arg;
- device_t ppbus = device_get_parent(dev);
- struct lp_data *sc = DEVTOSOFTC(dev);
- int len, s, j;
+ struct lp_data *sc = arg;
+ device_t ppbus = device_get_parent(sc->sc_dev);
+ int len, j;
u_char *bp;
u_char c, cl;
struct mbuf *top;
- s = splhigh();
-
+ ppb_assert_locked(ppbus);
if (sc->sc_ifp->if_flags & IFF_LINK0) {
/* Ack. the request */
@@ -500,13 +580,15 @@ lp_intr(void *arg)
top = m_devget(sc->sc_ifbuf + CLPIPHDRLEN, len, 0, sc->sc_ifp,
0);
if (top) {
+ ppb_unlock(ppbus);
if (bpf_peers_present(sc->sc_ifp->if_bpf))
lptap(sc->sc_ifp, top);
/* mbuf is free'd on failure. */
netisr_queue(NETISR_IP, top);
+ ppb_lock(ppbus);
}
- goto done;
+ return;
}
while ((ppb_rstr(ppbus) & LPIP_SHAKE)) {
len = sc->sc_ifp->if_mtu + LPIPHDRLEN;
@@ -517,7 +599,7 @@ lp_intr(void *arg)
ppb_wdtr(ppbus, 8);
j = LPMAXSPIN2;
- while((ppb_rstr(ppbus) & LPIP_SHAKE))
+ while ((ppb_rstr(ppbus) & LPIP_SHAKE))
if (!--j)
goto err;
@@ -550,14 +632,16 @@ lp_intr(void *arg)
top = m_devget(sc->sc_ifbuf + LPIPHDRLEN, len, 0, sc->sc_ifp,
0);
if (top) {
+ ppb_unlock(ppbus);
if (bpf_peers_present(sc->sc_ifp->if_bpf))
lptap(sc->sc_ifp, top);
/* mbuf is free'd on failure. */
netisr_queue(NETISR_IP, top);
+ ppb_lock(ppbus);
}
}
- goto done;
+ return;
err:
ppb_wdtr(ppbus, 0);
@@ -575,9 +659,6 @@ err:
sc->sc_ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
sc->sc_iferrs = 0;
}
-
-done:
- splx(s);
}
static __inline int
@@ -602,7 +683,7 @@ lpoutput(struct ifnet *ifp, struct mbuf
struct lp_data *sc = ifp->if_softc;
device_t dev = sc->sc_dev;
device_t ppbus = device_get_parent(dev);
- int s, err;
+ int err;
struct mbuf *mm;
u_char *cp = "\0\0";
u_char chksum = 0;
@@ -611,19 +692,18 @@ lpoutput(struct ifnet *ifp, struct mbuf
/* We need a sensible value if we abort */
cp++;
- ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ ppb_lock(ppbus);
+ ifp->if_drv_flags |= IFF_DRV_OACTIVE;
err = 1; /* assume we're aborting because of an error */
- s = splhigh();
-
/* Suspend (on laptops) or receive-errors might have taken us offline */
ppb_wctr(ppbus, IRQENABLE);
if (ifp->if_flags & IFF_LINK0) {
if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
lprintf("&");
- lp_intr(dev);
+ lp_intr(sc);
}
/* Alert other end to pending packet */
@@ -681,6 +761,7 @@ lpoutput(struct ifnet *ifp, struct mbuf
err = 0; /* No errors */
nend:
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
if (err) { /* if we didn't timeout... */
ifp->if_oerrors++;
lprintf("X");
@@ -695,15 +776,15 @@ lpoutput(struct ifnet *ifp, struct mbuf
if (!(ppb_rstr(ppbus) & CLPIP_SHAKE)) {
lprintf("^");
- lp_intr(dev);
+ lp_intr(sc);
}
- (void) splx(s);
+ ppb_unlock(ppbus);
return (0);
}
if (ppb_rstr(ppbus) & LPIP_SHAKE) {
lprintf("&");
- lp_intr(dev);
+ lp_intr(sc);
}
if (lpoutbyte(0x08, LPMAXSPIN1, ppbus))
@@ -726,6 +807,7 @@ end:
--cp;
ppb_wdtr(ppbus, txmitl[*cp] ^ 0x17);
+ ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
if (err) { /* if we didn't timeout... */
ifp->if_oerrors++;
lprintf("X");
@@ -740,10 +822,10 @@ end:
if (ppb_rstr(ppbus) & LPIP_SHAKE) {
lprintf("^");
- lp_intr(dev);
+ lp_intr(sc);
}
- (void) splx(s);
+ ppb_unlock(ppbus);
return (0);
}
@@ -752,6 +834,7 @@ static device_method_t lp_methods[] = {
DEVMETHOD(device_identify, lp_identify),
DEVMETHOD(device_probe, lp_probe),
DEVMETHOD(device_attach, lp_attach),
+ DEVMETHOD(device_detach, lp_detach),
{ 0, 0 }
};
@@ -762,5 +845,5 @@ static driver_t lp_driver = {
sizeof(struct lp_data),
};
-DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, 0, 0);
+DRIVER_MODULE(plip, ppbus, lp_driver, lp_devclass, lp_module_handler, 0);
MODULE_DEPEND(plip, ppbus, 1, 1, 1);
Modified: projects/jbuild/sys/dev/ppbus/immio.c
==============================================================================
--- projects/jbuild/sys/dev/ppbus/immio.c Sat Feb 28 17:56:11 2009 (r189180)
+++ projects/jbuild/sys/dev/ppbus/immio.c Sat Feb 28 17:56:25 2009 (r189181)
@@ -606,6 +606,7 @@ imm_attach(struct vpoio_data *vpo)
/*
* Initialize mode dependent in/out microsequences
*/
+ ppb_lock(ppbus);
if ((error = ppb_request_bus(ppbus, vpo->vpo_dev, PPB_WAIT)))
goto error;
@@ -632,6 +633,7 @@ imm_attach(struct vpoio_data *vpo)
ppb_release_bus(ppbus, vpo->vpo_dev);
error:
+ ppb_unlock(ppbus);
return (error);
}
Modified: projects/jbuild/sys/dev/ppbus/lpbb.c
==============================================================================
--- projects/jbuild/sys/dev/ppbus/lpbb.c Sat Feb 28 17:56:11 2009 (r189180)
+++ projects/jbuild/sys/dev/ppbus/lpbb.c Sat Feb 28 17:56:25 2009 (r189181)
@@ -103,16 +103,16 @@ lpbb_callback(device_t dev, int index, c
case IIC_REQUEST_BUS:
/* request the ppbus */
how = *(int *)data;
- mtx_lock(&Giant);
+ ppb_lock(ppbus);
error = ppb_request_bus(ppbus, dev, how);
- mtx_unlock(&Giant);
+ ppb_unlock(ppbus);
break;
case IIC_RELEASE_BUS:
/* release the ppbus */
- mtx_lock(&Giant);
+ ppb_lock(ppbus);
error = ppb_release_bus(ppbus, dev);
- mtx_unlock(&Giant);
+ ppb_unlock(ppbus);
break;
default:
@@ -129,25 +129,38 @@ lpbb_callback(device_t dev, int index, c
#define ALIM 0x20
#define I2CKEY 0x50
+/* Reset bus by setting SDA first and then SCL. */
+static void
+lpbb_reset_bus(device_t dev)
+{
+ device_t ppbus = device_get_parent(dev);
+
+ ppb_assert_locked(ppbus);
+ ppb_wdtr(ppbus, (u_char)~SDA_out);
+ ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out));
+}
+
static int
lpbb_getscl(device_t dev)
{
+ device_t ppbus = device_get_parent(dev);
int rval;
- mtx_lock(&Giant);
- rval = ((ppb_rstr(device_get_parent(dev)) & SCL_in) == SCL_in);
- mtx_unlock(&Giant);
+ ppb_lock(ppbus);
+ rval = ((ppb_rstr(ppbus) & SCL_in) == SCL_in);
+ ppb_unlock(ppbus);
return (rval);
}
static int
lpbb_getsda(device_t dev)
{
+ device_t ppbus = device_get_parent(dev);
int rval;
- mtx_lock(&Giant);
- rval = ((ppb_rstr(device_get_parent(dev)) & SDA_in) == SDA_in);
- mtx_unlock(&Giant);
+ ppb_lock(ppbus);
+ rval = ((ppb_rstr(ppbus) & SDA_in) == SDA_in);
+ ppb_unlock(ppbus);
return (rval);
}
@@ -156,12 +169,12 @@ lpbb_setsda(device_t dev, char val)
{
device_t ppbus = device_get_parent(dev);
- mtx_lock(&Giant);
+ ppb_lock(ppbus);
if (val == 0)
ppb_wdtr(ppbus, (u_char)SDA_out);
else
ppb_wdtr(ppbus, (u_char)~SDA_out);
- mtx_unlock(&Giant);
+ ppb_unlock(ppbus);
}
static void
@@ -169,12 +182,12 @@ lpbb_setscl(device_t dev, unsigned char
{
device_t ppbus = device_get_parent(dev);
- mtx_lock(&Giant);
+ ppb_lock(ppbus);
if (val == 0)
ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) & ~SCL_out));
else
ppb_wctr(ppbus, (u_char)(ppb_rctr(ppbus) | SCL_out));
- mtx_unlock(&Giant);
+ ppb_unlock(ppbus);
}
static int
@@ -182,23 +195,24 @@ lpbb_detect(device_t dev)
{
device_t ppbus = device_get_parent(dev);
+ ppb_lock(ppbus);
if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) {
+ ppb_unlock(ppbus);
device_printf(dev, "can't allocate ppbus\n");
return (0);
}
- /* reset bus */
- lpbb_setsda(dev, 1);
- lpbb_setscl(dev, 1);
+ lpbb_reset_bus(dev);
if ((ppb_rstr(ppbus) & I2CKEY) ||
((ppb_rstr(ppbus) & ALIM) != ALIM)) {
-
ppb_release_bus(ppbus, dev);
+ ppb_unlock(ppbus);
return (0);
}
ppb_release_bus(ppbus, dev);
+ ppb_unlock(ppbus);
return (1);
}
@@ -208,18 +222,17 @@ lpbb_reset(device_t dev, u_char speed, u
{
device_t ppbus = device_get_parent(dev);
- mtx_lock(&Giant);
+ ppb_lock(ppbus);
if (ppb_request_bus(ppbus, dev, PPB_DONTWAIT)) {
+ ppb_unlock(ppbus);
device_printf(dev, "can't allocate ppbus\n");
return (0);
}
- /* reset bus */
- lpbb_setsda(dev, 1);
- lpbb_setscl(dev, 1);
+ lpbb_reset_bus(dev);
ppb_release_bus(ppbus, dev);
- mtx_unlock(&Giant);
+ ppb_unlock(ppbus);
return (IIC_ENOADDR);
}
Modified: projects/jbuild/sys/dev/ppbus/lpt.c
==============================================================================
--- projects/jbuild/sys/dev/ppbus/lpt.c Sat Feb 28 17:56:11 2009 (r189180)
+++ projects/jbuild/sys/dev/ppbus/lpt.c Sat Feb 28 17:56:25 2009 (r189181)
@@ -105,9 +105,9 @@ static int volatile lptflag = 1;
#define BUFSTATSIZE 32
struct lpt_data {
- device_t dev;
- struct cdev *cdev;
- struct cdev *cdev_bypass;
+ device_t sc_dev;
+ struct cdev *sc_cdev;
+ struct cdev *sc_cdev_bypass;
short sc_state;
/* default case: negative prime, negative ack, handshake strobe,
prime once */
@@ -130,9 +130,10 @@ struct lpt_data {
#define LP_ENABLE_IRQ 0x04 /* enable IRQ on open */
#define LP_ENABLE_EXT 0x10 /* we shall use advanced mode when possible */
u_char sc_backoff ; /* time to call lptout() again */
+ struct callout sc_timer;
- struct resource *intr_resource; /* interrupt resource */
- void *intr_cookie; /* interrupt registration cookie */
+ struct resource *sc_intr_resource; /* interrupt resource */
+ void *sc_intr_cookie; /* interrupt cookie */
};
#define LPT_NAME "lpt" /* our official name */
@@ -144,8 +145,7 @@ static int lpt_detect(device_t dev);
#define DEVTOSOFTC(dev) \
((struct lpt_data *)device_get_softc(dev))
-static void lptintr(device_t dev);
-static void lpt_intr(void *arg); /* without spls */
+static void lptintr(void *arg);
static devclass_t lpt_devclass;
@@ -183,7 +183,6 @@ static d_ioctl_t lptioctl;
static struct cdevsw lpt_cdevsw = {
.d_version = D_VERSION,
- .d_flags = D_NEEDGIANT,
.d_open = lptopen,
.d_close = lptclose,
.d_read = lptread,
@@ -199,13 +198,17 @@ lpt_request_ppbus(device_t dev, int how)
struct lpt_data *sc = DEVTOSOFTC(dev);
int error;
+ /*
+ * We might already have the bus for a write(2) after an interrupted
+ * write(2) call.
+ */
+ ppb_assert_locked(ppbus);
if (sc->sc_state & HAVEBUS)
return (0);
- /* we have the bus only if the request succeded */
- if ((error = ppb_request_bus(ppbus, dev, how)) == 0)
+ error = ppb_request_bus(ppbus, dev, how);
+ if (error == 0)
sc->sc_state |= HAVEBUS;
-
return (error);
}
@@ -216,9 +219,12 @@ lpt_release_ppbus(device_t dev)
struct lpt_data *sc = DEVTOSOFTC(dev);
int error = 0;
- if ((error = ppb_release_bus(ppbus, dev)) == 0)
- sc->sc_state &= ~HAVEBUS;
-
+ ppb_assert_locked(ppbus);
+ if (sc->sc_state & HAVEBUS) {
+ error = ppb_release_bus(ppbus, dev);
+ if (error == 0)
+ sc->sc_state &= ~HAVEBUS;
+ }
return (error);
}
@@ -306,24 +312,25 @@ lpt_detect(device_t dev)
status = 1; /* assume success */
+ ppb_lock(ppbus);
if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) {
- printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
- status = 0;
- goto end_probe;
+ ppb_unlock(ppbus);
+ device_printf(dev, "cannot alloc ppbus (%d)!\n", error);
+ return (0);
}
for (i = 0; i < 18 && status; i++)
if (!lpt_port_test(ppbus, testbyte[i], 0xff)) {
status = 0;
- goto end_probe;
+ break;
}
-end_probe:
/* write 0's to control and data ports */
ppb_wdtr(ppbus, 0);
ppb_wctr(ppbus, 0);
lpt_release_ppbus(dev);
+ ppb_unlock(ppbus);
return (status);
}
@@ -363,21 +370,33 @@ lpt_attach(device_t dev)
int error;
sc->sc_primed = 0; /* not primed yet */
+ ppb_init_callout(ppbus, &sc->sc_timer, 0);
+ ppb_lock(ppbus);
if ((error = lpt_request_ppbus(dev, PPB_DONTWAIT))) {
- printf(LPT_NAME ": cannot alloc ppbus (%d)!\n", error);
+ ppb_unlock(ppbus);
+ device_printf(dev, "cannot alloc ppbus (%d)!\n", error);
return (0);
}
ppb_wctr(ppbus, LPC_NINIT);
-
- /* check if we can use interrupt, should be done by ppc stuff */
- lprintf(("oldirq %x\n", sc->sc_irq));
+ lpt_release_ppbus(dev);
+ ppb_unlock(ppbus);
/* declare our interrupt handler */
- sc->intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
+ sc->sc_intr_resource = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid,
RF_SHAREABLE);
- if (sc->intr_resource) {
+ if (sc->sc_intr_resource) {
+ error = bus_setup_intr(dev, sc->sc_intr_resource,
+ INTR_TYPE_TTY | INTR_MPSAFE, NULL, lptintr, sc,
+ &sc->sc_intr_cookie);
+ if (error) {
+ bus_release_resource(dev, SYS_RES_IRQ, rid,
+ sc->sc_intr_resource);
+ device_printf(dev,
+ "Unable to register interrupt handler\n");
+ return (error);
+ }
sc->sc_irq = LP_HAS_IRQ | LP_USE_IRQ | LP_ENABLE_IRQ;
device_printf(dev, "Interrupt-driven port\n");
} else {
@@ -386,17 +405,17 @@ lpt_attach(device_t dev)
}
lprintf(("irq %x\n", sc->sc_irq));
- lpt_release_ppbus(dev);
-
- sc->dev = dev;
- sc->cdev = make_dev(&lpt_cdevsw, unit,
+ sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
+ sc->sc_statbuf = malloc(BUFSTATSIZE, M_DEVBUF, M_WAITOK);
+ sc->sc_dev = dev;
+ sc->sc_cdev = make_dev(&lpt_cdevsw, unit,
UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d", unit);
- sc->cdev->si_drv1 = sc;
- sc->cdev->si_drv2 = 0;
- sc->cdev_bypass = make_dev(&lpt_cdevsw, unit,
+ sc->sc_cdev->si_drv1 = sc;
+ sc->sc_cdev->si_drv2 = 0;
+ sc->sc_cdev_bypass = make_dev(&lpt_cdevsw, unit,
UID_ROOT, GID_WHEEL, 0600, LPT_NAME "%d.ctl", unit);
- sc->cdev_bypass->si_drv1 = sc;
- sc->cdev_bypass->si_drv2 = (void *)LP_BYPASS;
+ sc->sc_cdev_bypass->si_drv1 = sc;
+ sc->sc_cdev_bypass->si_drv2 = (void *)LP_BYPASS;
return (0);
}
@@ -404,15 +423,21 @@ static int
lpt_detach(device_t dev)
{
struct lpt_data *sc = DEVTOSOFTC(dev);
+ device_t ppbus = device_get_parent(dev);
- destroy_dev(sc->cdev);
- destroy_dev(sc->cdev_bypass);
+ destroy_dev(sc->sc_cdev);
+ destroy_dev(sc->sc_cdev_bypass);
+ ppb_lock(ppbus);
lpt_release_ppbus(dev);
- if (sc->intr_resource != 0) {
- BUS_TEARDOWN_INTR(device_get_parent(dev), dev,
- sc->intr_resource, sc->intr_cookie);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->intr_resource);
+ ppb_unlock(ppbus);
+ callout_drain(&sc->sc_timer);
+ if (sc->sc_intr_resource != NULL) {
+ bus_teardown_intr(dev, sc->sc_intr_resource,
+ sc->sc_intr_cookie);
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->sc_intr_resource);
}
+ free(sc->sc_inbuf, M_DEVBUF);
+ free(sc->sc_statbuf, M_DEVBUF);
return (0);
}
@@ -420,18 +445,19 @@ lpt_detach(device_t dev)
static void
lptout(void *arg)
{
- device_t dev = (device_t)arg;
- struct lpt_data *sc = DEVTOSOFTC(dev);
-#ifdef LPT_DEBUG
+ struct lpt_data *sc = arg;
+ device_t dev = sc->sc_dev;
+#if defined(INVARIANTS) || defined(LPT_DEBUG)
device_t ppbus = device_get_parent(dev);
#endif
+ ppb_assert_locked(ppbus);
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)dev, sc->sc_backoff);
+ callout_reset(&sc->sc_timer, sc->sc_backoff, lptout, sc);
} else
sc->sc_state &= ~TOUT;
@@ -442,7 +468,7 @@ lptout(void *arg)
* Avoid possible hangs due to missed interrupts
*/
if (sc->sc_xfercnt) {
- lptintr(dev);
+ lptintr(sc);
} else {
sc->sc_state &= ~OBUSY;
wakeup(dev);
@@ -458,17 +484,19 @@ lptout(void *arg)
static int
lptopen(struct cdev *dev, int flags, int fmt, struct thread *td)
{
- int s;
int trys, err;
struct lpt_data *sc = dev->si_drv1;
- device_t lptdev = sc->dev;
+ device_t lptdev = sc->sc_dev;
device_t ppbus = device_get_parent(lptdev);
if (!sc)
return (ENXIO);
+ ppb_lock(ppbus);
if (sc->sc_state) {
- lprintf((LPT_NAME ": still open %x\n", sc->sc_state));
+ lprintf(("%s: still open %x\n", device_get_nameunit(lptdev),
+ sc->sc_state));
+ ppb_unlock(ppbus);
return(EBUSY);
} else
sc->sc_state |= LPTINIT;
@@ -478,6 +506,7 @@ lptopen(struct cdev *dev, int flags, int
/* Check for open with BYPASS flag set. */
if (sc->sc_flags & LP_BYPASS) {
sc->sc_state = OPEN;
+ ppb_unlock(ppbus);
return(0);
}
@@ -485,11 +514,12 @@ lptopen(struct cdev *dev, int flags, int
if ((err = lpt_request_ppbus(lptdev, PPB_WAIT|PPB_INTR)) != 0) {
/* give it a chance to try later */
sc->sc_state = 0;
+ ppb_unlock(ppbus);
return (err);
}
- s = spltty();
- lprintf((LPT_NAME " flags 0x%x\n", sc->sc_flags));
+ lprintf(("%s flags 0x%x\n", device_get_nameunit(lptdev),
+ sc->sc_flags));
/* set IRQ status according to ENABLE_IRQ flag
*/
@@ -514,21 +544,20 @@ lptopen(struct cdev *dev, int flags, int
do {
/* ran out of waiting for the printer */
if (trys++ >= LPINITRDY*4) {
- splx(s);
- sc->sc_state = 0;
lprintf(("status %x\n", ppb_rstr(ppbus)));
lpt_release_ppbus(lptdev);
+ sc->sc_state = 0;
+ ppb_unlock(ppbus);
return (EBUSY);
}
/* wait 1/4 second, give up if we get a signal */
- if (tsleep(lptdev, LPPRI|PCATCH, "lptinit", hz/4) !=
- EWOULDBLOCK) {
- sc->sc_state = 0;
- splx(s);
-
+ if (ppb_sleep(ppbus, lptdev, LPPRI | PCATCH, "lptinit",
+ hz / 4) != EWOULDBLOCK) {
lpt_release_ppbus(lptdev);
+ sc->sc_state = 0;
+ ppb_unlock(ppbus);
return (EBUSY);
}
@@ -547,23 +576,22 @@ lptopen(struct cdev *dev, int flags, int
ppb_wctr(ppbus, sc->sc_control);
- sc->sc_state = OPEN;
- sc->sc_inbuf = malloc(BUFSIZE, M_DEVBUF, M_WAITOK);
- sc->sc_statbuf = malloc(BUFSTATSIZE, M_DEVBUF, M_WAITOK);
+ sc->sc_state &= ~LPTINIT;
+ sc->sc_state |= OPEN;
sc->sc_xfercnt = 0;
- splx(s);
-
- /* release the ppbus */
- 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)lptdev,
- (sc->sc_backoff = hz/LPTOUTINITIAL));
+ sc->sc_backoff = hz / LPTOUTINITIAL;
+ callout_reset(&sc->sc_timer, sc->sc_backoff, lptout, sc);
}
+ /* release the ppbus */
+ lpt_release_ppbus(lptdev);
+ ppb_unlock(ppbus);
+
lprintf(("opened.\n"));
return(0);
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-projects
mailing list