changeset 1887:f1416dacc556

Try to improve error detection and recovery
author gthomas
date Thu, 03 Feb 2005 16:01:10 +0000
parents 5f0c796f46a6
children 6940990001c4
files packages/devs/eth/powerpc/ppc405/current/ChangeLog packages/devs/eth/powerpc/ppc405/current/src/if_ppc405.c packages/devs/eth/powerpc/ppc405/current/src/ppc405_enet.h
diffstat 3 files changed, 42 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/powerpc/ppc405/current/ChangeLog
+++ b/packages/devs/eth/powerpc/ppc405/current/ChangeLog
@@ -1,3 +1,8 @@
+2005-02-03  Gary Thomas  <gary@mlbassoc.com>
+
+	* src/ppc405_enet.h: 
+	* src/if_ppc405.c: Improve error detection and recovery.
+
 2003-10-02  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/ppc405_enet.h: Let default ESA be a pointer so that platforms
--- a/packages/devs/eth/powerpc/ppc405/current/src/if_ppc405.c
+++ b/packages/devs/eth/powerpc/ppc405/current/src/if_ppc405.c
@@ -9,7 +9,7 @@
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
-// Copyright (C) 2002, 2003 Gary Thomas
+// Copyright (C) 2002, 2003, 2005 Gary Thomas
 //
 // 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
@@ -405,6 +405,7 @@ ppc405_eth_init(struct cyg_netdevtab_ent
         os_printf("PPC405_ETH - Warning! ESA unknown\n");
         memcpy(&enaddr, qi->enaddr, sizeof(enaddr));
     }
+    memcpy(qi->cfg_enaddr, enaddr, sizeof(enaddr));
 
     // Configure the device
     if (!ppc405_eth_reset(sc, enaddr, 0)) {
@@ -612,6 +613,7 @@ ppc405_eth_int(struct eth_drv_sc *sc)
 {
     struct ppc405_eth_info *qi = (struct ppc405_eth_info *)sc->driver_private;
     unsigned long event, tx_event, rx_event, tx_deir, rx_deir;
+    bool need_reset = false;
 
     CYGARC_MFDCR(MAL0_TXEOBISR, tx_event);
     if (tx_event != 0) {
@@ -625,12 +627,17 @@ ppc405_eth_int(struct eth_drv_sc *sc)
     }
     if ((event = EMAC0_ISR) != 0) {
         if ((event & ~(EMAC0_ISR_SE0|EMAC0_ISR_SE1)) != 0) {
+            // Error other than signal quality
             os_printf("EMAC0_ISR: %x\n", event);
-        }
-        if ((event & (EMAC0_ISR_TE0|EMAC0_ISR_TE1)) != 0) {
-            // Some problem with transmit
-            CYGARC_MTDCR(MAL0_TXCASR, MAL_CASR_C0);
-            qi->tnext = qi->tbase;
+            if ((event & (EMAC0_ISR_TE0|EMAC0_ISR_TE1)) != 0) {
+                // Some problem with transmit - should be easily recoverable
+                CYGARC_MTDCR(MAL0_TXCASR, MAL_CASR_C0);
+                qi->tnext = qi->tbase;
+            }
+            if ((event & (EMAC0_ISR_OVR|EMAC0_ISR_BP|EMAC0_ISR_RP|EMAC0_ISR_ALE|EMAC0_ISR_BFCS)) != 0) {
+                // Rx errors - reset device
+                need_reset = true;
+            }
         }
         EMAC0_ISR = event;  // Reset the bits we handled
     }
@@ -639,11 +646,11 @@ ppc405_eth_int(struct eth_drv_sc *sc)
         CYGARC_MFDCR(MAL0_TXDEIR, tx_deir);
         CYGARC_MFDCR(MAL0_RXDEIR, rx_deir);
         if (dump_mal0_esr) {
-        os_printf("MAL0_ESR: %x, Tx: %x, Rx: %x\n", event, tx_deir, rx_deir);
-        os_printf("Tx buffer headers\n");
-        diag_dump_buf((void *)qi->tbase, qi->txnum*sizeof(mal_bd_t));
-        os_printf("Rx buffer headers\n");
-        diag_dump_buf((void *)qi->rbase, qi->rxnum*sizeof(mal_bd_t));
+            os_printf("MAL0_ESR: %x, Tx: %x, Rx: %x\n", event, tx_deir, rx_deir);
+            os_printf("Tx buffer headers\n");
+            diag_dump_buf((void *)qi->tbase, qi->txnum*sizeof(mal_bd_t));
+            os_printf("Rx buffer headers\n");
+            diag_dump_buf((void *)qi->rbase, qi->rxnum*sizeof(mal_bd_t));
         }
         if (tx_deir != 0) {
             // Fix Tx descriptor problems
@@ -659,6 +666,14 @@ ppc405_eth_int(struct eth_drv_sc *sc)
         }
         CYGARC_MTDCR(MAL0_ESR, event);  // Clear events just handled
     }
+    if (need_reset) {
+        // Something has gone awry - try resetting the device
+        os_printf("\n... PPC405 ethernet - hard reset after failure\n");
+        ppc405_eth_stop(sc);
+        if (!ppc405_eth_reset(sc, qi->cfg_enaddr, 0)) {        
+            os_printf("!! Failed? !!\n");
+        }
+    }
 }
 
 //
--- a/packages/devs/eth/powerpc/ppc405/current/src/ppc405_enet.h
+++ b/packages/devs/eth/powerpc/ppc405/current/src/ppc405_enet.h
@@ -160,16 +160,16 @@
 //
 // Interrupt status
 //
-#define EMAC0_ISR_OVR  0x02000000
-#define EMAC0_ISR_PP   0x01000000
-#define EMAC0_ISR_BP   0x00800000
-#define EMAC0_ISR_RP   0x00400000
-#define EMAC0_ISR_SE   0x00200000
-#define EMAC0_ISR_ALE  0x00100000
-#define EMAC0_ISR_BFCS 0x00080000
-#define EMAC0_ISR_PTLE 0x00040000
-#define EMAC0_ISR_ORE  0x00020000
-#define EMAC0_ISR_IRE  0x00010000
+#define EMAC0_ISR_OVR  0x02000000  // Rx overrun
+#define EMAC0_ISR_PP   0x01000000  // Pause packet received
+#define EMAC0_ISR_BP   0x00800000  // Rx bad packet
+#define EMAC0_ISR_RP   0x00400000  // Rx runt packet
+#define EMAC0_ISR_SE   0x00200000  // Rx short event
+#define EMAC0_ISR_ALE  0x00100000  // Rx alignment error
+#define EMAC0_ISR_BFCS 0x00080000  // Rx bad FCS
+#define EMAC0_ISR_PTLE 0x00040000  // Rx packet too long
+#define EMAC0_ISR_ORE  0x00020000  // Rx packet out of range
+#define EMAC0_ISR_IRE  0x00010000  // Rx packet in range error
 #define EMAC0_ISR_DBDM 0x00000200
 #define EMAC0_ISR_DB0  0x00000100
 #define EMAC0_ISR_SE0  0x00000080
@@ -356,5 +356,6 @@ struct ppc405_eth_info {
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     unsigned long       ints;            // Mask of interrupts in progress
 #endif
+    unsigned char       cfg_enaddr[6];   // Last configured ESA
 };