diff --git a/sys/dev/eisa/if_ep_eisa.c b/sys/dev/eisa/if_ep_eisa.c index a63dea9ea23f..38844c84b53d 100644 --- a/sys/dev/eisa/if_ep_eisa.c +++ b/sys/dev/eisa/if_ep_eisa.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep_eisa.c,v 1.18 1998/08/12 18:51:52 thorpej Exp $ */ +/* $NetBSD: if_ep_eisa.c,v 1.19 1998/11/04 00:29:55 fvdl Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -137,12 +137,12 @@ struct ep_eisa_product { int eep_flags; /* initial softc flags */ const char *eep_name; /* device name */ } ep_eisa_products[] = { - { "TCM5091", EP_CHIPSET_3C509, + { "TCM5091", ELINK_CHIPSET_3C509, 0, EISA_PRODUCT_TCM5091 }, - { "TCM5092", EP_CHIPSET_3C509, + { "TCM5092", ELINK_CHIPSET_3C509, 0, EISA_PRODUCT_TCM5092 }, - { "TCM5093", EP_CHIPSET_3C509, + { "TCM5093", ELINK_CHIPSET_3C509, 0, EISA_PRODUCT_TCM5093 }, /* @@ -150,13 +150,13 @@ struct ep_eisa_product { * MII connector for an external PHY. We treat it as * `manual' in the core driver. */ - { "TCM5920", EP_CHIPSET_VORTEX, + { "TCM5920", ELINK_CHIPSET_VORTEX, 0, EISA_PRODUCT_TCM5920 }, - { "TCM5970", EP_CHIPSET_VORTEX, + { "TCM5970", ELINK_CHIPSET_VORTEX, 0, EISA_PRODUCT_TCM5970 }, - { "TCM5971", EP_CHIPSET_VORTEX, + { "TCM5971", ELINK_CHIPSET_VORTEX, 0, EISA_PRODUCT_TCM5971 }, - { "TCM5972", EP_CHIPSET_VORTEX, + { "TCM5972", ELINK_CHIPSET_VORTEX, 0, EISA_PRODUCT_TCM5972 }, { NULL, 0, @@ -226,7 +226,7 @@ ep_eisa_attach(parent, self, aux) delay(1000); /* Read the IRQ from the card. */ - irq = bus_space_read_2(iot, ioh, EP_W0_RESOURCE_CFG) >> 12; + irq = bus_space_read_2(iot, ioh, ELINK_W0_RESOURCE_CFG) >> 12; eep = ep_eisa_lookup(ea); if (eep == NULL) { @@ -240,7 +240,7 @@ ep_eisa_attach(parent, self, aux) sc->disable = NULL; sc->enabled = 1; - sc->bustype = EP_BUS_EISA; + sc->bustype = ELINK_BUS_EISA; sc->ep_flags = eep->eep_flags; if (eisa_intr_map(ec, irq, &ih)) { diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c index 4fbfa226bc7c..973584cb2338 100644 --- a/sys/dev/ic/elink3.c +++ b/sys/dev/ic/elink3.c @@ -1,4 +1,4 @@ -/* $NetBSD: elink3.c,v 1.46 1998/08/28 18:16:02 thorpej Exp $ */ +/* $NetBSD: elink3.c,v 1.47 1998/11/04 00:29:28 fvdl Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -136,7 +136,7 @@ struct ep_media { int epm_mpbit; /* media present bit */ const char *epm_name; /* name of medium */ int epm_ifmedia; /* ifmedia word for medium */ - int epm_epmedia; /* EPMEDIA_* constant */ + int epm_epmedia; /* ELINKMEDIA_* constant */ }; /* @@ -150,24 +150,24 @@ struct ep_media { * MII and real PHYs attached; no `native' media. */ struct ep_media ep_vortex_media[] = { - { EP_PCI_10BASE_T, "10baseT", IFM_ETHER|IFM_10_T, - EPMEDIA_10BASE_T }, - { EP_PCI_10BASE_T, "10baseT-FDX", IFM_ETHER|IFM_10_T|IFM_FDX, - EPMEDIA_10BASE_T }, - { EP_PCI_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5, - EPMEDIA_AUI }, - { EP_PCI_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2, - EPMEDIA_10BASE_2 }, - { EP_PCI_100BASE_TX, "100baseTX", IFM_ETHER|IFM_100_TX, - EPMEDIA_100BASE_TX }, - { EP_PCI_100BASE_TX, "100baseTX-FDX",IFM_ETHER|IFM_100_TX|IFM_FDX, - EPMEDIA_100BASE_TX }, - { EP_PCI_100BASE_FX, "100baseFX", IFM_ETHER|IFM_100_FX, - EPMEDIA_100BASE_FX }, - { EP_PCI_100BASE_MII, "manual", IFM_ETHER|IFM_MANUAL, - EPMEDIA_MII }, - { EP_PCI_100BASE_T4, "100baseT4", IFM_ETHER|IFM_100_T4, - EPMEDIA_100BASE_T4 }, + { ELINK_PCI_10BASE_T, "10baseT", IFM_ETHER|IFM_10_T, + ELINKMEDIA_10BASE_T }, + { ELINK_PCI_10BASE_T, "10baseT-FDX", IFM_ETHER|IFM_10_T|IFM_FDX, + ELINKMEDIA_10BASE_T }, + { ELINK_PCI_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5, + ELINKMEDIA_AUI }, + { ELINK_PCI_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2, + ELINKMEDIA_10BASE_2 }, + { ELINK_PCI_100BASE_TX, "100baseTX", IFM_ETHER|IFM_100_TX, + ELINKMEDIA_100BASE_TX }, + { ELINK_PCI_100BASE_TX, "100baseTX-FDX",IFM_ETHER|IFM_100_TX|IFM_FDX, + ELINKMEDIA_100BASE_TX }, + { ELINK_PCI_100BASE_FX, "100baseFX", IFM_ETHER|IFM_100_FX, + ELINKMEDIA_100BASE_FX }, + { ELINK_PCI_100BASE_MII, "manual", IFM_ETHER|IFM_MANUAL, + ELINKMEDIA_MII }, + { ELINK_PCI_100BASE_T4, "100baseT4", IFM_ETHER|IFM_100_T4, + ELINKMEDIA_100BASE_T4 }, { 0, NULL, 0, 0 }, }; @@ -177,12 +177,12 @@ struct ep_media ep_vortex_media[] = { * in the 3c509, 3c579, and 3c589. */ struct ep_media ep_509_media[] = { - { EP_W0_CC_UTP, "10baseT", IFM_ETHER|IFM_10_T, - EPMEDIA_10BASE_T }, - { EP_W0_CC_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5, - EPMEDIA_AUI }, - { EP_W0_CC_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2, - EPMEDIA_10BASE_2 }, + { ELINK_W0_CC_UTP, "10baseT", IFM_ETHER|IFM_10_T, + ELINKMEDIA_10BASE_T }, + { ELINK_W0_CC_AUI, "10base5/AUI", IFM_ETHER|IFM_10_5, + ELINKMEDIA_AUI }, + { ELINK_W0_CC_BNC, "10base2/BNC", IFM_ETHER|IFM_10_2, + ELINKMEDIA_10BASE_2 }, { 0, NULL, 0, 0 }, }; @@ -242,14 +242,14 @@ ep_w1_reg(sc, reg) { switch (sc->ep_chipset) { - case EP_CHIPSET_CORKSCREW: + case ELINK_CHIPSET_CORKSCREW: return (reg + 0x10); - case EP_CHIPSET_ROADRUNNER: + case ELINK_CHIPSET_ROADRUNNER: switch (reg) { - case EP_W1_FREE_TX: - case EP_W1_RUNNER_RDCTL: - case EP_W1_RUNNER_WRCTL: + case ELINK_W1_FREE_TX: + case ELINK_W1_RUNNER_RDCTL: + case ELINK_W1_RUNNER_WRCTL: return (reg); } return (reg + 0x10); @@ -277,7 +277,7 @@ ep_complete_cmd(sc, cmd, arg) #ifdef notyet /* if this adapter family has S_COMMAND_IN_PROGRESS, use it */ - while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS) + while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS) ; else #else @@ -317,11 +317,11 @@ epconfig(sc, chipset, enaddr) u_int16_t x; if (epbusyeeprom(sc)) return; /* XXX why is eeprom busy? */ - bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND, + bus_space_write_2(iot, ioh, ELINK_W0_EEPROM_COMMAND, READ_EEPROM | i); if (epbusyeeprom(sc)) return; /* XXX why is eeprom busy? */ - x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA); + x = bus_space_read_2(iot, ioh, ELINK_W0_EEPROM_DATA); myla[(i << 1)] = x >> 8; myla[(i << 1) + 1] = x; } @@ -340,25 +340,25 @@ epconfig(sc, chipset, enaddr) * read back the threshold register directly, and see if the * threshold value was shifted or not. */ - bus_space_write_2(iot, ioh, EP_COMMAND, - SET_TX_AVAIL_THRESH | EP_LARGEWIN_PROBE ); + bus_space_write_2(iot, ioh, ELINK_COMMAND, + SET_TX_AVAIL_THRESH | ELINK_LARGEWIN_PROBE ); GO_WINDOW(5); - i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH); + i = bus_space_read_2(iot, ioh, ELINK_W5_TX_AVAIL_THRESH); GO_WINDOW(1); switch (i) { - case EP_LARGEWIN_PROBE: - case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK): + case ELINK_LARGEWIN_PROBE: + case (ELINK_LARGEWIN_PROBE & ELINK_LARGEWIN_MASK): sc->ep_pktlenshift = 0; break; - case (EP_LARGEWIN_PROBE << 2): + case (ELINK_LARGEWIN_PROBE << 2): sc->ep_pktlenshift = 2; break; default: printf("%s: wrote 0x%x to TX_AVAIL_THRESH, read back 0x%x. " "Interface disabled\n", - sc->sc_dev.dv_xname, EP_LARGEWIN_PROBE, (int) i); + sc->sc_dev.dv_xname, ELINK_LARGEWIN_PROBE, (int) i); return; } @@ -367,7 +367,7 @@ epconfig(sc, chipset, enaddr) * start the interface. * XXX should be in epinit()? */ - bus_space_write_2(iot, ioh, EP_COMMAND, + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift)); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); @@ -398,7 +398,7 @@ epconfig(sc, chipset, enaddr) /* * Display some additional information, if pertinent. */ - if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) + if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER) printf("%s: RoadRunner FIFO buffer enabled\n", sc->sc_dev.dv_xname); @@ -417,14 +417,14 @@ epconfig(sc, chipset, enaddr) * Now, determine which media we have. */ switch (sc->ep_chipset) { - case EP_CHIPSET_BOOMERANG: - case EP_CHIPSET_ROADRUNNER: + case ELINK_CHIPSET_BOOMERANG: + case ELINK_CHIPSET_ROADRUNNER: /* * If the device has MII, probe it. We won't be using * any `native' media in this case, only PHYs. If * we don't, just treat the Boomerang like the Vortex. */ - if (sc->ep_flags & EP_FLAGS_MII) { + if (sc->ep_flags & ELINK_FLAGS_MII) { mii_phy_probe(&sc->sc_dev, &sc->sc_mii, 0xffffffff); if (LIST_FIRST(&sc->sc_mii.mii_phys) == NULL) { ifmedia_add(&sc->sc_mii.mii_media, @@ -439,7 +439,7 @@ epconfig(sc, chipset, enaddr) } /* FALLTHROUGH */ - case EP_CHIPSET_VORTEX: + case ELINK_CHIPSET_VORTEX: ep_vortex_probemedia(sc); break; @@ -464,8 +464,8 @@ epconfig(sc, chipset, enaddr) /* Establish callback to reset card when we reboot. */ shutdownhook_establish(epshutdown, sc); - ep_complete_cmd(sc, EP_COMMAND, RX_RESET); - ep_complete_cmd(sc, EP_COMMAND, TX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET); } @@ -492,8 +492,8 @@ ep_internalconfig(sc) "5:3", "3:1", "1:1", "3:5" }; GO_WINDOW(3); - config0 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG); - config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2); + config0 = (u_int)bus_space_read_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG); + config1 = (u_int)bus_space_read_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2); GO_WINDOW(0); ram_size = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT; @@ -533,12 +533,12 @@ ep_509_probemedia(sc) int defmedia = 0; GO_WINDOW(0); - ep_w0_config = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL); + ep_w0_config = bus_space_read_2(iot, ioh, ELINK_W0_CONFIG_CTRL); printf("%s: ", sc->sc_dev.dv_xname); /* Sanity check that there are any media! */ - if ((ep_w0_config & EP_W0_CC_MEDIAMASK) == 0) { + if ((ep_w0_config & ELINK_W0_CC_MEDIAMASK) == 0) { printf("no media present!\n"); ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(ifm, IFM_ETHER|IFM_NONE); @@ -550,11 +550,11 @@ ep_509_probemedia(sc) */ if (epbusyeeprom(sc)) return; /* XXX why is eeprom busy? */ - bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND, + bus_space_write_2(iot, ioh, ELINK_W0_EEPROM_COMMAND, READ_EEPROM | EEPROM_ADDR_CFG); if (epbusyeeprom(sc)) return; /* XXX why is eeprom busy? */ - port = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA) >> 14; + port = bus_space_read_2(iot, ioh, ELINK_W0_EEPROM_DATA) >> 14; #define PRINT(s) printf("%s%s", sep, s); sep = ", " @@ -606,8 +606,8 @@ ep_vortex_probemedia(sc) const char *sep = "", *defmedianame = NULL; GO_WINDOW(3); - config1 = (u_int)bus_space_read_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2); - reset_options = (int)bus_space_read_1(iot, ioh, EP_W3_RESET_OPTIONS); + config1 = (u_int)bus_space_read_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2); + reset_options = (int)bus_space_read_1(iot, ioh, ELINK_W3_RESET_OPTIONS); GO_WINDOW(0); default_media = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT; @@ -615,7 +615,7 @@ ep_vortex_probemedia(sc) printf("%s: ", sc->sc_dev.dv_xname); /* Sanity check that there are any media! */ - if ((reset_options & EP_PCI_MEDIAMASK) == 0) { + if ((reset_options & ELINK_PCI_MEDIAMASK) == 0) { printf("no media present!\n"); ifmedia_add(ifm, IFM_ETHER|IFM_NONE, 0, NULL); ifmedia_set(ifm, IFM_ETHER|IFM_NONE); @@ -670,7 +670,7 @@ ep_tick(arg) int s; #ifdef DIAGNOSTIC - if ((sc->ep_flags & EP_FLAGS_MII) == 0) + if ((sc->ep_flags & ELINK_FLAGS_MII) == 0) panic("ep_tick"); #endif @@ -696,22 +696,22 @@ epinit(sc) bus_space_handle_t ioh = sc->sc_ioh; int i; - while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS) + while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS) ; - if (sc->bustype != EP_BUS_PCI) { + if (sc->bustype != ELINK_BUS_PCI) { GO_WINDOW(0); - bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, 0); - bus_space_write_2(iot, ioh, EP_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); + bus_space_write_2(iot, ioh, ELINK_W0_CONFIG_CTRL, 0); + bus_space_write_2(iot, ioh, ELINK_W0_CONFIG_CTRL, ENABLE_DRQ_IRQ); } - if (sc->bustype == EP_BUS_PCMCIA) { - bus_space_write_2(iot, ioh, EP_W0_RESOURCE_CFG, 0x3f00); + if (sc->bustype == ELINK_BUS_PCMCIA) { + bus_space_write_2(iot, ioh, ELINK_W0_RESOURCE_CFG, 0x3f00); } GO_WINDOW(2); for (i = 0; i < 6; i++) /* Reload the ether_addr. */ - bus_space_write_1(iot, ioh, EP_W2_ADDR_0 + i, + bus_space_write_1(iot, ioh, ELINK_W2_ADDR_0 + i, LLADDR(ifp->if_sadl)[i]); /* @@ -719,20 +719,20 @@ epinit(sc) * A bug workaround for busmastering (Vortex, Demon) cards. */ for (i = 0; i < 6; i++) - bus_space_write_1(iot, ioh, EP_W2_RECVMASK_0 + i, 0); + bus_space_write_1(iot, ioh, ELINK_W2_RECVMASK_0 + i, 0); - ep_complete_cmd(sc, EP_COMMAND, RX_RESET); - ep_complete_cmd(sc, EP_COMMAND, TX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET); GO_WINDOW(1); /* Window 1 is operating window */ for (i = 0; i < 31; i++) - bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS)); + bus_space_read_1(iot, ioh, ep_w1_reg(sc, ELINK_W1_TX_STATUS)); /* Set threshhold for for Tx-space avaiable interrupt. */ - bus_space_write_2(iot, ioh, EP_COMMAND, + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_TX_AVAIL_THRESH | (1600 >> sc->ep_pktlenshift)); - if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) { + if (sc->ep_chipset == ELINK_CHIPSET_ROADRUNNER) { /* * Enable options in the PCMCIA LAN COR register, via * RoadRunner Window 1. @@ -741,23 +741,23 @@ epinit(sc) */ u_int16_t cor; - bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, (1 << 11)); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, (1 << 11)); cor = bus_space_read_2(iot, ioh, 0) & ~0x30; - if (sc->ep_flags & EP_FLAGS_USESHAREDMEM) + if (sc->ep_flags & ELINK_FLAGS_USESHAREDMEM) cor |= 0x10; - if (sc->ep_flags & EP_FLAGS_FORCENOWAIT) + if (sc->ep_flags & ELINK_FLAGS_FORCENOWAIT) cor |= 0x20; bus_space_write_2(iot, ioh, 0, cor); - bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0); - bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_WRCTL, 0); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, 0); } /* Enable interrupts. */ - bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_RD_0_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); - bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_INTR_MASK | S_CARD_FAILURE | S_RX_COMPLETE | S_TX_COMPLETE | S_TX_AVAIL); /* @@ -766,13 +766,13 @@ epinit(sc) * already be queued. However, a single stray interrupt is * unimportant. */ - bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff); + bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | 0xff); epsetfilter(sc); epsetmedia(sc); - bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE); - bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_ENABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_ENABLE); epmbuffill(sc); @@ -780,7 +780,7 @@ epinit(sc) ifp->if_flags |= IFF_RUNNING; ifp->if_flags &= ~IFF_OACTIVE; - if (sc->ep_flags & EP_FLAGS_MII) { + if (sc->ep_flags & ELINK_FLAGS_MII) { /* Start the one second clock. */ timeout(ep_tick, sc, hz); } @@ -802,7 +802,7 @@ epsetfilter(sc) register struct ifnet *ifp = &sc->sc_ethercom.ec_if; GO_WINDOW(1); /* Window 1 is operating window */ - bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_COMMAND, SET_RX_FILTER | + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, SET_RX_FILTER | FIL_INDIVIDUAL | FIL_BRDCST | ((ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0 ) | ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); @@ -832,40 +832,40 @@ epsetmedia(sc) /* Turn everything off. First turn off linkbeat and UTP. */ GO_WINDOW(4); - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, 0x0); + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, 0x0); /* Turn off coax */ - bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER); + bus_space_write_2(iot, ioh, ELINK_COMMAND, STOP_TRANSCEIVER); delay(1000); /* * If the device has MII, select it, and then tell the * PHY which media to use. */ - if (sc->ep_flags & EP_FLAGS_MII) { + if (sc->ep_flags & ELINK_FLAGS_MII) { int config0, config1; GO_WINDOW(3); - if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) { + if (sc->ep_chipset == ELINK_CHIPSET_ROADRUNNER) { int resopt; resopt = bus_space_read_2(iot, ioh, - EP_W3_RESET_OPTIONS); + ELINK_W3_RESET_OPTIONS); bus_space_write_2(iot, ioh, - EP_W3_RESET_OPTIONS, resopt|EP_RUNNER_ENABLE_MII); + ELINK_W3_RESET_OPTIONS, resopt|ELINK_RUNNER_ENABLE_MII); } config0 = (u_int)bus_space_read_2(iot, ioh, - EP_W3_INTERNAL_CONFIG); + ELINK_W3_INTERNAL_CONFIG); config1 = (u_int)bus_space_read_2(iot, ioh, - EP_W3_INTERNAL_CONFIG + 2); + ELINK_W3_INTERNAL_CONFIG + 2); config1 = config1 & ~CONFIG_MEDIAMASK; - config1 |= (EPMEDIA_MII << CONFIG_MEDIAMASK_SHIFT); + config1 |= (ELINKMEDIA_MII << CONFIG_MEDIAMASK_SHIFT); - bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0); - bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG, config0); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2, config1); GO_WINDOW(1); /* back to operating window */ mii_mediachg(&sc->sc_mii); @@ -878,25 +878,25 @@ epsetmedia(sc) GO_WINDOW(4); switch (IFM_SUBTYPE(sc->sc_mii.mii_media.ifm_cur->ifm_media)) { case IFM_10_T: - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, JABBER_GUARD_ENABLE|LINKBEAT_ENABLE); break; case IFM_10_2: - bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER); + bus_space_write_2(iot, ioh, ELINK_COMMAND, START_TRANSCEIVER); DELAY(1000); /* 50ms not enmough? */ break; case IFM_100_TX: case IFM_100_FX: case IFM_100_T4: /* XXX check documentation */ - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, LINKBEAT_ENABLE); DELAY(1000); /* not strictly necessary? */ break; case IFM_10_5: - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, SQE_ENABLE); DELAY(1000); /* not strictly necessary? */ break; @@ -920,30 +920,31 @@ epsetmedia(sc) * Tell the chip which port to use. */ switch (sc->ep_chipset) { - case EP_CHIPSET_VORTEX: - case EP_CHIPSET_BOOMERANG: + case ELINK_CHIPSET_VORTEX: + case ELINK_CHIPSET_BOOMERANG: { int mctl, config0, config1; GO_WINDOW(3); config0 = (u_int)bus_space_read_2(iot, ioh, - EP_W3_INTERNAL_CONFIG); + ELINK_W3_INTERNAL_CONFIG); config1 = (u_int)bus_space_read_2(iot, ioh, - EP_W3_INTERNAL_CONFIG + 2); + ELINK_W3_INTERNAL_CONFIG + 2); config1 = config1 & ~CONFIG_MEDIAMASK; config1 |= (sc->sc_mii.mii_media.ifm_cur->ifm_data << CONFIG_MEDIAMASK_SHIFT); - bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0); - bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG, config0); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2, + config1); - mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL); + mctl = bus_space_read_2(iot, ioh, ELINK_W3_MAC_CONTROL); if (sc->sc_mii.mii_media.ifm_cur->ifm_media & IFM_FDX) mctl |= MAC_CONTROL_FDX; else mctl &= ~MAC_CONTROL_FDX; - bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl); + bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, mctl); break; } default: @@ -951,9 +952,9 @@ epsetmedia(sc) int w0_addr_cfg; GO_WINDOW(0); - w0_addr_cfg = bus_space_read_2(iot, ioh, EP_W0_ADDRESS_CFG); + w0_addr_cfg = bus_space_read_2(iot, ioh, ELINK_W0_ADDRESS_CFG); w0_addr_cfg &= 0x3fff; - bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, w0_addr_cfg | + bus_space_write_2(iot, ioh, ELINK_W0_ADDRESS_CFG, w0_addr_cfg | (sc->sc_mii.mii_media.ifm_cur->ifm_data << 14)); DELAY(1000); break; @@ -985,7 +986,7 @@ ep_media_status(ifp, req) /* * If we have MII, go ask the PHY what's going on. */ - if (sc->ep_flags & EP_FLAGS_MII) { + if (sc->ep_flags & ELINK_FLAGS_MII) { mii_pollstat(&sc->sc_mii); req->ifm_active = sc->sc_mii.mii_media_active; req->ifm_status = sc->sc_mii.mii_media_status; @@ -1001,11 +1002,11 @@ ep_media_status(ifp, req) req->ifm_status = 0; switch (sc->ep_chipset) { - case EP_CHIPSET_VORTEX: - case EP_CHIPSET_BOOMERANG: + case ELINK_CHIPSET_VORTEX: + case ELINK_CHIPSET_BOOMERANG: GO_WINDOW(4); req->ifm_status = IFM_AVALID; - if (bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE) & + if (bus_space_read_2(iot, ioh, ELINK_W4_MEDIA_TYPE) & LINKBEAT_DETECT) req->ifm_status |= IFM_ACTIVE; GO_WINDOW(1); /* back to operating window */ @@ -1060,24 +1061,24 @@ startagain: goto readcheck; } - if (bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_FREE_TX)) < + if (bus_space_read_2(iot, ioh, ep_w1_reg(sc, ELINK_W1_FREE_TX)) < len + pad + 4) { - bus_space_write_2(iot, ioh, EP_COMMAND, + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_TX_AVAIL_THRESH | ((len + pad + 4) >> sc->ep_pktlenshift)); /* not enough room in FIFO */ ifp->if_flags |= IFF_OACTIVE; return; } else { - bus_space_write_2(iot, ioh, EP_COMMAND, - SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE ); + bus_space_write_2(iot, ioh, ELINK_COMMAND, + SET_TX_AVAIL_THRESH | ELINK_THRESH_DISABLE ); } IF_DEQUEUE(&ifp->if_snd, m0); if (m0 == 0) /* not really needed */ return; - bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH | + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_TX_START_THRESH | ((len / 4 + sc->tx_start_thresh) /* >> sc->ep_pktlenshift*/) ); #if NBPFILTER > 0 @@ -1091,9 +1092,9 @@ startagain: */ sh = splhigh(); - txreg = ep_w1_reg(sc, EP_W1_TX_PIO_WR_1); + txreg = ep_w1_reg(sc, ELINK_W1_TX_PIO_WR_1); - if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) { + if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER) { /* * Prime the FIFO buffer counter (number of 16-bit * words about to be written to the FIFO). @@ -1101,13 +1102,13 @@ startagain: * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS * COUNTER IS NON-ZERO! */ - bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_WRCTL, (len + pad) >> 1); } bus_space_write_2(iot, ioh, txreg, len); bus_space_write_2(iot, ioh, txreg, 0xffff); /* Second is meaningless */ - if (EP_IS_BUS_32(sc->bustype)) { + if (ELINK_IS_BUS_32(sc->bustype)) { for (m = m0; m; ) { if (m->m_len > 3) { /* align our reads from core */ @@ -1163,10 +1164,10 @@ startagain: ++ifp->if_opackets; readcheck: - if ((bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS)) & + if ((bus_space_read_2(iot, ioh, ep_w1_reg(sc, ELINK_W1_RX_STATUS)) & ERR_INCOMPLETE) == 0) { /* We received a complete packet. */ - u_int16_t status = bus_space_read_2(iot, ioh, EP_STATUS); + u_int16_t status = bus_space_read_2(iot, ioh, ELINK_STATUS); if ((status & S_INTR_LATCH) == 0) { /* @@ -1212,7 +1213,7 @@ epstatus(sc) * Check the FIFO status and act accordingly */ GO_WINDOW(4); - fifost = bus_space_read_2(iot, ioh, EP_W4_FIFO_DIAG); + fifost = bus_space_read_2(iot, ioh, ELINK_W4_FIFO_DIAG); GO_WINDOW(1); if (fifost & FIFOS_RX_UNDERRUN) { @@ -1257,9 +1258,9 @@ eptxstat(sc) * We need to read+write TX_STATUS until we get a 0 status * in order to turn off the interrupt flag. */ - while ((i = bus_space_read_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS))) + while ((i = bus_space_read_1(iot, ioh, ep_w1_reg(sc, ELINK_W1_TX_STATUS))) & TXS_COMPLETE) { - bus_space_write_1(iot, ioh, ep_w1_reg(sc, EP_W1_TX_STATUS), + bus_space_write_1(iot, ioh, ep_w1_reg(sc, ELINK_W1_TX_STATUS), 0x0); if (i & TXS_JABBER) { @@ -1281,7 +1282,7 @@ eptxstat(sc) epreset(sc); } else if (i & TXS_MAX_COLLISION) { ++sc->sc_ethercom.ec_if.if_collisions; - bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_ENABLE); sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE; } else sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127; @@ -1304,9 +1305,9 @@ epintr(arg) return (0); for (;;) { - bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH); + bus_space_write_2(iot, ioh, ELINK_COMMAND, C_INTR_LATCH); - status = bus_space_read_2(iot, ioh, EP_STATUS); + status = bus_space_read_2(iot, ioh, ELINK_STATUS); if ((status & (S_TX_COMPLETE | S_TX_AVAIL | S_RX_COMPLETE | S_CARD_FAILURE)) == 0) { @@ -1327,7 +1328,7 @@ epintr(arg) * Due to the i386 interrupt queueing, we may get spurious * interrupts occasionally. */ - bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | + bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | (status & (C_INTR_LATCH | C_CARD_FAILURE | C_TX_COMPLETE | @@ -1338,7 +1339,7 @@ epintr(arg) C_UPD_STATS))); #if 0 - status = bus_space_read_2(iot, ioh, EP_STATUS); + status = bus_space_read_2(iot, ioh, ELINK_STATUS); printf("%s: intr%s%s%s%s\n", sc->sc_dev.dv_xname, (status & S_RX_COMPLETE)?" RX_COMPLETE":"", @@ -1389,7 +1390,7 @@ epread(sc) struct ether_header *eh; int len; - len = bus_space_read_2(iot, ioh, ep_w1_reg(sc, EP_W1_RX_STATUS)); + len = bus_space_read_2(iot, ioh, ep_w1_reg(sc, ELINK_W1_RX_STATUS)); again: if (ifp->if_flags & IFF_DEBUG) { @@ -1482,7 +1483,7 @@ again: */ if (epstatus(sc)) { len = bus_space_read_2(iot, ioh, - ep_w1_reg(sc, EP_W1_RX_STATUS)); + ep_w1_reg(sc, ELINK_W1_RX_STATUS)); /* Check if we are stuck and reset [see XXX comment] */ if (len & ERR_INCOMPLETE) { if (ifp->if_flags & IFF_DEBUG) @@ -1497,8 +1498,8 @@ again: return; abort: - bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK); - while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS) + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK); + while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS) ; } @@ -1543,9 +1544,9 @@ epget(sc, totlen) */ sh = splhigh(); - rxreg = ep_w1_reg(sc, EP_W1_RX_PIO_RD_1); + rxreg = ep_w1_reg(sc, ELINK_W1_RX_PIO_RD_1); - if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) { + if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER) { /* * Prime the FIFO buffer counter (number of 16-bit * words about to be read from the FIFO). @@ -1553,7 +1554,7 @@ epget(sc, totlen) * NOTE: NO OTHER ACCESS CAN BE PERFORMED WHILE THIS * COUNTER IS NON-ZERO! */ - bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, totlen >> 1); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, totlen >> 1); } while (totlen > 0) { @@ -1589,7 +1590,7 @@ epget(sc, totlen) m->m_data = newdata; } remaining = len = min(totlen, len); - if (EP_IS_BUS_32(sc->bustype)) { + if (ELINK_IS_BUS_32(sc->bustype)) { u_long offset = mtod(m, u_long); /* * Read bytes up to the point where we are aligned. @@ -1641,13 +1642,13 @@ epget(sc, totlen) rv = top; - bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK); - while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS) + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK); + while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS) ; out: - if (sc->ep_flags & EP_FLAGS_USEFIFOBUFFER) - bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0); + if (sc->ep_flags & ELINK_FLAGS_USEFIFOBUFFER) + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, 0); splx(sh); return rv; @@ -1797,35 +1798,35 @@ epstop(sc) bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; - if (sc->ep_flags & EP_FLAGS_MII) { + if (sc->ep_flags & ELINK_FLAGS_MII) { /* Stop the one second clock. */ untimeout(ep_tick, sc); } - if (sc->ep_chipset == EP_CHIPSET_ROADRUNNER) { + if (sc->ep_chipset == ELINK_CHIPSET_ROADRUNNER) { /* * Clear the FIFO buffer count, thus halting * any currently-running transactions. */ GO_WINDOW(1); /* sanity */ - bus_space_write_2(iot, ioh, EP_W1_RUNNER_WRCTL, 0); - bus_space_write_2(iot, ioh, EP_W1_RUNNER_RDCTL, 0); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_WRCTL, 0); + bus_space_write_2(iot, ioh, ELINK_W1_RUNNER_RDCTL, 0); } - bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISABLE); - bus_space_write_2(iot, ioh, EP_COMMAND, RX_DISCARD_TOP_PACK); - while (bus_space_read_2(iot, ioh, EP_STATUS) & S_COMMAND_IN_PROGRESS) + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISCARD_TOP_PACK); + while (bus_space_read_2(iot, ioh, ELINK_STATUS) & S_COMMAND_IN_PROGRESS) ; - bus_space_write_2(iot, ioh, EP_COMMAND, TX_DISABLE); - bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_DISABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, STOP_TRANSCEIVER); - ep_complete_cmd(sc, EP_COMMAND, RX_RESET); - ep_complete_cmd(sc, EP_COMMAND, TX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, RX_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, TX_RESET); - bus_space_write_2(iot, ioh, EP_COMMAND, C_INTR_LATCH); - bus_space_write_2(iot, ioh, EP_COMMAND, SET_RD_0_MASK); - bus_space_write_2(iot, ioh, EP_COMMAND, SET_INTR_MASK); - bus_space_write_2(iot, ioh, EP_COMMAND, SET_RX_FILTER); + bus_space_write_2(iot, ioh, ELINK_COMMAND, C_INTR_LATCH); + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_RD_0_MASK); + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_INTR_MASK); + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_RX_FILTER); epmbufempty(sc); } @@ -1842,7 +1843,7 @@ epshutdown(arg) if (sc->enabled) { epstop(sc); - ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET); + ep_complete_cmd(sc, ELINK_COMMAND, GLOBAL_RESET); } } @@ -1886,14 +1887,14 @@ epbusyeeprom(sc) bus_space_handle_t ioh = sc->sc_ioh; int i = 100, j; - if (sc->bustype == EP_BUS_PCMCIA) { + if (sc->bustype == ELINK_BUS_PCMCIA) { delay(1000); return 0; } j = 0; /* bad GCC flow analysis */ while (i--) { - j = bus_space_read_2(iot, ioh, EP_W0_EEPROM_COMMAND); + j = bus_space_read_2(iot, ioh, ELINK_W0_EEPROM_COMMAND); if (j & EEPROM_BUSY) delay(100); else @@ -1989,8 +1990,8 @@ ep_mii_setbit(sc, bit) u_int16_t val; /* We assume we're already in Window 4 */ - val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT); - bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, + val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT, val | bit); } @@ -2002,8 +2003,8 @@ ep_mii_clrbit(sc, bit) u_int16_t val; /* We assume we're already in Window 4 */ - val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT); - bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, + val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT, val & ~bit); } @@ -2014,7 +2015,7 @@ ep_mii_readbit(sc, bit) { /* We assume we're already in Window 4 */ - return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT) & + return (bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT) & bit); } @@ -2068,7 +2069,7 @@ ep_mii_readreg(self, phy, reg) GO_WINDOW(4); - bus_space_write_2(sc->sc_iot, sc->sc_ioh, EP_W4_BOOM_PHYSMGMT, 0); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_BOOM_PHYSMGMT, 0); ep_mii_sync(sc); ep_mii_sendbits(sc, MII_COMMAND_START, 2); @@ -2139,11 +2140,11 @@ ep_statchg(self) /* XXX Update ifp->if_baudrate */ GO_WINDOW(3); - mctl = bus_space_read_2(iot, ioh, EP_W3_MAC_CONTROL); + mctl = bus_space_read_2(iot, ioh, ELINK_W3_MAC_CONTROL); if (sc->sc_mii.mii_media_active & IFM_FDX) mctl |= MAC_CONTROL_FDX; else mctl &= ~MAC_CONTROL_FDX; - bus_space_write_2(iot, ioh, EP_W3_MAC_CONTROL, mctl); + bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, mctl); GO_WINDOW(1); /* back to operating window */ } diff --git a/sys/dev/ic/elink3reg.h b/sys/dev/ic/elink3reg.h index 77ec8db93d65..3eedc2a9e6f6 100644 --- a/sys/dev/ic/elink3reg.h +++ b/sys/dev/ic/elink3reg.h @@ -1,4 +1,4 @@ -/* $NetBSD: elink3reg.h,v 1.18 1998/08/26 01:29:03 thorpej Exp $ */ +/* $NetBSD: elink3reg.h,v 1.19 1998/11/04 00:29:29 fvdl Exp $ */ /* * Copyright (c) 1995 Herb Peyerl @@ -35,16 +35,27 @@ * These define the EEPROM data structure. They are used in the probe * function to verify the existance of the adapter after having sent * the ID_Sequence. - * - * There are others but only the ones we use are defined here. */ #define EEPROM_NODE_ADDR_0 0x0 /* Word */ #define EEPROM_NODE_ADDR_1 0x1 /* Word */ #define EEPROM_NODE_ADDR_2 0x2 /* Word */ #define EEPROM_PROD_ID 0x3 /* 0x9[0-f]50 */ +#define EEPROM_MFG_DATE 0x4 /* Manufacturing date */ +#define EEPROM_MFG_DIVSION 0x5 /* Manufacturing division */ +#define EEPROM_MFG_PRODUCT 0x6 /* Product code */ #define EEPROM_MFG_ID 0x7 /* 0x6d50 */ #define EEPROM_ADDR_CFG 0x8 /* Base addr */ #define EEPROM_RESOURCE_CFG 0x9 /* IRQ. Bits 12-15 */ +#define EEPROM_OEM_ADDR0 0xa +#define EEPROM_OEM_ADDR1 0xb +#define EEPROM_OEM_ADDR2 0xc +#define EEPROM_SOFTINFO 0xd +#define EEPROM_COMPAT 0xe +#define EEPROM_SOFTINFO2 0xf +#define EEPROM_CAP 0x10 +#define EEPROM_CONFIG_LOW 0x12 +#define EEPROM_CONFIG_HIGH 0x13 +#define EEPROM_CHECKSUM_EL3 0x17 /* * These are the registers for the 3Com 3c509 and their bit patterns when @@ -52,99 +63,99 @@ * Tasking EISA and ISA Technical Reference" "Beta Draft 10/30/92" manual * from 3com. */ -#define EP_COMMAND 0x0e /* Write. BASE+0x0e is always a command reg. */ -#define EP_STATUS 0x0e /* Read. BASE+0x0e is always status reg. */ -#define EP_WINDOW 0x0f /* Read. BASE+0x0f is always window reg. */ +#define ELINK_COMMAND 0x0e /* Write. BASE+0x0e is always a command reg. */ +#define ELINK_STATUS 0x0e /* Read. BASE+0x0e is always status reg. */ +#define ELINK_WINDOW 0x0f /* Read. BASE+0x0f is always window reg. */ /* * Window 0 registers. Setup. */ /* Write */ -#define EP_W0_EEPROM_DATA 0x0c -#define EP_W0_EEPROM_COMMAND 0x0a -#define EP_W0_RESOURCE_CFG 0x08 -#define EP_W0_ADDRESS_CFG 0x06 -#define EP_W0_CONFIG_CTRL 0x04 +#define ELINK_W0_EEPROM_DATA 0x0c +#define ELINK_W0_EEPROM_COMMAND 0x0a +#define ELINK_W0_RESOURCE_CFG 0x08 +#define ELINK_W0_ADDRESS_CFG 0x06 +#define ELINK_W0_CONFIG_CTRL 0x04 /* Read */ -#define EP_W0_PRODUCT_ID 0x02 -#define EP_W0_MFG_ID 0x00 +#define ELINK_W0_PRODUCT_ID 0x02 +#define ELINK_W0_MFG_ID 0x00 /* * Window 1 registers. Operating Set. */ /* Write */ -#define EP_W1_TX_PIO_WR_2 0x02 -#define EP_W1_TX_PIO_WR_1 0x00 +#define ELINK_W1_TX_PIO_WR_2 0x02 +#define ELINK_W1_TX_PIO_WR_1 0x00 /* Read */ -#define EP_W1_FREE_TX 0x0c -#define EP_W1_TX_STATUS 0x0b /* byte */ -#define EP_W1_TIMER 0x0a /* byte */ -#define EP_W1_RX_STATUS 0x08 -#define EP_W1_RX_PIO_RD_2 0x02 -#define EP_W1_RX_PIO_RD_1 0x00 - +#define ELINK_W1_FREE_TX 0x0c +#define ELINK_W1_TX_STATUS 0x0b /* byte */ +#define ELINK_W1_TIMER 0x0a /* byte */ +#define ELINK_W1_RX_STATUS 0x08 +#define ELINK_W1_RX_PIO_RD_2 0x02 +#define ELINK_W1_RX_PIO_RD_1 0x00 /* * Special registers used by the RoadRunner. These are used to program * a FIFO buffer to reduce the PCMCIA->PCI bridge latency during PIO. */ -#define EP_W1_RUNNER_RDCTL 0x16 -#define EP_W1_RUNNER_WRCTL 0x1c +#define ELINK_W1_RUNNER_RDCTL 0x16 +#define ELINK_W1_RUNNER_WRCTL 0x1c /* * Window 2 registers. Station Address Setup/Read */ /* Read/Write */ -#define EP_W2_RECVMASK_0 0x06 -#define EP_W2_ADDR_5 0x05 -#define EP_W2_ADDR_4 0x04 -#define EP_W2_ADDR_3 0x03 -#define EP_W2_ADDR_2 0x02 -#define EP_W2_ADDR_1 0x01 -#define EP_W2_ADDR_0 0x00 +#define ELINK_W2_RECVMASK_0 0x06 +#define ELINK_W2_ADDR_5 0x05 +#define ELINK_W2_ADDR_4 0x04 +#define ELINK_W2_ADDR_3 0x03 +#define ELINK_W2_ADDR_2 0x02 +#define ELINK_W2_ADDR_1 0x01 +#define ELINK_W2_ADDR_0 0x00 /* * Window 3 registers. Configuration and FIFO Management. */ /* Read */ -#define EP_W3_FREE_TX 0x0c -#define EP_W3_FREE_RX 0x0a +#define ELINK_W3_FREE_TX 0x0c +#define ELINK_W3_FREE_RX 0x0a /* Read/Write, at least on busmastering cards. */ -#define EP_W3_INTERNAL_CONFIG 0x00 /* 32 bits */ -#define EP_W3_OTHER_INT 0x04 /* 8 bits */ -#define EP_W3_PIO_RESERVED 0x05 /* 8 bits */ -#define EP_W3_MAC_CONTROL 0x06 /* 16 bits */ -#define EP_W3_RESET_OPTIONS 0x08 /* 16 bits */ +#define ELINK_W3_INTERNAL_CONFIG 0x00 /* 32 bits */ +#define ELINK_W3_OTHER_INT 0x04 /* 8 bits */ +#define ELINK_W3_PIO_RESERVED 0x05 /* 8 bits */ +#define ELINK_W3_MAC_CONTROL 0x06 /* 16 bits */ +#define ELINK_W3_RESET_OPTIONS 0x08 /* 16 bits */ /* * Window 4 registers. Diagnostics. */ /* Read/Write */ -#define EP_W4_MEDIA_TYPE 0x0a -#define EP_W4_CTRLR_STATUS 0x08 -#define EP_W4_NET_DIAG 0x06 -#define EP_W4_FIFO_DIAG 0x04 -#define EP_W4_HOST_DIAG 0x02 -#define EP_W4_TX_DIAG 0x00 +#define ELINK_W4_MEDIA_TYPE 0x0a +#define ELINK_W4_CTRLR_STATUS 0x08 +#define ELINK_W4_NET_DIAG 0x06 +#define ELINK_W4_FIFO_DIAG 0x04 +#define ELINK_W4_HOST_DIAG 0x02 +#define ELINK_W4_TX_DIAG 0x00 /* * Window 4 offset 8 is the PHY Management register on the * 3c90x. */ -#define EP_W4_BOOM_PHYSMGMT 0x08 +#define ELINK_W4_BOOM_PHYSMGMT 0x08 #define PHYSMGMT_CLK 0x0001 #define PHYSMGMT_DATA 0x0002 #define PHYSMGMT_DIR 0x0004 + /* * Window 5 Registers. Results and Internal status. */ /* Read */ -#define EP_W5_READ_0_MASK 0x0c -#define EP_W5_INTR_MASK 0x0a -#define EP_W5_RX_FILTER 0x08 -#define EP_W5_RX_EARLY_THRESH 0x06 -#define EP_W5_TX_AVAIL_THRESH 0x02 -#define EP_W5_TX_START_THRESH 0x00 +#define ELINK_W5_READ_0_MASK 0x0c +#define ELINK_W5_INTR_MASK 0x0a +#define ELINK_W5_RX_FILTER 0x08 +#define ELINK_W5_RX_EARLY_THRESH 0x06 +#define ELINK_W5_TX_AVAIL_THRESH 0x02 +#define ELINK_W5_TX_START_THRESH 0x00 /* * Window 6 registers. Statistics. @@ -152,6 +163,7 @@ /* Read/Write */ #define TX_TOTAL_OK 0x0c #define RX_TOTAL_OK 0x0a +#define UPPER_FRAMES_OK 0x09 #define TX_DEFERRALS 0x08 #define RX_FRAMES_OK 0x07 #define TX_FRAMES_OK 0x06 @@ -163,16 +175,17 @@ #define TX_CD_LOST 0x00 /* - * Window 7 registers. + * Window 7 registers. * Address and length for a single bus-master DMA transfer. - */ -#define EP_W7_MASTER_ADDDRES 0x00 -#define EP_W7_RX_ERROR 0x04 -#define EP_W7_MASTER_LEN 0x06 -#define EP_W7_RX_STATUS 0x08 -#define EP_W7_TIMER 0x0a -#define EP_W7_TX_STATUS 0x0b -#define EP_W7_MASTER_STATUS 0x0c + * Unused for elink3 cards. + */ +#define ELINK_W7_MASTER_ADDDRES 0x00 +#define ELINK_W7_RX_ERROR 0x04 +#define ELINK_W7_MASTER_LEN 0x06 +#define ELINK_W7_RX_STATUS 0x08 +#define ELINK_W7_TIMER 0x0a +#define ELINK_W7_TX_STATUS 0x0b +#define ELINK_W7_MASTER_STATUS 0x0c /* * Register definitions. @@ -186,62 +199,62 @@ * 10-0: 11-bit arg if any. For commands with no args; * this can be set to anything. */ -#define GLOBAL_RESET (u_short) 0x0000 /* Wait at least 1ms after issuing */ -#define WINDOW_SELECT (u_short) (0x1<<11) -#define START_TRANSCEIVER (u_short) (0x2<<11) /* Read ADDR_CFG reg to determine +#define GLOBAL_RESET (u_int16_t) 0x0000 /* Wait at least 1ms after issuing */ +#define WINDOW_SELECT (u_int16_t) (0x1<<11) +#define START_TRANSCEIVER (u_int16_t) (0x2<<11) /* Read ADDR_CFG reg to determine whether this is needed. If so; wait 800 uSec before using trans- ceiver. */ -#define RX_DISABLE (u_short) (0x3<<11) /* state disabled on power-up */ -#define RX_ENABLE (u_short) (0x4<<11) -#define RX_RESET (u_short) (0x5<<11) -#define RX_DISCARD_TOP_PACK (u_short) (0x8<<11) -#define TX_ENABLE (u_short) (0x9<<11) -#define TX_DISABLE (u_short) (0xa<<11) -#define TX_RESET (u_short) (0xb<<11) -#define REQ_INTR (u_short) (0xc<<11) +#define RX_DISABLE (u_int16_t) (0x3<<11) /* state disabled on power-up */ +#define RX_ENABLE (u_int16_t) (0x4<<11) +#define RX_RESET (u_int16_t) (0x5<<11) +#define RX_DISCARD_TOP_PACK (u_int16_t) (0x8<<11) +#define TX_ENABLE (u_int16_t) (0x9<<11) +#define TX_DISABLE (u_int16_t) (0xa<<11) +#define TX_RESET (u_int16_t) (0xb<<11) +#define REQ_INTR (u_int16_t) (0xc<<11) /* * The following C_* acknowledge the various interrupts. * Some of them don't do anything. See the manual. */ -#define ACK_INTR (u_short) (0xd << 11) -# define C_INTR_LATCH (u_short) (ACK_INTR|0x01) -# define C_CARD_FAILURE (u_short) (ACK_INTR|0x02) -# define C_TX_COMPLETE (u_short) (ACK_INTR|0x04) -# define C_TX_AVAIL (u_short) (ACK_INTR|0x08) -# define C_RX_COMPLETE (u_short) (ACK_INTR|0x10) -# define C_RX_EARLY (u_short) (ACK_INTR|0x20) -# define C_INT_RQD (u_short) (ACK_INTR|0x40) -# define C_UPD_STATS (u_short) (ACK_INTR|0x80) +#define ACK_INTR (u_int16_t) (0xd << 11) +# define C_INTR_LATCH (u_int16_t) (ACK_INTR|0x01) +# define C_CARD_FAILURE (u_int16_t) (ACK_INTR|0x02) +# define C_TX_COMPLETE (u_int16_t) (ACK_INTR|0x04) +# define C_TX_AVAIL (u_int16_t) (ACK_INTR|0x08) +# define C_RX_COMPLETE (u_int16_t) (ACK_INTR|0x10) +# define C_RX_EARLY (u_int16_t) (ACK_INTR|0x20) +# define C_INT_RQD (u_int16_t) (ACK_INTR|0x40) +# define C_UPD_STATS (u_int16_t) (ACK_INTR|0x80) -#define SET_INTR_MASK (u_short) (0x0e<<11) +#define SET_INTR_MASK (u_int16_t) (0x0e<<11) /* busmastering-cards only? */ -#define STATUS_ENABLE (u_short) (0xf<<11) +#define STATUS_ENABLE (u_int16_t) (0xf<<11) -#define SET_RD_0_MASK (u_short) (0x0f<<11) +#define SET_RD_0_MASK (u_int16_t) (0x0f<<11) -#define SET_RX_FILTER (u_short) (0x10<<11) -# define FIL_INDIVIDUAL (u_short) (0x01) -# define FIL_MULTICAST (u_short) (0x02) -# define FIL_BRDCST (u_short) (0x04) -# define FIL_PROMISC (u_short) (0x08) +#define SET_RX_FILTER (u_int16_t) (0x10<<11) +# define FIL_INDIVIDUAL (u_int16_t) (0x01) +# define FIL_MULTICAST (u_int16_t) (0x02) +# define FIL_BRDCST (u_int16_t) (0x04) +# define FIL_PROMISC (u_int16_t) (0x08) -#define SET_RX_EARLY_THRESH (u_short) (0x11<<11) -#define SET_TX_AVAIL_THRESH (u_short) (0x12<<11) -#define SET_TX_START_THRESH (u_short) (0x13<<11) -#define START_DMA (u_short) (0x14<<11) /* busmaster-only */ +#define SET_RX_EARLY_THRESH (u_int16_t) (0x11<<11) +#define SET_TX_AVAIL_THRESH (u_int16_t) (0x12<<11) +#define SET_TX_START_THRESH (u_int16_t) (0x13<<11) +#define START_DMA (u_int16_t) (0x14<<11) /* busmaster-only */ # define START_DMA_TX (START_DMA | 0x0)) /* busmaster-only */ # define START_DMA_RX (START_DMA | 0x1) /* busmaster-only */ -#define STATS_ENABLE (u_short) (0x15<<11) -#define STATS_DISABLE (u_short) (0x16<<11) -#define STOP_TRANSCEIVER (u_short) (0x17<<11) +#define STATS_ENABLE (u_int16_t) (0x15<<11) +#define STATS_DISABLE (u_int16_t) (0x16<<11) +#define STOP_TRANSCEIVER (u_int16_t) (0x17<<11) /* Only on adapters that support power management: */ -#define POWERUP (u_short) (0x1b<<11) -#define POWERDOWN (u_short) (0x1c<<11) -#define POWERAUTO (u_short) (0x1d<<11) +#define POWERUP (u_int16_t) (0x1b<<11) +#define POWERDOWN (u_int16_t) (0x1c<<11) +#define POWERAUTO (u_int16_t) (0x1d<<11) @@ -252,7 +265,7 @@ * The implicit two-bit upshift done by busmastering cards means * a value of 2047 disables threshold interrupts on both. */ -#define EP_THRESH_DISABLE 2047 +#define ELINK_THRESH_DISABLE 2047 /* @@ -273,17 +286,17 @@ * 1: Adapter Failure. * 0: Interrupt Latch. */ -#define S_INTR_LATCH (u_short) (0x0001) -#define S_CARD_FAILURE (u_short) (0x0002) -#define S_TX_COMPLETE (u_short) (0x0004) -#define S_TX_AVAIL (u_short) (0x0008) -#define S_RX_COMPLETE (u_short) (0x0010) -#define S_RX_EARLY (u_short) (0x0020) -#define S_INT_RQD (u_short) (0x0040) -#define S_UPD_STATS (u_short) (0x0080) -#define S_DMA_DONE (u_short) (0x0100) /* DMA cards only */ -#define S_DMA_IN_PROGRESS (u_short) (0x0800) /* DMA cards only */ -#define S_COMMAND_IN_PROGRESS (u_short) (0x1000) +#define S_INTR_LATCH (u_int16_t) (0x0001) +#define S_CARD_FAILURE (u_int16_t) (0x0002) +#define S_TX_COMPLETE (u_int16_t) (0x0004) +#define S_TX_AVAIL (u_int16_t) (0x0008) +#define S_RX_COMPLETE (u_int16_t) (0x0010) +#define S_RX_EARLY (u_int16_t) (0x0020) +#define S_INT_RQD (u_int16_t) (0x0040) +#define S_UPD_STATS (u_int16_t) (0x0080) +#define S_DMA_DONE (u_int16_t) (0x0100) /* DMA cards only */ +#define S_DMA_IN_PROGRESS (u_int16_t) (0x0800) /* DMA cards only */ +#define S_COMMAND_IN_PROGRESS (u_int16_t) (0x1000) /* * FIFO Registers. RX Status. @@ -301,15 +314,15 @@ * * 10-0: RX Bytes (0-1514) */ -#define ERR_INCOMPLETE (u_short) (0x8000) -#define ERR_RX (u_short) (0x4000) -#define ERR_MASK (u_short) (0x7800) -#define ERR_OVERRUN (u_short) (0x4000) -#define ERR_RUNT (u_short) (0x5800) -#define ERR_ALIGNMENT (u_short) (0x6000) -#define ERR_CRC (u_short) (0x6800) -#define ERR_OVERSIZE (u_short) (0x4800) -#define ERR_DRIBBLE (u_short) (0x1000) +#define ERR_INCOMPLETE (u_int16_t) (0x8000) +#define ERR_RX (u_int16_t) (0x4000) +#define ERR_MASK (u_int16_t) (0x7800) +#define ERR_OVERRUN (u_int16_t) (0x4000) +#define ERR_RUNT (u_int16_t) (0x5800) +#define ERR_ALIGNMENT (u_int16_t) (0x6000) +#define ERR_CRC (u_int16_t) (0x6800) +#define ERR_OVERSIZE (u_int16_t) (0x4800) +#define ERR_DRIBBLE (u_int16_t) (0x1000) /* * TX Status @@ -339,7 +352,7 @@ * RX status * Window 1/Port 0x08. */ -#define RX_BYTES_MASK (u_short) (0x07ff) +#define RX_BYTES_MASK (u_int16_t) (0x07ff) /* * Internal Config and MAC control (Window 3) @@ -360,63 +373,65 @@ * The low-order 16 bits should generally not be changed by software. * Offsets defined for two 16-bit words, to help out 16-bit busses. */ -#define CONFIG_RAMSIZE (u_short) 0x0007 -#define CONFIG_RAMSIZE_SHIFT (u_short) 0 +#define CONFIG_RAMSIZE (u_int16_t) 0x0007 +#define CONFIG_RAMSIZE_SHIFT 0 -#define CONFIG_RAMWIDTH (u_short) 0x0008 -#define CONFIG_RAMWIDTH_SHIFT (u_short) 3 +#define CONFIG_RAMWIDTH (u_int16_t) 0x0008 +#define CONFIG_RAMWIDTH_SHIFT 3 -#define CONFIG_RAMSPEED (u_short) 0x0030 -#define CONFIG_RAMSPEED_SHIFT (u_short) 4 -#define CONFIG_ROMSIZE (u_short) 0x00c0 -#define CONFIG_ROMSIZE_SHIFT (u_short) 6 +#define CONFIG_RAMSPEED (u_int16_t) 0x0030 +#define CONFIG_RAMSPEED_SHIFT 4 +#define CONFIG_ROMSIZE (u_int16_t) 0x00c0 +#define CONFIG_ROMSIZE_SHIFT 6 /* Window 3/port 2 */ -#define CONFIG_RAMSPLIT (u_short) 0x0003 -#define CONFIG_RAMSPLIT_SHIFT (u_short) 0 -#define CONFIG_MEDIAMASK (u_short) 0x0070 -#define CONFIG_MEDIAMASK_SHIFT (u_short) 4 +#define CONFIG_RAMSPLIT (u_int16_t) 0x0003 +#define CONFIG_RAMSPLIT_SHIFT 0 +#define CONFIG_MEDIAMASK (u_int16_t) 0x0070 +#define CONFIG_MEDIAMASK_SHIFT 4 -/* Active media in EP_W3_RESET_OPTIONS mediamask bits */ - -#define EPMEDIA_10BASE_T (u_short) 0x00 -#define EPMEDIA_AUI (u_short) 0x01 -#define EPMEDIA_RESV1 (u_short) 0x02 -#define EPMEDIA_10BASE_2 (u_short) 0x03 -#define EPMEDIA_100BASE_TX (u_short) 0x04 -#define EPMEDIA_100BASE_FX (u_short) 0x05 -#define EPMEDIA_MII (u_short) 0x06 -#define EPMEDIA_100BASE_T4 (u_short) 0x07 - - -#define CONFIG_AUTOSELECT (u_short) 0x0100 -#define CONFIG_AUTOSELECT_SHIFT (u_short) 8 +#define CONFIG_AUTOSELECT (u_int16_t) 0x0100 +#define CONFIG_AUTOSELECT_SHIFT 8 /* * MAC_CONTROL (Window 3) */ -#define MAC_CONTROL_FDX 0x20 /* full-duplex mode */ +#define MAC_CONTROL_FDX 0x20 /* full-duplex mode */ + + +/* Active media in INTERNAL_CONFIG media bits */ + +#define ELINKMEDIA_10BASE_T (u_int16_t) 0x00 +#define ELINKMEDIA_AUI (u_int16_t) 0x01 +#define ELINKMEDIA_RESV1 (u_int16_t) 0x02 +#define ELINKMEDIA_10BASE_2 (u_int16_t) 0x03 +#define ELINKMEDIA_100BASE_TX (u_int16_t) 0x04 +#define ELINKMEDIA_100BASE_FX (u_int16_t) 0x05 +#define ELINKMEDIA_MII (u_int16_t) 0x06 +#define ELINKMEDIA_100BASE_T4 (u_int16_t) 0x07 + /* * RESET_OPTIONS (Window 3, on Demon/Vortex/Bomerang only) * also mapped to PCI configuration space on PCI adaptors. * - * (same register as Vortex EP_W3_RESET_OPTIONS, mapped to pci-config space) + * (same register as Vortex ELINK_W3_RESET_OPTIONS, mapped to pci-config space) */ -#define EP_PCI_100BASE_T4 (1<<0) -#define EP_PCI_100BASE_TX (1<<1) -#define EP_PCI_100BASE_FX (1<<2) -#define EP_PCI_10BASE_T (1<<3) -#define EP_PCI_BNC (1<<4) -#define EP_PCI_AUI (1<<5) -#define EP_PCI_100BASE_MII (1<<6) -#define EP_PCI_INTERNAL_VCO (1<<8) +#define ELINK_PCI_100BASE_T4 (1<<0) +#define ELINK_PCI_100BASE_TX (1<<1) +#define ELINK_PCI_100BASE_FX (1<<2) +#define ELINK_PCI_10BASE_T (1<<3) +#define ELINK_PCI_BNC (1<<4) +#define ELINK_PCI_AUI (1<<5) +#define ELINK_PCI_100BASE_MII (1<<6) +#define ELINK_PCI_INTERNAL_VCO (1<<8) -#define EP_PCI_MEDIAMASK (EP_PCI_100BASE_T4|EP_PCI_100BASE_TX| \ - EP_PCI_100BASE_FX|EP_PCI_10BASE_T| \ - EP_PCI_BNC|EP_PCI_AUI|EP_PCI_100BASE_MII) +#define ELINK_PCI_MEDIAMASK (ELINK_PCI_100BASE_T4|ELINK_PCI_100BASE_TX| \ + ELINK_PCI_100BASE_FX|ELINK_PCI_10BASE_T| \ + ELINK_PCI_BNC|ELINK_PCI_AUI| \ + ELINK_PCI_100BASE_MII) -#define EP_RUNNER_ENABLE_MII 0x8000 +#define ELINK_RUNNER_ENABLE_MII 0x8000 /* * FIFO Status (Window 4) @@ -451,20 +466,20 @@ * 9-8: Unassigned. * 7-0: Built in self test bits for the RX and TX FIFO's. */ -#define FIFOS_RX_RECEIVING (u_short) 0x8000 -#define FIFOS_RX_UNDERRUN (u_short) 0x2000 -#define FIFOS_RX_STATUS_OVERRUN (u_short) 0x1000 -#define FIFOS_RX_OVERRUN (u_short) 0x0800 -#define FIFOS_TX_OVERRUN (u_short) 0x0400 +#define FIFOS_RX_RECEIVING (u_int16_t) 0x8000 +#define FIFOS_RX_UNDERRUN (u_int16_t) 0x2000 +#define FIFOS_RX_STATUS_OVERRUN (u_int16_t) 0x1000 +#define FIFOS_RX_OVERRUN (u_int16_t) 0x0800 +#define FIFOS_TX_OVERRUN (u_int16_t) 0x0400 /* * ISA/eisa CONFIG_CNTRL media-present bits. */ -#define EP_W0_CC_AUI (1<<13) -#define EP_W0_CC_BNC (1<<12) -#define EP_W0_CC_UTP (1<<9) -#define EP_W0_CC_MEDIAMASK (EP_W0_CC_AUI|EP_W0_CC_BNC|EP_W0_CC_UTP) - +#define ELINK_W0_CC_AUI (1<<13) +#define ELINK_W0_CC_BNC (1<<12) +#define ELINK_W0_CC_UTP (1<<9) +#define ELINK_W0_CC_MEDIAMASK (ELINK_W0_CC_AUI|ELINK_W0_CC_BNC| \ + ELINK_W0_CC_UTP) /* EEPROM state flags/commands */ #define EEPROM_BUSY (1<<15) @@ -487,9 +502,9 @@ #define MFG_ID 0x506d /* `TCM' */ #define PROD_ID_3C509 0x5090 /* 509[0-f] */ #define GO_WINDOW(x) bus_space_write_2(sc->sc_iot, \ - sc->sc_ioh, EP_COMMAND, WINDOW_SELECT|x) + sc->sc_ioh, ELINK_COMMAND, WINDOW_SELECT|x) /* Used to probe for large-packet support. */ -#define EP_LARGEWIN_PROBE EP_THRESH_DISABLE -#define EP_LARGEWIN_MASK 0xffc +#define ELINK_LARGEWIN_PROBE ELINK_THRESH_DISABLE +#define ELINK_LARGEWIN_MASK 0xffc diff --git a/sys/dev/ic/elink3var.h b/sys/dev/ic/elink3var.h index 647ff2493d66..1b9e8052f7aa 100644 --- a/sys/dev/ic/elink3var.h +++ b/sys/dev/ic/elink3var.h @@ -1,4 +1,4 @@ -/* $NetBSD: elink3var.h,v 1.18 1998/08/17 23:20:39 thorpej Exp $ */ +/* $NetBSD: elink3var.h,v 1.19 1998/11/04 00:29:29 fvdl Exp $ */ /* * Copyright (c) 1994 Herb Peyerl @@ -57,43 +57,43 @@ struct ep_softc { int tx_succ_ok; /* # packets sent in sequence */ /* w/o underrun */ - u_int ep_flags; /* capabilities flag (from EEPROM) */ -#define EP_FLAGS_PNP 0x00001 -#define EP_FLAGS_FULLDUPLEX 0x00002 -#define EP_FLAGS_LARGEPKT 0x00004 /* 4k packet support */ -#define EP_FLAGS_SLAVEDMA 0x00008 -#define EP_FLAGS_SECONDDMA 0x00010 -#define EP_FLAGS_FULLDMA 0x00020 -#define EP_FLAGS_FRAGMENTDMA 0x00040 -#define EP_FLAGS_CRC_PASSTHRU 0x00080 -#define EP_FLAGS_TXDONE 0x00100 -#define EP_FLAGS_NO_TXLENGTH 0x00200 -#define EP_FLAGS_RXREPEAT 0x00400 -#define EP_FLAGS_SNOOPING 0x00800 -#define EP_FLAGS_100MBIT 0x01000 -#define EP_FLAGS_POWERMGMT 0x02000 -#define EP_FLAGS_MII 0x04000 -#define EP_FLAGS_USEFIFOBUFFER 0x08000 /* RoadRunner only */ -#define EP_FLAGS_USESHAREDMEM 0x10000 /* RoadRunner only */ -#define EP_FLAGS_FORCENOWAIT 0x20000 /* RoadRunner only */ + u_int ep_flags; /* capabilities flag (from EELINKROM) */ +#define ELINK_FLAGS_PNP 0x00001 +#define ELINK_FLAGS_FULLDUPLEX 0x00002 +#define ELINK_FLAGS_LARGELINKKT 0x00004 /* 4k packet support */ +#define ELINK_FLAGS_SLAVEDMA 0x00008 +#define ELINK_FLAGS_SECONDDMA 0x00010 +#define ELINK_FLAGS_FULLDMA 0x00020 +#define ELINK_FLAGS_FRAGMENTDMA 0x00040 +#define ELINK_FLAGS_CRC_PASSTHRU 0x00080 +#define ELINK_FLAGS_TXDONE 0x00100 +#define ELINK_FLAGS_NO_TXLENGTH 0x00200 +#define ELINK_FLAGS_RXRELINKEAT 0x00400 +#define ELINK_FLAGS_SNOOPING 0x00800 +#define ELINK_FLAGS_100MBIT 0x01000 +#define ELINK_FLAGS_POWERMGMT 0x02000 +#define ELINK_FLAGS_MII 0x04000 +#define ELINK_FLAGS_USEFIFOBUFFER 0x08000 /* RoadRunner only */ +#define ELINK_FLAGS_USESHAREDMEM 0x10000 /* RoadRunner only */ +#define ELINK_FLAGS_FORCENOWAIT 0x20000 /* RoadRunner only */ u_short ep_chipset; /* Chipset family on this board */ -#define EP_CHIPSET_3C509 0x00 /* PIO: 3c509, 3c589 */ -#define EP_CHIPSET_VORTEX 0x01 /* 100mbit, single-pkt dma */ -#define EP_CHIPSET_BOOMERANG 0x02 /* Saner dma plus PIO */ -#define EP_CHIPSET_ROADRUNNER 0x03 /* like Boomerang, but for +#define ELINK_CHIPSET_3C509 0x00 /* PIO: 3c509, 3c589 */ +#define ELINK_CHIPSET_VORTEX 0x01 /* 100mbit, single-pkt dma */ +#define ELINK_CHIPSET_BOOMERANG 0x02 /* Saner dma plus PIO */ +#define ELINK_CHIPSET_ROADRUNNER 0x03 /* like Boomerang, but for PCMCIA; has shared memory plus FIFO buffer */ -#define EP_CHIPSET_CORKSCREW 0x04 /* like Boomerang, but DMA +#define ELINK_CHIPSET_CORKSCREW 0x04 /* like Boomerang, but DMA hacked to work w/ ISA */ u_char bustype; /* parent bus type */ -#define EP_BUS_ISA 0x0 -#define EP_BUS_PCMCIA 0x1 -#define EP_BUS_EISA 0x2 -#define EP_BUS_PCI 0x3 +#define ELINK_BUS_ISA 0x0 +#define ELINK_BUS_PCMCIA 0x1 +#define ELINK_BUS_EISA 0x2 +#define ELINK_BUS_PCI 0x3 -#define EP_IS_BUS_32(a) ((a) & 0x2) +#define ELINK_IS_BUS_32(a) ((a) & 0x2) int ep_pktlenshift; /* scale factor for pkt lengths */ #if NRND > 0 diff --git a/sys/dev/ic/elinkxl.c b/sys/dev/ic/elinkxl.c new file mode 100644 index 000000000000..f12a257a8482 --- /dev/null +++ b/sys/dev/ic/elinkxl.c @@ -0,0 +1,1704 @@ +/* $NetBSD: elinkxl.c,v 1.1 1998/11/04 00:29:29 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_inet.h" +#include "opt_ns.h" +#include "bpfilter.h" +#include "rnd.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if NRND > 0 +#include +#endif + +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#if NBPFILTER > 0 +#include +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include + +#include +/* #include */ +#include +#include + +#define ETHER_MIN_LEN 64 +#define ETHER_MAX_LEN 1518 +#define ETHER_ADDR_LEN 6 + +#ifdef DEBUG +int exdebug = 0; +#endif + +/* ifmedia callbacks */ +int ex_media_chg __P((struct ifnet *ifp)); +void ex_media_stat __P((struct ifnet *ifp, struct ifmediareq *req)); + +void ex_probe_media __P((struct ex_softc *)); +void ex_set_filter __P((struct ex_softc *)); +void ex_set_media __P((struct ex_softc *)); +struct mbuf *ex_get __P((struct ex_softc *, int)); +u_int16_t ex_read_eeprom __P((struct ex_softc *, int)); +void ex_init __P((struct ex_softc *)); +void ex_read __P((struct ex_softc *)); +void ex_reset __P((struct ex_softc *)); +void ex_set_mc __P((struct ex_softc *)); +void ex_getstats __P((struct ex_softc *)); +void ex_printstats __P((struct ex_softc *)); +void ex_tick __P((void *)); + +static int ex_eeprom_busy __P((struct ex_softc *)); +static int ex_add_rxbuf __P((struct ex_softc *, struct ex_rxdesc *)); +static void ex_init_txdescs __P((struct ex_softc *)); + +static void ex_shutdown __P((void *)); +static void ex_start __P((struct ifnet *)); +static void ex_txstat __P((struct ex_softc *)); +static u_int16_t ex_mchash __P((u_char *)); +static void ex_mii_writebits __P((struct ex_softc *, u_int, int)); + +void ex_mii_setbit __P((void *, u_int16_t)); +void ex_mii_clrbit __P((void *, u_int16_t)); +u_int16_t ex_mii_readbit __P((void *, u_int16_t)); +int ex_mii_readreg __P((struct device *, int, int)); +void ex_mii_writereg __P((struct device *, int, int, int)); +void ex_mii_statchg __P((struct device *)); + +/* + * Back-end attach and configure. + */ +void +ex_config(sc) + struct ex_softc *sc; +{ + struct ifnet *ifp; + u_int16_t val; + u_int8_t macaddr[ETHER_ADDR_LEN] = {0}; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + bus_dma_segment_t useg, dseg; + int urseg, drseg, i, error, attach_stage; + + ex_reset(sc); + + val = ex_read_eeprom(sc, EEPROM_OEM_ADDR0); + macaddr[0] = val >> 8; + macaddr[1] = val & 0xff; + val = ex_read_eeprom(sc, EEPROM_OEM_ADDR1); + macaddr[2] = val >> 8; + macaddr[3] = val & 0xff; + val = ex_read_eeprom(sc, EEPROM_OEM_ADDR2); + macaddr[4] = val >> 8; + macaddr[5] = val & 0xff; + + printf("%s: MAC address %s\n", sc->sc_dev.dv_xname, + ether_sprintf(macaddr)); + + attach_stage = 0; + + /* + * Allocate the upload descriptors, and create and load the DMA + * map for them. + */ + if ((error = bus_dmamem_alloc(sc->sc_dmat, + EX_NUPD * sizeof (struct ex_upd), NBPG, 0, &useg, 1, &urseg, + BUS_DMA_NOWAIT)) != 0) { + printf("%s: can't allocate upload descriptors, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 1; + + if ((error = bus_dmamem_map(sc->sc_dmat, &useg, urseg, + EX_NUPD * sizeof (struct ex_upd), (caddr_t *)&sc->sc_upd, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf("%s: can't map upload descriptors, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 2; + + if ((error = bus_dmamap_create(sc->sc_dmat, + EX_NUPD * sizeof (struct ex_upd), 1, + EX_NUPD * sizeof (struct ex_upd), 0, BUS_DMA_NOWAIT, + &sc->sc_upd_dmamap)) != 0) { + printf("%s: can't create upload desc. DMA map, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 3; + + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_upd_dmamap, + sc->sc_upd, EX_NUPD * sizeof (struct ex_upd), NULL, + BUS_DMA_NOWAIT)) != 0) { + printf("%s: can't load upload desc. DMA map, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 4; + + /* + * Allocate the download descriptors, and create and load the DMA + * map for them. + */ + if ((error = bus_dmamem_alloc(sc->sc_dmat, + EX_NDPD * sizeof (struct ex_dpd), NBPG, 0, &dseg, 1, &drseg, + BUS_DMA_NOWAIT)) != 0) { + printf("%s: can't allocate download descriptors, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 5; + + if ((error = bus_dmamem_map(sc->sc_dmat, &dseg, drseg, + EX_NDPD * sizeof (struct ex_dpd), (caddr_t *)&sc->sc_dpd, + BUS_DMA_NOWAIT|BUS_DMA_COHERENT)) != 0) { + printf("%s: can't map download descriptors, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + bzero(sc->sc_dpd, EX_NDPD * sizeof (struct ex_dpd)); + + attach_stage = 6; + + if ((error = bus_dmamap_create(sc->sc_dmat, + EX_NDPD * sizeof (struct ex_dpd), 1, + EX_NDPD * sizeof (struct ex_dpd), 0, BUS_DMA_NOWAIT, + &sc->sc_dpd_dmamap)) != 0) { + printf("%s: can't create download desc. DMA map, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 7; + + if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_dpd_dmamap, + sc->sc_dpd, EX_NDPD * sizeof (struct ex_dpd), NULL, + BUS_DMA_NOWAIT)) != 0) { + printf("%s: can't load download desc. DMA map, error = %d\n", + sc->sc_dev.dv_xname, error); + goto fail; + } + + attach_stage = 8; + + + /* + * Create the transmit buffer DMA maps. + */ + for (i = 0; i < EX_NDPD; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, + EX_NTFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT, + &sc->sc_tx_dmamaps[i])) != 0) { + printf("%s: can't create tx DMA map %d, error = %d\n", + sc->sc_dev.dv_xname, i, error); + goto fail; + } + } + + attach_stage = 9; + + /* + * Create the receive buffer DMA maps. + */ + for (i = 0; i < EX_NUPD; i++) { + if ((error = bus_dmamap_create(sc->sc_dmat, MCLBYTES, + EX_NRFRAGS, MCLBYTES, 0, BUS_DMA_NOWAIT, + &sc->sc_rx_dmamaps[i])) != 0) { + printf("%s: can't create rx DMA map %d, error = %d\n", + sc->sc_dev.dv_xname, i, error); + goto fail; + } + } + + attach_stage = 10; + + /* + * Create ring of upload descriptors, only once. The DMA engine + * will loop over this when receiving packets, stalling if it + * hits an UPD with a finished receive. + */ + for (i = 0; i < EX_NUPD; i++) { + sc->sc_rxdescs[i].rx_dmamap = sc->sc_rx_dmamaps[i]; + sc->sc_rxdescs[i].rx_upd = &sc->sc_upd[i]; + sc->sc_upd[i].upd_frags[0].fr_len = (MCLBYTES - 2) | EX_FR_LAST; + if (ex_add_rxbuf(sc, &sc->sc_rxdescs[i]) != 0) { + printf("%s: can't allocate or map rx buffers\n", + sc->sc_dev.dv_xname); + goto fail; + } + } + + bus_dmamap_sync(sc->sc_dmat, sc->sc_upd_dmamap, 0, + EX_NUPD * sizeof (struct ex_upd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + ex_init_txdescs(sc); + + attach_stage = 11; + + + GO_WINDOW(3); + val = bus_space_read_2(iot, ioh, ELINK_W3_RESET_OPTIONS); + if (val & ELINK_MEDIACAP_MII) + sc->ex_conf |= EX_CONF_MII; + + ifp = &sc->sc_ethercom.ec_if; + + if (sc->ex_conf & EX_CONF_MII) { + /* + * Find PHY, extract media information from it. + */ + sc->ex_mii.mii_ifp = ifp; + sc->ex_mii.mii_readreg = ex_mii_readreg; + sc->ex_mii.mii_writereg = ex_mii_writereg; + sc->ex_mii.mii_statchg = ex_mii_statchg; + ifmedia_init(&sc->ex_mii.mii_media, 0, ex_media_chg, + ex_media_stat); + mii_phy_probe(&sc->sc_dev, &sc->ex_mii, 0xffffffff); + if (LIST_FIRST(&sc->ex_mii.mii_phys) == NULL) { + ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER|IFM_NONE, + 0, NULL); + ifmedia_set(&sc->ex_mii.mii_media, IFM_ETHER|IFM_NONE); + } else { + ifmedia_set(&sc->ex_mii.mii_media, IFM_ETHER|IFM_AUTO); + } + } else { + ifmedia_init(&sc->ex_mii.mii_media, IFM_FDX, ex_media_chg, + ex_media_stat); + /* + * Extract media information from registers. + */ + if (val & ELINK_MEDIACAP_100BASET4) + ifmedia_add(&sc->ex_mii.mii_media, + IFM_ETHER | IFM_100_T4, ELINKMEDIA_100BASE_T4, + NULL); + else if (val & ELINK_MEDIACAP_100BASETX) + ifmedia_add(&sc->ex_mii.mii_media, + IFM_ETHER | IFM_100_TX, ELINKMEDIA_100BASE_TX, + NULL); + else if (val & ELINK_MEDIACAP_100BASEFX) + ifmedia_add(&sc->ex_mii.mii_media, + IFM_ETHER | IFM_100_FX, ELINKMEDIA_100BASE_FX, + NULL); + else if (val & ELINK_MEDIACAP_10BASET) + ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER | IFM_10_T, + ELINKMEDIA_10BASE_T, NULL); + else if (val & ELINK_MEDIACAP_10BASE2) + ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER | IFM_10_2, + ELINKMEDIA_10BASE_2, NULL); + else if (val & ELINK_MEDIACAP_10BASE5) + ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER | IFM_10_5, + ELINKMEDIA_AUI, NULL); +#ifdef notyet + else if (val & ELINK_MEDIACAP_10BASEFL) + ifmedia_add(&sc->ex_mii.mii_media, + IFM_ETHER | IFM_10_FL, 0, NULL); +#endif + ifmedia_add(&sc->ex_mii.mii_media, IFM_ETHER | IFM_NONE, 0, + NULL); + ifmedia_set(&sc->ex_mii.mii_media, IFM_ETHER | IFM_NONE); + } + + bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); + ifp->if_softc = sc; + ifp->if_start = ex_start; + ifp->if_ioctl = ex_ioctl; + ifp->if_watchdog = ex_watchdog; + ifp->if_flags = + IFF_BROADCAST | IFF_SIMPLEX | IFF_NOTRAILERS | IFF_MULTICAST; + + if_attach(ifp); + ether_ifattach(ifp, macaddr); + + GO_WINDOW(1); + + sc->tx_start_thresh = 20; + sc->tx_succ_ok = 0; + + /* TODO: set queues to 0 */ + +#if NBPFILTER > 0 + bpfattach(&sc->sc_ethercom.ec_if.if_bpf, ifp, DLT_EN10MB, + sizeof(struct ether_header)); +#endif + +#if NRND > 0 + rnd_attach_source(&sc->rnd_source, sc->sc_dev.dv_xname, RND_TYPE_NET); +#endif + + /* Establish callback to reset card when we reboot. */ + shutdownhook_establish(ex_shutdown, sc); + return; + + fail: + /* + * Free any resources we've allocated during the failed attach + * attempt. Do this in reverse order and fall though. + */ + switch (attach_stage) { + case 11: + { + struct ex_rxdesc *rxd; + + for (i = 0; i < EX_NUPD; i++) { + rxd = &sc->sc_rxdescs[i]; + if (rxd->rx_mbhead != NULL) { + bus_dmamap_unload(sc->sc_dmat, rxd->rx_dmamap); + m_freem(rxd->rx_mbhead); + } + } + } + /* FALLTHROUGH */ + + case 10: + for (i = 0; i < EX_NUPD; i++) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_dmamaps[i]); + /* FALLTHROUGH */ + + case 9: + for (i = 0; i < EX_NDPD; i++) + bus_dmamap_destroy(sc->sc_dmat, sc->sc_tx_dmamaps[i]); + /* FALLTHROUGH */ + case 8: + bus_dmamap_unload(sc->sc_dmat, sc->sc_dpd_dmamap); + /* FALLTHROUGH */ + + case 7: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_dpd_dmamap); + /* FALLTHROUGH */ + + case 6: + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_dpd, + EX_NDPD * sizeof (struct ex_dpd)); + /* FALLTHROUGH */ + + case 5: + bus_dmamem_free(sc->sc_dmat, &dseg, drseg); + break; + + case 4: + bus_dmamap_unload(sc->sc_dmat, sc->sc_upd_dmamap); + /* FALLTHROUGH */ + + case 3: + bus_dmamap_destroy(sc->sc_dmat, sc->sc_upd_dmamap); + /* FALLTHROUGH */ + + case 2: + bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_upd, + EX_NUPD * sizeof (struct ex_upd)); + /* FALLTHROUGH */ + + case 1: + bus_dmamem_free(sc->sc_dmat, &useg, urseg); + break; + } + +} + +/* + * Bring device up. + */ +void +ex_init(sc) + struct ex_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; + int s, i; + + s = splnet(); + + ex_waitcmd(sc); + ex_stop(sc); + + /* + * 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 < ETHER_ADDR_LEN; i++) { + bus_space_write_1(iot, ioh, ELINK_W2_ADDR_0 + i, + LLADDR(ifp->if_sadl)[i]); + bus_space_write_1(iot, ioh, ELINK_W2_RECVMASK_0 + i, 0); + } + + GO_WINDOW(3); + + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_RESET); + ex_waitcmd(sc); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_RESET); + ex_waitcmd(sc); + + /* + * Disable reclaim threshold for 90xB, set free threshold to + * 6 * 256 = 1536 for 90x. + */ + if (sc->ex_conf & EX_CONF_90XB) + bus_space_write_2(iot, ioh, ELINK_COMMAND, + ELINK_TXRECLTHRESH | 255); + else + bus_space_write_1(iot, ioh, ELINK_TXFREETHRESH, 6); + + bus_space_write_2(iot, ioh, ELINK_COMMAND, + SET_RX_EARLY_THRESH | ELINK_THRESH_DISABLE); + + bus_space_write_4(iot, ioh, ELINK_DMACTRL, + bus_space_read_4(iot, ioh, ELINK_DMACTRL) | ELINK_DMAC_UPRXEAREN); + + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_RD_0_MASK | S_MASK); + bus_space_write_2(iot, ioh, ELINK_COMMAND, SET_INTR_MASK | S_MASK); + + bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | 0xff); + + ex_set_media(sc); + ex_set_mc(sc); + + + bus_space_write_2(iot, ioh, ELINK_COMMAND, STATS_ENABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_ENABLE); + bus_space_write_4(iot, ioh, ELINK_UPLISTPTR, sc->sc_upddma); + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_ENABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, ELINK_UPUNSTALL); + + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + ex_start(ifp); + + GO_WINDOW(1); + + splx(s); + + timeout(ex_tick, sc, hz); +} + +/* + * Multicast hash filter according to the 3Com spec. + */ +static u_int16_t +ex_mchash(addr) + u_char *addr; +{ + u_int32_t crc, carry; + int i, j; + u_char c; + + /* Compute CRC for the address value. */ + crc = 0xffffffff; /* initial value */ + + for (i = 0; i < 6; i++) { + c = addr[i]; + for (j = 0; i < 8; i++) { + carry = ((crc & 0x80000000) ? 1 : 0) ^ (c & 0x01); + crc <<= 1; + c >>= 1; + if (carry) + crc = (crc ^ 0x04c11db6) | carry; + } + } + + /* Return the filter bit position. */ + return(crc & 0x000000ff); +} + + +/* + * Set multicast receive filter. Also take care of promiscuous mode + * here (XXX). + */ +void +ex_set_mc(sc) + register struct ex_softc *sc; +{ + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + struct ethercom *ec = &sc->sc_ethercom; + struct ether_multi *enm; + struct ether_multistep estep; + int i; + u_int16_t mask = FIL_INDIVIDUAL | FIL_BRDCST; + + if (ifp->if_flags & IFF_PROMISC) + mask |= FIL_PROMISC; + + if (!(ifp->if_flags & IFF_MULTICAST)) + goto out; + + if (!(sc->ex_conf & EX_CONF_90XB) || ifp->if_flags & IFF_ALLMULTI) { + mask |= (ifp->if_flags & IFF_MULTICAST) ? FIL_MULTICAST : 0; + } else { + ETHER_FIRST_MULTI(estep, ec, enm); + while (enm != NULL) { + if (bcmp(enm->enm_addrlo, enm->enm_addrhi, + ETHER_ADDR_LEN) != 0) + goto out; + i = ex_mchash(enm->enm_addrlo); + bus_space_write_2(sc->sc_iot, sc->sc_ioh, + ELINK_COMMAND, ELINK_SETHASHFILBIT | i); + ETHER_NEXT_MULTI(estep, enm); + } + mask |= FIL_MULTIHASH; + } + out: + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, + SET_RX_FILTER | mask); +} + + +static void +ex_txstat(sc) + struct ex_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int i; + + /* + * We need to read+write TX_STATUS until we get a 0 status + * in order to turn off the interrupt flag. + */ + while ((i = bus_space_read_1(iot, ioh, ELINK_TXSTATUS)) & TXS_COMPLETE) { + bus_space_write_1(iot, ioh, ELINK_TXSTATUS, 0x0); + + if (i & TXS_JABBER) { + ++sc->sc_ethercom.ec_if.if_oerrors; + if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG) + printf("%s: jabber (%x)\n", + sc->sc_dev.dv_xname, i); + ex_init(sc); + /* TODO: be more subtle here */ + } else if (i & TXS_UNDERRUN) { + ++sc->sc_ethercom.ec_if.if_oerrors; + if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG) + printf("%s: fifo underrun (%x) @%d\n", + sc->sc_dev.dv_xname, i, + sc->tx_start_thresh); + if (sc->tx_succ_ok < 100) + sc->tx_start_thresh = min(ETHER_MAX_LEN, + sc->tx_start_thresh + 20); + sc->tx_succ_ok = 0; + ex_init(sc); + /* TODO: be more subtle here */ + } else if (i & TXS_MAX_COLLISION) { + ++sc->sc_ethercom.ec_if.if_collisions; + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_ENABLE); + sc->sc_ethercom.ec_if.if_flags &= ~IFF_OACTIVE; + } else + sc->tx_succ_ok = (sc->tx_succ_ok+1) & 127; + } +} + +int +ex_media_chg(ifp) + struct ifnet *ifp; +{ + struct ex_softc *sc = ifp->if_softc; + + if (ifp->if_flags & IFF_UP) + ex_init(sc); + return 0; +} + +void +ex_set_media(sc) + struct ex_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int config0, config1; + + if (((sc->ex_conf & EX_CONF_MII) && + (sc->ex_mii.mii_media_active & IFM_FDX)) + || (!(sc->ex_conf & EX_CONF_MII) && + (sc->ex_mii.mii_media.ifm_media & IFM_FDX))) { + bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, + MAC_CONTROL_FDX); + } else { + bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, 0); + } + + /* + * If the device has MII, select it, and then tell the + * PHY which media to use. + */ + if (sc->ex_conf & EX_CONF_MII) { + GO_WINDOW(3); + + config0 = (u_int)bus_space_read_2(iot, ioh, + ELINK_W3_INTERNAL_CONFIG); + config1 = (u_int)bus_space_read_2(iot, ioh, + ELINK_W3_INTERNAL_CONFIG + 2); + + config1 = config1 & ~CONFIG_MEDIAMASK; + config1 |= (ELINKMEDIA_MII << CONFIG_MEDIAMASK_SHIFT); + + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG, config0); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2, config1); + mii_mediachg(&sc->ex_mii); + return; + } + + GO_WINDOW(4); + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, 0); + bus_space_write_2(iot, ioh, ELINK_COMMAND, STOP_TRANSCEIVER); + delay(800); + + /* + * Now turn on the selected media/transceiver. + */ + switch (IFM_SUBTYPE(sc->ex_mii.mii_media.ifm_cur->ifm_media)) { + case IFM_10_T: + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, + JABBER_GUARD_ENABLE|LINKBEAT_ENABLE); + break; + + case IFM_10_2: + bus_space_write_2(iot, ioh, ELINK_COMMAND, START_TRANSCEIVER); + DELAY(800); + break; + + case IFM_100_TX: + case IFM_100_FX: + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, + LINKBEAT_ENABLE); + DELAY(800); + break; + + case IFM_10_5: + bus_space_write_2(iot, ioh, ELINK_W4_MEDIA_TYPE, + SQE_ENABLE); + DELAY(800); + break; + + case IFM_MANUAL: + break; + + case IFM_NONE: + return; + + default: + panic("ex_set_media: impossible"); + } + + GO_WINDOW(3); + config0 = (u_int)bus_space_read_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG); + config1 = (u_int)bus_space_read_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2); + + config1 = config1 & ~CONFIG_MEDIAMASK; + config1 |= (sc->ex_mii.mii_media.ifm_cur->ifm_data << + CONFIG_MEDIAMASK_SHIFT); + + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG, config0); + bus_space_write_2(iot, ioh, ELINK_W3_INTERNAL_CONFIG + 2, config1); +} + +/* + * Get currently-selected media from card. + * (if_media callback, may be called before interface is brought up). + */ +void +ex_media_stat(ifp, req) + struct ifnet *ifp; + struct ifmediareq *req; +{ + struct ex_softc *sc = ifp->if_softc; + + if (sc->ex_conf & EX_CONF_MII) { + mii_pollstat(&sc->ex_mii); + req->ifm_status = sc->ex_mii.mii_media_status; + req->ifm_active = sc->ex_mii.mii_media_active; + } else { + GO_WINDOW(4); + req->ifm_status = IFM_AVALID; + req->ifm_active = sc->ex_mii.mii_media.ifm_cur->ifm_media; + if (bus_space_read_2(sc->sc_iot, sc->sc_ioh, + ELINK_W4_MEDIA_TYPE) & LINKBEAT_DETECT) + req->ifm_status |= IFM_ACTIVE; + GO_WINDOW(1); + } +} + + + +/* + * Start outputting on the interface. + */ +static void +ex_start(ifp) + struct ifnet *ifp; +{ + struct ex_softc *sc = ifp->if_softc; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + volatile struct ex_fraghdr *fr = NULL; + volatile struct ex_dpd *dpd = NULL, *prevdpd = NULL; + struct ex_txdesc *txp; + bus_dmamap_t dmamap; + int offset, totlen; + + if (sc->tx_head || sc->tx_free == NULL) + return; + + txp = NULL; + + /* + * We're finished if there is nothing more to add to the list or if + * we're all filled up with buffers to transmit. + */ + while (ifp->if_snd.ifq_head != NULL && sc->tx_free != NULL) { + struct mbuf *mb_head; + int segment, error; + + /* + * Grab a packet to transmit. + */ + IF_DEQUEUE(&ifp->if_snd, mb_head); + + /* + * Get pointer to next available tx desc. + */ + txp = sc->tx_free; + sc->tx_free = txp->tx_next; + txp->tx_next = NULL; + dmamap = txp->tx_dmamap; + + /* + * Go through each of the mbufs in the chain and initialize + * the transmit buffer descriptors with the physical address + * and size of the mbuf. + */ + reload: + error = bus_dmamap_load_mbuf(sc->sc_dmat, dmamap, + mb_head, BUS_DMA_NOWAIT); + switch (error) { + case 0: + /* Success. */ + break; + + case EFBIG: + { + struct mbuf *mn; + + /* + * We ran out of segments. We have to recopy this + * mbuf chain first. Bail out if we can't get the + * new buffers. + */ + printf("%s: too many segments, ", sc->sc_dev.dv_xname); + + MGETHDR(mn, M_DONTWAIT, MT_DATA); + if (mn == NULL) { + m_freem(mb_head); + printf("aborting\n"); + goto out; + } + if (mb_head->m_pkthdr.len > MHLEN) { + MCLGET(mn, M_DONTWAIT); + if ((mn->m_flags & M_EXT) == 0) { + m_freem(mn); + m_freem(mb_head); + printf("aborting\n"); + goto out; + } + } + m_copydata(mb_head, 0, mb_head->m_pkthdr.len, + mtod(mn, caddr_t)); + mn->m_pkthdr.len = mn->m_len = mb_head->m_pkthdr.len; + m_freem(mb_head); + mb_head = mn; + printf("retrying\n"); + goto reload; + } + + default: + /* + * Some other problem; report it. + */ + printf("%s: can't load mbuf chain, error = %d\n", + sc->sc_dev.dv_xname, error); + m_freem(mb_head); + goto out; + } + + fr = &txp->tx_dpd->dpd_frags[0]; + totlen = 0; + for (segment = 0; segment < dmamap->dm_nsegs; segment++, fr++) { + fr->fr_addr = dmamap->dm_segs[segment].ds_addr; + fr->fr_len = dmamap->dm_segs[segment].ds_len; + totlen += fr->fr_len; + } + fr--; + fr->fr_len |= EX_FR_LAST; + txp->tx_mbhead = mb_head; + + bus_dmamap_sync(sc->sc_dmat, dmamap, 0, dmamap->dm_mapsize, + BUS_DMASYNC_PREWRITE); + + dpd = txp->tx_dpd; + dpd->dpd_nextptr = 0; + dpd->dpd_fsh = totlen; + + bus_dmamap_sync(sc->sc_dmat, sc->sc_dpd_dmamap, + ((caddr_t)dpd - (caddr_t)sc->sc_dpd), + sizeof (struct ex_dpd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + + /* + * No need to stall the download engine, we know it's + * not busy right now. + * + * Fix up pointers in both the "soft" tx and the physical + * tx list. + */ + if (sc->tx_head != NULL) { + prevdpd = sc->tx_tail->tx_dpd; + offset = ((caddr_t)prevdpd - (caddr_t)sc->sc_dpd); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dpd_dmamap, + offset, sizeof (struct ex_dpd), + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + prevdpd->dpd_nextptr = DPD_DMADDR(sc, txp); + bus_dmamap_sync(sc->sc_dmat, sc->sc_dpd_dmamap, + offset, sizeof (struct ex_dpd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + sc->tx_tail->tx_next = txp; + sc->tx_tail = txp; + } else { + sc->tx_tail = sc->tx_head = txp; + } + +#if NBPFILTER > 0 + /* + * Pass packet to bpf if there is a listener. + */ + if (ifp->if_bpf) + bpf_mtap(ifp->if_bpf, mb_head); +#endif + } + out: + if (sc->tx_head) { + sc->tx_tail->tx_dpd->dpd_fsh |= EX_DPD_DNIND; + bus_dmamap_sync(sc->sc_dmat, sc->sc_dpd_dmamap, + ((caddr_t)sc->tx_tail->tx_dpd - (caddr_t)sc->sc_dpd), + sizeof (struct ex_dpd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + ifp->if_flags |= IFF_OACTIVE; + bus_space_write_2(iot, ioh, ELINK_COMMAND, ELINK_DNUNSTALL); + bus_space_write_4(iot, ioh, ELINK_DNLISTPTR, + DPD_DMADDR(sc, sc->tx_head)); + } +} + + +int +ex_intr(arg) + void *arg; +{ + struct ex_softc *sc = arg; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + u_int16_t stat; + int ret = 0; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + + for (;;) { + stat = bus_space_read_2(iot, ioh, ELINK_STATUS); + if (!(stat & S_MASK)) + break; + /* + * Acknowledge interrupts. + */ + bus_space_write_2(iot, ioh, ELINK_COMMAND, ACK_INTR | + (stat & S_MASK)); + ret = 1; + if (stat & S_HOST_ERROR) { + printf("%s: adapter failure (%x)\n", + sc->sc_dev.dv_xname, stat); + bus_space_write_2(iot, ioh, ELINK_COMMAND, + C_INTR_LATCH); + ex_reset(sc); + ex_init(sc); + return 1; + } + if (stat & S_TX_COMPLETE) { + ex_txstat(sc); + } + if (stat & S_UPD_STATS) { + ex_getstats(sc); + } + if (stat & S_DN_COMPLETE) { + struct ex_txdesc *txp, *ptxp = NULL; + bus_dmamap_t txmap; + for (txp = sc->tx_head; txp != NULL; + txp = txp->tx_next) { + bus_dmamap_sync(sc->sc_dmat, + sc->sc_dpd_dmamap, + (caddr_t)txp->tx_dpd - (caddr_t)sc->sc_dpd, + sizeof (struct ex_dpd), + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + if (txp->tx_mbhead != NULL) { + txmap = txp->tx_dmamap; + bus_dmamap_sync(sc->sc_dmat, txmap, + 0, txmap->dm_mapsize, + BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dmat, txmap); + m_freem(txp->tx_mbhead); + txp->tx_mbhead = NULL; + } + ptxp = txp; + } + + /* + * Move finished tx buffers back to the tx free list. + */ + if (sc->tx_free) { + sc->tx_ftail->tx_next = sc->tx_head; + sc->tx_ftail = ptxp; + } else + sc->tx_ftail = sc->tx_free = sc->tx_head; + + sc->tx_head = sc->tx_tail = NULL; + ifp->if_flags &= ~IFF_OACTIVE; + } + + if (stat & S_UP_COMPLETE) { + struct ex_rxdesc *rxd; + struct mbuf *m; + struct ex_upd *upd; + bus_dmamap_t rxmap; + u_int32_t pktstat; + + rcvloop: + rxd = sc->rx_head; + rxmap = rxd->rx_dmamap; + m = rxd->rx_mbhead; + upd = rxd->rx_upd; + pktstat = upd->upd_pktstatus; + + bus_dmamap_sync(sc->sc_dmat, rxmap, 0, + rxmap->dm_mapsize, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + bus_dmamap_sync(sc->sc_dmat, sc->sc_upd_dmamap, + ((caddr_t)upd - (caddr_t)sc->sc_upd), + sizeof (struct ex_upd), + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + + if (pktstat & EX_UPD_COMPLETE) { + /* + * Remove first packet from the chain. + */ + sc->rx_head = rxd->rx_next; + rxd->rx_next = NULL; + + /* + * Add a new buffer to the receive chain. + * If this fails, the old buffer is recycled + * instead. + */ + if (ex_add_rxbuf(sc, rxd) == 0) { + struct ether_header *eh; + u_int16_t total_len; + + + if (pktstat & EX_UPD_ERR) { + ifp->if_ierrors++; + m_freem(m); + goto rcvloop; + } + + total_len = pktstat & EX_UPD_PKTLENMASK; + if (total_len < + sizeof(struct ether_header)) { + m_freem(m); + goto rcvloop; + } + m->m_pkthdr.rcvif = ifp; + m->m_pkthdr.len = m->m_len = + total_len - + sizeof(struct ether_header); + eh = mtod(m, struct ether_header *); +#if NBPFILTER > 0 + if (ifp->if_bpf) { + bpf_tap(ifp->if_bpf, + mtod(m, caddr_t), + total_len); + /* + * Only pass this packet up + * if it is for us. + */ + if ((ifp->if_flags & + IFF_PROMISC) && + (eh->ether_dhost[0] & 1) + == 0 && + bcmp(eh->ether_dhost, + LLADDR(ifp->if_sadl), + sizeof(eh->ether_dhost)) + != 0) { + m_freem(m); + goto rcvloop; + } + } +#endif /* NBPFILTER > 0 */ + m->m_data += + sizeof(struct ether_header); + ether_input(ifp, eh, m); + } + goto rcvloop; + } + /* + * Just in case we filled up all UPDs and the DMA engine + * stalled. We could be more subtle about this, + * but we can only do that by reading a register + * first, so just always do it. + */ + bus_space_write_2(iot, ioh, ELINK_COMMAND, + ELINK_UPUNSTALL); + } + } + if (ret) { + bus_space_write_2(iot, ioh, ELINK_COMMAND, C_INTR_LATCH); + if (ifp->if_snd.ifq_head != NULL) + ex_start(ifp); + } + return ret; +} + +int +ex_ioctl(ifp, cmd, data) + register struct ifnet *ifp; + u_long cmd; + caddr_t data; +{ + struct ex_softc *sc = ifp->if_softc; + struct ifaddr *ifa = (struct ifaddr *)data; + struct ifreq *ifr = (struct ifreq *)data; + int s, error = 0; + + s = splnet(); + + switch (cmd) { + + case SIOCSIFADDR: + ifp->if_flags |= IFF_UP; + switch (ifa->ifa_addr->sa_family) { +#ifdef INET + case AF_INET: + ex_init(sc); + arp_ifinit(&sc->sc_ethercom.ec_if, ifa); + break; +#endif +#ifdef NS + case AF_NS: + { + register struct ns_addr *ina = &IA_SNS(ifa)->sns_addr; + + if (ns_nullhost(*ina)) + ina->x_host = *(union ns_host *) + LLADDR(ifp->if_sadl); + else + bcopy(ina->x_host.c_host, LLADDR(ifp->if_sadl), + ifp->if_addrlen); + /* Set new address. */ + ex_init(sc); + break; + } +#endif + default: + ex_init(sc); + break; + } + break; + case SIOCSIFMEDIA: + case SIOCGIFMEDIA: + error = ifmedia_ioctl(ifp, ifr, &sc->ex_mii.mii_media, cmd); + break; + + case SIOCSIFFLAGS: + if ((ifp->if_flags & IFF_UP) == 0 && + (ifp->if_flags & IFF_RUNNING) != 0) { + /* + * If interface is marked down and it is running, then + * stop it. + */ + ex_stop(sc); + ifp->if_flags &= ~IFF_RUNNING; + } else if ((ifp->if_flags & IFF_UP) != 0 && + (ifp->if_flags & IFF_RUNNING) == 0) { + /* + * If interface is marked up and it is stopped, then + * start it. + */ + ex_init(sc); + } else + ex_set_mc(sc); + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + error = (cmd == SIOCADDMULTI) ? + ether_addmulti(ifr, &sc->sc_ethercom) : + ether_delmulti(ifr, &sc->sc_ethercom); + + if (error == ENETRESET) { + /* + * Multicast list has changed; set the hardware filter + * accordingly. + */ + ex_set_mc(sc); + error = 0; + } + break; + + default: + error = EINVAL; + break; + } + + splx(s); + return (error); +} + +void +ex_getstats(sc) + struct ex_softc *sc; +{ + bus_space_handle_t ioh = sc->sc_ioh; + bus_space_tag_t iot = sc->sc_iot; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + u_int8_t upperok; + + GO_WINDOW(6); + upperok = bus_space_read_1(iot, ioh, UPPER_FRAMES_OK); + ifp->if_ipackets += bus_space_read_1(iot, ioh, RX_FRAMES_OK); + ifp->if_ipackets += (upperok & 0x03) << 8; + ifp->if_opackets += bus_space_read_1(iot, ioh, TX_FRAMES_OK); + ifp->if_opackets += (upperok & 0x30) << 4; + ifp->if_ierrors += bus_space_read_1(iot, ioh, RX_OVERRUNS); + ifp->if_oerrors += bus_space_read_1(iot, ioh, TX_DEFERRALS); + ifp->if_collisions += bus_space_read_1(iot, ioh, TX_COLLISIONS); + /* + * There seems to be no way to get the exact number of collisions, + * this is the number that occured at the very least. + */ + ifp->if_collisions += 2 * bus_space_read_1(iot, ioh, + TX_AFTER_X_COLLISIONS); + ifp->if_ibytes += bus_space_read_2(iot, ioh, RX_TOTAL_OK); + ifp->if_obytes += bus_space_read_2(iot, ioh, TX_TOTAL_OK); + + /* + * Clear the following to avoid stats overflow interrupts + */ + bus_space_read_1(iot, ioh, TX_AFTER_1_COLLISION); + bus_space_read_1(iot, ioh, TX_NO_SQE); + bus_space_read_1(iot, ioh, TX_CD_LOST); + GO_WINDOW(4); + bus_space_read_1(iot, ioh, ELINK_W4_BADSSD); + upperok = bus_space_read_1(iot, ioh, ELINK_W4_UBYTESOK); + ifp->if_ibytes += (upperok & 0x0f) << 16; + ifp->if_obytes += (upperok & 0xf0) << 12; + GO_WINDOW(1); +} + +void +ex_printstats(sc) + struct ex_softc *sc; +{ + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + + ex_getstats(sc); + printf("in %ld out %ld ierror %ld oerror %ld ibytes %ld obytes %ld\n", + ifp->if_ipackets, ifp->if_opackets, ifp->if_ierrors, + ifp->if_oerrors, ifp->if_ibytes, ifp->if_obytes); +} + +void +ex_tick(arg) + void *arg; +{ + struct ex_softc *sc = arg; + int s = splnet(); + + if (sc->ex_conf & EX_CONF_MII) + mii_tick(&sc->ex_mii); + + if (!(bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS) + & S_COMMAND_IN_PROGRESS)) + ex_getstats(sc); + + splx(s); + + timeout(ex_tick, sc, hz); +} + + +void +ex_reset(sc) + struct ex_softc *sc; +{ + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, GLOBAL_RESET); + ex_waitcmd(sc); +} + +void +ex_watchdog(ifp) + struct ifnet *ifp; +{ + struct ex_softc *sc = ifp->if_softc; + + log(LOG_ERR, "%s: device timeout\n", sc->sc_dev.dv_xname); + ++sc->sc_ethercom.ec_if.if_oerrors; + + ex_reset(sc); + ex_init(sc); +} + +void +ex_stop(sc) + struct ex_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + struct ifnet *ifp = &sc->sc_ethercom.ec_if; + struct ex_txdesc *tx; + struct ex_rxdesc *rx; + int i; + + bus_space_write_2(iot, ioh, ELINK_COMMAND, RX_DISABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, TX_DISABLE); + bus_space_write_2(iot, ioh, ELINK_COMMAND, STOP_TRANSCEIVER); + + for (tx = sc->tx_head ; tx != NULL; tx = tx->tx_next) { + if (tx->tx_mbhead == NULL) + continue; + m_freem(tx->tx_mbhead); + tx->tx_mbhead = NULL; + bus_dmamap_unload(sc->sc_dmat, tx->tx_dmamap); + tx->tx_dpd->dpd_fsh = tx->tx_dpd->dpd_nextptr = 0; + bus_dmamap_sync(sc->sc_dmat, sc->sc_dpd_dmamap, + ((caddr_t)tx->tx_dpd - (caddr_t)sc->sc_dpd), + sizeof (struct ex_dpd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + } + sc->tx_tail = sc->tx_head = NULL; + ex_init_txdescs(sc); + + sc->rx_tail = sc->rx_head = 0; + for (i = 0; i < EX_NUPD; i++) { + rx = &sc->sc_rxdescs[i]; + if (rx->rx_mbhead != NULL) { + bus_dmamap_unload(sc->sc_dmat, rx->rx_dmamap); + m_freem(rx->rx_mbhead); + rx->rx_mbhead = NULL; + } + ex_add_rxbuf(sc, rx); + } + + bus_space_write_2(iot, ioh, ELINK_COMMAND, C_INTR_LATCH); + + untimeout(ex_tick, sc); + + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + ifp->if_timer = 0; +} + +static void +ex_init_txdescs(sc) + struct ex_softc *sc; +{ + int i; + + for (i = 0; i < EX_NDPD; i++) { + sc->sc_txdescs[i].tx_dmamap = sc->sc_tx_dmamaps[i]; + sc->sc_txdescs[i].tx_dpd = &sc->sc_dpd[i]; + if (i < EX_NDPD - 1) + sc->sc_txdescs[i].tx_next = &sc->sc_txdescs[i + 1]; + else + sc->sc_txdescs[i].tx_next = NULL; + } + sc->tx_free = &sc->sc_txdescs[0]; + sc->tx_ftail = &sc->sc_txdescs[EX_NDPD-1]; +} + + +/* + * Before reboots, reset card completely. + */ +static void +ex_shutdown(arg) + void *arg; +{ + register struct ex_softc *sc = arg; + + ex_stop(sc); +} + +/* + * Read EEPROM data. + * XXX what to do if EEPROM doesn't unbusy? + */ +u_int16_t +ex_read_eeprom(sc, offset) + struct ex_softc *sc; + int offset; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + u_int16_t data = 0; + + GO_WINDOW(0); + if (ex_eeprom_busy(sc)) + goto out; + bus_space_write_1(iot, ioh, ELINK_W0_EEPROM_COMMAND, + READ_EEPROM | (offset & 0x3f)); + if (ex_eeprom_busy(sc)) + goto out; + data = bus_space_read_2(iot, ioh, ELINK_W0_EEPROM_DATA); +out: + return data; +} + +static int +ex_eeprom_busy(sc) + struct ex_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int i = 100; + + while (i--) { + if (!(bus_space_read_2(iot, ioh, ELINK_W0_EEPROM_COMMAND) & + EEPROM_BUSY)) + return 0; + delay(100); + } + printf("\n%s: eeprom stays busy.\n", sc->sc_dev.dv_xname); + return (1); +} + +/* + * Create a new rx buffer and add it to the 'soft' rx list. + */ +static int +ex_add_rxbuf(sc, rxd) + struct ex_softc *sc; + struct ex_rxdesc *rxd; +{ + struct mbuf *m, *oldm; + bus_dmamap_t rxmap; + int error, rval = 0; + + oldm = rxd->rx_mbhead; + rxmap = rxd->rx_dmamap; + + MGETHDR(m, M_DONTWAIT, MT_DATA); + if (m != NULL) { + MCLGET(m, M_DONTWAIT); + if ((m->m_flags & M_EXT) == 0) { + m_freem(m); + if (oldm == NULL) + return 1; + m = oldm; + m->m_data = m->m_ext.ext_buf; + rval = 1; + } + } else { + if (oldm == NULL) + return 1; + m = oldm; + m->m_data = m->m_ext.ext_buf; + rval = 1; + } + + /* + * Setup the DMA map for this receive buffer. + */ + if (m != oldm) { + if (oldm != NULL) + bus_dmamap_unload(sc->sc_dmat, rxmap); + error = bus_dmamap_load(sc->sc_dmat, rxmap, + m->m_ext.ext_buf, MCLBYTES, NULL, BUS_DMA_NOWAIT); + if (error) { + printf("%s: can't load rx buffer, error = %d\n", + sc->sc_dev.dv_xname, error); + panic("ex_add_rxbuf"); /* XXX */ + } + } + + /* + * Align for data after 14 byte header. + */ + m->m_data += 2; + + rxd->rx_mbhead = m; + rxd->rx_upd->upd_pktstatus = MCLBYTES - 2; + rxd->rx_upd->upd_frags[0].fr_addr = rxmap->dm_segs[0].ds_addr + 2; + rxd->rx_upd->upd_nextptr = 0; + + /* + * Attach it to the end of the list. + */ + if (sc->rx_head != NULL) { + sc->rx_tail->rx_next = rxd; + sc->rx_tail->rx_upd->upd_nextptr = sc->sc_upddma + + ((caddr_t)rxd->rx_upd - (caddr_t)sc->sc_upd); + bus_dmamap_sync(sc->sc_dmat, sc->sc_upd_dmamap, + (caddr_t)sc->rx_tail->rx_upd - (caddr_t)sc->sc_upd, + sizeof (struct ex_upd), + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + } else { + sc->rx_head = rxd; + } + sc->rx_tail = rxd; + + bus_dmamap_sync(sc->sc_dmat, rxmap, 0, rxmap->dm_mapsize, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + bus_dmamap_sync(sc->sc_dmat, sc->sc_upd_dmamap, + ((caddr_t)rxd->rx_upd - (caddr_t)sc->sc_upd), + sizeof (struct ex_upd), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); + return (rval); +} + +void +ex_mii_setbit(v, bit) + void *v; + u_int16_t bit; +{ + struct ex_softc *sc = v; + u_int16_t val; + + val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT); + val |= bit; + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT, val); +} + +void +ex_mii_clrbit(v, bit) + void *v; + u_int16_t bit; +{ + struct ex_softc *sc = v; + u_int16_t val; + + val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT); + val &= ~bit; + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT, val); +} + +u_int16_t +ex_mii_readbit(v, bit) + void *v; + u_int16_t bit; +{ + struct ex_softc *sc = v; + u_int16_t val; + + val = bus_space_read_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT); + return (val & bit); +} + +/* + * The reason why all this stuff below is here, is that we need a special + * readreg function. It needs to check if we're accessing the internal + * PHY on 905B-TX boards, or not. If so, the read must fail immediately, + * because 905B-TX boards seem to return garbage from the MII if you + * try to access non-existing PHYs. + */ + +int +ex_mii_readreg(v, phy, reg) + struct device *v; + int phy; + int reg; +{ + struct ex_softc *sc = (struct ex_softc *)v; + int val = 0; + int err =0; + int i; + + if ((sc->ex_conf & EX_CONF_INTPHY) && phy != ELINK_INTPHY_ID) + return 0; + + GO_WINDOW(4); + + bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_W4_PHYSMGMT, 0); + + ex_mii_clrbit(sc, ELINK_PHY_DIR); + for (i = 0; i < 32; i++) { + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_setbit(sc, ELINK_PHY_CLK); + } + ex_mii_writebits(sc, MII_COMMAND_START, 2); + ex_mii_writebits(sc, MII_COMMAND_READ, 2); + ex_mii_writebits(sc, phy, 5); + ex_mii_writebits(sc, reg, 5); + + ex_mii_clrbit(sc, ELINK_PHY_DIR); + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_setbit(sc, ELINK_PHY_CLK); + ex_mii_clrbit(sc, ELINK_PHY_CLK); + + err = ex_mii_readbit(sc, ELINK_PHY_DATA); + ex_mii_setbit(sc, ELINK_PHY_CLK); + + for (i = 0; i < 16; i++) { + val <<= 1; + ex_mii_clrbit(sc, ELINK_PHY_CLK); + if (err == 0 && ex_mii_readbit(sc, ELINK_PHY_DATA)) + val |= 1; + ex_mii_setbit(sc, ELINK_PHY_CLK); + } + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_setbit(sc, ELINK_PHY_CLK); + + GO_WINDOW(1); + + return (err ? 0 : val); +} + +static void +ex_mii_writebits(sc, data, nbits) + struct ex_softc *sc; + unsigned int data; + int nbits; +{ + int i; + + ex_mii_setbit(sc, ELINK_PHY_DIR); + for (i = 1 << (nbits -1); i; i = i >> 1) { + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_readbit(sc, ELINK_PHY_CLK); + if (data & i) + ex_mii_setbit(sc, ELINK_PHY_DATA); + else + ex_mii_clrbit(sc, ELINK_PHY_DATA); + ex_mii_setbit(sc, ELINK_PHY_CLK); + ex_mii_readbit(sc, ELINK_PHY_CLK); + } +} + +void +ex_mii_writereg(v, phy, reg, data) + struct device *v; + int phy; + int reg; + int data; +{ + struct ex_softc *sc = (struct ex_softc *)v; + int i; + + GO_WINDOW(4); + + ex_mii_clrbit(sc, ELINK_PHY_DIR); + for (i = 0; i < 32; i++) { + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_setbit(sc, ELINK_PHY_CLK); + } + ex_mii_writebits(sc, MII_COMMAND_START, 2); + ex_mii_writebits(sc, MII_COMMAND_WRITE, 2); + ex_mii_writebits(sc, phy, 5); + ex_mii_writebits(sc, reg, 5); + ex_mii_writebits(sc, MII_COMMAND_ACK, 2); + ex_mii_writebits(sc, data, 16); + + ex_mii_clrbit(sc, ELINK_PHY_CLK); + ex_mii_setbit(sc, ELINK_PHY_CLK); + + GO_WINDOW(1); +} + +void +ex_mii_statchg(v) + struct device *v; +{ + struct ex_softc *sc = (struct ex_softc *)v; + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + int mctl; + + /* XXX Update ifp->if_baudrate */ + + GO_WINDOW(3); + mctl = bus_space_read_2(iot, ioh, ELINK_W3_MAC_CONTROL); + if (sc->ex_mii.mii_media_active & IFM_FDX) + mctl |= MAC_CONTROL_FDX; + else + mctl &= ~MAC_CONTROL_FDX; + bus_space_write_2(iot, ioh, ELINK_W3_MAC_CONTROL, mctl); + GO_WINDOW(1); /* back to operating window */ +} diff --git a/sys/dev/ic/elinkxlreg.h b/sys/dev/ic/elinkxlreg.h new file mode 100644 index 000000000000..b3cd52be2bd0 --- /dev/null +++ b/sys/dev/ic/elinkxlreg.h @@ -0,0 +1,311 @@ +/* $NetBSD: elinkxlreg.h,v 1.1 1998/11/04 00:29:29 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * This file defines the registers specific to the EtherLink XL family + * of NICs. + */ + +#define EEPROM_SOFTINFO3 0x15 /* Software info #3 */ +#define EEPROM_SUBVENDOR_ELXL 0x17 /* Subsys vendor id */ +#define EEPROM_SUBSYSID 0x18 /* Subsys id */ +#define EEPROM_MEDIA 0x19 /* Media options (90xB) */ +#define EEPROM_CHECKSUM_ELXL 0x20 /* EEPROM checksum */ + +/* + * Flat address space registers (outside the windows) + */ + +#define ELINK_TXPKTID 0x18 /* 90xB only */ +#define ELINK_TIMER 0x1a +#define ELINK_TXSTATUS 0x1b +#define ELINK_INTSTATUSAUTO 0x1e +#define ELINK_DMACTRL 0x20 +# define ELINK_DMAC_DNCMPLREQ 0x00000002 +# define ELINK_DMAC_DNSTALLED 0x00000004 +# define ELINK_DMAC_UPCOMPLETE 0x00000008 +# define ELINK_DMAC_DNCOMPLETE 0x00000010 +# define ELINK_DMAC_UPRXEAREN 0x00000020 +# define ELINK_DMAC_ARNCNTDN 0x00000040 +# define ELINK_DMAC_DNINPROG 0x00000080 +# define ELINK_DMAC_CNTSPEED 0x00000100 +# define ELINK_DMAC_CNTDNMODE 0x00000200 +# define ELINK_DMAC_ALTSEQDIS 0x00010000 +# define ELINK_DMAC_DEFEATMWI 0x00100000 +# define ELINK_DMAC_DEFEATMRL 0x00200000 +# define ELINK_DMAC_UPOVERDIS 0x00400000 +# define ELINK_DMAC_TARGABORT 0x40000000 +# define ELINK_DMAC_MSTRABORT 0x80000000 +#define ELINK_DNLISTPTR 0x24 +#define ELINK_DNBURSTTHRESH 0x2a /* 90xB only */ +#define ELINK_DNPRIOTHRESH 0x2c /* 90xB only */ +#define ELINK_DNPOLL 0x2d /* 90xB only */ +#define ELINK_TXFREETHRESH 0x2f /* 90x only */ +#define ELINK_UPPKTSTATUS 0x30 +#define ELINK_FREETIMER 0x34 +#define ELINK_COUNTDOWN 0x36 +#define ELINK_UPLISTPTR 0x38 +#define ELINK_UPPRIOTHRESH 0x3c /* 90xB only */ +#define ELINK_UPPOLL 0x3d /* 90xB only */ +#define ELINK_UPBURSTTHRESH 0x3e /* 90xB only */ +#define ELINK_REALTIMECNT 0x40 /* 90xB only */ +#define ELINK_DNMAXBURST 0x78 /* 90xB only */ +#define ELINK_UPMAXBURST 0x7a /* 90xB only */ + +/* + * This is reset options for the other cards, media options for + * the 90xB NICs. Reset options are in a seperate register for + * the 90xB. + */ +#define ELINK_W3_MEDIA_OPTIONS 0x08 +# define ELINK_MEDIACAP_100BASET4 0x0001 +# define ELINK_MEDIACAP_100BASETX 0x0002 +# define ELINK_MEDIACAP_100BASEFX 0x0004 +# define ELINK_MEDIACAP_10BASET 0x0008 +# define ELINK_MEDIACAP_10BASE2 0x0010 +# define ELINK_MEDIACAP_10BASE5 0x0020 +# define ELINK_MEDIACAP_MII 0x0040 +# define ELINK_MEDIACAP_10BASEFL 0x0080 + +/* + * Window 4, offset 8 is defined for MII/PHY access for EtherLink XL + * cards. + */ +#define ELINK_W4_PHYSMGMT 0x08 +# define ELINK_PHY_CLK 0x0001 +# define ELINK_PHY_DATA 0x0002 +# define ELINK_PHY_DIR 0x0004 + +/* + * Counter in window 4 for packets with a bad start-of-stream delimiter/ + */ +#define ELINK_W4_BADSSD 0x0c +#define ELINK_W4_UBYTESOK 0x0c + +/* + * Define for extra multicast hash filter bit implemented in the 90xB + */ +#define FIL_MULTIHASH 0x10 + +/* + * Defines for the interrupt status register, only for the 90x[B] + */ +#define S_HOST_ERROR 0x0002 +#define S_LINK_EVENT 0x0100 +#define S_DN_COMPLETE 0x0200 +#define S_UP_COMPLETE 0x0400 + +#define S_MASK \ + (S_HOST_ERROR | S_TX_COMPLETE | S_UPD_STATS | S_DN_COMPLETE | S_UP_COMPLETE) + + +/* + * Window 7 registers. These are different for 90x and 90xB than + * for the EtherLink III / Fast EtherLink cards. + */ + +#define ELINK_W7_VLANMASK 0x00 /* 90xB only */ +#define ELINK_W7_VLANTYPE 0x04 /* 90xB only */ +#define ELINK_W7_TIMER 0x0a /* 90x only */ +#define ELINK_W7_TXSTATUS 0x0b /* 90x only */ +#define ELINK_W7_POWEREVENT 0x0c /* 90xB only */ +#define ELINK_W7_INTSTATUS 0x0e + +/* + * Command definitions. + */ +#define ELINK_UPSTALL 0x3000 +#define ELINK_UPUNSTALL 0x3001 +#define ELINK_DNSTALL 0x3002 +#define ELINK_DNUNSTALL 0x3003 +#define ELINK_TXRECLTHRESH 0xc000 +#define ELINK_TXSTARTTHRESH 0x9800 +#define ELINK_SETHASHFILBIT 0xcc00 + +/* + * The Internal Config register is different on 90xB cards. The + * different masks / shifts are defined here. + */ + +/* + * Lower 16 bits. + */ +#define CONFIG_TXLARGE (u_int16_t) 0x4000 +#define CONFIG_TXLARGE_SHIFT 14 + +#define CONFIG_RXLARGE (u_int16_t) 0x8000 +#define CONFIG_RXLARGE_SHIFT 15 + +/* + * Upper 16 bits. + */ +#define CONFIG_XCVR_SEL (u_int16_t) 0x00f0 +#define CONFIG_XCVR_SEL_SHIFT 4 + +#define CONFIG_AUTOSEL (u_int16_t) 0x0100 +#define CONFIG_AUTOSEL_SHIFT 8 + +#define CONFIG_DISABLEROM (u_int16_t) 0x0200 +#define CONFIG_DISABLEROM_SHIFT 9 + +/* + * ID of internal PHY. + */ + +#define ELINK_INTPHY_ID 24 + +/* + * Fragment header as laid out in memory for DMA access. + */ + +struct ex_fraghdr { + volatile u_int32_t fr_addr; /* phys addr of frag */ + volatile u_int32_t fr_len; /* length of frag */ +}; + +#define EX_FR_LENMASK 0x00001fff /* mask for length in fr_len field */ +#define EX_FR_LAST 0x80000000 /* indicates last fragment */ + +#define EX_NDPD 128 +#define EX_NUPD 64 + +/* + * Note: the number of receive fragments in an UPD is 1, since we're + * receiving into one contiguous mbuf. + */ +#define EX_NRFRAGS 1 /* # fragments in rcv pkt (< 64) */ +#define EX_NTFRAGS 32 /* # fragments in tx pkt (< 64) */ + +/* + * Type 0 Download Packet Descriptor (DPD). + */ +struct ex_dpd { + volatile u_int32_t dpd_nextptr; /* prt to next fragheader */ + volatile u_int32_t dpd_fsh; /* frame start header */ + volatile struct ex_fraghdr dpd_frags[EX_NTFRAGS]; +}; + +/* + * Type 1 DPD, supported by 90xB. + */ +struct ex_dpd1 { + volatile u_int32_t dpd_nextptr; + volatile u_int32_t dpd_schedtime; /* time to download */ + volatile u_int32_t dpd_fsh; + volatile struct ex_fraghdr dpd_frags[EX_NTFRAGS]; +}; + +struct ex_upd { + volatile u_int32_t upd_nextptr; + volatile u_int32_t upd_pktstatus; + volatile struct ex_fraghdr upd_frags[EX_NRFRAGS]; +}; + +/* + * Higher level linked list of upload packet descriptors. + */ +struct ex_rxdesc { + struct ex_rxdesc *rx_next; + struct mbuf *rx_mbhead; + bus_dmamap_t rx_dmamap; + struct ex_upd *rx_upd; +}; + +/* + * .. and for download packet descriptors. + */ +struct ex_txdesc { + struct ex_txdesc *tx_next; + struct mbuf *tx_mbhead; + bus_dmamap_t tx_dmamap; + struct ex_dpd *tx_dpd; +}; + +#define DPD_DMADDR(s,t) \ + ((s)->sc_dpddma + ((caddr_t)((t)->tx_dpd) - (caddr_t)((s)->sc_dpd))) + +/* + * Frame Start Header bitfields. + */ + +#define EX_DPD_DNIND 0x80000000 /* intr on download done */ +#define EX_DPD_TXIND 0x00008000 /* intr on tx done */ +#define EX_DPD_NOCRC 0x00002000 /* no CRC append */ + +/* + * Lower 12 bits are the tx length for the 90x family. The 90xB + * assumes that the tx length is the sum of all frame lengths, + * and uses the bits as below. It also defines some more bits in + * the upper part. + */ +#define EX_DPD_EMPTY 0x20000000 /* no data in this DPD */ +#define EX_DPD_UPDEFEAT 0x10000000 /* don't round tx lengths up */ +#define EX_DPD_UDPCKSUM 0x08000000 /* do hardware UDP checksum */ +#define EX_DPD_TCPCKSUM 0x04000000 /* do hardware TCP checksum */ +#define EX_DPD_IPCKSUM 0x02000000 /* do hardware IP checksum */ +#define EX_DPD_DNCMPLT 0x01000000 /* packet has been downloaded */ +#define EX_DPD_IDMASK 0x000003fc /* mask for packet id */ +# define EX_DPD_IDSHIFT 2 +#define EX_DPD_RNDMASK 0x00000003 /* mask for rounding */ + /* 0 -> dword, 2 -> word, 1,3 -> none */ + +/* + * Schedtime bitfields. + */ +#define EX_SCHED_TIMEVALID 0x20000000 /* field contains value */ +#define EX_SCHED_LDCOUNT 0x10000000 /* load schedtime onto NIC */ +#define EX_SCHED_TIMEMASK 0x00ffffff + +/* + * upd_pktstatus bitfields. + */ +#define EX_UPD_PKTLENMASK 0x00001fff /* 12:0 -> packet length */ +#define EX_UPD_ERROR 0x00004000 /* rcv error */ +#define EX_UPD_COMPLETE 0x00008000 /* rcv complete */ +#define EX_UPD_OVERRUN 0x00010000 /* rcv overrun */ +#define EX_UPD_RUNT 0x00020000 /* pkt < 60 bytes */ +#define EX_UPD_ALIGNERR 0x00040000 /* alignment error */ +#define EX_UPD_CRCERR 0x00080000 /* CRC error */ +#define EX_UPD_OVERSIZED 0x00100000 /* oversize frame */ +#define EX_UPD_DRIBBLEBITS 0x00800000 /* pkt had dribble bits */ +#define EX_UPD_OVERFLOW 0x01000000 /* insufficient space for pkt */ +#define EX_UPD_IPCKSUMERR 0x02000000 /* IP cksum error (90xB) */ +#define EX_UPD_TCPCKSUMERR 0x04000000 /* TCP cksum error (90xB) */ +#define EX_UPD_UDPCKSUMERR 0x08000000 /* UDP cksum error (90xB) */ + +#define EX_UPD_ERR 0x001f4000 /* Errors we check for */ diff --git a/sys/dev/ic/elinkxlvar.h b/sys/dev/ic/elinkxlvar.h new file mode 100644 index 000000000000..ef06cbcc70bc --- /dev/null +++ b/sys/dev/ic/elinkxlvar.h @@ -0,0 +1,130 @@ +/* $NetBSD: elinkxlvar.h,v 1.1 1998/11/04 00:29:29 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "rnd.h" + +#if NRND > 0 +#include +#endif + +/* + * Ethernet software status per interface. + */ +struct ex_softc { + struct device sc_dev; + void *sc_ih; + + struct ethercom sc_ethercom; /* Ethernet common part */ + bus_space_tag_t sc_iot; /* bus cookie */ + bus_space_handle_t sc_ioh; /* bus i/o handle */ + bus_dma_tag_t sc_dmat; /* bus dma tag */ + bus_dmamap_t sc_dpd_dmamap; + bus_dmamap_t sc_upd_dmamap; +#define sc_upddma sc_upd_dmamap->dm_segs[0].ds_addr +#define sc_dpddma sc_dpd_dmamap->dm_segs[0].ds_addr + struct ex_upd *sc_upd; + struct ex_dpd *sc_dpd; + bus_dmamap_t sc_tx_dmamaps[EX_NDPD]; /* DMA maps for DPDs */ + bus_dmamap_t sc_rx_dmamaps[EX_NUPD]; /* DMA maps for UPDs */ + struct ex_rxdesc sc_rxdescs[EX_NUPD]; + struct ex_txdesc sc_txdescs[EX_NDPD]; + + struct ex_rxdesc *rx_head; + struct ex_rxdesc *rx_tail; + + struct ex_txdesc *tx_head; + struct ex_txdesc *tx_tail; + struct ex_txdesc *tx_free; + struct ex_txdesc *tx_ftail; + + int tx_start_thresh; /* Current TX_start_thresh. */ + int tx_succ_ok; /* # packets sent in sequence */ + + u_int ex_connectors; /* Connectors on this card. */ + mii_data_t ex_mii; /* mii bus data */ + u_int ex_conf; /* config flags */ + +#define EX_CONF_MII 0x0001 /* has MII bus */ +#define EX_CONF_INTPHY 0x0002 /* has internal PHY */ +#define EX_CONF_90XB 0x0004 /* is 90xB */ + + + /* + * XXX code duplication from elink3var.h + */ + u_int ex_flags; /* capabilities flag (from EEPROM) */ +#define EX_FLAGS_PNP 0x0001 +#define EX_FLAGS_FULLDUPLEX 0x0002 +#define EX_FLAGS_LARGEPKT 0x0004 /* 4k packet support */ +#define EX_FLAGS_SLAVEDMA 0x0008 +#define EX_FLAGS_SECONDDMA 0x0010 +#define EX_FLAGS_FULLDMA 0x0020 +#define EX_FLAGS_FRAGMENTDMA 0x0040 +#define EX_FLAGS_CRC_PASSTHRU 0x0080 +#define EX_FLAGS_TXDONE 0x0100 +#define EX_FLAGS_NO_TXLENGTH 0x0200 +#define EX_FLAGS_RXREPEAT 0x0400 +#define EX_FLAGS_SNOOPING 0x0800 +#define EX_FLAGS_100MBIT 0x1000 +#define EX_FLAGS_POWERMGMT 0x2000 + + u_char ex_bustype; /* parent bus type (currently unused) */ + +#define EX_BUS_PCI 0 + +#if NRND > 0 + rndsource_element_t rnd_source; +#endif + + /* power management hooks */ + int (*enable) __P((struct ex_softc *)); + void (*disable) __P((struct ex_softc *)); + int enabled; +}; + +#define ex_waitcmd(sc) \ + while (bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS) \ + & S_COMMAND_IN_PROGRESS); + +u_int16_t exreadeeprom __P((bus_space_tag_t, bus_space_handle_t, int)); +void ex_config __P((struct ex_softc *)); + +int ex_intr __P((void *)); +void ex_stop __P((struct ex_softc *)); +void ex_watchdog __P((struct ifnet *)); +int ex_ioctl __P((struct ifnet *ifp, u_long, caddr_t)); diff --git a/sys/dev/isa/if_ep_isa.c b/sys/dev/isa/if_ep_isa.c index e3b84bb896be..fd67e8f68caa 100644 --- a/sys/dev/isa/if_ep_isa.c +++ b/sys/dev/isa/if_ep_isa.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep_isa.c,v 1.23 1998/08/12 18:51:54 thorpej Exp $ */ +/* $NetBSD: if_ep_isa.c,v 1.24 1998/11/04 00:30:14 fvdl Exp $ */ /*- * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc. @@ -272,7 +272,7 @@ ep_isa_probe(parent, match, aux) "ep_isa_probe: can't map Etherlink iobase\n"); return 0; } - if (bus_space_read_2(iot, ioh2, EP_W0_EEPROM_COMMAND) + if (bus_space_read_2(iot, ioh2, ELINK_W0_EEPROM_COMMAND) & EEPROM_TST_MODE) { printf( "3COM 3C509 Ethernet card in PnP mode\n"); @@ -332,7 +332,7 @@ ep_isa_attach(parent, self, aux) sc->sc_iot = iot; sc->sc_ioh = ioh; - sc->bustype = EP_BUS_ISA; + sc->bustype = ELINK_BUS_ISA; sc->enable = NULL; sc->disable = NULL; @@ -341,13 +341,13 @@ ep_isa_attach(parent, self, aux) chipset = (int)(long)ia->ia_aux; if ((chipset & 0xfff0) == PROD_ID_3C509) { printf(": 3Com 3C509 Ethernet\n"); - epconfig(sc, EP_CHIPSET_3C509, NULL); + epconfig(sc, ELINK_CHIPSET_3C509, NULL); } else { /* * XXX: Maybe a 3c515, but the check in ep_isa_probe looks * at the moment only for a 3c509. */ - printf(": unknown 3Com Ethernet card: 0x%04x\n", chipset); + printf(": unknown 3Com Ethernet card: %04x\n", chipset); return; } diff --git a/sys/dev/isapnp/if_ep_isapnp.c b/sys/dev/isapnp/if_ep_isapnp.c index 6c9bfd567e61..150e3118e0cb 100644 --- a/sys/dev/isapnp/if_ep_isapnp.c +++ b/sys/dev/isapnp/if_ep_isapnp.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep_isapnp.c,v 1.16 1998/08/12 18:51:54 thorpej Exp $ */ +/* $NetBSD: if_ep_isapnp.c,v 1.17 1998/11/04 00:30:36 fvdl Exp $ */ /* * Copyright (c) 1997 Jonathan Stone @@ -117,7 +117,7 @@ ep_isapnp_attach(parent, self, aux) sc->sc_iot = ipa->ipa_iot; sc->sc_ioh = ipa->ipa_io[0].h; - sc->bustype = EP_BUS_ISA; + sc->bustype = ELINK_BUS_ISA; sc->sc_ih = isa_intr_establish(ipa->ipa_ic, ipa->ipa_irq[0].num, ipa->ipa_irq[0].type, IPL_NET, epintr, sc); @@ -128,5 +128,5 @@ ep_isapnp_attach(parent, self, aux) /* XXX 3c515 */ - epconfig(sc, EP_CHIPSET_3C509, NULL); + epconfig(sc, ELINK_CHIPSET_3C509, NULL); } diff --git a/sys/dev/pci/files.pci b/sys/dev/pci/files.pci index 038d3191a7d4..4a907aec7f4e 100644 --- a/sys/dev/pci/files.pci +++ b/sys/dev/pci/files.pci @@ -1,4 +1,4 @@ -# $NetBSD: files.pci,v 1.48 1998/10/31 00:45:48 thorpej Exp $ +# $NetBSD: files.pci,v 1.49 1998/11/04 00:31:05 fvdl Exp $ # # Config file and device description for machine-independent PCI code. # Included by ports that need it. Requires that the SCSI files be @@ -58,6 +58,11 @@ file dev/pci/if_en_pci.c en_pci attach ep at pci with ep_pci file dev/pci/if_ep_pci.c ep_pci +# 3Com 3c90x[B] Ethernet controllers +# device declaration in sys/conf/files +attach ex at pci with ex_pci +file dev/pci/if_ex_pci.c ex_pci + # Digital DEFPA PCI FDDI Controller device fpa: pdq, fddi, ifnet, arp attach fpa at pci diff --git a/sys/dev/pci/if_ep_pci.c b/sys/dev/pci/if_ep_pci.c index 17330bdcdbc0..3d8d95fc8ff9 100644 --- a/sys/dev/pci/if_ep_pci.c +++ b/sys/dev/pci/if_ep_pci.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep_pci.c,v 1.28 1998/08/12 18:51:55 thorpej Exp $ */ +/* $NetBSD: if_ep_pci.c,v 1.29 1998/11/04 00:31:05 fvdl Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -136,7 +136,7 @@ struct ep_pci_product { int epp_flags; /* initial softc flags */ const char *epp_name; /* device name */ } ep_pci_products[] = { - { PCI_PRODUCT_3COM_3C590, EP_CHIPSET_VORTEX, + { PCI_PRODUCT_3COM_3C590, ELINK_CHIPSET_VORTEX, 0, "3c590" }, /* @@ -144,21 +144,22 @@ struct ep_pci_product { * external PHY. We treat it as `manual' in the * core driver. */ - { PCI_PRODUCT_3COM_3C595TX, EP_CHIPSET_VORTEX, + { PCI_PRODUCT_3COM_3C595TX, ELINK_CHIPSET_VORTEX, 0, "3c595-TX" }, - { PCI_PRODUCT_3COM_3C595T4, EP_CHIPSET_VORTEX, + { PCI_PRODUCT_3COM_3C595T4, ELINK_CHIPSET_VORTEX, 0, "3c595-T4" }, - { PCI_PRODUCT_3COM_3C595MII, EP_CHIPSET_VORTEX, + { PCI_PRODUCT_3COM_3C595MII, ELINK_CHIPSET_VORTEX, 0, "3c595-MII" }, - - { PCI_PRODUCT_3COM_3C900TPO, EP_CHIPSET_BOOMERANG, +#ifdef EP_DRIVES_90X + { PCI_PRODUCT_3COM_3C900TPO, ELINK_CHIPSET_BOOMERANG, 0, "3c900-TPO" }, - { PCI_PRODUCT_3COM_3C900COMBO, EP_CHIPSET_BOOMERANG, + { PCI_PRODUCT_3COM_3C900COMBO, ELINK_CHIPSET_BOOMERANG, 0, "3c900-COMBO" }, - { PCI_PRODUCT_3COM_3C905TX, EP_CHIPSET_BOOMERANG, - EP_FLAGS_MII, "3c905-TX" }, - { PCI_PRODUCT_3COM_3C905T4, EP_CHIPSET_BOOMERANG, - EP_FLAGS_MII, "3c905-T4" }, + { PCI_PRODUCT_3COM_3C905TX, ELINK_CHIPSET_BOOMERANG, + ELINK_FLAGS_MII, "3c905-TX" }, + { PCI_PRODUCT_3COM_3C905T4, ELINK_CHIPSET_BOOMERANG, + ELINK_FLAGS_MII, "3c905-T4" }, +#endif { 0, 0, 0, NULL }, @@ -226,7 +227,7 @@ ep_pci_attach(parent, self, aux) sc->disable = NULL; sc->enabled = 1; - sc->bustype = EP_BUS_PCI; + sc->bustype = ELINK_BUS_PCI; sc->ep_flags = epp->epp_flags; /* Enable the card. */ diff --git a/sys/dev/pci/if_ex_pci.c b/sys/dev/pci/if_ex_pci.c new file mode 100644 index 000000000000..6ae583a09ed9 --- /dev/null +++ b/sys/dev/pci/if_ex_pci.c @@ -0,0 +1,240 @@ +/* $NetBSD: if_ex_pci.c,v 1.1 1998/11/04 00:31:05 fvdl Exp $ */ + +/*- + * Copyright (c) 1998 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Frank van der Linden. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the NetBSD + * Foundation, Inc. and its contributors. + * 4. Neither the name of The NetBSD Foundation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include "opt_inet.h" +#include "opt_ns.h" +#include "bpfilter.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#ifdef INET +#include +#include +#include +#include +#include +#endif + +#ifdef NS +#include +#include +#endif + +#if NBPFILTER > 0 +#include +#include +#endif + +#include +#include +#include + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* + * PCI constants. + * XXX These should be in a common file! + */ +#define PCI_CONN 0x48 /* Connector type */ +#define PCI_CBIO 0x10 /* Configuration Base IO Address */ +#define PCI_CAPPTR 0x34 +#define PCI_CAPID 0xdc +#define PCI_POWERCAP 0xde +#define PCI_POWERCTL 0xe0 + +int ex_pci_match __P((struct device *, struct cfdata *, void *)); +void ex_pci_attach __P((struct device *, struct device *, void *)); + +struct cfattach ex_pci_ca = { + sizeof(struct ex_softc), ex_pci_match, ex_pci_attach +}; + +int +ex_pci_match(parent, match, aux) + struct device *parent; + struct cfdata *match; + void *aux; +{ + struct pci_attach_args *pa = (struct pci_attach_args *) aux; + + if (PCI_VENDOR(pa->pa_id) != PCI_VENDOR_3COM) + return 0; + + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_3COM_3C900TPO: + case PCI_PRODUCT_3COM_3C900COMBO: + case PCI_PRODUCT_3COM_3C905TX: + case PCI_PRODUCT_3COM_3C905T4: + case PCI_PRODUCT_3COM_3C900BTPO: + case PCI_PRODUCT_3COM_3C900BCOMBO: + case PCI_PRODUCT_3COM_3C905BT4: + case PCI_PRODUCT_3COM_3C905BTX: + break; + default: + return 0; + } + + return 1; +} + +void +ex_pci_attach(parent, self, aux) + struct device *parent, *self; + void *aux; +{ + struct ex_softc *sc = (void *)self; + struct pci_attach_args *pa = aux; + pci_chipset_tag_t pc = pa->pa_pc; + pci_intr_handle_t ih; + char *model; + const char *intrstr = NULL; + int pmode; + + if (pci_mapreg_map(pa, PCI_CBIO, PCI_MAPREG_TYPE_IO, 0, + &sc->sc_iot, &sc->sc_ioh, NULL, NULL)) { + printf(": can't map i/o space\n"); + return; + } + + sc->sc_dmat = pa->pa_dmat; + + sc->ex_bustype = EX_BUS_PCI; + sc->ex_conf = 0; + + switch (PCI_PRODUCT(pa->pa_id)) { + case PCI_PRODUCT_3COM_3C900TPO: + case PCI_PRODUCT_3COM_3C900COMBO: + model = "3Com 3C900 Ethernet"; + break; + case PCI_PRODUCT_3COM_3C905TX: + case PCI_PRODUCT_3COM_3C905T4: + sc->ex_conf = EX_CONF_MII; + model = "3Com 3C905 Ethernet"; + break; + case PCI_PRODUCT_3COM_3C900BTPO: + case PCI_PRODUCT_3COM_3C900BCOMBO: + sc->ex_conf = EX_CONF_90XB; + model = "3Com 3C900B Ethernet"; + break; + case PCI_PRODUCT_3COM_3C905BTX: + case PCI_PRODUCT_3COM_3C905BT4: + sc->ex_conf = (EX_CONF_MII | EX_CONF_90XB); + if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_3COM_3C905BTX) + sc->ex_conf |= EX_CONF_INTPHY; + model = "3Com 3C905B Ethernet"; + break; + default: + model = "unknown model!"; + break; + } + + printf(": %s\n", model); + + sc->enable = NULL; + sc->disable = NULL; + sc->enabled = 1; + + /* Enable the card. */ + pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, + pci_conf_read(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG) | + PCI_COMMAND_MASTER_ENABLE); + + /* Get it out of power save mode if needed (BIOS bugs) */ + if ((pci_conf_read(pc, pa->pa_tag, PCI_CAPPTR) & 0xff) == PCI_CAPID && + (pci_conf_read(pc, pa->pa_tag, PCI_CAPID) & 0xff) == 0x01) { + pmode = pci_conf_read(pc, pa->pa_tag, PCI_POWERCTL) & 0x3; + if (pmode == 3) { + /* + * The card has lost all configuration data in + * this state, so punt. + */ + printf("%s: unable to wake up from power state D3\n", + sc->sc_dev.dv_xname); + return; + } + if (pmode != 0) { + printf("%s: waking up from power state D%d\n", + sc->sc_dev.dv_xname, pmode); + pci_conf_write(pc, pa->pa_tag, PCI_POWERCTL, 0); + } + } + + /* Map and establish the interrupt. */ + if (pci_intr_map(pc, pa->pa_intrtag, pa->pa_intrpin, + pa->pa_intrline, &ih)) { + printf("%s: couldn't map interrupt\n", sc->sc_dev.dv_xname); + return; + } + intrstr = pci_intr_string(pc, ih); + sc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, ex_intr, sc); + if (sc->sc_ih == NULL) { + printf("%s: couldn't establish interrupt", + sc->sc_dev.dv_xname); + if (intrstr != NULL) + printf(" at %s", intrstr); + printf("\n"); + return; + } + printf("%s: interrupting at %s\n", sc->sc_dev.dv_xname, intrstr); + + ex_config(sc); + +} diff --git a/sys/dev/pcmcia/if_ep_pcmcia.c b/sys/dev/pcmcia/if_ep_pcmcia.c index a97f9f202190..a54596e81560 100644 --- a/sys/dev/pcmcia/if_ep_pcmcia.c +++ b/sys/dev/pcmcia/if_ep_pcmcia.c @@ -1,4 +1,4 @@ -/* $NetBSD: if_ep_pcmcia.c,v 1.16 1998/08/17 23:20:40 thorpej Exp $ */ +/* $NetBSD: if_ep_pcmcia.c,v 1.17 1998/11/04 00:31:33 fvdl Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -146,15 +146,15 @@ struct ep_pcmcia_product { int epp_expfunc; /* expected function */ const char *epp_name; /* device name */ } ep_pcmcia_products[] = { - { PCMCIA_PRODUCT_3COM_3C562, EP_CHIPSET_3C509, + { PCMCIA_PRODUCT_3COM_3C562, ELINK_CHIPSET_3C509, 0, 0, PCMCIA_STR_3COM_3C562 }, - { PCMCIA_PRODUCT_3COM_3C589, EP_CHIPSET_3C509, + { PCMCIA_PRODUCT_3COM_3C589, ELINK_CHIPSET_3C509, 0, 0, PCMCIA_STR_3COM_3C589 }, - { PCMCIA_PRODUCT_3COM_3C574, EP_CHIPSET_ROADRUNNER, - EP_FLAGS_MII, 0, + { PCMCIA_PRODUCT_3COM_3C574, ELINK_CHIPSET_ROADRUNNER, + ELINK_FLAGS_MII, 0, PCMCIA_STR_3COM_3C574 }, { 0, 0, @@ -342,14 +342,14 @@ ep_pcmcia_attach(parent, self, aux) break; } - sc->bustype = EP_BUS_PCMCIA; + sc->bustype = ELINK_BUS_PCMCIA; epp = ep_pcmcia_lookup(pa); if (epp == NULL) panic("ep_pcmcia_attach: impossible"); printf(": %s\n", epp->epp_name); - + sc->enable = ep_pcmcia_enable; sc->disable = ep_pcmcia_disable;