/* Initialize interface. */ static void el_init(void *xsc) { struct el_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; u_short base = sc->el_base; /* First, reset the board. */ dprintf(("Resetting board...\n")); el_hardreset(sc); /* 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)); 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); /* Configure TX */ dprintf(("Configuring tx...\n")); outb(base+EL_TXC,0); /* Start reception */ dprintf(("Starting reception...\n")); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); /* Set flags appropriately */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; /* And start output. */ el_start(ifp); }
/* Initialize interface. */ void el_init(int unit) { struct el_softc *sc; struct ifnet *ifp; int s; u_short base; /* Set up pointers */ sc = &el_softc[unit]; ifp = &sc->arpcom.ac_if; base = sc->el_base; /* If address not known, do nothing. */ if(ifp->if_addrlist == (struct ifaddr *)0) return; s = splimp(); /* First, reset the board. */ dprintf(("Resetting board...\n")); el_hardreset(unit); /* 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)); 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); /* Configure TX */ dprintf(("Configuring tx...\n")); outb(base+EL_TXC,0); /* Start reception */ dprintf(("Starting reception...\n")); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); /* Set flags appropriately */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; /* And start output. */ el_start(ifp); splx(s); }
/* * Initialize interface. */ void elinit(struct el_softc *sc) { struct ifnet *ifp = &sc->sc_ethercom.ec_if; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; /* First, reset the board. */ el_hardreset(sc); /* Configure rx. */ DPRINTF(("Configuring rx...\n")); if (ifp->if_flags & IFF_PROMISC) bus_space_write_1(iot, ioh, EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC); else bus_space_write_1(iot, ioh, EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD); bus_space_write_1(iot, ioh, EL_RBC, 0); /* Configure TX. */ DPRINTF(("Configuring tx...\n")); bus_space_write_1(iot, ioh, EL_TXC, 0); /* Start reception. */ DPRINTF(("Starting reception...\n")); bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); /* Set flags appropriately. */ ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; /* And start output. */ elstart(ifp); }
/* Attach the interface to the kernel data structures. By the time * this is called, we know that the card exists at the given I/O address. * We still assume that the IRQ given is correct. */ static int el_attach(struct isa_device *idev) { struct el_softc *sc; struct ifnet *ifp; dprintf(("Attaching el%d...\n",idev->id_unit)); /* Get things pointing to the right places. */ idev->id_intr = (inthand2_t *)elintr; sc = &el_softc[idev->id_unit]; ifp = &sc->arpcom.ac_if; /* Now reset the board */ dprintf(("Resetting board...\n")); el_hardreset(sc); /* Initialize ifnet structure */ ifp->if_softc = sc; if_initname(ifp, "el", idev->id_unit); ifp->if_mtu = ETHERMTU; ifp->if_start = el_start; ifp->if_ioctl = el_ioctl; ifp->if_watchdog = el_watchdog; ifp->if_init = el_init; ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX); ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); ifq_set_ready(&ifp->if_snd); /* Now we can attach the interface */ dprintf(("Attaching interface...\n")); ether_ifattach(ifp, sc->arpcom.ac_enaddr, &el_serializer); dprintf(("el_attach() finished.\n")); return(1); }
/* * Controller interrupt. */ int elintr(void *arg) { struct el_softc *sc = arg; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; u_int8_t rxstat; int len; DPRINTF(("elintr: ")); /* Check board status. */ if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) { (void)bus_space_read_1(iot, ioh, EL_RXC); bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); return 0; } for (;;) { rxstat = bus_space_read_1(iot, ioh, EL_RXS); if (rxstat & EL_RXS_STALE) break; /* If there's an overflow, reinit the board. */ if ((rxstat & EL_RXS_NOFLOW) == 0) { DPRINTF(("overflow.\n")); el_hardreset(sc); /* Put board back into receive mode. */ if (sc->sc_ethercom.ec_if.if_flags & IFF_PROMISC) bus_space_write_1(iot, ioh, EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_PROMISC); else bus_space_write_1(iot, ioh, EL_RXC, EL_RXC_AGF | EL_RXC_DSHORT | EL_RXC_DDRIB | EL_RXC_DOFLOW | EL_RXC_ABROAD); (void)bus_space_read_1(iot, ioh, EL_AS); bus_space_write_1(iot, ioh, EL_RBC, 0); break; } /* Incoming packet. */ len = bus_space_read_1(iot, ioh, EL_RBL); len |= bus_space_read_1(iot, ioh, EL_RBH) << 8; DPRINTF(("receive len=%d rxstat=%x ", len, rxstat)); bus_space_write_1(iot, ioh, EL_AC, EL_AC_HOST); /* Pass data up to upper levels. */ elread(sc, len); /* Is there another packet? */ if ((bus_space_read_1(iot, ioh, EL_AS) & EL_AS_RXBUSY) != 0) break; rnd_add_uint32(&sc->rnd_source, rxstat); DPRINTF(("<rescan> ")); } (void)bus_space_read_1(iot, ioh, EL_RXC); bus_space_write_1(iot, ioh, EL_AC, EL_AC_IRQE | EL_AC_RX); return 1; }
/* controller interrupt */ static void elintr(void *arg) { int unit = (int)arg; struct el_softc *sc; int base; int stat, rxstat, len, done; lwkt_serialize_enter(&el_serializer); /* Get things pointing properly */ sc = &el_softc[unit]; base = sc->el_base; dprintf(("elintr: ")); /* Check board status */ stat = inb(base+EL_AS); if(stat & EL_AS_RXBUSY) { inb(base+EL_RXC); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); lwkt_serialize_exit(&el_serializer); return; } done = 0; while(!done) { rxstat = inb(base+EL_RXS); if(rxstat & EL_RXS_STALE) { inb(base+EL_RXC); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); lwkt_serialize_exit(&el_serializer); return; } /* If there's an overflow, reinit the board. */ if(!(rxstat & EL_RXS_NOFLOW)) { dprintf(("overflow.\n")); 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)); else outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); inb(base+EL_AS); outb(base+EL_RBC,0); inb(base+EL_RXC); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); lwkt_serialize_exit(&el_serializer); return; } /* Incoming packet */ len = inb(base+EL_RBL); len |= inb(base+EL_RBH) << 8; dprintf(("receive len=%d rxstat=%x ",len,rxstat)); outb(base+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(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)); else outb(base+EL_RXC,(EL_RXC_ABROAD|EL_RXC_AGF|EL_RXC_DSHORT|EL_RXC_DDRIB|EL_RXC_DOFLOW)); inb(base+EL_AS); outb(base+EL_RBC,0); inb(base+EL_RXC); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); lwkt_serialize_exit(&el_serializer); 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); dprintf(("%6D-->",sc->el_pktbuf+6,":")); dprintf(("%6D\n",sc->el_pktbuf,":")); /* Pass data up to upper levels */ elread(sc,(caddr_t)(sc->el_pktbuf),len); /* Is there another packet? */ stat = inb(base+EL_AS); /* If so, do it all again (i.e. don't set done to 1) */ if(!(stat & EL_AS_RXBUSY)) dprintf(("<rescan> ")); else done = 1; } inb(base+EL_RXC); outb(base+EL_AC,(EL_AC_IRQE|EL_AC_RX)); lwkt_serialize_exit(&el_serializer); }
/* Attach the interface to the kernel data structures. By the time * this is called, we know that the card exists at the given I/O address. * We still assume that the IRQ given is correct. */ int el_attach(struct isa_device *idev) { struct el_softc *sc; struct ifnet *ifp; struct ifaddr *ifa; struct sockaddr_dl *sdl; u_short base; int t; dprintf(("Attaching el%d...\n",idev->id_unit)); /* Get things pointing to the right places. */ sc = &el_softc[idev->id_unit]; ifp = &sc->arpcom.ac_if; base = sc->el_base; /* Now reset the board */ dprintf(("Resetting board...\n")); el_hardreset(idev->id_unit); /* Initialize ifnet structure */ ifp->if_unit = idev->id_unit; ifp->if_name = "el"; ifp->if_mtu = ETHERMTU; ifp->if_init = el_init; ifp->if_output = ether_output; ifp->if_start = el_start; ifp->if_ioctl = el_ioctl; ifp->if_reset = el_reset; ifp->if_watchdog = el_watchdog; ifp->if_flags = (IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS); /* Now we can attach the interface */ dprintf(("Attaching interface...\n")); if_attach(ifp); kdc_el[idev->id_unit].kdc_state = DC_BUSY; /* Put the station address in the ifa address list's AF_LINK * entry, if any. */ ifa = ifp->if_addrlist; while ((ifa != NULL) && (ifa->ifa_addr != NULL) && (ifa->ifa_addr->sa_family != AF_LINK)) ifa = ifa->ifa_next; if((ifa != NULL) && (ifa->ifa_addr != NULL)) { sdl = (struct sockaddr_dl *)ifa->ifa_addr; sdl->sdl_type = IFT_ETHER; sdl->sdl_alen = ETHER_ADDR_LEN; sdl->sdl_slen = 0; bcopy(sc->arpcom.ac_enaddr,LLADDR(sdl),ETHER_ADDR_LEN); } /* Print out some information for the user */ printf("el%d: 3c501 address %s\n",idev->id_unit, ether_sprintf(sc->arpcom.ac_enaddr)); /* Finally, attach to bpf filter if it is present. */ #if NBPFILTER > 0 dprintf(("Attaching to BPF...\n")); bpfattach(&sc->bpf,ifp,DLT_EN10MB,sizeof(struct ether_header)); #endif dprintf(("el_attach() finished.\n")); return(1); }