changeset 833:da5d1a18f69c

82546 eeprom fixes
author msalter
date Tue, 18 Mar 2003 02:47:45 +0000
parents 71beb8096c67
children a440f07b6d29
files packages/devs/eth/intel/i82544/current/ChangeLog packages/devs/eth/intel/i82544/current/src/if_i82544.c
diffstat 2 files changed, 45 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/intel/i82544/current/ChangeLog
+++ b/packages/devs/eth/intel/i82544/current/ChangeLog
@@ -1,3 +1,8 @@
+2003-03-17  Mark Salter  <msalter@redhat.com>
+
+	* src/if_i82544.c: Fix 82546 EEPROM access. Fix ESA address for second
+	port of 82546.
+
 2003-03-11  Mark Salter  <msalter@redhat.com>
 
 	* src/if_i82544.c (find_82544s_match_func): Add 82546 devid.
--- a/packages/devs/eth/intel/i82544/current/src/if_i82544.c
+++ b/packages/devs/eth/intel/i82544/current/src/if_i82544.c
@@ -394,6 +394,10 @@ static inline cyg_uint32 bus_to_virt(cyg
 #define EE_CS		0x02            // EEPROM chip select.
 #define EE_DATA_WRITE	0x04            // EEPROM chip data in.
 #define EE_DATA_READ	0x08            // EEPROM chip data out.
+#define EE_REQ          0x40            // EEPROM request (82546 only)
+#define EE_GNT          0x80            // EEPROM grant   (82546 only)
+#define EE_PRES         0x100           // EEPROM present (82546 only)
+#define EE_SIZE         0x200           // EEPROM size    (82546 only)
 #define EE_ENB		(0x10|EE_CS)
 
 
@@ -793,10 +797,9 @@ static int mii_read_register( struct i82
         value = MII_READ_REGVAL();
         MII_IDLE();
     }
-    else if( p_i82544->device == 0x1008 )
+    else
     {
-        // An 82544, read MII register via MDIC register.
-        // UNTESTED
+        // Others, read MII register via MDIC register.
         
         cyg_uint32 mdic = (2<<26) | (phy<<21) | (regnum<<16);
 
@@ -832,10 +835,9 @@ static void mii_write_register( struct i
         MII_WRITE_REGVAL( value );
         MII_IDLE();
     }
-    else if( p_i82544->device == 0x1008 )
+    else
     {
-        // An 82544, write MII register via MDIC register.
-        // UNTESTED
+        // Others, write MII register via MDIC register.
 
         cyg_uint32 mdic = (1<<26) | (phy<<21) | (regnum<<16) | (value&0xFFFF);
 
@@ -901,7 +903,17 @@ static void show_phy( struct i82544 *p_i
 static inline void ee_select( int ioaddr )
 {
     cyg_uint32 l;
-    l = EE_ENB;
+    l = INL( ioaddr + I82544_EECD );
+    if (l & EE_PRES) {
+	// i82546 has EE_PRES bit and requires REQ/GNT before EEPROM access
+	l |= EE_REQ;
+	OUTL( l, ioaddr + I82544_EECD );
+	EE_DELAY();
+	while ((l & EE_GNT) == 0)
+	    l = INL( ioaddr + I82544_EECD );
+    }
+    l &= ~0x3f;
+    l |= EE_ENB;
     OUTL( l, ioaddr + I82544_EECD );
     EE_DELAY();
     l |= EE_CS;
@@ -914,19 +926,25 @@ static inline void ee_select( int ioaddr
 static inline void ee_deselect( int ioaddr )
 {
     cyg_uint32 l;
-    l = EE_ENB;
+    l = INL( ioaddr + I82544_EECD ) & ~0x3f;
+    l |= EE_ENB;
     OUTL( l, ioaddr + I82544_EECD );
     EE_PRINTF( "ee_deselect 1   : " EE_STUFF  );
     EE_DELAY();
     EE_DELAY();
     EE_DELAY();
-    l = EE_ENB & ~EE_CS;
+    l &= ~EE_CS;
     OUTL( l, ioaddr + I82544_EECD );
     l = INL( ioaddr + I82544_EECD );
     EE_PRINTF( "ee_deselect 2   : " EE_STUFF  );
     EE_DELAY();
     EE_DELAY();
     EE_DELAY();
+    if (l & EE_REQ) {
+	l &= ~EE_REQ;
+	OUTL( l, ioaddr + I82544_EECD );
+	EE_DELAY();
+    }
 }
 
 static inline void ee_clock_up( int ioaddr )
@@ -988,74 +1006,21 @@ static inline void ee_write_data_bit( in
 static int
 get_eeprom_size( struct i82544 *p_i82544 )
 {
-//    int i, addrbits, tmp;
-//    cyg_uint32 ioaddr = p_i82544->io_address;
+    cyg_uint32 l, ioaddr = p_i82544->io_address;
 
 #ifdef DEBUG_EE
     diag_printf( "get_eeprom_size\n" );
 #endif
 
-#if 1
-    return 6;
-#else    
-    // Should already be not-selected, but anyway:
-    EE_SELECT();
-
-#ifdef DEBUG_EE
-    diag_printf( "send command\n" );
-#endif
-    
-    // Shift the read command bits out.
-    for (i = 3; i >= 0; i--) { // Doc says to shift out a zero then:
-        tmp = (6 & (1 << i)) ? 1 : 0; // "6" is the "read" command.
-        EE_WRITE_DATA_BIT(tmp);
-        EE_CLOCK_UP();
-        EE_CLOCK_DOWN();
-    }
-#ifdef DEBUG_EE
-    diag_printf( "send address zero\n" );
-#endif
-    // Now clock out address zero, looking for the dummy 0 data bit
-    for ( i = 1; i <= 12; i++ ) {
-        EE_WRITE_DATA_BIT(0);
-        EE_CLOCK_UP();
-        tmp = EE_READ_DATA_BIT();
-        EE_CLOCK_DOWN();
-        if ( !tmp )
-            break;
-    }
-
+    l = INL( ioaddr + I82544_EECD );
+    if (l & EE_PRES) {
 #ifdef DEBUG_EE
-    diag_printf( "eeprom data bits %d\n", i );
+	diag_printf("eeprom size: %d\n", (l & EE_SIZE) ? 8 : 6 );
 #endif
-    
-    if ( 6 != i && 8 != i && 1 != i) {
-#ifdef DEBUG_EE
-        diag_printf( "*****EEPROM data bits not 6, 8 or 1*****\n" );
-#endif
-        addrbits = 1; // Flag no eeprom here.
+	return (l & EE_SIZE) ? 8 : 6;
     }
-    else
-        addrbits = i;
-
-    // read in the data regardless
-    tmp = 0;
-    for (i = 15; i >= 0; i--) {
-        EE_CLOCK_UP();
-        if ( EE_READ_DATA_BIT() )
-            tmp |= (1<<i);
-        EE_CLOCK_DOWN();
-    }
-
-#ifdef DEBUG_EE
-    diag_printf( "eeprom first data word %x\n", tmp );
-#endif
-   
-    // Terminate the EEPROM access.
-    EE_DESELECT();
-    
-    return addrbits;
-#endif    
+
+    return 6;
 }
 
 static int
@@ -1257,6 +1222,12 @@ i82544_init(struct cyg_netdevtab_entry *
 #ifdef DEBUG_EE
                 os_printf("Valid EEPROM checksum\n");
 #endif
+		// Second port of dual-port 82546 uses EEPROM ESA | 1
+		if (p_i82544->device == 0x1010) {
+		    cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(p_i82544->devid);
+		    if (CYG_PCI_DEV_GET_FN(devfn) == 1)
+			mac_address[5] |= 1;
+		}
                 eth_set_mac_address(p_i82544, mac_address, 0);
             }
         }