This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
i82559 driver updates
- From: Mark Salter <msalter at redhat dot com>
- To: ecos-patches at sources dot redhat dot com
- Date: Sat, 22 Feb 2003 11:46:40 -0500 (EST)
- Subject: i82559 driver updates
This fixes a bug in writing the EEPROM mac address on big endian platforms.
Also, it supports writing to eeprom the mac address gotten from the
CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA macro. And finally, it changes
set_mac_address to use a read-modify-write algorithm rather than a
static table which is not correct for all cards.
--Mark
Index: devs/eth/intel/i82559/current/ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82559/current/ChangeLog,v
retrieving revision 1.19
diff -u -p -5 -r1.19 ChangeLog
--- devs/eth/intel/i82559/current/ChangeLog 12 Feb 2003 13:52:12 -0000 1.19
+++ devs/eth/intel/i82559/current/ChangeLog 22 Feb 2003 16:40:22 -0000
@@ -1,5 +1,12 @@
+2003-02-22 Mark Salter <msalter at redhat dot com>
+
+ * src/if_i82559.c: Fix endian issues with EEPROM writing.
+ Use read-modify-write to set EEPROM mac address. Support
+ writing to EEPROM the mac address obtained from
+ CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA.
+
2003-02-12 Mark Salter <msalter at redhat dot com>
* src/if_i82559.c: Remove restriction preventing combination of
*_GET_ESA and *_HAS_EEPROM.
Index: devs/eth/intel/i82559/current/src/if_i82559.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82559/current/src/if_i82559.c,v
retrieving revision 1.20
diff -u -p -5 -r1.20 if_i82559.c
--- devs/eth/intel/i82559/current/src/if_i82559.c 12 Feb 2003 14:01:14 -0000 1.20
+++ devs/eth/intel/i82559/current/src/if_i82559.c 22 Feb 2003 16:40:33 -0000
@@ -1274,10 +1274,71 @@ read_eeprom(long ioaddr, int location, i
OUTW(EE_ENB & ~EE_CS, ee_addr);
eeprom_delay(EEPROM_DONE_DELAY);
return retval;
}
+
+static int
+read_eeprom_esa(struct i82559 *p_i82559, char *addr)
+{
+ int addr_length, i, count;
+ cyg_uint16 checksum;
+ cyg_uint32 ioaddr = p_i82559->io_address;
+
+ // read eeprom and get 82559's mac address
+ addr_length = get_eeprom_size(ioaddr);
+ // (this is the length of the *EEPROM*s address, not MAC address)
+
+ // If length is 1, it _probably_ means there's no EEPROM
+ // present. Couldn't find an explicit mention of this in the
+ // docs, but length=1 appears to be the behaviour in that case.
+ if (1 == addr_length) {
+#ifdef DEBUG_EE
+ os_printf("Error: No EEPROM present for device %d\n",
+ p_i82559->index);
+#endif
+ } else {
+ for (checksum = 0, i = 0, count = 0; count < 64; count++) {
+ cyg_uint16 value;
+ // read word from eeprom
+ value = read_eeprom(ioaddr, count, addr_length);
+#ifdef DEBUG_EE
+ os_printf( "%2d: %04x\n", count, value );
+#endif
+ checksum += value;
+ if (count < 3) {
+ addr[i++] = value & 0xFF;
+ addr[i++] = (value >> 8) & 0xFF;
+ }
+ }
+
+#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC
+ // If the EEPROM checksum is wrong, the MAC address read
+ // from the EEPROM is probably wrong as well. In that
+ // case, we don't set mac_addr_ok, but continue the
+ // initialization. If then somebody calls i82559_start
+ // without calling eth_set_mac_address() first, we refuse
+ // to bring up the interface, because running with an
+ // invalid MAC address is not a very brilliant idea.
+
+ if ((checksum & 0xFFFF) != 0xBABA) {
+ // selftest verified checksum, verify again
+#ifdef DEBUG_EE
+ os_printf("Warning: Invalid EEPROM checksum %04X for device %d\n",
+ checksum, p_i82559->index);
+#endif
+ } else // trailing block
+#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC
+ {
+#ifdef DEBUG_EE
+ os_printf("Valid EEPROM checksum\n");
+#endif
+ return 1;
+ }
+ }
+ return 0;
+}
#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM
// ------------------------------------------------------------------------
//
// NETWORK INTERFACE INITIALIZATION
@@ -1406,84 +1467,55 @@ i82559_init(struct cyg_netdevtab_entry *
// Acquire the ESA either from extenal means (probably RedBoot
// variables) or from the attached EEPROM - if there is one.
#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA
int ok = false;
+ int wflag = 0;
CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA( p_i82559, mac_address, ok );
- if ( ok )
- eth_set_mac_address(p_i82559, mac_address, 0);
+ if ( ok ) {
+#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM
+#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM
+ if ( CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM == p_i82559->index )
+#endif // CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM
+ {
+ cyg_uint8 tmp_addr[ETHER_ADDR_LEN];
+ // write eeprom address unless it is already there
+ wflag = 1;
+ if (read_eeprom_esa(p_i82559, tmp_addr)) {
+ int i;
+ for (i = 0; i < ETHER_ADDR_LEN; i++)
+ if (tmp_addr[i] != mac_address[i])
+ break;
+ if (i >= ETHER_ADDR_LEN)
+ wflag = 0;
+ }
+ }
+#endif // ! CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM
+ eth_set_mac_address(p_i82559, mac_address, wflag);
+ }
#else // ! CYGHWR_DEVS_ETH_INTEL_I82559_GET_ESA
#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_NO_EEPROM
- int addr_length, i;
- cyg_uint16 checksum;
#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM
if ( CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM == p_i82559->index ) {
#endif // CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM
- // read eeprom and get 82559's mac address
- addr_length = get_eeprom_size(ioaddr);
- // (this is the length of the *EEPROM*s address, not MAC address)
+ if (read_eeprom_esa(p_i82559, mac_address)) {
+ // record the MAC address in the device structure
+ p_i82559->mac_address[0] = mac_address[0];
+ p_i82559->mac_address[1] = mac_address[1];
+ p_i82559->mac_address[2] = mac_address[2];
+ p_i82559->mac_address[3] = mac_address[3];
+ p_i82559->mac_address[4] = mac_address[4];
+ p_i82559->mac_address[5] = mac_address[5];
- // If length is 1, it _probably_ means there's no EEPROM
- // present. Couldn't find an explicit mention of this in the
- // docs, but length=1 appears to be the behaviour in that case.
- if (1 == addr_length) {
-#ifdef DEBUG_EE
- os_printf("Error: No EEPROM present for device %d\n",
- p_i82559->index);
-#endif
- } else {
- for (checksum = 0, i = 0, count = 0; count < 64; count++) {
- cyg_uint16 value;
- // read word from eeprom
- value = read_eeprom(ioaddr, count, addr_length);
-#ifdef DEBUG_EE
- // os_printf( "%2d: %04x\n", count, value );
-#endif
- checksum += value;
- if (count < 3) {
- mac_address[i++] = value & 0xFF;
- mac_address[i++] = (value >> 8) & 0xFF;
- }
- }
-
-#ifndef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM_WITHOUT_CRC
- // If the EEPROM checksum is wrong, the MAC address read
- // from the EEPROM is probably wrong as well. In that
- // case, we don't set mac_addr_ok, but continue the
- // initialization. If then somebody calls i82559_start
- // without calling eth_set_mac_address() first, we refuse
- // to bring up the interface, because running with an
- // invalid MAC address is not a very brilliant idea.
-
- if ((checksum & 0xFFFF) != 0xBABA) {
- // selftest verified checksum, verify again
-#ifdef DEBUG_EE
- os_printf("Warning: Invalid EEPROM checksum %04X for device %d\n",
- checksum, p_i82559->index);
-#endif
- } else // trailing block
-#endif
- {
p_i82559->mac_addr_ok = 1;
-#ifdef DEBUG_EE
- os_printf("Valid EEPROM checksum\n");
-#endif
- eth_set_mac_address(p_i82559, mac_address, 0);
- }
- }
- // record the MAC address in the device structure
- p_i82559->mac_address[0] = mac_address[0];
- p_i82559->mac_address[1] = mac_address[1];
- p_i82559->mac_address[2] = mac_address[2];
- p_i82559->mac_address[3] = mac_address[3];
- p_i82559->mac_address[4] = mac_address[4];
- p_i82559->mac_address[5] = mac_address[5];
+ eth_set_mac_address(p_i82559, mac_address, 0);
+ }
#ifdef CYGHWR_DEVS_ETH_INTEL_I82559_HAS_ONE_EEPROM
}
else { // We are now "in" another device
#if 1 < CYGNUM_DEVS_ETH_INTEL_I82559_DEV_COUNT
@@ -3187,43 +3219,43 @@ static int i82559_configure(struct i8255
return 0;
}
// ------------------------------------------------------------------------
+#if 0
+// The following table below doesn't really work with all cards.
+// The safest way to proceed is to do a read-modify-write of the
+// EEPROM contents rather than relying on a static table.
+
+#ifdef CYGPKG_DEVS_ETH_INTEL_I82559_WRITE_EEPROM
// We use this as a templete when writing a new MAC address into the
// eeproms. The MAC address in the first few bytes is over written
// with the correct MAC address and then the whole lot is programmed
// into the serial EEPROM. The checksum is calculated on the fly and
// sent instead of the last two bytes.
// The values are copied from the Intel EtherPro10/100+ &c devices
// in the EBSA boards.
-
-#ifdef CYGPKG_DEVS_ETH_INTEL_I82559_WRITE_EEPROM
-
-#define ee00 0x00, 0x00 // shorthand
-
-static char eeprom_burn[126] = {
+static cyg_uint16 eeprom_burn[64] = {
/* halfword addresses! */
-/* 0: */ 0x00, 0x90, 0x27, 0x8c, 0x57, 0x82, 0x03, 0x02,
-/* 4: */ ee00 , 0x01, 0x02, 0x01, 0x47, ee00 ,
-/* 8: */ 0x13, 0x72, 0x06, 0x83, 0xa2, 0x40, 0x0c, 0x00,
-/* C: */ 0x86, 0x80, ee00 , ee00 , ee00 ,
-/* 10: */ ee00 , ee00 , ee00 , ee00 ,
-/* 14: */ ee00 , ee00 , ee00 , ee00 ,
-/* 18: */ ee00 , ee00 , ee00 , ee00 ,
-/* 1C: */ ee00 , ee00 , ee00 , ee00 ,
-/* 20: */ ee00 , ee00 , ee00 , ee00 ,
-/* 24: */ ee00 , ee00 , ee00 , ee00 ,
-/* 28: */ ee00 , ee00 , ee00 , ee00 ,
-/* 2C: */ ee00 , ee00 , ee00 , ee00 ,
-/* 30: */ 0x28, 0x01, ee00 , ee00 , ee00 ,
-/* 34: */ ee00 , ee00 , ee00 , ee00 ,
-/* 38: */ ee00 , ee00 , ee00 , ee00 ,
-/* 3C: */ ee00 , ee00 , ee00
+/* 0: */ 0x9000, 0x8c27, 0x8257, 0x0203,
+/* 4: */ 0x0000, 0x0201, 0x4701, 0x0000,
+/* 8: */ 0x7213, 0x8306, 0x40A2, 0x000c,
+/* C: */ 0x8086, 0x0000, 0x0000, 0x0000,
+/* 10: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 14: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 18: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 1C: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 20: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 24: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 28: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 2C: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 30: */ 0x0128, 0x0000, 0x0000, 0x0000,
+/* 34: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 38: */ 0x0000, 0x0000, 0x0000, 0x0000,
+/* 3C: */ 0x0000, 0x0000, 0x0000, 0x0000,
};
-#undef ee00
-
+#endif
#endif
// ------------------------------------------------------------------------
//
// Function : eth_set_mac_address
@@ -3314,15 +3346,21 @@ eth_set_mac_address(struct i82559* p_i82
#endif
} else {
int checksum, i, count;
// (this is the length of the *EEPROM*s address, not MAC address)
int addr_length;
+ cyg_uint16 eeprom_burn[64];
addr_length = get_eeprom_size( ioaddr );
+ for (i = 0; i < 63; i++)
+ eeprom_burn[i] = read_eeprom( ioaddr, i, addr_length );
+
// now set this address in the device eeprom ....
- (void)memcpy(eeprom_burn,addr,6);
+ eeprom_burn[0] = p_i82559->mac_address[0] | (p_i82559->mac_address[1] << 8);
+ eeprom_burn[1] = p_i82559->mac_address[2] | (p_i82559->mac_address[3] << 8);
+ eeprom_burn[2] = p_i82559->mac_address[4] | (p_i82559->mac_address[5] << 8);
// No idea what these were for...
// eeprom_burn[20] &= 0xfe;
// eeprom_burn[20] |= p_i82559->index;