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]

DP83816 - improve error handling


Plus some other cleanups.

-- 
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: devs/eth/ns/dp83816/current/src/if_dp83816.c
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c,v
retrieving revision 1.1
diff -u -5 -p -r1.1 if_dp83816.c
--- devs/eth/ns/dp83816/current/src/if_dp83816.c	30 Sep 2003 15:25:31 -0000	1.1
+++ devs/eth/ns/dp83816/current/src/if_dp83816.c	30 Sep 2003 21:03:43 -0000
@@ -96,50 +96,22 @@ dp83816_deliver(struct eth_drv_sc *sc)
     // Allow interrupts to happen again
     cyg_drv_interrupt_unmask(dp->interrupt);
 #endif
 }
 
-static bool 
-dp83816_init(struct cyg_netdevtab_entry *tab)
+static bool
+dp83816_reset(dp83816_priv_data_t *dp)
 {
-    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
-    dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
-    cyg_uint8 *base;
-    cyg_uint32 stat;
-    dp83816_bd_t *bdp;
     unsigned char *bp;
+    dp83816_bd_t *bdp;
+    cyg_uint32 stat;
     int i, timeout;
-    bool esa_ok;
-    unsigned char enaddr[6];
 
-    // Get physical device address
-#ifdef CYGPKG_REDBOOT
-#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
-    esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA);
-#else
-    esa_ok = false;
-#endif
-#else
-    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,         
-                                         dp->esa_key, enaddr, CONFIG_ESA);
-#endif
-    if (!esa_ok) {
-        // Can't figure out ESA
-        diag_printf("DP83816 - Warning! ESA unknown\n");
-        memcpy(&enaddr, dp->enaddr, sizeof(enaddr));
-    }
-
-    DEBUG_FUNCTION();
-
-    CYGHWR_NS_DP83816_PLF_INIT(dp);
-    base = dp->base;
-    if (!base) return false;  // No device found
-
-    DP_OUT(base, DP_CR, _CR_RST);  // Reset device
+    DP_OUT(dp->base, DP_CR, _CR_RST);  // Reset device
     timeout = 10000;
     do {
-        DP_IN(base, DP_CR, stat);
+        DP_IN(dp->base, DP_CR, stat);
     } while (((stat & _CR_RST) != 0) && (--timeout > 0));
     if (timeout == 0) {
         diag_printf("DP83816 - reset timed out! - stat: %x\n", stat);
         return false;
     }
@@ -150,11 +122,11 @@ dp83816_init(struct cyg_netdevtab_entry 
         bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1));
         bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE);  // Max buffer
         bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp));
         bp += _DP83816_BUFSIZE;
     }
-    bdp--;  bdp->next = (dp83816_bd_t *)0;
+    bdp--;  bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(dp->rxd));
     DP_OUT(dp->base, DP_RXCFG, _RXCFG_MXDMA_128 | ((64/32)<<_RXCFG_DRTH_SHIFT));
     DP_OUT(dp->base, DP_RXDP, CYGARC_PHYSICAL_ADDRESS(dp->rxd));
     // Tx ring
     bdp = dp->txfill = dp->txint = CYGARC_UNCACHED_ADDRESS(dp->txd);
     bp = dp->txbuf;
@@ -162,27 +134,66 @@ dp83816_init(struct cyg_netdevtab_entry 
         bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(bdp+1));
         bdp->stat = 0;  // Driver owns buffer for now
         bdp->buf = (unsigned char *)_h2le(CYGARC_PHYSICAL_ADDRESS(bp));
         bp += _DP83816_BUFSIZE;
     }
