From 79e277f155becd235626c8a3a382f3e6326f0b95 Mon Sep 17 00:00:00 2001 From: Warner Losh Date: Tue, 6 Sep 2005 22:55:32 +0000 Subject: [PATCH] Work around a bug I've seen on Linksys EC2T cards. For some reason, as yet unknown, those cards report their MAC address a byte at a time. However, other AX88x90 cards report the MAC address a word at a time. Add a heuristic which looks at the high order bytes of the first 6 words. If they are all '0', assume the card is behaving like the Linksys EC2T card. Since the default prefix for these cards appears to be 00:e0:98, this appears to be a safe heuristic. While some cards have been observed with different prefixes, they all work with this heuristic. I'm unsure if this is a bug in the EC2T card, or if it is a bug in the initialization of the card. No other OS has this heuristic (although w/o it, the MAC address that is used works). --- sys/dev/ed/if_ed_pccard.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/sys/dev/ed/if_ed_pccard.c b/sys/dev/ed/if_ed_pccard.c index 9afa7006804..a39e161a6bb 100644 --- a/sys/dev/ed/if_ed_pccard.c +++ b/sys/dev/ed/if_ed_pccard.c @@ -431,9 +431,32 @@ ax88x90_geteprom(struct ed_softc *sc) /* Get Data */ for (i = 0; i < 16; i++) - prom[i] = ed_asic_inb(sc, 0); + prom[i] = ed_asic_inw(sc, 0); + + /* + * Work around a bug I've seen on Linksys EC2T cards. On + * these cards, the node address is contained in the low order + * bytes of the prom, with the upper byte being 0. On other + * cards, the bytes are packed two per word. I'm unsure why + * this is the case, and why no other open source OS has a + * similar workaround. The Linksys EC2T card is still extremely + * popular on E-Bay, fetching way more than any other 10Mbps + * only card. I might be able to test to see if prom[7] and + * prom[15] == 0x5757, since that appears to be a reliable + * test. On the EC2T cards, I get 0x0057 in prom[14,15] instead. + */ for (i = 0; i < ETHER_ADDR_LEN; i++) - sc->enaddr[i] = prom[i]; + if (prom[i] & 0xff00) + break; + if (i == ETHER_ADDR_LEN) { + for (i = 0; i < ETHER_ADDR_LEN; i++) + sc->enaddr[i] = prom[i] & 0xff; + } else { + for (i = 0; i < ETHER_ADDR_LEN; i += 2) { + sc->enaddr[i] = prom[i / 2] & 0xff; + sc->enaddr[i + 1] = (prom[i / 2] >> 8) & 0xff; + } + } } static int