Index: if_el.c =================================================================== RCS file: /home/ncvs/src/sys/i386/isa/if_el.c,v retrieving revision 1.49 diff -u -r1.49 if_el.c --- if_el.c 2000/05/28 13:40:42 1.49 +++ if_el.c 2000/06/06 18:08:02 @@ -31,6 +31,9 @@ #include #include #include +#include +#include +#include #include #include @@ -42,13 +45,8 @@ #include -#include #include -#ifndef COMPAT_OLDISA -#error "The el device requires the old isa compatibility shims" -#endif - /* For debugging convenience */ #ifdef EL_DEBUG #define dprintf(x) printf x @@ -57,73 +55,94 @@ #endif /* el_softc: per line info and status */ -static struct el_softc { - struct arpcom arpcom; /* Ethernet common */ - u_short el_base; /* Base I/O addr */ - char el_pktbuf[EL_BUFSIZ]; /* Frame buffer */ -} el_softc[NEL]; +struct el_softc { + struct arpcom arpcom; /* Ethernet common */ + char el_pktbuf[EL_BUFSIZ]; /* Frame buffer */ + bus_space_tag_t bst; + bus_space_handle_t bsh; + void *irqh; + struct resource *res_io; + struct resource *res_irq; + int rid_io; + int rid_irq; +}; /* Prototypes */ -static int el_attach(struct isa_device *); +static int el_attach(device_t); +static int el_detach(device_t); static void el_init(void *); static int el_ioctl(struct ifnet *,u_long,caddr_t); -static int el_probe(struct isa_device *); +static int el_probe(device_t); static void el_start(struct ifnet *); static void el_reset(void *); static void el_watchdog(struct ifnet *); static void el_stop(void *); static int el_xmit(struct el_softc *,int); -static ointhand2_t elintr; +static void elintr(void *); static __inline void elread(struct el_softc *,caddr_t,int); static struct mbuf *elget(caddr_t,int,struct ifnet *); static __inline void el_hardreset(void *); + +static device_method_t el_methods[] = { + DEVMETHOD(device_attach, el_attach), + DEVMETHOD(device_detach, el_detach), + DEVMETHOD(device_probe, el_probe), + + { 0, 0 } +}; -/* isa_driver structure for autoconf */ -struct isa_driver eldriver = { - INTR_TYPE_NET, - el_probe, - el_attach, - "el" +static driver_t el_driver = { + "el", + el_methods, + sizeof(struct el_softc) }; -COMPAT_ISA_DRIVER(el, eldriver); + +static devclass_t el_devclass; + +DRIVER_MODULE(el, isa, el_driver, el_devclass, 0, 0); /* Probe routine. See if the card is there and at the right place. */ static int -el_probe(struct isa_device *idev) +el_probe(device_t dev) { struct el_softc *sc; - u_short base; /* Just for convenience */ u_char station_addr[ETHER_ADDR_LEN]; int i; /* Grab some info for our structure */ - sc = &el_softc[idev->id_unit]; - sc->el_base = idev->id_iobase; - base = sc->el_base; + sc = (struct el_softc *)device_get_softc(dev); + if (sc == NULL) + return (ENXIO); + sc->res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid_io, + 0, ~0, 1, RF_ACTIVE); + if (sc->res_io == NULL) + return (ENXIO); + sc->bst = rman_get_bustag(sc->res_io); + sc->bsh = rman_get_bushandle(sc->res_io); /* First check the base */ - if((base < 0x280) || (base > 0x3f0)) { - printf("el%d: ioaddr must be between 0x280 and 0x3f0\n", - idev->id_unit); - return(0); + if ((sc->bsh < 0x280) || (sc->bsh > 0x3f0)) { + device_printf(dev, "ioaddr must be between 0x280 and 0x3f0\n"); + el_detach(dev); + return (ENXIO); } /* Now attempt to grab the station address from the PROM * and see if it contains the 3com vendor code. */ - dprintf(("Probing 3c501 at 0x%x...\n",base)); + dprintf(("Probing 3c501 at 0x%x...\n",sc->bsh)); /* Reset the board */ dprintf(("Resetting board...\n")); - outb(base+EL_AC,EL_AC_RESET); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_RESET); DELAY(5); - outb(base+EL_AC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, 0); dprintf(("Reading station address...\n")); /* Now read the address */ for(i=0;ibst, sc->bsh, EL_GPBL, i); + station_addr[i] = bus_space_read_1(sc->bst, sc->bsh, EL_EAW); } dprintf(("Address is %6D\n",station_addr, ":")); @@ -133,12 +152,15 @@ if((station_addr[0] != 0x02) || (station_addr[1] != 0x60) || (station_addr[2] != 0x8c)) { dprintf(("Bad vendor code.\n")); - return(0); + el_detach(dev); + return (ENXIO); } else { dprintf(("Vendor code ok.\n")); /* Copy the station address into the arpcom structure */ bcopy(station_addr,sc->arpcom.ac_enaddr,ETHER_ADDR_LEN); - return(1); + /* Drop resources until attach */ + el_detach(dev); + return (0); } } @@ -148,21 +170,18 @@ void *xsc; { register struct el_softc *sc = xsc; - register int base; register int j; - base = sc->el_base; - /* First reset the board */ - outb(base+EL_AC,EL_AC_RESET); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_RESET); DELAY(5); - outb(base+EL_AC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, 0); /* Then give it back its ethernet address. Thanks to the mach * source code for this undocumented goodie... */ for(j=0;jarpcom.ac_enaddr[j]); + bus_space_write_1(sc->bst, sc->bsh, j, sc->arpcom.ac_enaddr[j]); } /* Attach the interface to the kernel data structures. By the time @@ -170,19 +189,28 @@ * We still assume that the IRQ given is correct. */ static int -el_attach(struct isa_device *idev) +el_attach(device_t dev) { struct el_softc *sc; struct ifnet *ifp; - u_short base; - dprintf(("Attaching el%d...\n",idev->id_unit)); + dprintf(("Attaching ...\n")); /* Get things pointing to the right places. */ - idev->id_ointr = elintr; - sc = &el_softc[idev->id_unit]; + sc = (struct el_softc *)device_get_softc(dev); + if (sc == NULL) + return (ENXIO); + sc->res_io = bus_alloc_resource(dev, SYS_RES_IOPORT, &sc->rid_io, + 0, ~0, 1, RF_ACTIVE); + sc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &sc->rid_irq, + 0, ~0, 1, RF_ACTIVE); + if (sc->res_io == NULL || sc->res_irq == NULL) { + el_detach(dev); + return (ENXIO); + } + bus_setup_intr(dev, sc->res_irq, INTR_TYPE_NET, elintr, sc, &sc->irqh); + ifp = &sc->arpcom.ac_if; - base = sc->el_base; /* Now reset the board */ dprintf(("Resetting board...\n")); @@ -190,7 +218,7 @@ /* Initialize ifnet structure */ ifp->if_softc = sc; - ifp->if_unit = idev->id_unit; + ifp->if_unit = device_get_unit(dev); ifp->if_name = "el"; ifp->if_mtu = ETHERMTU; ifp->if_output = ether_output; @@ -206,15 +234,34 @@ ether_ifattach(ifp); /* Print out some information for the user */ - printf("el%d: 3c501 address %6D\n",idev->id_unit, - sc->arpcom.ac_enaddr, ":"); + device_printf(dev, "3c501 address %6D\n", sc->arpcom.ac_enaddr, ":"); /* Finally, attach to bpf filter if it is present. */ dprintf(("Attaching to BPF...\n")); bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); dprintf(("el_attach() finished.\n")); - return(1); + return (0); +} + +static int +el_detach(device_t dev) +{ + struct el_softc *sc; + + sc = (struct el_softc *)device_get_softc(dev); + if (sc == NULL) + return (ENXIO); + if (sc->res_io != NULL) + bus_release_resource(dev, SYS_RES_IOPORT, sc->rid_io, + sc->res_io); + if (sc->res_irq != NULL) { + bus_teardown_intr(dev, sc->res_irq, sc->irqh); + bus_release_resource(dev, SYS_RES_IRQ, sc->rid_irq, + sc->res_irq); + } + + return (0); } /* This routine resets the interface. */ @@ -237,7 +284,7 @@ { struct el_softc *sc = xsc; - outb(sc->el_base+EL_AC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, 0); } /* Initialize interface. */ @@ -248,11 +295,9 @@ struct el_softc *sc = xsc; struct ifnet *ifp; int s; - u_short base; /* Set up pointers */ ifp = &sc->arpcom.ac_if; - base = sc->el_base; /* If address not known, do nothing. */ if(TAILQ_EMPTY(&ifp->if_addrhead)) /* XXX unlikely */ @@ -267,18 +312,22 @@ /* Configure rx */ dprintf(("Configuring rx...\n")); if(ifp->if_flags & IFF_PROMISC) - outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, (EL_RXC_PROMISC| + EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); else - outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); - outb(base+EL_RBC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, (EL_RXC_ABROAD| + EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); + bus_space_write_1(sc->bst, sc->bsh, EL_RBC, 0); /* Configure TX */ dprintf(("Configuring tx...\n")); - outb(base+EL_TXC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_TXC, 0); /* Start reception */ dprintf(("Starting reception...\n")); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, (EL_AC_IRQE|EL_AC_RX)); /* Set flags appropriately */ ifp->if_flags |= IFF_RUNNING; @@ -298,13 +347,11 @@ el_start(struct ifnet *ifp) { struct el_softc *sc; - u_short base; struct mbuf *m, *m0; int s, i, len, retries, done; /* Get things pointing in the right directions */ sc = ifp->if_softc; - base = sc->el_base; dprintf(("el_start()...\n")); s = splimp(); @@ -329,8 +376,8 @@ } /* Disable the receiver */ - outb(base+EL_AC,EL_AC_HOST); - outb(base+EL_RBC,0); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_HOST); + bus_space_write_1(sc->bst, sc->bsh, EL_RBC, 0); /* Copy the datagram to the buffer. */ len = 0; @@ -351,9 +398,10 @@ /* Transfer datagram to board */ dprintf(("el: xfr pkt length=%d...\n",len)); i = EL_BUFSIZ - len; - outb(base+EL_GPBL,(i & 0xff)); - outb(base+EL_GPBH,((i>>8)&0xff)); - outsb(base+EL_BUF,sc->el_pktbuf,len); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBL, (i & 0xff)); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBH, ((i>>8)&0xff)); + bus_space_write_multi_1(sc->bst, sc->bsh, EL_BUF, + sc->el_pktbuf, len); /* Now transmit the datagram */ retries=0; @@ -364,15 +412,19 @@ break; } /* Check out status */ - i = inb(base+EL_TXS); + i = bus_space_read_1(sc->bst, sc->bsh, EL_TXS); dprintf(("tx status=0x%x\n",i)); if(!(i & EL_TXS_READY)) { dprintf(("el: err txs=%x\n",i)); sc->arpcom.ac_if.if_oerrors++; if(i & (EL_TXS_COLL|EL_TXS_COLL16)) { - if((!(i & EL_TXC_DCOLL16)) && retries < 15) { + if((!(i & EL_TXC_DCOLL16)) && + retries < 15) { retries++; - outb(base+EL_AC,EL_AC_HOST); + bus_space_write_1(sc->bst, + sc->bsh, + EL_AC, + EL_AC_HOST); } } else @@ -389,8 +441,9 @@ /* Now give the card a chance to receive. * Gotta love 3c501s... */ - (void)inb(base+EL_AS); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_AS); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, + (EL_AC_IRQE|EL_AC_RX)); splx(s); /* Interrupt here */ s = splimp(); @@ -409,11 +462,12 @@ gpl = EL_BUFSIZ - len; dprintf(("el: xmit...")); - outb((sc->el_base)+EL_GPBL,(gpl & 0xff)); - outb((sc->el_base)+EL_GPBH,((gpl>>8)&0xff)); - outb((sc->el_base)+EL_AC,EL_AC_TXFRX); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBL, (gpl & 0xff)); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBH, ((gpl>>8)&0xff)); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_TXFRX); i = 20000; - while((inb((sc->el_base)+EL_AS) & EL_AS_TXBUSY) && (i>0)) + while((bus_space_read_1(sc->bst, sc->bsh, EL_AS) & EL_AS_TXBUSY) && + (i>0)) i--; if(i == 0) { dprintf(("tx not ready\n")); @@ -445,32 +499,32 @@ /* controller interrupt */ static void -elintr(int unit) +elintr(void *arg) { register struct el_softc *sc; - register int base; int stat, rxstat, len, done; /* Get things pointing properly */ - sc = &el_softc[unit]; - base = sc->el_base; + sc = arg; dprintf(("elintr: ")); /* Check board status */ - stat = inb(base+EL_AS); + stat = bus_space_read_1(sc->bst, sc->bsh, EL_AS); if(stat & EL_AS_RXBUSY) { - (void)inb(base+EL_RXC); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_RXC); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, + (EL_AC_IRQE|EL_AC_RX)); return; } done = 0; while(!done) { - rxstat = inb(base+EL_RXS); + rxstat = bus_space_read_1(sc->bst, sc->bsh, EL_RXS); if(rxstat & EL_RXS_STALE) { - (void)inb(base+EL_RXC); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_RXC); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, + (EL_AC_IRQE|EL_AC_RX)); return; } @@ -480,44 +534,60 @@ el_hardreset(sc); /* Put board back into receive mode */ if(sc->arpcom.ac_if.if_flags & IFF_PROMISC) - outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, + (EL_RXC_PROMISC|EL_RXC_AGF| + EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); else - outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); - (void)inb(base+EL_AS); - outb(base+EL_RBC,0); - (void)inb(base+EL_RXC); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, + (EL_RXC_ABROAD|EL_RXC_AGF| + EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_AS); + bus_space_write_1(sc->bst, sc->bsh, EL_RBC, 0); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_RXC); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, + (EL_AC_IRQE|EL_AC_RX)); return; } /* Incoming packet */ - len = inb(base+EL_RBL); - len |= inb(base+EL_RBH) << 8; + len = bus_space_read_1(sc->bst, sc->bsh, EL_RBL); + len |= bus_space_read_1(sc->bst, sc->bsh, EL_RBH) << 8; dprintf(("receive len=%d rxstat=%x ",len,rxstat)); - outb(base+EL_AC,EL_AC_HOST); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_HOST); /* If packet too short or too long, restore rx mode and return */ - if((len <= sizeof(struct ether_header)) || (len > ETHER_MAX_LEN)) { + if((len <= sizeof(struct ether_header)) || + (len > ETHER_MAX_LEN)) { if(sc->arpcom.ac_if.if_flags & IFF_PROMISC) - outb(base+EL_RXC,(EL_RXC_PROMISC|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, + (EL_RXC_PROMISC|EL_RXC_AGF| + EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); else - outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); - (void)inb(base+EL_AS); - outb(base+EL_RBC,0); - (void)inb(base+EL_RXC); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + bus_space_write_1(sc->bst, sc->bsh, EL_RXC, + (EL_RXC_ABROAD|EL_RXC_AGF| + EL_RXC_DSHORT|EL_RXC_DDRIB| + EL_RXC_DOFLOW)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_AS); + bus_space_write_1(sc->bst, sc->bsh, EL_RBC, 0); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_RXC); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, + (EL_AC_IRQE|EL_AC_RX)); return; } sc->arpcom.ac_if.if_ipackets++; /* Copy the data into our buffer */ - outb(base+EL_GPBL,0); - outb(base+EL_GPBH,0); - insb(base+EL_BUF,sc->el_pktbuf,len); - outb(base+EL_RBC,0); - outb(base+EL_AC,EL_AC_RX); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBL, 0); + bus_space_write_1(sc->bst, sc->bsh, EL_GPBH, 0); + bus_space_read_multi_1(sc->bst, sc->bsh, EL_BUF, sc->el_pktbuf, + len); + bus_space_write_1(sc->bst, sc->bsh, EL_RBC, 0); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, EL_AC_RX); dprintf(("%6D-->",sc->el_pktbuf+6,":")); dprintf(("%6D\n",sc->el_pktbuf,":")); @@ -526,7 +596,7 @@ elread(sc,(caddr_t)(sc->el_pktbuf),len); /* Is there another packet? */ - stat = inb(base+EL_AS); + stat = bus_space_read_1(sc->bst, sc->bsh, EL_AS); /* If so, do it all again (i.e. don't set done to 1) */ if(!(stat & EL_AS_RXBUSY)) @@ -535,8 +605,8 @@ done = 1; } - (void)inb(base+EL_RXC); - outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); + (void)bus_space_read_1(sc->bst, sc->bsh, EL_RXC); + bus_space_write_1(sc->bst, sc->bsh, EL_AC, (EL_AC_IRQE|EL_AC_RX)); return; }