-    bdp--;  bdp->next = (dp83816_bd_t *)0;
+    bdp--;  bdp->next = (dp83816_bd_t *)_h2le(CYGARC_PHYSICAL_ADDRESS(dp->txd));
     DP_OUT(dp->base, DP_TXCFG, _TXCFG_ATP |
                                _TXCFG_MXDMA_128 |
                                ((256/32)<<_TXCFG_FLTH_SHIFT) |
                                ((512/32)<<_TXCFG_DRTH_SHIFT));
     DP_OUT(dp->base, DP_TXDP, CYGARC_PHYSICAL_ADDRESS(dp->txd));
     dp->txbusy = 0;
     // Fill in ESA
     for (i = 0;  i < 6;  i+=2) {
         DP_OUT(dp->base, DP_RFCR, i);
-        DP_OUT(dp->base, DP_RFDR, enaddr[i] | (enaddr[i+1]<<8));
+        DP_OUT(dp->base, DP_RFDR, dp->enaddr[i] | (dp->enaddr[i+1]<<8));
     }
     // Setup up acceptance criteria
     DP_OUT(dp->base, DP_RFCR, _RFCR_RFEN | _RFCR_AAB | _RFCR_APM);
     // Set up interrupts
     DP_IN(dp->base, DP_ISR, stat);  // Clear any current interrupts
     DP_OUT(dp->base, DP_IMR, 0xFFFFFFFF);  // Enable them all!
+    DP_OUT(dp->base, DP_IER, 1);
+    return true;
+}
+
+static bool 
+dp83816_init(struct cyg_netdevtab_entry *tab)
+{
+    struct eth_drv_sc *sc = (struct eth_drv_sc *)tab->device_instance;
+    dp83816_priv_data_t *dp = (dp83816_priv_data_t *)sc->driver_private;
+    cyg_uint8 *base;
+    bool esa_ok;
+    unsigned char enaddr[6];
+
+    // Get physical device address
+#ifdef CYGPKG_REDBOOT
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+    esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA);
+#else
+    esa_ok = false;
+#endif
+#else
+    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,         
+                                         dp->esa_key, enaddr, CONFIG_ESA);
+#endif
+    if (esa_ok) {
+        memcpy(dp->enaddr, enaddr, sizeof(enaddr));
+    } else {
+        // Can't figure out ESA
+        diag_printf("DP83816 - Warning! ESA unknown\n");
+    }
+
+    DEBUG_FUNCTION();
+
+    CYGHWR_NS_DP83816_PLF_INIT(dp);
+    base = dp->base;
+    if (!base) return false;  // No device found
+
+    if (!dp83816_reset(dp)) return false;
+
     diag_printf("DP83816 - ESA: %02x:%02x:%02x:%02x:%02x:%02x\n",
                 dp->enaddr[0], dp->enaddr[1], dp->enaddr[2],
                 dp->enaddr[3], dp->enaddr[4], dp->enaddr[5] );
 
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
@@ -195,15 +206,14 @@ dp83816_init(struct cyg_netdevtab_entry 
         &dp->interrupt_handle,   // handle to intr obj
         &dp->interrupt_object ); // space for int obj
 
     cyg_drv_interrupt_attach(dp->interrupt_handle);
     cyg_drv_interrupt_unmask(dp->interrupt);
-    DP_OUT(dp->base, DP_IER, 1);
 #endif
 
     // Initialize upper level driver
-    (sc->funs->eth_drv->init)(sc, enaddr);
+    (sc->funs->eth_drv->init)(sc, dp->enaddr);
 
     return true;
 }
 
 static void
@@ -279,17 +289,13 @@ dp83816_send(struct eth_drv_sc *sc, stru
     for (i = 0;  i < sg_len;  i++) {
         memcpy(data, (unsigned char *)sg_list[i].buf, sg_list[i].len);
         data += sg_list[i].len;
     }
     bdp->key = key;
-    bdp->stat = _h2le(total_len | BD_OWN | BD_INTR);
+    bdp->stat = _h2le(len | BD_OWN | BD_INTR);
     dp->txbusy++;
-    if (bdp->next == (dp83816_bd_t *)0) {
-        bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
-    } else {
-        bdp++;
-    }
+    bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
     dp->txfill = bdp;
     // Kick the device, in case it went idle
     DP_OUT(dp->base, DP_CR, _CR_TXE);
 }
 
