summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorNiklas Hallqvist <niklas@cvs.openbsd.org>1997-07-30 11:12:29 +0000
committerNiklas Hallqvist <niklas@cvs.openbsd.org>1997-07-30 11:12:29 +0000
commitebf09a5432e7b2f7330349a287ea06557130d024 (patch)
tree4b31be4473c64d35c413d75be8765ad785c33e53 /sys
parent4c8a97d907a4ec836ce801ead5d8529e1699b553 (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.c37
-rw-r--r--sys/dev/ic/elink3.c687
-rw-r--r--sys/dev/ic/elink3reg.h166
-rw-r--r--sys/dev/ic/elink3var.h38
-rw-r--r--sys/dev/isa/if_ep_isa.c22
-rw-r--r--sys/dev/pci/if_ep_pci.c14
-rw-r--r--sys/dev/pcmcia/if_ep_pcmcia.c31
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);
}