From 21179174532b3c3b55bf93df67183e5b4aa258e7 Mon Sep 17 00:00:00 2001 From: rsm Date: Fri, 9 Apr 2004 17:34:54 +0000 Subject: Band-aid fix to extract MAC address from some CEM2/CEM28 cards with broken CIS. Really needs a better interface to the CIS in pccard driver. Reviewed by: imp (mentor) --- sys/dev/xe/if_xe_pccard.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/sys/dev/xe/if_xe_pccard.c b/sys/dev/xe/if_xe_pccard.c index 7b3a3bb..0704e1d 100644 --- a/sys/dev/xe/if_xe_pccard.c +++ b/sys/dev/xe/if_xe_pccard.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include "card_if.h" /* @@ -82,6 +83,18 @@ extern int xe_debug; #define XE_PROD_ETHER_MASK 0x0100 #define XE_PROD_MODEM_MASK 0x1000 +#define XE_BOGUS_MAC_OFFSET 0x90 + +/* MAC vendor prefix used by most Xircom cards is 00:80:c7 */ +#define XE_MAC_ADDR_0 0x00 +#define XE_MAC_ADDR_1 0x80 +#define XE_MAC_ADDR_2 0xc7 + +/* Some (all?) REM56 cards have vendor prefix 00:10:a4 */ +#define XE_REM56_MAC_ADDR_0 0x00 +#define XE_REM56_MAC_ADDR_1 0x10 +#define XE_REM56_MAC_ADDR_2 0xa4 + struct xe_pccard_product { struct pccard_product product; @@ -172,6 +185,73 @@ xe_cemfix(device_t dev) } /* + * Fixing for CE2-class cards with bogus CIS entry for MAC address. This + * should be in a type 0x22 tuple, but some cards seem to use 0x89. + * This function looks for a sensible MAC address tuple starting at the given + * offset in attribute memory, ignoring the tuple type field. + */ +static int +xe_macfix(device_t dev, int offset) +{ + struct xe_softc *sc = (struct xe_softc *) device_get_softc(dev); + bus_space_tag_t bst; + bus_space_handle_t bsh; + struct resource *r; + int rid, i; + u_int8_t cisdata[9]; + u_int8_t required[6] = { 0x08, PCCARD_TPLFE_TYPE_LAN_NID, ETHER_ADDR_LEN, + XE_MAC_ADDR_0, XE_MAC_ADDR_1, XE_MAC_ADDR_2 }; + + DEVPRINTF(2, (dev, "macfix\n")); + + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, 0, + ~0, 4 << 10, RF_ACTIVE); + if (!r) { + device_printf(dev, "macfix: Can't map in attribute memory\n"); + return (-1); + } + + bsh = rman_get_bushandle(r); + bst = rman_get_bustag(r); + + CARD_SET_RES_FLAGS(device_get_parent(dev), dev, SYS_RES_MEMORY, rid, + PCCARD_A_MEM_ATTR); + + /* + * Looking for (relative to offset): + * + * 0x00 0x?? Tuple type (ignored) + * 0x02 0x08 Tuple length (must be 8) + * 0x04 0x04 Address type? (must be 4) + * 0x06 0x06 Address length (must be 6) + * 0x08 0x00 Manufacturer ID, byte 1 + * 0x0a 0x80 Manufacturer ID, byte 2 + * 0x0c 0xc7 Manufacturer ID, byte 3 + * 0x0e 0x?? Card ID, byte 1 + * 0x10 0x?? Card ID, byte 2 + * 0x12 0x?? Card ID, byte 3 + */ + for (i = 0; i < 9; i++) { + cisdata[i] = bus_space_read_1(bst, bsh, offset + (2 * i) + 2); + if (i < 6 && required[i] != cisdata[i]) { + device_printf(dev, "macfix: Can't find valid MAC address\n"); + bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + return (-1); + } + } + + for (i = 0; i < ETHER_ADDR_LEN; i++) { + sc->arpcom.ac_enaddr[i] = cisdata[i + 3]; + } + + bus_release_resource(dev, SYS_RES_MEMORY, rid, r); + + /* success! */ + return (0); +} + +/* * PCMCIA probe routine. * Identify the device. Called from the bus driver when the card is * inserted or otherwise powers up. @@ -252,6 +332,19 @@ xe_pccard_probe(device_t dev) /* Get MAC address */ pccard_get_ether(dev, scp->arpcom.ac_enaddr); + /* Deal with bogus MAC address */ + if (xpp->product.pp_vendor == PCMCIA_VENDOR_XIRCOM + && scp->ce2 + && (scp->arpcom.ac_enaddr[0] != XE_MAC_ADDR_0 + || scp->arpcom.ac_enaddr[1] != XE_MAC_ADDR_1 + || scp->arpcom.ac_enaddr[2] != XE_MAC_ADDR_2) + && xe_macfix(dev, XE_BOGUS_MAC_OFFSET) < 0) { + device_printf(dev, + "Unable to find MAC address for your %s card\n", + scp->card_type); + return (ENODEV); + } + /* Success */ return (0); } -- cgit v1.1