This is the mail archive of the ecos-patches@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

i82544 fix


2003-05-16  Mark Salter  <msalter@redhat.com>

	* include/i82544_info.h: Add link flag.
	* src/if_i82544.c: Allow booting when not using ASD and link is down.


Index: devs/eth/intel/i82544/current/include/i82544_info.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82544/current/include/i82544_info.h,v
retrieving revision 1.2
diff -u -p -5 -r1.2 i82544_info.h
--- devs/eth/intel/i82544/current/include/i82544_info.h	23 May 2002 23:00:43 -0000	1.2
+++ devs/eth/intel/i82544/current/include/i82544_info.h	16 May 2003 13:51:23 -0000
@@ -7,11 +7,11 @@
 //
 //==========================================================================
 //####ECOSGPLCOPYRIGHTBEGIN####
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
-// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
 //
 // eCos is free software; you can redistribute it and/or modify it under
 // the terms of the GNU General Public License as published by the Free
 // Software Foundation; either version 2 or (at your option) any later version.
 //
@@ -136,11 +136,12 @@ typedef struct i82544 {
     cyg_uint8                           // (split up for atomic byte access)
         found:1,                        // was hardware discovered?
         mac_addr_ok:1,                  // can we bring up?
         active:1,                       // has this if been brung up?
         hardwired_esa:1,                // set if ESA is hardwired via CDL
-        spare1:4; 
+        link:1,                         // set if link is up
+        spare1:3; 
     cyg_uint8                           // Count nested sends to reject
         within_send:8;                  //     nested requests to send
     cyg_uint8
         tx_in_progress:1,               // transmit in progress flag
         tx_queue_full:1,                // all Tx descriptors used flag
Index: devs/eth/intel/i82544/current/src/if_i82544.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/intel/i82544/current/src/if_i82544.c,v
retrieving revision 1.8
diff -u -p -5 -r1.8 if_i82544.c
--- devs/eth/intel/i82544/current/src/if_i82544.c	19 Mar 2003 19:55:36 -0000	1.8
+++ devs/eth/intel/i82544/current/src/if_i82544.c	16 May 2003 13:52:11 -0000
@@ -1356,10 +1356,13 @@ i82544_setup( struct i82544 *p_i82544 )
     ctrl |= I82544_CTRL_SLU | I82544_CTRL_ASDE;
     ctrl &= ~(I82544_CTRL_ILOS | I82544_CTRL_FRCSPD | I82544_CTRL_FRCDPLX);
     OUTL( ctrl, ioaddr + I82544_CTRL );
     udelay(20);
 
+    // we can assume link is up with autonegotiation
+    p_i82544->link = 1;
+
     // wait up to 5 seconds for link to come up
     {
 	int delay_cnt = 500;
 	while ((mii_read_register( p_i82544, PHY_ADDRESS, 1 ) & 0x4) == 0) {
 	    udelay(10000);
@@ -1446,21 +1449,26 @@ i82544_setup( struct i82544 *p_i82544 )
     // Force speed renegotiation.
 
     {
         cyg_uint16 phy_ctrl;
         cyg_uint16 phy_stat;
+	int delay_cnt = 100 * 5;  // wait five seconds, then give up
         
+	p_i82544->link = 0;
         phy_ctrl = mii_read_register( p_i82544, PHY_ADDRESS, 0 );
         phy_ctrl |= 0x1200;
 //        os_printf("PHY ctrl %04x\n",phy_ctrl);
         mii_write_register( p_i82544, PHY_ADDRESS, 0, phy_ctrl );
         // Wait for it to complete
         do {
-            udelay(100);
+            udelay(10000);
             phy_stat = mii_read_register( p_i82544, PHY_ADDRESS, 1 );
             phy_stat = mii_read_register( p_i82544, PHY_ADDRESS, 1 );
-        } while( (phy_stat & 0x0020) == 0 );
+        } while( (phy_stat & 0x0020) == 0 && (delay_cnt-- > 0) );
+
+        if (phy_stat & 0x0020)
+            p_i82544->link = 1;
     }
 
 #ifdef DEBUG    
     show_phy( p_i82544, PHY_ADDRESS );
 #endif    
@@ -1485,11 +1493,11 @@ i82544_setup( struct i82544 *p_i82544 )
     // duplex) and we have to transfer the settings from the PHY by
     // hand. Additionally, the settings in the PHY ctrl register seem
     // bogus, so we read the values out of the PHY specific status
     // register instead.
     
-    {
+    if (p_i82544->link) {
         cyg_uint16 phy_pssr;
         
         phy_pssr = mii_read_register( p_i82544, PHY_ADDRESS, 17 );
 
         ctrl = INL( ioaddr + I82544_CTRL );
@@ -2144,10 +2152,47 @@ TxDone(struct i82544* p_i82544)
     p_i82544->tx_pointer = txp;
 
 }
 
 
+static cyg_bool
+check_link(struct i82544 *p_i82544)
+{
+    if ( p_i82544->link == 0 ) 
+    {
+        cyg_uint16 phy_pssr;
+        cyg_uint16 phy_stat;
+
+	phy_stat = mii_read_register( p_i82544, PHY_ADDRESS, 1 );
+        if (phy_stat & 0x20)
+	{
+            cyg_uint32 ioaddr;
+	    cyg_uint32 ctrl;
+
+	    p_i82544->link = 1;
+
+	    ioaddr = p_i82544->io_address;      // get device I/O address
+
+	    phy_pssr = mii_read_register( p_i82544, PHY_ADDRESS, 17 );
+
+	    ctrl = INL( ioaddr + I82544_CTRL );
+	    ctrl &= ~(I82544_CTRL_SPEED | I82544_CTRL_FD);
+	    if( phy_pssr & (1<<13) )
+		ctrl |= I82544_CTRL_FD;
+
+	    // Transfer speed
+	    ctrl |= ((phy_pssr>>14)&3)<<8;
+	    ctrl |= I82544_CTRL_FRCDPLX | I82544_CTRL_FRCSPD;
+
+	    OUTL( ctrl, ioaddr + I82544_CTRL );
+	}
+    }
+
+    return p_i82544->link == 1;
+}
+
+
 // ------------------------------------------------------------------------
 //
 //  Function : i82544_can_send
 //
 // ------------------------------------------------------------------------
@@ -2170,15 +2215,19 @@ i82544_can_send(struct eth_drv_sc *sc)
 #endif
         return 0;
     }
 
     ioaddr = p_i82544->io_address;      // get device I/O address
-    
+
     if ( p_i82544->active )
     {
         cyg_int32 txh, txt, diff;
         
+
+	if (!check_link(p_i82544))
+	    return 0;
+
         // Poll for Tx completion
         TxDone( p_i82544 );
 
 #ifndef CYGPKG_IO_ETH_DRIVERS_STAND_ALONE
 	// We are not prepared to receive a packet now if we are in a polled
@@ -2426,10 +2475,13 @@ i82544_poll(struct eth_drv_sc *sc)
 #ifdef DEBUG
         os_printf( "i82544_poll: Bad device pointer %x\n", p_i82544 );
 #endif
         return;
     }
+
+    if (!check_link(p_i82544))
+        return;
 
     // As it happens, this driver always requests the DSR to be called:
     (void)eth_isr( p_i82544->vector, (cyg_addrword_t)p_i82544 );
 
     // (no harm in calling this ints-off also, when polled)


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]