if_dc - ADMTek AN983B problem (solution)
arg-bsd at arg.me.uk
Sun Jun 1 16:43:44 PDT 2003
if_dc driver fails to read MAC address from AN983B (on-board ethernet on
MSI motherboard in this case). Not only does it get the wrong value of
MAC address, but it permanently trashes the EEPROM contents, so that it
is necessary to use the manufacturer's utility to re-set the MAC address
in the EEPROM before it will work again in Windows.
if_dc only claims to support the AN985B, not the AN983B, though they
appear from the datasheet to be the equivalent and have the same
device ID ('985 is cardbus, '983 is ordinary PCI). If the EEPROM
reading code in the driver is commented out, the driver works OK and
the EEPROM is not corrupted.
I had expected this to be the usual sort of problem with
on-motherboard devices being configured in a non-standard way
(and maybe storing the MAC address elsewhere), but in fact it
seems to be a perfectly standard implementation with an EEPROM
dedicated to the AN983B (adjacent to it on the PCB).
For this device, the only thing that the driver attempts to read from
the EEPROM is the MAC address. However, according to the datasheet
(and confirmed by testing) the MAC address is automatically loaded into
the PAR0/PAR1 registers after reset, so we can simply read it from
those registers directly rather than doing the bit twiddling to
access the EEPROM by brute force.
The enclosed patch does this, and works well for me (I've minimised
the changes, so only 3 lines of diff).
I'm working in RELENG_4, but there have been no relevant changes to
the driver and the patch applies unchanged to -current too.
I only have this one type of motherboard for testing; I don't have
any AN985B cards to see if my patch upsets them.
Also, the driver treats the "Accton EN2242" as equivalent to the
AN985B - I'm guessing that this is just a card built from the
AN983B but using different vendor/device Ids for branding purposes,
so I've made my patch apply to these too, but again I can't test.
The code that I've replaced looks a bit odd: it seems to read
the MAC address from a copy of the EEPROM in the softc that
it recorded earlier, then immediately over-writes that by
reading it directly from the EEPROM again. Did this ever work?
-------------- next part --------------
RCS file: /usr/cvsbase/repository/src/sys/pci/if_dc.c,v
retrieving revision 220.127.116.11
diff -u -r18.104.22.168 if_dc.c
--- if_dc.c 5 Mar 2003 18:42:33 -0000 22.214.171.124
+++ if_dc.c 1 Jun 2003 23:35:14 -0000
@@ -1871,7 +1871,7 @@
sc->dc_flags |= DC_TX_USE_TX_INTR;
sc->dc_flags |= DC_TX_ADMTEK_WAR;
sc->dc_pmode = DC_PMODE_MII;
- dc_read_srom(sc, sc->dc_romwidth);
+ /* Don't read SROM for - auto-loaded on reset */
@@ -1994,9 +1994,8 @@
- bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
- dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
+ *(u_int32_t *)(&eaddr) = CSR_READ_4(sc, DC_AL_PAR0);
+ *(u_int16_t *)(&eaddr) = CSR_READ_4(sc, DC_AL_PAR1);
bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr, 6);
More information about the freebsd-net