diff --git a/sys/dev/xe/if_xe_pccard.c b/sys/dev/xe/if_xe_pccard.c index baf905389589..cfa5253f3548 100644 --- a/sys/dev/xe/if_xe_pccard.c +++ b/sys/dev/xe/if_xe_pccard.c @@ -186,73 +186,6 @@ xe_cemfix(device_t dev) return (0); } -/* - * 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; - uint8_t cisdata[9]; - uint8_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->enaddr[i] = cisdata[i + 3]; - } - - bus_release_resource(dev, SYS_RES_MEMORY, rid, r); - - /* success! */ - return (0); -} - static int xe_pccard_product_match(device_t dev, const struct pccard_product* ent, int vpfmatch) { @@ -279,6 +212,46 @@ xe_pccard_get_product(device_t dev) sizeof(xe_pccard_products[0]), xe_pccard_product_match)); } +/* + * Fixing for CE2-class cards with bogus CIS entry for MAC address. + */ +static int +xe_pccard_mac(const struct pccard_tuple *tuple, void *argp) +{ + uint8_t *enaddr = argp, test; + int i; + + /* Code 0x89 is Xircom special cis node contianing the MAC */ + if (tuple->code != 0x89) + return (0); + + /* Make sure this is a sane node */ + if (tuple->length != ETHER_ADDR_LEN + 2) + return (0); + test = pccard_tuple_read_1(tuple, 0); + if (test != PCCARD_TPLFE_TYPE_LAN_NID) + return (0); + test = pccard_tuple_read_1(tuple, 1); + if (test != ETHER_ADDR_LEN) + return (0); + + /* Copy the MAC ADDR and return success */ + for (i = 0; i < ETHER_ADDR_LEN; i++) + enaddr[i] = pccard_tuple_read_1(tuple, i + 2); + return (1); +} + +static int +xe_bad_mac(uint8_t *enaddr) +{ + int i; + uint8_t sum; + + for (i = 0, sum = 0; i < ETHER_ADDR_LEN; i++) + sum |= enaddr[i]; + return (sum == 0); +} + /* * PCMCIA attach routine. * Identify the device. Called from the bus driver when the card is @@ -296,6 +269,7 @@ xe_pccard_attach(device_t dev) const char *cis3_str=NULL; const struct xe_pccard_product *xpp; int err; + device_t pdev; DEVPRINTF(2, (dev, "pccard_attach\n")); @@ -315,7 +289,7 @@ xe_pccard_attach(device_t dev) DEVPRINTF(1, (dev, "cis3_str = %s\n", cis3_str)); DEVPRINTF(1, (dev, "cis4_str = %s\n", cis4_str)); - + pdev = device_get_parent(dev); xpp = xe_pccard_get_product(dev); if (xpp == NULL) return (ENXIO); @@ -338,12 +312,8 @@ xe_pccard_attach(device_t dev) pccard_get_ether(dev, scp->enaddr); /* Deal with bogus MAC address */ - if (xpp->product.pp_vendor == PCMCIA_VENDOR_XIRCOM - && scp->ce2 - && (scp->enaddr[0] != XE_MAC_ADDR_0 - || scp->enaddr[1] != XE_MAC_ADDR_1 - || scp->enaddr[2] != XE_MAC_ADDR_2) - && xe_macfix(dev, XE_BOGUS_MAC_OFFSET) < 0) { + if (xe_bad_mac(scp->enaddr) + && !CARD_CIS_SCAN(pdev, xe_pccard_mac, scp->enaddr)) { device_printf(dev, "Unable to find MAC address for your %s card\n", device_get_desc(dev));