changeset 1306:093db8861a73

Trying to get a handle on device going suddenly idle...
author gthomas
date Tue, 14 Oct 2003 13:44:28 +0000
parents d256c2b5a157
children 1750695510ac
files packages/devs/eth/ns/dp83816/current/ChangeLog packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
diffstat 2 files changed, 40 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/ns/dp83816/current/ChangeLog
+++ b/packages/devs/eth/ns/dp83816/current/ChangeLog
@@ -1,3 +1,10 @@
+2003-10-14  Gary Thomas  <gary@mlbassoc.com>
+
+	* src/if_dp83816.c (dp83816_poll): Try to better detect condition
+	where device just stops.  This seems to be related to Rx overruns,
+	but there is no status reported.  The best that can be done is
+	detect the condition and then reset/restart the device.
+
 2003-10-02  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/dp83816.h: Let default ESA be a pointer, so platforms can more
--- a/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
+++ b/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
@@ -330,12 +330,16 @@ dp83816_RxEvent(struct eth_drv_sc *sc)
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
     dp83816_bd_t *bdp = CYGARC_UNCACHED_ADDRESS(dp->rxd);
     dp83816_bd_t *bdfirst = CYGARC_UNCACHED_ADDRESS(dp->rxd);
-    int len;
+    int len, err;
 
     DEBUG_FUNCTION();
 
     while (true) {
         if ((_le2h(bdp->stat) & BD_OWN) != 0) {
+            err = _le2h(bdp->stat) & (BD_RXA|BD_RXO|BD_LONG|BD_RUNT|BD_ISE|BD_CRCE|BD_FAE|BD_COL);
+            if (err != 0) {
+                diag_printf("RxError: %x\n", err);
+            }
             len = _le2h(bdp->stat) & BD_LENGTH_MASK;
             dp->rxnext = bdp;
             (sc->funs->eth_drv->recv)(sc, len);
@@ -371,49 +375,53 @@ dp83816_recv(struct eth_drv_sc *sc, stru
 }
 
 static void
+dp83816_warm_reset(struct eth_drv_sc *sc)
+{
+    struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
+    dp83816_bd_t *bdp;
+    int len, err;
+    int i;
+
+    // Free up any active Tx buffers
+    bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
+    for (i = 0; i < dp->txnum; i++, bdp++) {
+        if (bdp->key) {
+            (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
+        }
+    }
+    // Reset the device
+    dp83816_reset(dp);
+    DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE);
+}
+
+static void
 dp83816_poll(struct eth_drv_sc *sc)
 {
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
     unsigned long stat, cr_stat;
-    dp83816_bd_t *bdp;
-    int i;
 
     DP_IN(dp->base, DP_ISR, stat);
     do {
         if ((stat & (_ISR_TXDESC|_ISR_TXOK)) != 0) {
             dp83816_TxEvent(sc);
         }
-        if ((stat & (_ISR_RXDESC|_ISR_RXOK)) != 0) {
+        if ((stat & (_ISR_RXDESC|_ISR_RXOK|_ISR_RXERR)) != 0) {
             dp83816_RxEvent(sc);
         }
+        DP_IN(dp->base, DP_CR, cr_stat);
         if ((stat & (_ISR_HIBERR|_ISR_TXURN|_ISR_RXORN)) != 0) {            
-            diag_printf("DP83816 - major error: %x", stat);
-            DP_IN(dp->base, DP_CR, stat);
-            diag_printf(", cmd: %x\n", stat);
+            diag_printf("DP83816 - major error: %x, cmd_stat: %x\n", stat, cr_stat);
             // Try to reset the device
-            bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
-            for (i = 0; i < dp->txnum; i++, bdp++) {
-                if (bdp->key) {
-                    (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
-                }
-            }
-            dp83816_reset(dp);
-            DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE);
+            dp83816_warm_reset(sc);
         }
-        DP_IN(dp->base, DP_CR, cr_stat);
         if (((cr_stat & _CR_RXE) == 0) ||
             ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0))) {
+#if 0
             // What happened?
-            diag_printf("DP83816 went to lunch? - stat: %x, txbusy: %x\n", cr_stat, dp->txbusy);
+            diag_printf("DP83816 went to lunch? - stat: %x/%x, txbusy: %x\n", cr_stat, stat, dp->txbusy);
+#endif
             // Try to reset the device
-            bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
-            for (i = 0; i < dp->txnum; i++, bdp++) {
-                if (bdp->key) {
-                    (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
-                }
-            }
-            dp83816_reset(dp);
-            DP_OUT(dp->base, DP_CR, _CR_RXE | _CR_TXE);
+            dp83816_warm_reset(sc);
         }
         DP_IN(dp->base, DP_ISR, stat);
     } while (stat != 0);