@@ -302,16 +308,13 @@ dp83816_TxEvent(struct eth_drv_sc *sc)
     DEBUG_FUNCTION();
     while ((_le2h(bdp->stat) & (BD_OWN|BD_INTR)) == BD_INTR) {
         // Tell higher level we sent this packet
         (sc->funs->eth_drv->tx_done)(sc, bdp->key, 0);
         bdp->stat = 0;  // retake buffer
+        bdp->key = 0;
         dp->txbusy--;
-        if (bdp->next == (dp83816_bd_t *)0) {
-            bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
-        } else {
-            bdp++;
-        }
+        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
     }
     dp->txint = bdp;
 }
 
 //
@@ -324,10 +327,11 @@ dp83816_TxEvent(struct eth_drv_sc *sc)
 static void
 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;
 
     DEBUG_FUNCTION();
 
     while (true) {
@@ -335,14 +339,13 @@ dp83816_RxEvent(struct eth_drv_sc *sc)
             len = _le2h(bdp->stat) & BD_LENGTH_MASK;
             dp->rxnext = bdp;
             (sc->funs->eth_drv->recv)(sc, len);
             bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE);  // Give back buffer
         }
-        if (bdp->next == (dp83816_bd_t *)0) {
+        bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(_le2h((unsigned long)bdp->next)));
+        if (bdp == bdfirst) {
             break;
-        } else {
-            bdp++;
         }
     }
 }
 
 //
@@ -369,22 +372,50 @@ dp83816_recv(struct eth_drv_sc *sc, stru
 
 static void
 dp83816_poll(struct eth_drv_sc *sc)
 {
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
-    unsigned long stat;
+    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) {
             dp83816_RxEvent(sc);
         }
-        if ((stat & (_ISR_HIBERR|_ISR_TXURN|_ISR_RXORN)) != 0) {
-            diag_printf("DP83816 - major error: %x\n", 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);
+            // 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);
+        }
+        DP_IN(dp->base, DP_CR, cr_stat);
+        if (((cr_stat & _CR_RXE) == 0) ||
+            ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0))) {
+            // What happened?
+            diag_printf("DP83816 went to lunch? - stat: %x, txbusy: %x\n", cr_stat, dp->txbusy);
+            // 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);
         }
         DP_IN(dp->base, DP_ISR, stat);
     } while (stat != 0);
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     CYGHWR_NS_DP83816_PLF_INT_CLEAR(dp);
Index: devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl,v
retrieving revision 1.2
diff -u -5 -p -r1.2 moab_eth_dp83816.inl
--- devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl	30 Sep 2003 17:50:56 -0000	1.2
+++ devs/eth/powerpc/moab/current/include/moab_eth_dp83816.inl	30 Sep 2003 21:01:11 -0000
@@ -119,11 +119,11 @@ static dp83816_priv_data_t dp83816_eth1_
     dp83816_eth_txbd,                      // Tx buffer headers
 };
 
 ETH_DRV_SC(dp83816_sc,
            &dp83816_eth1_priv_data, // Driver specific data
-           CYGDAT_DEVS_ETH_MOAB_ETH1_NAME,
+           "eth1",
            dp83816_start,
            dp83816_stop,
            dp83816_control,
            dp83816_can_send,
            dp83816_send,
@@ -131,11 +131,11 @@ ETH_DRV_SC(dp83816_sc,
            dp83816_deliver,     // "pseudoDSR" called from fast net thread
            dp83816_poll,        // poll function, encapsulates ISR and DSR
            dp83816_int_vector);
 
 NETDEVTAB_ENTRY(dp83816_netdev, 
-                CYGDAT_DEVS_ETH_MOAB_ETH1_NAME,
+                "eth1",
                 dp83816_init, 
                 &dp83816_sc);
 
 #if defined(CYGPKG_REDBOOT) 
 #include <pkgconf/redboot.h>

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