diff options
Diffstat (limited to 'sys/dev/ppbus/if_plip.c')
| -rw-r--r-- | sys/dev/ppbus/if_plip.c | 281 |
1 files changed, 153 insertions, 128 deletions
diff --git a/sys/dev/ppbus/if_plip.c b/sys/dev/ppbus/if_plip.c index f2085e4c6bdd..033889e64919 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 */ |
