patch-2.4.22 linux-2.4.22/drivers/net/e100/e100_test.c

Next file: linux-2.4.22/drivers/net/e1000/Makefile
Previous file: linux-2.4.22/drivers/net/e100/e100_phy.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.21/drivers/net/e100/e100_test.c linux-2.4.22/drivers/net/e100/e100_test.c
@@ -25,7 +25,7 @@
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *******************************************************************************/
 
-#include "e100.h"
+#include "e100_phy.h"
 #include "e100_config.h"
 
 extern u16 e100_eeprom_read(struct e100_private *, u16);
@@ -46,6 +46,7 @@
 static void e100_diag_loopback_cu_ru_exec(struct e100_private *);
 static u8 e100_diag_check_pkt(u8 *);
 static void e100_diag_loopback_free(struct e100_private *);
+static int e100_cable_diag(struct e100_private *bdp);
 
 #define LB_PACKET_SIZE 1500
 
@@ -60,46 +61,52 @@
 e100_run_diag(struct net_device *dev, u64 *test_info, u32 flags)
 {
 	struct e100_private* bdp = dev->priv;
-	u8 test_result = true;
-
-	e100_isolate_driver(bdp);
+	u8 test_result = 0;
 
+	if (!e100_get_link_state(bdp)) {
+		test_result = ETH_TEST_FL_FAILED;
+		test_info[test_link] = true;
+	}
+	if (!e100_diag_eeprom(dev)) {
+		test_result = ETH_TEST_FL_FAILED;
+		test_info[test_eeprom] = true;
+	}
 	if (flags & ETH_TEST_FL_OFFLINE) {
 		u8 fail_mask;
-		
-		fail_mask = e100_diag_selftest(dev);
-		if (fail_mask) {
-			test_result = false;
-			if (fail_mask & REGISTER_TEST_FAIL)
-				test_info [E100_REG_TEST_FAIL] = true;
-			if (fail_mask & ROM_TEST_FAIL)
-				test_info [E100_ROM_TEST_FAIL] = true;
-			if (fail_mask & SELF_TEST_FAIL)
-				test_info [E100_MAC_TEST_FAIL] = true;
-			if (fail_mask & TEST_TIMEOUT)
-				test_info [E100_CHIP_TIMEOUT] = true;
+		if (netif_running(dev)) {
+			spin_lock_bh(&dev->xmit_lock);
+			e100_close(dev);
+			spin_unlock_bh(&dev->xmit_lock);
+		}
+		if (e100_diag_selftest(dev)) {
+			test_result = ETH_TEST_FL_FAILED;
+			test_info[test_self_test] = true;
 		}
 
 		fail_mask = e100_diag_loopback(dev);
 		if (fail_mask) {
-			test_result = false;
+			test_result = ETH_TEST_FL_FAILED;
 			if (fail_mask & PHY_LOOPBACK)
-				test_info [E100_LPBK_PHY_FAIL] = true;
+				test_info[test_loopback_phy] = true;
 			if (fail_mask & MAC_LOOPBACK)
-				test_info [E100_LPBK_MAC_FAIL] = true;
+				test_info[test_loopback_mac] = true;
 		}
-	}
 
-	if (!e100_diag_eeprom(dev)) {
-		test_result = false;
-		test_info [E100_EEPROM_TEST_FAIL] = true;
+		test_info[cable_diag] = e100_cable_diag(bdp);
+		/* Need hw init regardless of netif_running */
+		e100_hw_init(bdp);
+		if (netif_running(dev)) {
+			e100_open(dev);
+		}
+	}
+	else {
+		test_info[test_self_test] = false;
+		test_info[test_loopback_phy] = false;
+		test_info[test_loopback_mac] = false;
+		test_info[cable_diag] = false;
 	}
 
-	set_current_state(TASK_UNINTERRUPTIBLE);
-	schedule_timeout(HZ * 2);
-    	e100_deisolate_driver(bdp, false);
-
-	return flags | (test_result ? 0 : ETH_TEST_FL_FAILED);
+	return flags | test_result;
 }
 
 /**
@@ -126,8 +133,6 @@
 		}
 	}
 
-	e100_configure_device(bdp);
-
 	return retval;
 }
 
@@ -165,14 +170,14 @@
 	u8 rc = 0;
 
 	printk(KERN_DEBUG "%s: PHY loopback test starts\n", dev->name);
-	e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET);
+	e100_hw_init(dev->priv);
 	if (!e100_diag_one_loopback(dev, PHY_LOOPBACK)) {
 		rc |= PHY_LOOPBACK;
 	}
 	printk(KERN_DEBUG "%s: PHY loopback test ends\n", dev->name);
 
 	printk(KERN_DEBUG "%s: MAC loopback test starts\n", dev->name);
-	e100_sw_reset(dev->priv, PORT_SELECTIVE_RESET);
+	e100_hw_init(dev->priv);
 	if (!e100_diag_one_loopback(dev, MAC_LOOPBACK)) {
 		rc |= MAC_LOOPBACK;
 	}
@@ -257,15 +262,10 @@
 		if (set_loopback)
                         /* Set PHY loopback mode */
                         e100_phy_set_loopback(bdp);
-                else {	/* Back to normal speed and duplex */
-                	if (bdp->params.e100_speed_duplex == E100_AUTONEG)
-				/* Reset PHY and do autoneg */
-                        	e100_phy_autoneg(bdp);
-			else    
-				/* Reset PHY and force speed and duplex */
-				e100_force_speed_duplex(bdp);
-		}
-                /* Wait for PHY state change */
+		else
+			/* Reset PHY loopback mode */
+			e100_phy_reset(bdp);	
+		/* Wait for PHY state change */
 		set_current_state(TASK_UNINTERRUPTIBLE);
                 schedule_timeout(HZ);
 	} else { /* For MAC loopback wait 500 msec to take effect */
@@ -348,10 +348,6 @@
 e100_diag_loopback_cu_ru_exec(struct e100_private *bdp)
 {
 	/*load CU & RU base */ 
-	if (!e100_wait_exec_cmplx(bdp, 0, SCB_CUC_LOAD_BASE, 0))
-		printk(KERN_ERR "e100: SCB_CUC_LOAD_BASE failed\n");
-	if(!e100_wait_exec_cmplx(bdp, 0, SCB_RUC_LOAD_BASE, 0))
-		printk(KERN_ERR "e100: SCB_RUC_LOAD_BASE failed!\n");
 	if(!e100_wait_exec_cmplx(bdp, bdp->loopback.dma_handle, SCB_RUC_START, 0))
 		printk(KERN_ERR "e100: SCB_RUC_START failed!\n");
 
@@ -433,3 +429,72 @@
 			    bdp->loopback.dma_handle);
 }
 
