if_dc - ADMTek AN983B problem (solution)

Andrew Gordon arg-bsd at arg.me.uk
Sun Jun 1 16:43:44 PDT 2003


Problem:

  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.

Analysis:

   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).

Solution:

  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.

Caveats:

  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 --------------
Index: if_dc.c
===================================================================
RCS file: /usr/cvsbase/repository/src/sys/pci/if_dc.c,v
retrieving revision 1.9.2.41
diff -u -r1.9.2.41 if_dc.c
--- if_dc.c	5 Mar 2003 18:42:33 -0000	1.9.2.41
+++ 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	*/
 		break;
 	case DC_DEVICEID_98713:
 	case DC_DEVICEID_98713_CP:
@@ -1994,9 +1994,8 @@
 		break;
 	case DC_TYPE_AL981:
 	case DC_TYPE_AN985:
-		bcopy(&sc->dc_srom[DC_AL_EE_NODEADDR], (caddr_t)&eaddr,
-		    ETHER_ADDR_LEN);
-		dc_read_eeprom(sc, (caddr_t)&eaddr, DC_AL_EE_NODEADDR, 3, 0);
+		*(u_int32_t *)(&eaddr[0]) = CSR_READ_4(sc, DC_AL_PAR0);
+		*(u_int16_t *)(&eaddr[4]) = CSR_READ_4(sc, DC_AL_PAR1);
 		break;
 	case DC_TYPE_CONEXANT:
 		bcopy(sc->dc_srom + DC_CONEXANT_EE_NODEADDR, &eaddr, 6);


More information about the freebsd-net mailing list