diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-07-30 11:12:29 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1997-07-30 11:12:29 +0000 |
commit | ebf09a5432e7b2f7330349a287ea06557130d024 (patch) | |
tree | 4b31be4473c64d35c413d75be8765ad785c33e53 /sys | |
parent | 4c8a97d907a4ec836ce801ead5d8529e1699b553 (diff) |
Sync to NetBSD. Adapt to use bus_space_multi_raw* interface of OpenBSD.
Some KNF too.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/eisa/if_ep_eisa.c | 37 | ||||
-rw-r--r-- | sys/dev/ic/elink3.c | 687 | ||||
-rw-r--r-- | sys/dev/ic/elink3reg.h | 166 | ||||
-rw-r--r-- | sys/dev/ic/elink3var.h | 38 | ||||
-rw-r--r-- | sys/dev/isa/if_ep_isa.c | 22 | ||||
-rw-r--r-- | sys/dev/pci/if_ep_pci.c | 14 | ||||
-rw-r--r-- | sys/dev/pcmcia/if_ep_pcmcia.c | 31 |
7 files changed, 820 insertions, 175 deletions
diff --git a/sys/dev/eisa/if_ep_eisa.c b/sys/dev/eisa/if_ep_eisa.c index b79dc46f391..55cbc786eeb 100644 --- a/sys/dev/eisa/if_ep_eisa.c +++ b/sys/dev/eisa/if_ep_eisa.c @@ -1,6 +1,8 @@ -/* $NetBSD: if_ep_eisa.c,v 1.9 1996/10/21 22:31:04 thorpej Exp $ */ +/* $OpenBSD: if_ep_eisa.c,v 1.8 1997/07/30 11:12:25 niklas Exp $ */ +/* $NetBSD: if_ep_eisa.c,v 1.13 1997/04/18 00:50:33 cgd Exp $ */ /* + * Copyright (c) 1997 Jonathan Stone <jonathan@NetBSD.org> * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org> * All rights reserved. * @@ -94,7 +96,11 @@ ep_eisa_match(parent, match, aux) /* must match one of our known ID strings */ if (strcmp(ea->ea_idstring, "TCM5091") && strcmp(ea->ea_idstring, "TCM5092") && - strcmp(ea->ea_idstring, "TCM5093")) + strcmp(ea->ea_idstring, "TCM5093") && + strcmp(ea->ea_idstring, "TCM5920") && + strcmp(ea->ea_idstring, "TCM5970") && + strcmp(ea->ea_idstring, "TCM5971") && + strcmp(ea->ea_idstring, "TCM5972")) return (0); return (1); @@ -109,10 +115,11 @@ ep_eisa_attach(parent, self, aux) struct eisa_attach_args *ea = aux; bus_space_tag_t iot = ea->ea_iot; bus_space_handle_t ioh; - u_int16_t k, conn = 0; + u_int16_t k; eisa_chipset_tag_t ec = ea->ea_ec; eisa_intr_handle_t ih; const char *model, *intrstr; + int chipset; u_int irq; /* Map i/o space. */ @@ -138,18 +145,32 @@ ep_eisa_attach(parent, self, aux) /* Read the IRQ from the card. */ irq = bus_space_read_2(iot, ioh, EP_W0_RESOURCE_CFG) >> 12; - GO_WINDOW(0); - conn = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL); - + chipset = EP_CHIPSET_3C509; /* assume dumb chipset */ if (strcmp(ea->ea_idstring, "TCM5091") == 0) model = EISA_PRODUCT_TCM5091; else if (strcmp(ea->ea_idstring, "TCM5092") == 0) model = EISA_PRODUCT_TCM5092; else if (strcmp(ea->ea_idstring, "TCM5093") == 0) model = EISA_PRODUCT_TCM5093; + else if (strcmp(ea->ea_idstring, "TCM5920") == 0) { + model = EISA_PRODUCT_TCM5920; + chipset = EP_CHIPSET_VORTEX; + } + else if (strcmp(ea->ea_idstring, "TCM5970") == 0) { + model = EISA_PRODUCT_TCM5970; + chipset = EP_CHIPSET_VORTEX; + } + else if (strcmp(ea->ea_idstring, "TCM5971") == 0) { + model = EISA_PRODUCT_TCM5971; + chipset = EP_CHIPSET_VORTEX; + } + else if (strcmp(ea->ea_idstring, "TCM5972") == 0) { + model = EISA_PRODUCT_TCM5972; + chipset = EP_CHIPSET_VORTEX; + } else model = "unknown model!"; - printf(": <%s> ", model); + printf(": %s\n", model); if (eisa_intr_map(ec, irq, &ih)) { printf("couldn't map interrupt (%u)\n", irq); @@ -168,5 +189,5 @@ ep_eisa_attach(parent, self, aux) if (intrstr != NULL) printf("%s, ", intrstr); - epconfig(sc, conn); + epconfig(sc, chipset); } diff --git a/sys/dev/ic/elink3.c b/sys/dev/ic/elink3.c index c182da11b12..9a923c2476c 100644 --- a/sys/dev/ic/elink3.c +++ b/sys/dev/ic/elink3.c @@ -1,7 +1,8 @@ -/* $OpenBSD: elink3.c,v 1.17 1997/01/05 04:03:26 deraadt Exp $ */ -/* $NetBSD: elink3.c,v 1.11 1996/10/21 22:34:21 thorpej Exp $ */ +/* $OpenBSD: elink3.c,v 1.18 1997/07/30 11:12:22 niklas Exp $ */ +/* $NetBSD: elink3.c,v 1.32 1997/05/14 00:22:00 thorpej Exp $ */ /* + * Copyright (c) 1996, 1997 Jonathan Stone <jonathan@NetBSD.org> * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org> * All rights reserved. * @@ -44,7 +45,6 @@ #include <sys/device.h> #include <net/if.h> -#include <net/netisr.h> #include <net/if_dl.h> #include <net/if_types.h> #include <net/netisr.h> @@ -73,55 +73,147 @@ #define ETHER_MAX_LEN 1518 #define ETHER_ADDR_LEN 6 +/* + * Structure to map media-present bits in boards to + * ifmedia codes and printable media names. Used for table-driven + * ifmedia initialization. + */ +struct ep_media { + int epm_eeprom_data; /* bitmask for eeprom config */ + int epm_conn; /* sc->ep_connectors code for medium */ + char* epm_name; /* name of medium */ + int epm_ifmedia; /* ifmedia word for medium */ + int epm_ifdata; +}; + +/* + * ep_media table for Vortex/Demon/Boomerang: + * map from media-present bits in register RESET_OPTIONS+2 + * to ifmedia "media words" and printable names. + * + * XXX indexed directly by INTERNAL_CONFIG default_media field, + * (i.e., EPMEDIA_ constants) forcing order of entries. + * Note that 3 is reserved. + */ +struct ep_media ep_vortex_media[8] = { + { EP_PCI_UTP, EPC_UTP, "utp", /*IFM_ETHER|IFM_10_T*/0, + EPMEDIA_10BASE_T }, + { EP_PCI_AUI, EPC_AUI, "aui", /*IFM_ETHER|IFM_10_5*/0, + EPMEDIA_AUI }, + { 0, 0, "reserved", /*IFM_NONE*/0, EPMEDIA_RESV1 }, + { EP_PCI_BNC, EPC_BNC, "bnc", /*IFM_ETHER|IFM_10_2*/0, + EPMEDIA_10BASE_2 }, + { EP_PCI_100BASE_TX, EPC_100TX, "100-TX", /*IFM_ETHER|IFM_100_TX*/0, + EPMEDIA_100BASE_TX }, + { EP_PCI_100BASE_FX, EPC_100FX, "100-FX", /*IFM_ETHER|IFM_100_FX*/0, + EPMEDIA_100BASE_FX }, + { EP_PCI_100BASE_MII,EPC_MII, "mii", /*IFM_ETHER|IFM_100_TX*/0, + EPMEDIA_MII }, + { EP_PCI_100BASE_T4, EPC_100T4, "100-T4", /*IFM_ETHER|IFM_100_T4*/0, + EPMEDIA_100BASE_T4 } +}; + +/* + * ep_media table for 3c509/3c509b/3c579/3c589: + * map from media-present bits in register CNFG_CNTRL + * (window 0, offset ?) to ifmedia "media words" and printable names. + */ +struct ep_media ep_isa_media[3] = { + { EP_W0_CC_UTP, EPC_UTP, "utp", /*IFM_ETHER|IFM_10_T*/0, EPMEDIA_10BASE_T }, + { EP_W0_CC_AUI, EPC_AUI, "aui", /*IFM_ETHER|IFM_10_5*/0, EPMEDIA_AUI }, + { EP_W0_CC_BNC, EPC_BNC, "bnc", /*IFM_ETHER|IFM_10_2*/0, EPMEDIA_10BASE_2 }, +}; + +#ifdef __NetBSD__ +/* Map vortex reset_options bits to if_media codes. */ +const u_int ep_default_to_media[8] = { + IFM_ETHER | IFM_10_T, + IFM_ETHER | IFM_10_5, + 0, /* reserved by 3Com */ + IFM_ETHER | IFM_10_2, + IFM_ETHER | IFM_100_TX, + IFM_ETHER | IFM_100_FX, + IFM_ETHER | IFM_100_TX, /* XXX really MII: need to talk to PHY */ + IFM_ETHER | IFM_100_T4, +}; +#endif + +/* Autoconfig defintion of driver back-end */ struct cfdriver ep_cd = { NULL, "ep", DV_IFNET }; -static void eptxstat __P((struct ep_softc *)); -static int epstatus __P((struct ep_softc *)); -void epinit __P((struct ep_softc *)); -int epioctl __P((struct ifnet *, u_long, caddr_t)); -void epstart __P((struct ifnet *)); -void epwatchdog __P((struct ifnet *)); -void epreset __P((struct ep_softc *)); -void epread __P((struct ep_softc *)); +#ifdef __NetBSD__ +void ep_internalconfig __P((struct ep_softc *sc)); +#endif +void ep_vortex_probemedia __P((struct ep_softc *sc)); +void ep_isa_probemedia __P((struct ep_softc *sc)); +void eptxstat __P((struct ep_softc *)); +int epstatus __P((struct ep_softc *)); +void epinit __P((struct ep_softc *)); +int epioctl __P((struct ifnet *, u_long, caddr_t)); +void epstart __P((struct ifnet *)); +void epwatchdog __P((struct ifnet *)); +void epreset __P((struct ep_softc *)); +void epshutdown __P((void *)); +void epread __P((struct ep_softc *)); struct mbuf *epget __P((struct ep_softc *, int)); -void epmbuffill __P((void *)); -void epmbufempty __P((struct ep_softc *)); -void epsetfilter __P((struct ep_softc *)); -void epsetlink __P((struct ep_softc *)); +void epmbuffill __P((void *)); +void epmbufempty __P((struct ep_softc *)); +void epsetfilter __P((struct ep_softc *)); +int epsetmedia __P((struct ep_softc *, int)); +int epbusyeeprom __P((struct ep_softc *)); +static inline void ep_complete_cmd __P((struct ep_softc *sc, u_int cmd, + u_int arg)); + +/* + * Issue a (reset) command, and be sure it has completed. + * Used for commands that reset part or all of the board. + * On newer hardware we could poll SC_COMMAND_IN_PROGRESS, + * but older hardware doesn't implement it and we must delay. + * It's easiest to just delay always. + */ +static inline void +ep_complete_cmd(sc, cmd, arg) + struct ep_softc *sc; + u_int cmd, arg; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; -static int epbusyeeprom __P((struct ep_softc *)); + bus_space_write_2(iot, ioh, 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) + ; + else +#else + DELAY(100000); /* need at least 1 ms, but be generous. */ +#endif +} + +/* + * Back-end attach and configure. + */ void -epconfig(sc, conn) +epconfig(sc, chipset) struct ep_softc *sc; - u_int16_t conn; + u_short chipset; { struct ifnet *ifp = &sc->sc_arpcom.ac_if; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; u_int16_t i; - sc->ep_connectors = 0; - if (conn & IS_AUI) { - printf("aui"); - sc->ep_connectors |= AUI; - } - if (conn & IS_BNC) { - if (sc->ep_connectors) - printf("/"); - printf("bnc"); - sc->ep_connectors |= BNC; - } - if (conn & IS_UTP) { - if (sc->ep_connectors) - printf("/"); - printf("utp"); - sc->ep_connectors |= UTP; - } - if (!sc->ep_connectors) - printf("no connectors!"); + sc->ep_chipset = chipset; + + /* + * We could have been groveling around in other register + * windows in the front-end; make sure we're in window 0 + * to read the EEPROM. + */ + GO_WINDOW(0); /* * Read the station address from the eeprom @@ -129,24 +221,60 @@ epconfig(sc, conn) for (i = 0; i < 3; i++) { u_int16_t x; if (epbusyeeprom(sc)) - return; + return; /* XXX why is eeprom busy? */ bus_space_write_2(iot, ioh, EP_W0_EEPROM_COMMAND, READ_EEPROM | i); if (epbusyeeprom(sc)) - return; + return; /* XXX why is eeprom busy? */ x = bus_space_read_2(iot, ioh, EP_W0_EEPROM_DATA); sc->sc_arpcom.ac_enaddr[(i << 1)] = x >> 8; sc->sc_arpcom.ac_enaddr[(i << 1) + 1] = x; } - printf(" address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); + printf("address %s\n", ether_sprintf(sc->sc_arpcom.ac_enaddr)); - bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_AVAIL_THRESH | 1800 ); + /* + * Vortex-based (3c59x pci,eisa) and Boomerang (3c900,3c515?) cards + * allow FDDI-sized (4500) byte packets. Commands only take an + * 11-bit parameter, and 11 bits isn't enough to hold a full-size + * packet length. + * Commands to these cards implicitly upshift a packet size + * or threshold by 2 bits. + * To detect cards with large-packet support, we probe by setting + * the transmit threshold register, then change windows and + * 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 ); GO_WINDOW(5); i = bus_space_read_2(iot, ioh, EP_W5_TX_AVAIL_THRESH); GO_WINDOW(1); - if (i == 1800*4) + switch (i) { + case EP_LARGEWIN_PROBE: + case (EP_LARGEWIN_PROBE & EP_LARGEWIN_MASK): + sc->txashift = 0; + break; + + case (EP_LARGEWIN_PROBE << 2): sc->txashift = 2; + /* XXX does the 3c515 support Vortex-style RESET_OPTIONS? */ + break; + + default: + printf("%s: wrote %d to TX_AVAIL_THRESH, read back %d. " + "Interface disabled\n", + sc->sc_dev.dv_xname, EP_THRESH_DISABLE, (int) i); + return; + } + + /* + * Ensure Tx-available interrupts are enabled for + * start the interface. + * XXX should be in epinit()? + */ + bus_space_write_2(iot, ioh, EP_COMMAND, + SET_TX_AVAIL_THRESH | (1600 >> sc->txashift)); bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); ifp->if_softc = sc; @@ -159,15 +287,246 @@ epconfig(sc, conn) if_attach(ifp); ether_ifattach(ifp); + /* + * Finish configuration: + * determine chipset if the front-end couldn't do so, + * show board details, set media. + */ + +#ifdef __NetBSD__ + /* print RAM size */ + ep_internalconfig(sc); +#endif + GO_WINDOW(0); + +#ifdef __NetBSD__ + ifmedia_init(&sc->sc_media, 0, ep_media_change, ep_media_status); +#endif + + /* + * If we've got an indirect (ISA, PCMCIA?) board, the chipset + * is unknown. If the board has large-packet support, it's a + * Vortex/Boomerang, otherwise it's a 3c509. + * XXX use eeprom capability word instead? + */ + if (sc->ep_chipset == EP_CHIPSET_UNKNOWN && sc->txashift) { + printf("warning: unknown chipset, possibly 3c515?\n"); +#ifdef notyet + sc->sc_chipset = EP_CHIPSET_VORTEX; +#endif /* notyet */ + } + + /* + * Ascertain which media types are present and inform ifmedia. + */ + switch (sc->ep_chipset) { + /* on a direct bus, the attach routine can tell, but check anyway. */ + case EP_CHIPSET_VORTEX: + case EP_CHIPSET_BOOMERANG2: + ep_vortex_probemedia(sc); + break; + + /* on ISA we can't yet tell 3c509 from 3c515. Assume the former. */ + case EP_CHIPSET_3C509: + default: + ep_isa_probemedia(sc); + break; + } + + GO_WINDOW(1); /* Window 1 is operating window */ + #if NBPFILTER > 0 bpfattach(&sc->sc_arpcom.ac_if.if_bpf, ifp, DLT_EN10MB, - sizeof(struct ether_header)); + sizeof (struct ether_header)); #endif sc->tx_start_thresh = 20; /* probably a good starting point. */ + + /* 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); +} + +#ifdef __NetBSD__ +/* Is this info worth an extra line of dmesg output? */ + +/* + * Show interface-model-independent info from window 3 + * internal-configuration register. + */ +void +ep_internalconfig(sc) + struct ep_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; + + u_int config0; + u_int config1; + + int ram_size, ram_width, ram_speed, rom_size, ram_split; + /* + * NVRAM buffer Rx:Tx config names for busmastering cards + * (Demon, Vortex, and later). + */ + const char *onboard_ram_config[] = { + "5:3", "3:1", "1:1", "(undefined)" }; + + 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); + GO_WINDOW(0); + + ram_size = (config0 & CONFIG_RAMSIZE) >> CONFIG_RAMSIZE_SHIFT; + ram_width = (config0 & CONFIG_RAMWIDTH) >> CONFIG_RAMWIDTH_SHIFT; + ram_speed = (config0 & CONFIG_RAMSPEED) >> CONFIG_RAMSPEED_SHIFT; + rom_size = (config0 & CONFIG_ROMSIZE) >> CONFIG_ROMSIZE_SHIFT; + + ram_split = (config1 & CONFIG_RAMSPLIT) >> CONFIG_RAMSPLIT_SHIFT; + + printf("%s: %dKB %s-wide FIFO, %s Rx:Tx split, ", + sc->sc_dev.dv_xname, 8 << ram_size, (ram_width) ? "word" : "byte", + onboard_ram_config[ram_split]); } +#endif /* + * Find supported media on 3c509-generation hardware that doesn't have + * a "reset_options" register in window 3. + * Use the config_cntrl register in window 0 instead. + * Used on original, 10Mbit ISA (3c509), 3c509B, and pre-Demon EISA cards + * that implement CONFIG_CTRL. We don't have a good way to set the + * default active mediuim; punt to ifconfig instead. + * + * XXX what about 3c515, pcmcia 10/100? + */ +void +ep_isa_probemedia(sc) + struct ep_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; +#ifdef __NetBSD__ + struct ifmedia *ifm = &sc->sc_media; +#endif + int conn, i; + u_int16_t ep_w0_config, port; + + conn = 0; + GO_WINDOW(0); + ep_w0_config = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL); + for (i = 0; i < 3; i++) { + struct ep_media * epm = ep_isa_media + i; + + if ((ep_w0_config & epm->epm_eeprom_data) != 0) { +#ifdef __NetBSD__ + ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_ifdata, 0); +#endif + if (conn) + printf("/"); + printf(epm->epm_name); + conn |= epm->epm_conn; + } + } + sc->ep_connectors = conn; + + /* get default medium from EEPROM */ + if (epbusyeeprom(sc)) + return; /* XXX why is eeprom busy? */ + bus_space_write_2(iot, ioh, EP_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); + port = port >> 14; + + printf(" (default %s)\n", ep_vortex_media[port].epm_name); +#ifdef __NetBSD__ + /* tell ifconfig what currently-active media is. */ + ifmedia_set(ifm, ep_default_to_media[port]); +#endif + + /* XXX autoselect not yet implemented */ +} + + +/* + * Find media present on large-packet-capable elink3 devices. + * Show onboard configuration of large-packet-capable elink3 devices + * (Demon, Vortex, Boomerang), which do not implement CONFIG_CTRL in window 0. + * Use media and card-version info in window 3 instead. + * + * XXX how much of this works with 3c515, pcmcia 10/100? + */ +void +ep_vortex_probemedia(sc) + struct ep_softc *sc; +{ + bus_space_tag_t iot = sc->sc_iot; + bus_space_handle_t ioh = sc->sc_ioh; +#ifdef __NetBSD__ + struct ifmedia *ifm = &sc->sc_media; +#endif + u_int config1, conn; + int reset_options; + int default_media; /* 3-bit encoding of default (EEPROM) media */ + int autoselect; /* boolean: should default to autoselect */ + const char *medium_name; + register int i; + + 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); + GO_WINDOW(0); + + default_media = (config1 & CONFIG_MEDIAMASK) >> CONFIG_MEDIAMASK_SHIFT; + autoselect = (config1 & CONFIG_AUTOSELECT) >> CONFIG_AUTOSELECT_SHIFT; + + /* set available media options */ + conn = 0; + for (i = 0; i < 8; i++) { + struct ep_media * epm = ep_vortex_media + i; + + if ((reset_options & epm->epm_eeprom_data) != 0) { + if (conn) printf("/"); + printf(epm->epm_name); + conn |= epm->epm_conn; +#ifdef __NetBSD__ + ifmedia_add(ifm, epm->epm_ifmedia, epm->epm_ifdata, 0); +#endif /* __NetBSD__ */ + } + } + + sc->ep_connectors = conn; + + /* Show eeprom's idea of default media. */ + medium_name = (default_media > 8) + ? "(unknown/impossible media)" + : ep_vortex_media[default_media].epm_name; + printf(" default %s%s\n", + medium_name, (autoselect)? ", autoselect" : "" ); + +#ifdef notyet + /* + * Set default: either the active interface the card + * reads from the EEPROM, or if autoselect is true, + * whatever we find is actually connected. + * + * XXX autoselect not yet implemented. + */ +#endif /* notyet */ + +#ifdef __NetBSD__ + /* tell ifconfig what currently-active media is. */ + ifmedia_set(ifm, ep_default_to_media[default_media]); +#endif /* __NetBSD__ */ +} + +/* + * Bring device up. + * * The order in here seems important. Otherwise we may not receive * interrupts. ?! */ @@ -204,17 +563,25 @@ epinit(sc) sc->sc_arpcom.ac_enaddr[i]); if (sc->bustype == EP_BUS_PCI || sc->bustype == EP_BUS_EISA) - /* Reset the station-address receive filter */ + /* + * Reset the station-address receive filter. + * 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, EP_W2_RECVMASK_0 + i, 0); - bus_space_write_2(iot, ioh, EP_COMMAND, RX_RESET); - bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET); + ep_complete_cmd(sc, EP_COMMAND, RX_RESET); + ep_complete_cmd(sc, EP_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_TX_STATUS); + /* Set threshhold for for Tx-space avaiable interrupt. */ + bus_space_write_2(iot, ioh, EP_COMMAND, + SET_TX_AVAIL_THRESH | (1600 >> sc->txashift)); + + /* Enable interrupts. */ bus_space_write_2(iot, ioh, EP_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 | @@ -229,7 +596,11 @@ epinit(sc) bus_space_write_2(iot, ioh, EP_COMMAND, ACK_INTR | 0xff); epsetfilter(sc); - epsetlink(sc); +#ifdef __NetBSD__ + epsetmedia(sc, sc->sc_media.ifm_cur->ifm_data); +#else + epsetmedia(sc, 0); /* XXX */ +#endif bus_space_write_2(iot, ioh, EP_COMMAND, RX_ENABLE); bus_space_write_2(iot, ioh, EP_COMMAND, TX_ENABLE); @@ -244,6 +615,11 @@ epinit(sc) epstart(ifp); } +/* + * Set multicast receive filter. + * elink3 hardware has no selective multicast filter in hardware. + * Enable reception of all multicasts and filter in software. + */ void epsetfilter(sc) register struct ep_softc *sc; @@ -257,13 +633,23 @@ epsetfilter(sc) ((ifp->if_flags & IFF_PROMISC) ? FIL_PROMISC : 0 )); } -void -epsetlink(sc) - register struct ep_softc *sc; +/* + * Set active media to a specific given EPMEDIA_<> value. + * For vortex/demon/boomerang cards, update media field in w3_internal_config, + * and power on selected transceiver. + * For 3c509-generation cards (3c509/3c579/3c589/3c509B), + * update media field in w0_address_config, and power on selected xcvr. + */ +int +epsetmedia(sc, medium) + struct ep_softc *sc; + int medium; { - register struct ifnet *ifp = &sc->sc_arpcom.ac_if; + struct ifnet *ifp = &sc->sc_arpcom.ac_if; bus_space_tag_t iot = sc->sc_iot; bus_space_handle_t ioh = sc->sc_ioh; + int w4_media; + int config0, config1; /* * you can `ifconfig (link0|-link0) ep0' to get the following @@ -273,32 +659,112 @@ epsetlink(sc) * link1 if the card has a UTP connector, and link0 is * set too, then you get the UTP port. */ + + /* + * First, change the media-control bits in EP_W4_MEDIA_TYPE. + */ + + /* Turn everything off. First turn off linkbeat and UTP. */ GO_WINDOW(4); - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, DISABLE_UTP); - if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & BNC)) { - if (sc->bustype == EP_BUS_PCMCIA) { - GO_WINDOW(0); - bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG,3<<14); - GO_WINDOW(1); - } + w4_media = bus_space_read_2(iot, ioh, EP_W4_MEDIA_TYPE); + w4_media = w4_media & ~(ENABLE_UTP|SQE_ENABLE); + bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, w4_media); + + /* Turn off coax */ + bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER); + delay(1000); + +#ifndef __NetBSD__ + /* XXX what media? */ + medium = 0; + if (!(ifp->if_flags & IFF_LINK0) && (sc->ep_connectors & EPC_BNC)) + medium = EPMEDIA_10BASE_2; + else if (ifp->if_flags & IFF_LINK0) + if ((ifp->if_flags & IFF_LINK1) && + (sc->ep_connectors & EPC_UTP)) + medium = EPMEDIA_10BASE_T; + else + medium = EPMEDIA_AUI; +#endif + + /* + * Now turn on the selected media/transceiver. + */ + GO_WINDOW(4); + switch (medium) { + case EPMEDIA_10BASE_T: + bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + w4_media | ENABLE_UTP); + break; + + case EPMEDIA_10BASE_2: bus_space_write_2(iot, ioh, EP_COMMAND, START_TRANSCEIVER); - delay(1000); + DELAY(1000); /* 50ms not enmough? */ + break; + + /* XXX following only for new-generation cards */ + case EPMEDIA_100BASE_TX: + case EPMEDIA_100BASE_FX: + case EPMEDIA_100BASE_T4: /* XXX check documentation */ + bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + w4_media | LINKBEAT_ENABLE); + DELAY(1000); /* not strictly necessary? */ + break; + + case EPMEDIA_AUI: + bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, + w4_media | SQE_ENABLE); + DELAY(1000); /* not strictly necessary? */ + break; + case EPMEDIA_MII: + break; + default: +#if defined(DEBUG) + printf("%s unknown media 0x%x\n", sc->sc_dev.dv_xname, medium); +#endif + break; + } - if (ifp->if_flags & IFF_LINK0) { - bus_space_write_2(iot, ioh, EP_COMMAND, STOP_TRANSCEIVER); - delay(1000); - if ((ifp->if_flags & IFF_LINK1) && (sc->ep_connectors & UTP)) { - if (sc->bustype == EP_BUS_PCMCIA) { - GO_WINDOW(0); - bus_space_write_2(iot, ioh, - EP_W0_ADDRESS_CFG,0<<14); - GO_WINDOW(4); - } - bus_space_write_2(iot, ioh, EP_W4_MEDIA_TYPE, - ENABLE_UTP); - } + + /* + * Tell the chip which PHY [sic] to use. + */ + switch (sc->ep_chipset) { + case EP_CHIPSET_VORTEX: + case EP_CHIPSET_BOOMERANG2: + 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); + +#if defined(DEBUG) + printf("%s: read 0x%x, 0x%x from EP_W3_CONFIG register\n", + sc->sc_dev.dv_xname, config0, config1); +#endif + config1 = config1 & ~CONFIG_MEDIAMASK; + config1 |= (medium << CONFIG_MEDIAMASK_SHIFT); + +#if defined(DEBUG) + printf("epsetmedia: %s: medium 0x%x, 0x%x to EP_W3_CONFIG\n", + sc->sc_dev.dv_xname, medium, config1); +#endif + bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG, config0); + bus_space_write_2(iot, ioh, EP_W3_INTERNAL_CONFIG + 2, config1); + break; + + case EP_CHIPSET_3C509: + GO_WINDOW(0); + config0 = bus_space_read_2(iot, ioh, EP_W0_ADDRESS_CFG); + config0 &= 0x3fff; + bus_space_write_2(iot, ioh, EP_W0_ADDRESS_CFG, + config0 | (medium << 14)); + DELAY(1000); + break; } - GO_WINDOW(1); + + GO_WINDOW(1); /* Window 1 is operating window */ + return (0); } /* @@ -316,7 +782,7 @@ epstart(ifp) int sh, len, pad; /* Don't transmit if interface is busy or not running */ - if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) + if ((ifp->if_flags & (IFF_RUNNING | IFF_OACTIVE)) != IFF_RUNNING) return; startagain: @@ -353,7 +819,7 @@ startagain: return; } else { bus_space_write_2(iot, ioh, EP_COMMAND, - SET_TX_AVAIL_THRESH | (2044 >> sc->txashift)); + SET_TX_AVAIL_THRESH | EP_THRESH_DISABLE); } IF_DEQUEUE(&ifp->if_snd, m0); @@ -361,7 +827,7 @@ startagain: return; bus_space_write_2(iot, ioh, EP_COMMAND, SET_TX_START_THRESH | - (len / 4 + sc->tx_start_thresh)); + ((len / 4 + sc->tx_start_thresh) /*>> sc->txashift*/)); #if NBPFILTER > 0 if (ifp->if_bpf) @@ -380,9 +846,9 @@ startagain: if (EP_IS_BUS_32(sc->bustype)) { for (m = m0; m; ) { if (m->m_len > 3) - bus_space_write_multi_4(iot, ioh, - EP_W1_TX_PIO_WR_1, mtod(m, u_int32_t *), - m->m_len / 4); + bus_space_write_raw_multi_4(iot, ioh, + EP_W1_TX_PIO_WR_1, mtod(m, u_int8_t *), + m->m_len & ~3); if (m->m_len & 3) bus_space_write_multi_1(iot, ioh, EP_W1_TX_PIO_WR_1, @@ -394,9 +860,9 @@ startagain: } else { for (m = m0; m; ) { if (m->m_len > 1) - bus_space_write_multi_2(iot, ioh, - EP_W1_TX_PIO_WR_1, mtod(m, u_int16_t *), - m->m_len / 2); + bus_space_write_raw_multi_2(iot, ioh, + EP_W1_TX_PIO_WR_1, mtod(m, u_int8_t *), + m->m_len & ~1); if (m->m_len & 1) bus_space_write_1(iot, ioh, EP_W1_TX_PIO_WR_1, *(mtod(m, u_int8_t *) + m->m_len - 1)); @@ -424,12 +890,10 @@ readcheck: * completely busted? */ epread(sc); - } - else + } else /* Got an interrupt, return to get it serviced. */ return; - } - else { + } else { /* Check if we are stuck and reset [see XXX comment] */ if (epstatus(sc)) { if (ifp->if_flags & IFF_DEBUG) @@ -450,7 +914,7 @@ readcheck: * It happens at times when there is a lot of broadcast traffic * on the cable (once in a blue moon). */ -static int +int epstatus(sc) register struct ep_softc *sc; { @@ -495,7 +959,7 @@ epstatus(sc) } -static void +void eptxstat(sc) register struct ep_softc *sc; { @@ -648,6 +1112,7 @@ again: ++ifp->if_ipackets; + /* We assume the header fit entirely in one mbuf. */ eh = mtod(m, struct ether_header *); #if NBPFILTER > 0 @@ -673,6 +1138,7 @@ again: } #endif + /* We assume the header fit entirely in one mbuf. */ m_adj(m, sizeof(struct ether_header)); ether_input(ifp, eh, m); @@ -698,7 +1164,7 @@ again: if (len & ERR_INCOMPLETE) { if (ifp->if_flags & IFF_DEBUG) printf("%s: adapter reset\n", - sc->sc_dev.dv_xname); + sc->sc_dev.dv_xname); epreset(sc); return; } @@ -780,9 +1246,9 @@ epget(sc, totlen) if (EP_IS_BUS_32(sc->bustype)) { if (len > 3) { len &= ~3; - bus_space_read_multi_4(iot, ioh, - EP_W1_RX_PIO_RD_1, mtod(m, u_int32_t *), - len / 4); + bus_space_read_raw_multi_4(iot, ioh, + EP_W1_RX_PIO_RD_1, mtod(m, u_int8_t *), + len); } else bus_space_read_multi_1(iot, ioh, EP_W1_RX_PIO_RD_1, mtod(m, u_int8_t *), @@ -790,9 +1256,9 @@ epget(sc, totlen) } else { if (len > 1) { len &= ~1; - bus_space_read_multi_2(iot, ioh, - EP_W1_RX_PIO_RD_1, mtod(m, u_int16_t *), - len / 2); + bus_space_read_raw_multi_2(iot, ioh, + EP_W1_RX_PIO_RD_1, mtod(m, u_int8_t *), + len); } else *(mtod(m, u_int8_t *)) = bus_space_read_1(iot, ioh, @@ -869,10 +1335,10 @@ epioctl(ifp, cmd, data) /* * deal with flags changes: * IFF_MULTICAST, IFF_PROMISC, - * IFF_LINK0, IFF_LINK1, + * IFF_LINK0, IFF_LINK1. */ epsetfilter(sc); - epsetlink(sc); + epsetmedia(sc, 0); /* XXX */ } break; @@ -938,8 +1404,10 @@ epstop(sc) ; 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, EP_COMMAND, RX_RESET); - bus_space_write_2(iot, ioh, EP_COMMAND, TX_RESET); + + ep_complete_cmd(sc, EP_COMMAND, RX_RESET); + ep_complete_cmd(sc, EP_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); @@ -949,6 +1417,19 @@ epstop(sc) } /* + * Before reboots, reset card completely. + */ +void +epshutdown(arg) + void *arg; +{ + register struct ep_softc *sc = arg; + + epstop(sc); + ep_complete_cmd(sc, EP_COMMAND, GLOBAL_RESET); +} + +/* * We get eeprom data from the id_port given an offset into the * eeprom. Basically; after the ID_sequence is sent to all of * the cards; they enter the ID_CMD state where they will accept @@ -980,7 +1461,7 @@ epreadeeprom(iot, ioh, offset) return (data); } -static int +int epbusyeeprom(sc) struct ep_softc *sc; { @@ -1000,8 +1481,8 @@ epbusyeeprom(sc) sc->sc_dev.dv_xname); return (1); } - if (sc->bustype != EP_BUS_PCMCIA && j & EEPROM_TST_MODE) { - printf("\n%s: erase pencil mark, or disable plug-n-play mode!\n", + if (sc->bustype != EP_BUS_PCMCIA && (j & EEPROM_TST_MODE)) { + printf("\n%s: erase pencil mark, or disable PnP mode!\n", sc->sc_dev.dv_xname); return (1); } diff --git a/sys/dev/ic/elink3reg.h b/sys/dev/ic/elink3reg.h index 13fe7af4ea2..d0bbdaa0a36 100644 --- a/sys/dev/ic/elink3reg.h +++ b/sys/dev/ic/elink3reg.h @@ -1,5 +1,5 @@ -/* $OpenBSD: elink3reg.h,v 1.6 1996/11/28 23:27:50 niklas Exp $ */ -/* $NetBSD: elink3reg.h,v 1.5 1996/10/21 22:34:23 thorpej Exp $ */ +/* $OpenBSD: elink3reg.h,v 1.7 1997/07/30 11:12:23 niklas Exp $ */ +/* $NetBSD: elink3reg.h,v 1.13 1997/04/27 09:42:34 veego Exp $ */ /* * Copyright (c) 1995 Herb Peyerl <hpeyerl@beer.org> @@ -102,6 +102,12 @@ /* Read */ #define EP_W3_FREE_TX 0x0c #define EP_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 */ /* * Window 4 registers. Diagnostics. @@ -205,29 +211,53 @@ # 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 SET_INTR_MASK (u_short) (0x0e<<11) + +/* busmastering-cards only? */ +#define STATUS_ENABLE (u_short) (0x0f<<11) + #define SET_RD_0_MASK (u_short) (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_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 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) +/* 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) + +/* + * Command parameter that disables threshold interrupts + * PIO (3c509) cards use 2044. The fifo word-oriented and 2044--2047 work. + * "busmastering" cards need 8188. + * The implicit two-bit upshift done by busmastering cards means + * a value of 2047 disables threshold interrupts on both. + */ +#define EP_THRESH_DISABLE 2047 + /* * Status register. All windows. * * 15-13: Window number(0-7). * 12: Command_in_progress. - * 11: reserved. + * 11: reserved / DMA in progress on busmaster cards. * 10: reserved. * 9: reserved. - * 8: reserved. + * 8: reserved / DMA done on busmaster cards. * 7: Update Statistics. * 6: Interrupt Requested. * 5: RX Early. @@ -245,6 +275,8 @@ #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) /* @@ -298,6 +330,79 @@ #define TXS_STATUS_OVERFLOW 0x04 /* + * RX status + * Window 1/Port 0x08. + */ +#define RX_BYTES_MASK (u_short) (0x07ff) + +/* + * Internal Config and MAC control (Window 3) + * Window 3 / Port 0: 32-bit internal config register: + * bits 0-2: fifo buffer ram size + * 3: ram width (word/byte) (ro) + * 4-5: ram speed + * 6-7: rom size + * 8-15: reserved + * + * 16-17: ram split (5:3, 3:1, or 1:1). + * 18-19: reserved + * 20-22: selected media type + * 21: unused + * 24: (nonvolatile) driver should autoselect media + * 25-31: reseerved + * + * 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_RAMWIDTH (u_short) 0x0008 +#define CONFIG_RAMWIDTH_SHIFT (u_short) 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 + +/* 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 + +/* 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 + +/* + * RESET_OPTIONS (Window 4, 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) + */ +#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_UTP EP_PCI_10BASE_T +#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) + +/* * FIFO Status (Window 4) * * Supports FIFO diagnostics @@ -337,28 +442,49 @@ #define FIFOS_TX_OVERRUN (u_short) 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) + + +/* EEPROM state flags/commands */ +#define EEPROM_BUSY (1<<15) +#define EEPROM_TST_MODE (1<<14) +#define READ_EEPROM (1<<7) + +/* window 4, MEDIA_STATUS bits */ +#define SQE_ENABLE 0x08 /* Enables SQE on AUI ports */ +#define JABBER_GUARD_ENABLE 0x40 +#define LINKBEAT_ENABLE 0x80 +#define ENABLE_UTP (JABBER_GUARD_ENABLE|LINKBEAT_ENABLE) +#define DISABLE_UTP 0x0 +#define LINKBEAT_DETECT 0x800 + +/* + * ep_connectors softc media-preset bitflags + */ +#define EPC_AUI 0x01 +#define EPC_BNC 0x02 +#define EPC_RESERVED 0x04 +#define EPC_UTP 0x08 +#define EPC_100TX 0x10 +#define EPC_100FX 0x20 +#define EPC_MII 0x40 +#define EPC_100T4 0x80 + +/* * Misc defines for various things. */ #define TAG_ADAPTER 0xd0 #define ACTIVATE_ADAPTER_TO_CONFIG 0xff #define ENABLE_DRQ_IRQ 0x0001 #define MFG_ID 0x506d /* `TCM' */ -#define PROD_ID 0x5090 +#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) -#define AUI 0x1 -#define BNC 0x2 -#define UTP 0x4 -#define IS_AUI (1<<13) -#define IS_BNC (1<<12) -#define IS_UTP (1<<9) -#define EEPROM_BUSY (1<<15) -#define EEPROM_TST_MODE (1<<14) -#define READ_EEPROM (1<<7) -#define ENABLE_UTP 0xc0 -#define DISABLE_UTP 0x0 -#define RX_BYTES_MASK (u_short) (0x07ff) -#define IS_PCI_AUI (1<<5) -#define IS_PCI_BNC (1<<4) -#define IS_PCI_UTP (1<<3) +/* Used to probe for large-packet support. */ +#define EP_LARGEWIN_PROBE EP_THRESH_DISABLE +#define EP_LARGEWIN_MASK 0xffc diff --git a/sys/dev/ic/elink3var.h b/sys/dev/ic/elink3var.h index ec731b50dbb..4d03a5a7b51 100644 --- a/sys/dev/ic/elink3var.h +++ b/sys/dev/ic/elink3var.h @@ -1,5 +1,5 @@ -/* $OpenBSD: elink3var.h,v 1.7 1996/11/28 23:27:51 niklas Exp $ */ -/* $NetBSD: elink3var.h,v 1.6 1996/10/21 22:34:25 thorpej Exp $ */ +/* $OpenBSD: elink3var.h,v 1.8 1997/07/30 11:12:23 niklas Exp $ */ +/* $NetBSD: elink3var.h,v 1.12 1997/03/30 22:47:11 jonathan Exp $ */ /* * Copyright (c) 1994 Herb Peyerl <hpeyerl@beer.org> @@ -38,9 +38,15 @@ struct ep_softc { struct device sc_dev; void *sc_ih; +#ifdef __NetBSD__ + struct ethercom sc_ethercom; /* Ethernet common part */ + struct ifmedia sc_media; /* media control */ +#else struct arpcom sc_arpcom; /* Ethernet common part */ +#endif bus_space_tag_t sc_iot; /* bus cookie */ bus_space_handle_t sc_ioh; /* bus i/o handle */ + u_int ep_connectors; /* Connectors on this card. */ #define MAX_MBS 8 /* # of mbufs we keep around */ struct mbuf *mb[MAX_MBS]; /* spare mbuf storage. */ int next_mb; /* Which mbuf to use next. */ @@ -49,8 +55,29 @@ struct ep_softc { int tx_succ_ok; /* # packets sent in sequence */ /* w/o underrun */ - char ep_connectors; /* Connectors on this card. */ - u_char txashift; /* shift in SET_TX_AVAIL_THRESH */ + u_int ep_flags; /* capabilities flag (from EEPROM) */ +#define EP_FLAGS_PNP 0x0001 +#define EP_FLAGS_FULLDUPLEX 0x0002 +#define EP_FLAGS_LARGEPKT 0x0004 /* 4k packet support */ +#define EP_FLAGS_SLAVEDMA 0x0008 +#define EP_FLAGS_SECONDDMA 0x0010 +#define EP_FLAGS_FULLDMA 0x0020 +#define EP_FLAGS_FRAGMENTDMA 0x0040 +#define EP_FLAGS_CRC_PASSTHRU 0x0080 +#define EP_FLAGS_TXDONE 0x0100 +#define EP_FLAGS_NO_TXLENGTH 0x0200 +#define EP_FLAGS_RXREPEAT 0x0400 +#define EP_FLAGS_SNOOPING 0x0800 +#define EP_FLAGS_100MBIT 0x1000 +#define EP_FLAGS_POWERMGMT 0x2000 + + u_short ep_chipset; /* Chipset family on this board */ +#define EP_CHIPSET_UNKNOWN 0x00 /* unknown (assume 3c509) */ +#define EP_CHIPSET_3C509 0x01 /* PIO: 3c509, 3c589 */ +#define EP_CHIPSET_VORTEX 0x02 /* 100mbit, single-pkt dma */ +#define EP_CHIPSET_BOOMERANG 0x03 /* Saner dma plus PIO */ +#define EP_CHIPSET_BOOMERANG2 0x04 /* Saner dma, no PIO */ + u_char bustype; #define EP_BUS_ISA 0x0 #define EP_BUS_PCMCIA 0x1 @@ -59,12 +86,13 @@ struct ep_softc { #define EP_IS_BUS_32(a) ((a) & 0x2) + u_char txashift; /* shift in SET_TX_AVAIL_THRESH */ u_char pcmcia_flags; #define EP_REATTACH 0x01 #define EP_ABSENT 0x02 }; u_int16_t epreadeeprom __P((bus_space_tag_t, bus_space_handle_t, int)); -void epconfig __P((struct ep_softc *, u_int16_t)); +void epconfig __P((struct ep_softc *, u_short)); int epintr __P((void *)); void epstop __P((struct ep_softc *)); diff --git a/sys/dev/isa/if_ep_isa.c b/sys/dev/isa/if_ep_isa.c index 5f9d68496f2..6b85f8cd9ed 100644 --- a/sys/dev/isa/if_ep_isa.c +++ b/sys/dev/isa/if_ep_isa.c @@ -189,7 +189,7 @@ ep_isa_probe(parent, match, aux) continue; model = htons(epreadeeprom(iot, ioh, EEPROM_PROD_ID)); - if ((model & 0xfff0) != PROD_ID) { + if ((model & 0xfff0) != PROD_ID_3C509) { #ifndef trusted printf( "ep_isa_probe: ignoring model %04x\n", model); @@ -254,7 +254,7 @@ ep_isa_attach(parent, self, aux) struct isa_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh; - u_short conn = 0; + int chipset; /* Map i/o space. */ if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) @@ -264,12 +264,18 @@ ep_isa_attach(parent, self, aux) sc->sc_ioh = ioh; sc->bustype = EP_BUS_ISA; - GO_WINDOW(0); - conn = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL); - - printf(": <3Com 3C509 Ethernet> "); - - epconfig(sc, conn); + chipset = (int)(long)ia->ia_aux; + if ((chipset & 0xfff0) == PROD_ID_3C509) { + printf(": 3Com 3C509 Ethernet\n"); + epconfig(sc, EP_CHIPSET_3C509); + } 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: %04x\n", chipset); + epconfig(sc, EP_CHIPSET_UNKNOWN); + } sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname); diff --git a/sys/dev/pci/if_ep_pci.c b/sys/dev/pci/if_ep_pci.c index 6a205592233..6fec8862f49 100644 --- a/sys/dev/pci/if_ep_pci.c +++ b/sys/dev/pci/if_ep_pci.c @@ -123,7 +123,6 @@ ep_pci_attach(parent, self, aux) bus_addr_t iobase; bus_size_t iosize; pci_intr_handle_t ih; - u_short conn = 0; pcireg_t i; char *model; const char *intrstr = NULL; @@ -143,17 +142,6 @@ ep_pci_attach(parent, self, aux) i = pci_conf_read(pc, pa->pa_tag, PCI_CONN); - /* - * Bits 13,12,9 of the isa adapter are the same as bits - * 5,4,3 of the pci adapter - */ - if (i & IS_PCI_AUI) - conn |= IS_AUI; - if (i & IS_PCI_BNC) - conn |= IS_BNC; - if (i & IS_PCI_UTP) - conn |= IS_UTP; - GO_WINDOW(0); switch (PCI_PRODUCT(pa->pa_id)) { @@ -180,7 +168,7 @@ ep_pci_attach(parent, self, aux) printf(": <%s> ", model); - epconfig(sc, conn); + epconfig(sc, EP_CHIPSET_VORTEX); /* Enable the card. */ pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, diff --git a/sys/dev/pcmcia/if_ep_pcmcia.c b/sys/dev/pcmcia/if_ep_pcmcia.c index 13850142f24..c91badd574f 100644 --- a/sys/dev/pcmcia/if_ep_pcmcia.c +++ b/sys/dev/pcmcia/if_ep_pcmcia.c @@ -1,5 +1,4 @@ -/* $OpenBSD: if_ep_pcmcia.c,v 1.6 1996/11/28 23:28:15 niklas Exp $ */ -/* $NetBSD: if_ep.c,v 1.90 1996/04/11 22:29:15 cgd Exp $ */ +/* $OpenBSD: if_ep_pcmcia.c,v 1.7 1997/07/30 11:12:28 niklas Exp $ */ /* * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> @@ -75,11 +74,11 @@ int ep_pcmcia_match __P((struct device *, void *, void *)); void ep_pcmcia_attach __P((struct device *, struct device *, void *)); int ep_pcmcia_detach __P((struct device *)); -static int ep_pcmcia_isasetup __P((struct device *, void *, - void *, struct pcmcia_link *)); -static int epmod __P((struct pcmcia_link *, struct device *, - struct pcmcia_conf *, struct cfdata * cf)); -static int ep_remove __P((struct pcmcia_link *, struct device *)); +int ep_pcmcia_isasetup __P((struct device *, void *, void *, + struct pcmcia_link *)); +int epmod __P((struct pcmcia_link *, struct device *, struct pcmcia_conf *, + struct cfdata *)); +int ep_remove __P((struct pcmcia_link *, struct device *)); struct cfattach ep_pcmcia_ca = { sizeof(struct ep_softc), ep_pcmcia_match, ep_pcmcia_attach, @@ -87,7 +86,7 @@ struct cfattach ep_pcmcia_ca = { }; /* additional setup needed for pcmcia devices */ -static int +int ep_pcmcia_isasetup(parent, match, aux, pc_link) struct device *parent; void *match; @@ -126,7 +125,7 @@ ep_pcmcia_isasetup(parent, match, aux, pc_link) } /* modify config entry */ -static int +int epmod(pc_link, self, pc_cf, cf) struct pcmcia_link *pc_link; struct device *self; @@ -137,14 +136,14 @@ epmod(pc_link, self, pc_cf, cf) /* struct pcmciadevs *dev = pc_link->device;*/ /* struct ep_softc *sc = (void *) self;*/ - if ((err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self, - pc_cf, cf)) != 0) { + if ((err = PCMCIA_BUS_CONFIG(pc_link->adapter, pc_link, self, pc_cf, + cf)) != 0) { printf("bus_config failed %d\n", err); return err; } if (pc_cf->io[0].len > 0x10) - pc_cf->io[0].len = 0x10; + pc_cf->io[0].len = 0x10; #if 0 pc_cf->cfgtype = DOSRESET; #endif @@ -153,7 +152,7 @@ epmod(pc_link, self, pc_cf, cf) return 0; } -static int +int ep_remove(pc_link, self) struct pcmcia_link *pc_link; struct device *self; @@ -203,7 +202,6 @@ ep_pcmcia_attach(parent, self, aux) struct isa_attach_args *ia = aux; bus_space_tag_t iot = ia->ia_iot; bus_space_handle_t ioh; - u_short conn = 0; if (bus_space_map(iot, ia->ia_iobase, ia->ia_iosize, 0, &ioh)) panic("ep_isa_attach: can't map i/o space"); @@ -211,12 +209,9 @@ ep_pcmcia_attach(parent, self, aux) sc->sc_iot = iot; sc->sc_ioh = ioh; - GO_WINDOW(0); - conn = bus_space_read_2(iot, ioh, EP_W0_CONFIG_CTRL); - printf(": "); - epconfig(sc, conn); + epconfig(sc, EP_CHIPSET_3C509); sc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE, IPL_NET, epintr, sc, sc->sc_dev.dv_xname); } |