+static int
+e100_cable_diag(struct e100_private *bdp)
+{	
+	int saved_open_circut = 0xffff;
+	int saved_short_circut = 0xffff;
+	int saved_distance = 0xffff;
+	int saved_same = 0;
+	int cable_status = E100_CABLE_UNKNOWN;
+	int i;
+	
+	/* If we have link, */	
+	if (e100_get_link_state(bdp))
+		return E100_CABLE_OK;
+	
+	if (bdp->rev_id < D102_REV_ID)
+		return E100_CABLE_UNKNOWN;
+
+	/* Disable MDI/MDI-X auto switching */
+        e100_mdi_write(bdp, MII_NCONFIG, bdp->phy_addr,
+		MDI_MDIX_RESET_ALL_MASK);
+	/* Set to 100 Full as required by cable test */
+	e100_mdi_write(bdp, MII_BMCR, bdp->phy_addr,
+		BMCR_SPEED100 | BMCR_FULLDPLX);
+
+	/* Test up to 100 times */
+	for (i = 0; i < 100; i++) {
+		u16 ctrl_reg;
+		int distance, open_circut, short_circut, near_end;
+
+		/* Enable and execute cable test */
+		e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,
+			(HWI_TEST_ENABLE | HWI_TEST_EXECUTE));
+		/* Wait for cable test finished */
+		set_current_state(TASK_UNINTERRUPTIBLE);
+		schedule_timeout(HZ/100 + 1);
+		/* Read results */
+		e100_mdi_read(bdp, HWI_CONTROL_REG, bdp->phy_addr, &ctrl_reg);
+		distance = ctrl_reg & HWI_TEST_DISTANCE;
+		open_circut = ctrl_reg & HWI_TEST_HIGHZ_PROBLEM;
+		short_circut = ctrl_reg & HWI_TEST_LOWZ_PROBLEM;
+
+		if ((distance == saved_distance) &&
+	    	    (open_circut == saved_open_circut) &&
+	    	    (short_circut == saved_short_circut)) 
+			saved_same++;
+		else {
+			saved_same = 0;
+			saved_distance = distance;
+			saved_open_circut = open_circut;
+			saved_short_circut = short_circut;
+		}
+		/* If results are the same 3 times */
+		if (saved_same == 3) {
+			near_end = ((distance * HWI_REGISTER_GRANULARITY) <
+			       HWI_NEAR_END_BOUNDARY);
+			if (open_circut)
+				cable_status = (near_end) ? 
+					E100_CABLE_OPEN_NEAR : E100_CABLE_OPEN_FAR;
+			if (short_circut)
+				cable_status = (near_end) ?
+					E100_CABLE_SHORT_NEAR : E100_CABLE_SHORT_FAR;
+			break;
+		}
+	}
+	/* Reset cable test */
+        e100_mdi_write(bdp, HWI_CONTROL_REG, bdp->phy_addr,					       HWI_RESET_ALL_MASK);
+	return cable_status;
+}
+

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)