Date: Sat, 28 Feb 2009 17:56:26 +0000 (UTC) From: John Birrell <jb@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r189181 - projects/jbuild/sys/dev/ppbus Message-ID: <200902281756.n1SHuQQL017067@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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 ***
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200902281756.n1SHuQQL017067>