summaryrefslogtreecommitdiffstats
path: root/sys/dev/ep
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2005-06-28 21:56:04 +0000
committerimp <imp@FreeBSD.org>2005-06-28 21:56:04 +0000
commit59032ef458fae9ee6d8a1bd23739f5d489a4d467 (patch)
tree865a9c838c8fdd502d48ce93aae6102826860532 /sys/dev/ep
parent074ec1e21457fbc3a38b600a0df597375bc9bc3b (diff)
downloadFreeBSD-src-59032ef458fae9ee6d8a1bd23739f5d489a4d467.zip
FreeBSD-src-59032ef458fae9ee6d8a1bd23739f5d489a4d467.tar.gz
Add a chipset field to the lookup. Use this chipset type to determine
which command to use to read the eeprom and which devices have an MII. Simplify code by no longer using the OLDCARD compat rouintes (I don't know if this breaks OLDCARD on pc98 or not, but OLDCARD on pc98 days are numbered, I hope). This also removes a number of kludges that we had before because they are OBE. Add a convenience routine to lookup the device to avoid many casts in many places. Tested with: 3C589D-TP, 3CCSH572BT Approved by: re (scottl, blanket ep)
Diffstat (limited to 'sys/dev/ep')
-rw-r--r--sys/dev/ep/if_ep_pccard.c226
1 files changed, 58 insertions, 168 deletions
diff --git a/sys/dev/ep/if_ep_pccard.c b/sys/dev/ep/if_ep_pccard.c
index 3e5e6a7..b3537e7 100644
--- a/sys/dev/ep/if_ep_pccard.c
+++ b/sys/dev/ep/if_ep_pccard.c
@@ -58,124 +58,57 @@ __FBSDID("$FreeBSD$");
#include <dev/pccard/pccardvar.h>
#include <dev/pccard/pccard_cis.h>
-#include "card_if.h"
#include "pccarddevs.h"
-static const char *ep_pccard_identify(u_short id);
-
-/*
- * Initialize the device - called from Slot manager.
- */
-static int
-ep_pccard_probe(device_t dev)
+struct ep_pccard_product
{
- struct ep_softc *sc = device_get_softc(dev);
- struct ep_board *epb = &sc->epb;
- const char *desc;
- uint16_t result;
- uint8_t enaddr[6];
- int error;
-
- error = ep_alloc(dev);
- if (error)
- return (error);
-
- /*
- * It appears that the eeprom comes in two sizes. There's
- * a 512 byte eeprom and a 2k eeprom. Bit 13 of the eeprom
- * command register is supposed to contain the size of the
- * eeprom.
- */
- /*
- * XXX - Certain (newer?) 3Com cards need epb->cmd_off ==
- * 2. Sadly, you need to have a correct cmd_off in order to
- * identify the card. So we have to hit it with both and
- * cross our virtual fingers. There's got to be a better way
- * to do this. jyoung@accessus.net 09/11/1999
- */
-
- epb->cmd_off = 0;
-
- /* XXX check return */
- error = ep_get_e(sc, EEPROM_PROD_ID, &result);
- epb->prod_id = result;
+ struct pccard_product prod;
+ int chipset;
+};
- if ((desc = ep_pccard_identify(epb->prod_id)) == NULL) {
- if (bootverbose)
- device_printf(dev, "Pass 1 of 2 detection "
- "failed (nonfatal) id 0x%x\n", epb->prod_id);
- epb->cmd_off = 2;
- /* XXX check return */
- error = ep_get_e(sc, EEPROM_PROD_ID, &result);
- epb->prod_id = result;
- if ((desc = ep_pccard_identify(epb->prod_id)) == NULL) {
- device_printf(dev, "Unit failed to come ready or "
- "product ID unknown! (id 0x%x)\n", epb->prod_id);
- ep_free(dev);
- return (ENXIO);
- }
- }
- /*
- * For reasons unknown, getting the MAC address here makes the
- * 3C574 and 3C556 families get the right MAC address later.
- * otherwise, the ID field is used for each of the words of the
- * MAC address instead of the proper one. It is unclear why
- * ep_get_macaddr would have this side effect, or even what
- * that side effect really is.
- */
- ep_get_macaddr(sc, enaddr);
- device_set_desc(dev, desc);
- ep_free(dev);
- return (0);
-}
+#define EP_CHIP_589 1 /* Classic 3c5x9 chipset */
+#define EP_CHIP_574 2 /* Roadrunner */
+
+static const struct ep_pccard_product ep_pccard_products[] = {
+ { PCMCIA_CARD(3COM, 3C1), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3C562), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3C589), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3CXEM556), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3CXEM556INT), EP_CHIP_589 },
+ { PCMCIA_CARD(3COM, 3C574), EP_CHIP_574 },
+ { PCMCIA_CARD(3COM, 3CCFEM556BI), EP_CHIP_574 },
+ { { NULL } }
+};
-static const char *
-ep_pccard_identify(u_short id)
+static const struct ep_pccard_product *
+ep_pccard_lookup(device_t dev)
{
- /* Determine device type and associated MII capabilities */
- switch (id) {
- case 0x6055: /* 3C556 */
- return ("3Com 3C556");
- case 0x4057: /* 3C574 */
- return ("3Com 3C574");
- case 0x4b57: /* 3C574B */
- return ("3Com 3C574B, Megahertz 3CCFE574BT or "
- "Fast Etherlink 3C574-TX");
- case 0x2b57: /* 3CXSH572BT */
- return ("3Com OfficeConnect 572BT");
- case 0x9058: /* 3C589 */
- return ("3Com Etherlink III 3C589");
- case 0x2056: /* 3C562/3C563 */
- return ("3Com 3C562D/3C563D");
- case 0x0010: /* 3C1 */
- return ("3Com Megahertz C1");
- case 0x0035:
- return ("3Com 3CCEM556");
- default:
- return (NULL);
- }
+ return ((const struct ep_pccard_product *)pccard_product_lookup(dev,
+ (const struct pccard_product *)ep_pccard_products,
+ sizeof(ep_pccard_products[0]), NULL));
}
static int
-ep_pccard_card_attach(struct ep_board * epb)
+ep_pccard_probe(device_t dev)
{
- /* Determine device type and associated MII capabilities */
- switch (epb->prod_id) {
- case 0x6055: /* 3C556 */
- case 0x2b57: /* 3C572BT */
- case 0x4057: /* 3C574, 3C574-TX */
- case 0x4b57: /* 3C574B */
- epb->mii_trans = 1;
- return (1);
- case 0x2056: /* 3C562D/3C563D */
- case 0x9058: /* 3C589 */
- case 0x0010: /* 3C1 */
- case 0x0035: /* 3C[XC]EM556 */
- epb->mii_trans = 0;
- return (1);
- default:
- return (0);
- }
+ const struct ep_pccard_product *pp;
+ int error;
+ uint32_t fcn = PCCARD_FUNCTION_UNSPEC;
+
+ /* Make sure we're a network function */
+ error = pccard_get_function(dev, &fcn);
+ if (error != 0)
+ return (error);
+ if (fcn != PCCARD_FUNCTION_NETWORK)
+ return (ENXIO);
+
+ /* Check to see if we know about this card */
+ if ((pp = ep_pccard_lookup(dev)) == NULL)
+ return EIO;
+ if (pp->prod.pp_name != NULL)
+ device_set_desc(dev, pp->prod.pp_name);
+
+ return 0;
}
static int
@@ -184,34 +117,30 @@ ep_pccard_attach(device_t dev)
struct ep_softc *sc = device_get_softc(dev);
uint16_t result;
int error = 0;
+ const struct ep_pccard_product *pp;
+
+ if ((pp = ep_pccard_lookup(dev)) == NULL)
+ panic("ep_pccard_attach: can't find product in attach.");
if ((error = ep_alloc(dev))) {
device_printf(dev, "ep_alloc() failed! (%d)\n", error);
goto bad;
}
- sc->epb.cmd_off = 0;
-
- /* XXX check return */
- error = ep_get_e(sc, EEPROM_PROD_ID, &result);
- sc->epb.prod_id = result;
- if (!ep_pccard_card_attach(&sc->epb)) {
+ if (pp->chipset == EP_CHIP_589) {
+ sc->epb.mii_trans = 0;
+ sc->epb.cmd_off = 0;
+ } else {
+ sc->epb.mii_trans = 1;
sc->epb.cmd_off = 2;
- error = ep_get_e(sc, EEPROM_PROD_ID, &result);
- sc->epb.prod_id = result;
- error = ep_get_e(sc, EEPROM_RESOURCE_CFG, &result);
- sc->epb.res_cfg = result;
- if (!ep_pccard_card_attach(&sc->epb)) {
- device_printf(dev,
- "Probe found ID, attach failed so ignore card!\n");
- error = ENXIO;
- goto bad;
- }
}
- error = ep_get_e(sc, EEPROM_ADDR_CFG, &result);
+
+ error = ep_get_e(sc, EEPROM_PROD_ID, &result);
+ sc->epb.prod_id = result;
/* ROM size = 0, ROM base = 0 */
/* For now, ignore AUTO SELECT feature of 3C589B and later. */
+ error = ep_get_e(sc, EEPROM_ADDR_CFG, &result);
CSR_WRITE_2(sc, EP_W0_ADDRESS_CFG, result & 0xc000);
/*
@@ -243,8 +172,8 @@ ep_pccard_attach(device_t dev)
device_printf(dev, "ep_attach() failed! (%d)\n", error);
goto bad;
}
- if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE, ep_intr,
- sc, &sc->ep_intrhand))) {
+ if ((error = bus_setup_intr(dev, sc->irq, INTR_TYPE_NET | INTR_MPSAFE,
+ ep_intr, sc, &sc->ep_intrhand))) {
device_printf(dev, "bus_setup_intr() failed! (%d)\n", error);
goto bad;
}
@@ -254,51 +183,12 @@ bad:
return (error);
}
-static const struct pccard_product ep_pccard_products[] = {
- PCMCIA_CARD(3COM, 3C1),
- PCMCIA_CARD(3COM, 3C562),
- PCMCIA_CARD(3COM, 3C574), /* ROADRUNNER */
- PCMCIA_CARD(3COM, 3C589),
- PCMCIA_CARD(3COM, 3CCFEM556BI), /* ROADRUNNER */
- PCMCIA_CARD(3COM, 3CXEM556),
- PCMCIA_CARD(3COM, 3CXEM556INT),
- {NULL}
-};
-
-static int
-ep_pccard_match(device_t dev)
-{
- const struct pccard_product *pp;
- int error;
- uint32_t fcn = PCCARD_FUNCTION_UNSPEC;
-
- /* Make sure we're a network function */
- error = pccard_get_function(dev, &fcn);
- if (error != 0)
- return (error);
- if (fcn != PCCARD_FUNCTION_NETWORK)
- return (ENXIO);
-
- if ((pp = pccard_product_lookup(dev, ep_pccard_products,
- sizeof(ep_pccard_products[0]), NULL)) != NULL) {
- if (pp->pp_name != NULL)
- device_set_desc(dev, pp->pp_name);
- return 0;
- }
- return EIO;
-}
-
static device_method_t ep_pccard_methods[] = {
/* Device interface */
- DEVMETHOD(device_probe, pccard_compat_probe),
- DEVMETHOD(device_attach, pccard_compat_attach),
+ DEVMETHOD(device_probe, ep_pccard_probe),
+ DEVMETHOD(device_attach, ep_pccard_attach),
DEVMETHOD(device_detach, ep_detach),
- /* Card interface */
- DEVMETHOD(card_compat_match, ep_pccard_match),
- DEVMETHOD(card_compat_probe, ep_pccard_probe),
- DEVMETHOD(card_compat_attach, ep_pccard_attach),
-
{0, 0}
};
OpenPOWER on IntegriCloud