static void ex_probemedia(void) { int i, j; struct mtabentry *m; /* test for presence of connectors */ GO_WINDOW(3); i = CSR_READ_1(ELINK_W3_RESET_OPTIONS); j = (CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2) & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT; GO_WINDOW(0); for (ether_medium = 0, m = mediatab; ether_medium < sizeof(mediatab) / sizeof(mediatab[0]); ether_medium++, m++) { if (j == m->address_cfg) { if (!(i & m->config_bit)) { printf("%s not present\n", m->name); goto bad; } printf("using %s\n", m->name); return; } } printf("unknown connector\n"); bad: ether_medium = -1; }
/* * Back-end attach and configure. */ void epconfig(struct ep_softc *sc, u_short chipset, u_int8_t *enaddr) { struct ifnet *ifp = &sc->sc_arpcom.ac_if; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; u_int16_t i; sc->ep_chipset = chipset; /* * We could have been groveling around in other register * windows in the front-end; make sure we're in window 0 * to read the EEPROM. */ GO_WINDOW(0); if (enaddr == NULL) { /* * Read the station address from the eeprom. */ for (i = 0; i < 3; i++) { u_int16_t x = ep_read_eeprom(sc, i); sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8; sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x; } } else {
void ep_get_media(struct ep_softc *sc) { u_int16_t config; GO_WINDOW(0); config = inw(BASE + EP_W0_CONFIG_CTRL); if (config & IS_AUI) sc->ep_connectors |= AUI; if (config & IS_BNC) sc->ep_connectors |= BNC; if (config & IS_UTP) sc->ep_connectors |= UTP; if (!(sc->ep_connectors & 7)) { if (bootverbose) if_printf(&sc->arpcom.ac_if, "no connectors!\n"); } /* * This works for most of the cards so we'll do it here. * The cards that require something different can override * this later on. */ sc->ep_connector = inw(BASE + EP_W0_ADDRESS_CFG) >> ACF_CONNECTOR_BITS; return; }
static int ep_mca_attach(device_t dev) { struct ep_softc *sc = device_get_softc(dev); int error = 0; if ((error = ep_alloc(dev))) goto bad; sc->stat = F_ACCESS_32_BITS; ep_get_media(sc); GO_WINDOW(sc, 0); SET_IRQ(sc, rman_get_start(sc->irq)); if ((error = ep_attach(sc))) goto bad; if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ep_intr, sc, &sc->ep_intrhand))) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); goto bad; } return (0); bad: ep_free(dev); return (error); }
void ex_set_media(void) { int config0, config1; CSR_WRITE_2(ELINK_W3_MAC_CONTROL, 0); if (ether_medium == ETHERMEDIUM_MII) goto setcfg; GO_WINDOW(4); CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, 0); CSR_WRITE_2(ELINK_COMMAND, STOP_TRANSCEIVER); delay(800); switch (ether_medium) { case ETHERMEDIUM_UTP: CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, JABBER_GUARD_ENABLE | LINKBEAT_ENABLE); break; case ETHERMEDIUM_BNC: CSR_WRITE_2(ELINK_COMMAND, START_TRANSCEIVER); delay(800); break; case ETHERMEDIUM_AUI: CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, SQE_ENABLE); delay(800); break; case ETHERMEDIUM_100TX: CSR_WRITE_2(ELINK_W4_MEDIA_TYPE, LINKBEAT_ENABLE); break; } setcfg: GO_WINDOW(3); config0 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG); config1 = CSR_READ_2(ELINK_W3_INTERNAL_CONFIG + 2); config1 = config1 & ~CONFIG_MEDIAMASK; config1 |= (mediatab[ether_medium].address_cfg << CONFIG_MEDIAMASK_SHIFT); CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG, config0); CSR_WRITE_2(ELINK_W3_INTERNAL_CONFIG + 2, config1); }
static int ep_ifmedia_upd(struct ifnet *ifp) { struct ep_softc * sc = ifp->if_softc; int i = 0, j; GO_WINDOW(0); outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); GO_WINDOW(4); outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP); GO_WINDOW(0); switch (IFM_SUBTYPE(sc->ifmedia.ifm_media)) { case IFM_10_T: if (sc->ep_connectors & UTP) { i = ACF_CONNECTOR_UTP; GO_WINDOW(4); outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); } break; case IFM_10_2: if (sc->ep_connectors & BNC) { i = ACF_CONNECTOR_BNC; outw(BASE + EP_COMMAND, START_TRANSCEIVER); DELAY(DELAY_MULTIPLE * 1000); } break; case IFM_10_5: if (sc->ep_connectors & AUI) i = ACF_CONNECTOR_AUI; break; default: i = sc->ep_connector; if_printf(ifp, "strange connector type in EEPROM: " "assuming AUI\n"); break; } GO_WINDOW(0); j = inw(BASE + EP_W0_ADDRESS_CFG) & 0x3fff; outw(BASE + EP_W0_ADDRESS_CFG, j | (i << ACF_CONNECTOR_BITS)); return (0); }
/* * Bring device up. */ void ex_init(void) { int i; ex_waitcmd(); EtherStop(); /* * Set the station address and clear the station mask. The latter * is needed for 90x cards, 0 is the default for 90xB cards. */ GO_WINDOW(2); for (i = 0; i < 6; i++) { CSR_WRITE_1(ELINK_W2_ADDR_0 + i, myethaddr[i]); CSR_WRITE_1(ELINK_W2_RECVMASK_0 + i, 0); } GO_WINDOW(3); CSR_WRITE_2(ELINK_COMMAND, RX_RESET); ex_waitcmd(); CSR_WRITE_2(ELINK_COMMAND, TX_RESET); ex_waitcmd(); CSR_WRITE_2(ELINK_COMMAND, SET_INTR_MASK | 0); /* disable */ CSR_WRITE_2(ELINK_COMMAND, ACK_INTR | 0xff); ex_set_media(); CSR_WRITE_2(ELINK_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST); CSR_WRITE_4(ELINK_DNLISTPTR, 0); CSR_WRITE_2(ELINK_COMMAND, TX_ENABLE); CSR_WRITE_4(ELINK_UPLISTPTR, RECVBUF_PHYS); CSR_WRITE_2(ELINK_COMMAND, RX_ENABLE); CSR_WRITE_2(ELINK_COMMAND, ELINK_UPUNSTALL); GO_WINDOW(1); }
void ep_get_macaddr(struct ep_softc *sc, uint8_t *addr) { int i; u_int16_t * macaddr = (u_int16_t *)addr; GO_WINDOW(0); for(i = EEPROM_NODE_ADDR_0; i <= EEPROM_NODE_ADDR_2; i++) { macaddr[i] = htons(get_e(sc, i)); } return; }
/* * Read EEPROM data. * XXX what to do if EEPROM doesn't unbusy? */ uint16_t ex_read_eeprom(int offset) { uint16_t data = 0; GO_WINDOW(0); if (ex_eeprom_busy()) goto out; CSR_WRITE_1(ELINK_W0_EEPROM_COMMAND, READ_EEPROM | (offset & 0x3f)); if (ex_eeprom_busy()) goto out; data = CSR_READ_2(ELINK_W0_EEPROM_DATA); out: return data; }
int ep_alloc(device_t dev) { struct ep_softc * sc = device_get_softc(dev); int rid; int error = 0; rid = 0; sc->iobase = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (!sc->iobase) { device_printf(dev, "No I/O space?!\n"); error = ENXIO; goto bad; } rid = 0; sc->irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE); if (!sc->irq) { device_printf(dev, "No irq?!\n"); error = ENXIO; goto bad; } if_initname(&sc->arpcom.ac_if, device_get_name(dev), device_get_unit(dev)); sc->stat = 0; /* 16 bit access */ sc->ep_io_addr = rman_get_start(sc->iobase); sc->ep_btag = rman_get_bustag(sc->iobase); sc->ep_bhandle = rman_get_bushandle(sc->iobase); sc->ep_connectors = 0; sc->ep_connector = 0; GO_WINDOW(0); sc->epb.cmd_off = 0; sc->epb.prod_id = get_e(sc, EEPROM_PROD_ID); sc->epb.res_cfg = get_e(sc, EEPROM_RESOURCE_CFG); bad: return (error); }
static int ep_pccard_attach(device_t dev) { struct ep_softc * sc = device_get_softc(dev); struct ifnet * ifp = &sc->arpcom.ac_if; int error = 0; if ((error = ep_alloc(dev))) { device_printf(dev, "ep_alloc() failed! (%d)\n", error); goto bad; } sc->epb.cmd_off = 0; sc->epb.prod_id = get_e(sc, EEPROM_PROD_ID); if (!ep_pccard_card_attach(&sc->epb)) { sc->epb.cmd_off = 2; sc->epb.prod_id = get_e(sc, EEPROM_PROD_ID); sc->epb.res_cfg = get_e(sc, EEPROM_RESOURCE_CFG); if (!ep_pccard_card_attach(&sc->epb)) { device_printf(dev, "Probe found ID, attach failed so ignore card!\n"); error = ENXIO; goto bad; } } /* ROM size = 0, ROM base = 0 */ /* For now, ignore AUTO SELECT feature of 3C589B and later. */ outw(BASE + EP_W0_ADDRESS_CFG, get_e(sc, EEPROM_ADDR_CFG) & 0xc000); /* Fake IRQ must be 3 */ outw(BASE + EP_W0_RESOURCE_CFG, (sc->epb.res_cfg & 0x0fff) | 0x3000); outw(BASE + EP_W0_PRODUCT_ID, sc->epb.prod_id); if (sc->epb.mii_trans) { /* * turn on the MII transciever */ GO_WINDOW(3); outw(BASE + EP_W3_OPTIONS, 0x8040); DELAY(1000); outw(BASE + EP_W3_OPTIONS, 0xc040); outw(BASE + EP_COMMAND, RX_RESET); outw(BASE + EP_COMMAND, TX_RESET); while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); DELAY(1000); outw(BASE + EP_W3_OPTIONS, 0x8040); } else { ep_get_media(sc); } if ((error = ep_attach(sc))) { device_printf(dev, "ep_attach() failed! (%d)\n", error); goto bad; } error = bus_setup_intr(dev, sc->irq, INTR_MPSAFE, ep_intr, sc, &sc->ep_intrhand, sc->arpcom.ac_if.if_serializer); if (error) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); goto bad; } ifp->if_cpuid = ithread_cpuid(rman_get_start(sc->irq)); KKASSERT(ifp->if_cpuid >= 0 && ifp->if_cpuid < ncpus); return (0); bad: ep_free(dev); return (error); }
static int ep_eisa_attach(device_t dev) { struct ep_softc *sc = device_get_softc(dev); struct resource *eisa_io = NULL; uint32_t eisa_iobase; int irq; int error = 0; int rid; rid = 1; eisa_io = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (!eisa_io) { device_printf(dev, "No I/O space?!\n"); error = ENXIO; goto bad; } eisa_iobase = rman_get_start(eisa_io); /* Reset and Enable the card */ outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_RESET_ADAPTER); DELAY(1000); /* we must wait at least 1 ms */ outb(eisa_iobase + EP_W0_CONFIG_CTRL, W0_P4_CMD_ENABLE_ADAPTER); /* Now the registers are availible through the lower ioport */ if ((error = ep_alloc(dev))) { device_printf(dev, "ep_alloc() failed! (%d)\n", error); goto bad; } switch (eisa_get_id(dev)) { case EISA_DEVICE_ID_3COM_3C579_BNC: case EISA_DEVICE_ID_3COM_3C579_TP: sc->stat = F_ACCESS_32_BITS; break; } ep_get_media(sc); irq = rman_get_start(sc->irq); if (irq == 9) irq = 2; GO_WINDOW(sc, 0); SET_IRQ(sc, irq); if ((error = ep_attach(sc))) { device_printf(dev, "ep_attach() failed! (%d)\n", error); goto bad; } if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ep_intr, sc, &sc->ep_intrhand))) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); goto bad; } return (0); bad: if (eisa_io) bus_release_resource(dev, SYS_RES_IOPORT, 0, eisa_io); ep_free(dev); return (error); }
static int ep_pccard_attach(device_t dev) { struct ep_softc *sc = device_get_softc(dev); uint16_t result; int error = 0; const struct ep_pccard_product *pp; if ((pp = ep_pccard_lookup(dev)) == NULL) panic("ep_pccard_attach: can't find product in attach."); if (pp->chipset == EP_CHIP_574) { sc->epb.mii_trans = 1; sc->epb.cmd_off = 2; } else { sc->epb.mii_trans = 0; sc->epb.cmd_off = 0; } if ((error = ep_alloc(dev))) { device_printf(dev, "ep_alloc() failed! (%d)\n", error); goto bad; } if (pp->chipset == EP_CHIP_C1) sc->stat |= F_HAS_TX_PLL; /* ROM size = 0, ROM base = 0 */ /* For now, ignore AUTO SELECT feature of 3C589B and later. */ error = ep_get_e(sc, EEPROM_ADDR_CFG, &result); CSR_WRITE_2(sc, EP_W0_ADDRESS_CFG, result & 0xc000); /* * Fake IRQ must be 3 for 3C589 and 3C589B. 3C589D and newer * ignore this value. 3C589C is unknown, as are the other * cards supported by this driver, but it appears to never hurt * and always helps. */ SET_IRQ(sc, 3); CSR_WRITE_2(sc, EP_W0_PRODUCT_ID, sc->epb.prod_id); if (sc->epb.mii_trans) { /* * turn on the MII transciever */ GO_WINDOW(sc, 3); CSR_WRITE_2(sc, EP_W3_OPTIONS, 0x8040); DELAY(1000); CSR_WRITE_2(sc, EP_W3_OPTIONS, 0xc040); CSR_WRITE_2(sc, EP_COMMAND, RX_RESET); CSR_WRITE_2(sc, EP_COMMAND, TX_RESET); EP_BUSY_WAIT(sc); DELAY(1000); CSR_WRITE_2(sc, EP_W3_OPTIONS, 0x8040); } else ep_get_media(sc); /* * The 3C562 (a-c revisions) stores the MAC in the CIS in a * way that's unique to 3com. If we have one of these cards, * scan the CIS for that MAC address, and use it if we find * it. The NetBSD driver says that the ROADRUNNER chips also * do this, which may be true, but none of the cards that I * have include this TUPLE. Always prefer the MAC addr in the * CIS tuple to the one returned by the card, as it appears that * only those cards that need it have this special tuple. */ if (pccard_cis_scan(dev, ep_pccard_mac, sc->eaddr)) sc->stat |= F_ENADDR_SKIP; if ((error = ep_attach(sc))) { device_printf(dev, "ep_attach() failed! (%d)\n", error); goto bad; } if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, NULL, ep_intr, sc, &sc->ep_intrhand))) { device_printf(dev, "bus_setup_intr() failed! (%d)\n", error); goto bad; } return (0); bad: ep_free(dev); return (error); }
int ep_attach(struct ep_softc *sc) { struct ifnet * ifp = NULL; struct ifmedia * ifm = NULL; u_short * p; uint8_t ether_addr[ETHER_ADDR_LEN]; int i; sc->gone = 0; ep_get_macaddr(sc, ether_addr); /* * Setup the station address */ p = (u_short*)ether_addr; GO_WINDOW(2); for (i = 0; i < 3; i++) { outw(BASE + EP_W2_ADDR_0 + (i * 2), ntohs(p[i])); } ifp = &sc->arpcom.ac_if; ifp->if_softc = sc; ifp->if_mtu = ETHERMTU; ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_start = ep_if_start; ifp->if_ioctl = ep_if_ioctl; ifp->if_watchdog = ep_if_watchdog; ifp->if_init = ep_if_init; ifq_set_maxlen(&ifp->if_snd, IFQ_MAXLEN); ifq_set_ready(&ifp->if_snd); if (!sc->epb.mii_trans) { ifmedia_init(&sc->ifmedia, 0, ep_ifmedia_upd, ep_ifmedia_sts); if (sc->ep_connectors & AUI) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_5, 0, NULL); if (sc->ep_connectors & UTP) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_T, 0, NULL); if (sc->ep_connectors & BNC) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_10_2, 0, NULL); if (!sc->ep_connectors) ifmedia_add(&sc->ifmedia, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(&sc->ifmedia, IFM_ETHER|ep_media2if_media[sc->ep_connector]); ifm = &sc->ifmedia; ifm->ifm_media = ifm->ifm_cur->ifm_media; ep_ifmedia_upd(ifp); } ether_ifattach(ifp, ether_addr, NULL); #ifdef EP_LOCAL_STATS sc->rx_no_first = sc->rx_no_mbuf = sc->rx_bpf_disc = sc->rx_overrunf = sc->rx_overrunl = sc->tx_underrun = 0; #endif EP_FSET(sc, F_RX_FIRST); sc->top = sc->mcur = 0; return 0; }
static int vx_pci_attach(device_t dev) { struct vx_softc *sc = device_get_softc(dev); struct ifnet *ifp = &sc->arpcom.ac_if; int rid; rid = PCIR_MAPS; sc->vx_res = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &rid, RF_ACTIVE); if (sc->vx_res == NULL) goto bad; sc->vx_btag = rman_get_bustag(sc->vx_res); sc->vx_bhandle = rman_get_bushandle(sc->vx_res); rid = 0; sc->vx_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_SHAREABLE | RF_ACTIVE); if (sc->vx_irq == NULL) goto bad; if (vxattach(dev) == 0) { goto bad; } /* defect check for 3C590 */ if (pci_get_device(dev) == PCI_PRODUCT_3COM_3C590) { GO_WINDOW(0); if (vxbusyeeprom(sc)) goto bad; CSR_WRITE_2(sc, VX_W0_EEPROM_COMMAND, EEPROM_CMD_RD | EEPROM_SOFT_INFO_2); if (vxbusyeeprom(sc)) goto bad; if (!(CSR_READ_2(sc, VX_W0_EEPROM_DATA) & NO_RX_OVN_ANOMALY)) { kprintf("Warning! Defective early revision adapter!\n"); } } ifq_set_cpuid(&ifp->if_snd, rman_get_cpuid(sc->vx_irq)); if (bus_setup_intr(dev, sc->vx_irq, INTR_MPSAFE, vxintr, sc, &sc->vx_intrhand, ifp->if_serializer) ) { ether_ifdetach(&sc->arpcom.ac_if); goto bad; } return(0); bad: if (sc->vx_res != NULL) bus_release_resource(dev, SYS_RES_IOPORT, 0, sc->vx_res); if (sc->vx_irq != NULL) bus_release_resource(dev, SYS_RES_IRQ, 0, sc->vx_irq); return(ENXIO); }
/************************************************************************** ETH_RESET - Reset adapter ***************************************************************************/ static void t595_reset(struct nic *nic) { int i; /*********************************************************** Reset 3Com 595 card *************************************************************/ /* stop card */ outw(RX_DISABLE, BASE + VX_COMMAND); outw(RX_DISCARD_TOP_PACK, BASE + VX_COMMAND); VX_BUSY_WAIT; outw(TX_DISABLE, BASE + VX_COMMAND); outw(STOP_TRANSCEIVER, BASE + VX_COMMAND); udelay(8000); outw(RX_RESET, BASE + VX_COMMAND); VX_BUSY_WAIT; outw(TX_RESET, BASE + VX_COMMAND); VX_BUSY_WAIT; outw(C_INTR_LATCH, BASE + VX_COMMAND); outw(SET_RD_0_MASK, BASE + VX_COMMAND); outw(SET_INTR_MASK, BASE + VX_COMMAND); outw(SET_RX_FILTER, BASE + VX_COMMAND); /* * initialize card */ VX_BUSY_WAIT; GO_WINDOW(0); /* Disable the card */ /* outw(0, BASE + VX_W0_CONFIG_CTRL); */ /* Configure IRQ to none */ /* outw(SET_IRQ(0), BASE + VX_W0_RESOURCE_CFG); */ /* Enable the card */ /* outw(ENABLE_DRQ_IRQ, BASE + VX_W0_CONFIG_CTRL); */ GO_WINDOW(2); /* Reload the ether_addr. */ for (i = 0; i < ETH_ALEN; i++) outb(nic->node_addr[i], BASE + VX_W2_ADDR_0 + i); outw(RX_RESET, BASE + VX_COMMAND); VX_BUSY_WAIT; outw(TX_RESET, BASE + VX_COMMAND); VX_BUSY_WAIT; /* Window 1 is operating window */ GO_WINDOW(1); for (i = 0; i < 31; i++) inb(BASE + VX_W1_TX_STATUS); outw(SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); outw(SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL, BASE + VX_COMMAND); /* * Attempt to get rid of any stray interrupts that occured during * configuration. On the i386 this isn't possible because one may * already be queued. However, a single stray interrupt is * unimportant. */ outw(ACK_INTR | 0xff, BASE + VX_COMMAND); outw(SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST|FIL_MULTICAST, BASE + VX_COMMAND); vxsetlink(); /*{ int i,j; i = CONNECTOR_TX; GO_WINDOW(3); j = inl(BASE + VX_W3_INTERNAL_CFG) & ~INTERNAL_CONNECTOR_MASK; outl(BASE + VX_W3_INTERNAL_CFG, j | (i <<INTERNAL_CONNECTOR_BITS)); GO_WINDOW(4); outw(LINKBEAT_ENABLE, BASE + VX_W4_MEDIA_TYPE); GO_WINDOW(1); }*/ /* start tranciever and receiver */ outw(RX_ENABLE, BASE + VX_COMMAND); outw(TX_ENABLE, BASE + VX_COMMAND); }
/************************************************************************** ETH_RESET - Reset adapter ***************************************************************************/ void epreset(void) { int i; /*********************************************************** Reset 3Com 509 card *************************************************************/ epstop(); /* * initialize card */ while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS) continue; GO_WINDOW(0); /* Disable the card */ outw(BASE + EP_W0_CONFIG_CTRL, 0); /* Configure IRQ to none */ outw(BASE + EP_W0_RESOURCE_CFG, SET_IRQ(0)); /* Enable the card */ outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); GO_WINDOW(2); /* Reload the ether_addr. */ for (i = 0; i < 6; i++) outb(BASE + EP_W2_ADDR_0 + i, eth_myaddr[i]); outw(BASE + EP_COMMAND, RX_RESET); outw(BASE + EP_COMMAND, TX_RESET); /* Window 1 is operating window */ GO_WINDOW(1); for (i = 0; i < 31; i++) inb(BASE + EP_W1_TX_STATUS); /* get rid of stray intr's */ outw(BASE + EP_COMMAND, ACK_INTR | 0xff); outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS); outw(BASE + EP_COMMAND, SET_INTR_MASK); outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST); /* configure BNC */ if (ether_medium == ETHERMEDIUM_BNC) { outw(BASE + EP_COMMAND, START_TRANSCEIVER); delay(1000); } /* configure UTP */ if (ether_medium == ETHERMEDIUM_UTP) { GO_WINDOW(4); outw(BASE + EP_W4_MEDIA_TYPE, ENABLE_UTP); GO_WINDOW(1); } /* start tranciever and receiver */ outw(BASE + EP_COMMAND, RX_ENABLE); outw(BASE + EP_COMMAND, TX_ENABLE); /* set early threshold for minimal packet length */ outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | 64); outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16); }
/* * The order in here seems important. Otherwise we may not receive * interrupts. ?! */ static void ep_if_init(void *xsc) { struct ep_softc *sc = xsc; struct ifnet *ifp = &sc->arpcom.ac_if; int i; if (sc->gone) return; crit_enter(); while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); GO_WINDOW(0); outw(BASE + EP_COMMAND, STOP_TRANSCEIVER); GO_WINDOW(4); outw(BASE + EP_W4_MEDIA_TYPE, DISABLE_UTP); GO_WINDOW(0); /* Disable the card */ outw(BASE + EP_W0_CONFIG_CTRL, 0); /* Enable the card */ outw(BASE + EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); GO_WINDOW(2); /* Reload the ether_addr. */ for (i = 0; i < 6; i++) outb(BASE + EP_W2_ADDR_0 + i, sc->arpcom.ac_enaddr[i]); outw(BASE + EP_COMMAND, RX_RESET); outw(BASE + EP_COMMAND, TX_RESET); while (inw(BASE + EP_STATUS) & S_COMMAND_IN_PROGRESS); /* Window 1 is operating window */ GO_WINDOW(1); for (i = 0; i < 31; i++) inb(BASE + EP_W1_TX_STATUS); /* get rid of stray intr's */ outw(BASE + EP_COMMAND, ACK_INTR | 0xff); outw(BASE + EP_COMMAND, SET_RD_0_MASK | S_5_INTS); outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); if (ifp->if_flags & IFF_PROMISC) outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_GROUP | FIL_BRDCST | FIL_ALL); else outw(BASE + EP_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_GROUP | FIL_BRDCST); if (!sc->epb.mii_trans) { ep_ifmedia_upd(ifp); } outw(BASE + EP_COMMAND, RX_ENABLE); outw(BASE + EP_COMMAND, TX_ENABLE); ifp->if_flags |= IFF_RUNNING; ifq_clr_oactive(&ifp->if_snd); /* just in case */ #ifdef EP_LOCAL_STATS sc->rx_no_first = sc->rx_no_mbuf = sc->rx_overrunf = sc->rx_overrunl = sc->tx_underrun = 0; #endif EP_FSET(sc, F_RX_FIRST); if (sc->top) { m_freem(sc->top); sc->top = sc->mcur = 0; } outw(BASE + EP_COMMAND, SET_RX_EARLY_THRESH | RX_INIT_EARLY_THRESH); outw(BASE + EP_COMMAND, SET_TX_START_THRESH | 16); /* * Store up a bunch of mbuf's for use later. (MAX_MBS). First we free up * any that we had in case we're being called from intr or somewhere * else. */ GO_WINDOW(1); if_devstart(ifp); crit_exit(); }
void ep_intr(void *arg) { struct ep_softc *sc = arg; struct ifnet *ifp = &sc->arpcom.ac_if; int status; /* * quick fix: Try to detect an interrupt when the card goes away. */ if (sc->gone || inw(BASE + EP_STATUS) == 0xffff) { return; } outw(BASE + EP_COMMAND, SET_INTR_MASK); /* disable all Ints */ rescan: while ((status = inw(BASE + EP_STATUS)) & S_5_INTS) { /* first acknowledge all interrupt sources */ outw(BASE + EP_COMMAND, ACK_INTR | (status & S_MASK)); if (status & (S_RX_COMPLETE | S_RX_EARLY)) epread(sc); if (status & S_TX_AVAIL) { /* we need ACK */ ifp->if_timer = 0; ifq_clr_oactive(&ifp->if_snd); GO_WINDOW(1); inw(BASE + EP_W1_FREE_TX); if_devstart(ifp); } if (status & S_CARD_FAILURE) { ifp->if_timer = 0; #ifdef EP_LOCAL_STATS kprintf("\n"); if_printf(ifp, "\n\tStatus: %x\n", status); GO_WINDOW(4); kprintf("\tFIFO Diagnostic: %x\n", inw(BASE + EP_W4_FIFO_DIAG)); kprintf("\tStat: %x\n", sc->stat); kprintf("\tIpackets=%d, Opackets=%d\n", ifp->if_ipackets, ifp->if_opackets); kprintf("\tNOF=%d, NOMB=%d, RXOF=%d, RXOL=%d, TXU=%d\n", sc->rx_no_first, sc->rx_no_mbuf, sc->rx_overrunf, sc->rx_overrunl, sc->tx_underrun); #else #ifdef DIAGNOSTIC if_printf(ifp, "Status: %x (input buffer overflow)\n", status); #else IFNET_STAT_INC(ifp, ierrors, 1); #endif #endif ep_if_init(sc); return; } if (status & S_TX_COMPLETE) { ifp->if_timer = 0; /* we need ACK. we do it at the end */ /* * We need to read TX_STATUS until we get a 0 status in order to * turn off the interrupt flag. */ while ((status = inb(BASE + EP_W1_TX_STATUS)) & TXS_COMPLETE) { if (status & TXS_SUCCES_INTR_REQ); else if (status & (TXS_UNDERRUN | TXS_JABBER | TXS_MAX_COLLISION)) { outw(BASE + EP_COMMAND, TX_RESET); if (status & TXS_UNDERRUN) { #ifdef EP_LOCAL_STATS sc->tx_underrun++; #endif } else { if (status & TXS_JABBER); else /* TXS_MAX_COLLISION - we shouldn't get here */ IFNET_STAT_INC(ifp, collisions, 1); } IFNET_STAT_INC(ifp, oerrors, 1); outw(BASE + EP_COMMAND, TX_ENABLE); /* * To have a tx_avail_int but giving the chance to the * Reception */ if (!ifq_is_empty(&ifp->if_snd)) outw(BASE + EP_COMMAND, SET_TX_AVAIL_THRESH | 8); } outb(BASE + EP_W1_TX_STATUS, 0x0); /* pops up the next * status */ } /* while */ ifq_clr_oactive(&ifp->if_snd); GO_WINDOW(1); inw(BASE + EP_W1_FREE_TX); if_devstart(ifp); } /* end TX_COMPLETE */ } outw(BASE + EP_COMMAND, C_INTR_LATCH); /* ACK int Latch */ if ((status = inw(BASE + EP_STATUS)) & S_5_INTS) goto rescan; /* re-enable Ints */ outw(BASE + EP_COMMAND, SET_INTR_MASK | S_5_INTS); }