changeset 2254:b56324487ec7

* src/if_dp83816.c (dp83816_init): Make ESA diag_printf() controlled by DEBUG flag. (dp83816_init): (dp83816_poll): Fixed interrupt enable, masking and acknowledges so that the driver correctly handles Ctrl-C interrupts in RedBoot. * src/if_dp83816.c (dp83816_poll): Removed test for locked up transmit engine. This test triggers in otherwise normal situations and the warm reset messes things up a lot in both the driver and network stack. (dp83816_recv): Avoid memcpy() when passed a NULL buffer, this can happen when the stack runs out of MBUFs.
author jlarmour
date Thu, 20 Jul 2006 15:52:34 +0000
parents 84fb9d197d62
children 3327c37c28d1
files packages/devs/eth/ns/dp83816/current/ChangeLog packages/devs/eth/ns/dp83816/current/src/dp83816.h packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
diffstat 3 files changed, 107 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/packages/devs/eth/ns/dp83816/current/ChangeLog
+++ b/packages/devs/eth/ns/dp83816/current/ChangeLog
@@ -13,6 +13,23 @@ 2004-08-24  Gary Thomas  <gary@mlbassoc.
 	* src/if_dp83816.c: Enable start/stop functions (device was always
 	enabled once configured before)
 
+2004-05-14  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/if_dp83816.c (dp83816_init): Make ESA diag_printf()
+	controlled by DEBUG flag.
+	(dp83816_init): 
+	(dp83816_poll): Fixed interrupt enable, masking and acknowledges
+	so that the driver correctly handles Ctrl-C interrupts in RedBoot.
+
+2004-05-13  Nick Garnett  <nickg@ecoscentric.com>
+
+	* src/if_dp83816.c (dp83816_poll): Removed test for locked up
+	transmit engine. This test triggers in otherwise normal situations
+	and the warm reset messes things up a lot in both the driver and
+	network stack.
+	(dp83816_recv): Avoid memcpy() when passed a NULL buffer, this can
+	happen when the stack runs out of MBUFs.
+
 2003-10-14  Gary Thomas  <gary@mlbassoc.com>
 
 	* src/if_dp83816.c (dp83816_poll): Try to better detect condition
@@ -37,6 +54,7 @@ 2003-09-30  Gary Thomas  <gary@mlbassoc.
 // -------------------------------------------
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+// Copyright (C) 2004 eCosCentric Limited
 //
 // 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
--- a/packages/devs/eth/ns/dp83816/current/src/dp83816.h
+++ b/packages/devs/eth/ns/dp83816/current/src/dp83816.h
@@ -10,6 +10,7 @@
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
 // Copyright (C) 2003 Gary Thomas
+// Copyright (C) 2004 eCosCentric Limited
 //
 // 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
@@ -63,10 +64,10 @@
 // 2 for added data IO output: get_reg, put_reg
 // 4 for packet allocation/free output
 // 8 for only startup status, so we can tell we're installed OK
-#define DEBUG 0x0
-
+#define DEBUG 0
+__externC int norecurse;
 #if DEBUG & 1
-#define DEBUG_FUNCTION() do { diag_printf("%s\n", __FUNCTION__); } while (0)
+#define DEBUG_FUNCTION() do { if (!norecurse) { norecurse=1; diag_printf("%s\n", __FUNCTION__); norecurse=0;}} while (0)
 #define DEBUG_LINE() do { diag_printf("%d\n", __LINE__); } while (0)
 #else
 #define DEBUG_FUNCTION() do {} while(0)
@@ -76,10 +77,10 @@
 // ------------------------------------------------------------------------
 // Buffer descriptors
 typedef struct dp83816_bd {
-    struct dp83816_bd *next;  // Next descriptor
-    unsigned long      stat;  // Buffer status & flags
-    unsigned char     *buf;   // Buffer memory
-    unsigned long      key;   // Internal use only
+    volatile struct dp83816_bd *next;  // Next descriptor
+    volatile unsigned long      stat;  // Buffer status & flags
+    volatile unsigned char     *buf;   // Buffer memory
+    volatile unsigned long      key;   // Internal use only
 } dp83816_bd_t;
 
 // ------------------------------------------------------------------------
--- a/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
+++ b/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c
@@ -10,6 +10,7 @@
 // This file is part of eCos, the Embedded Configurable Operating System.
 // Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
 // Copyright (C) 2003, 2004 Gary Thomas
+// Copyright (C) 2004 eCosCentric Limited
 //
 // 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
@@ -62,10 +63,15 @@
 #include <cyg/hal/hal_if.h>
 #include <cyg/io/eth/eth_drv.h>
 #include <cyg/io/eth/netdev.h>
+#include <string.h> // memcpy
 
 #include "dp83816.h"
 #include CYGDAT_DEVS_ETH_NS_DP83816_INL
 
+#if DEBUG & 1
+int norecurse;
+#endif
+
 #ifdef CYGHWR_NS_DP83816_USE_EEPROM
 static cyg_uint16 dp83816_eeprom_read(struct dp83816_priv_data *dp, int location);
 #endif
@@ -121,6 +127,7 @@ dp83816_reset(dp83816_priv_data_t *dp)
         diag_printf("DP83816 - reset timed out! - stat: %x\n", stat);
         return false;
     }
+
     // Rx ring
     bdp = dp->rxnext = CYGARC_UNCACHED_ADDRESS(dp->rxd);
     bp = dp->rxbuf;
@@ -145,6 +152,7 @@ dp83816_reset(dp83816_priv_data_t *dp)
     bdp--;  bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(dp->txd));
     DP_OUT(dp->base, DP_TXCFG, _TXCFG_ATP |
                                _TXCFG_MXDMA_128 |
+           /* _TXCFG_CSI | */
                                ((256/32)<<_TXCFG_FLTH_SHIFT) |
                                ((512/32)<<_TXCFG_DRTH_SHIFT));
     DP_OUT(dp->base, DP_TXDP, CYGARC_PHYSICAL_ADDRESS(dp->txd));
@@ -169,7 +177,7 @@ dp83816_init(struct cyg_netdevtab_entry 
     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;
+    bool esa_ok = false;
     unsigned char enaddr[6];
 
     DEBUG_FUNCTION();
@@ -178,8 +186,36 @@ dp83816_init(struct cyg_netdevtab_entry 
     base = dp->base;
     if (!base) return false;  // No device found
 
+#ifdef CYGPKG_REDBOOT
+#ifdef CYGSEM_REDBOOT_FLASH_CONFIG
+    esa_ok = flash_get_config(dp->esa_key, enaddr, CONFIG_ESA);
+#endif
+#elif defined (CONFIG_ESA)
+    esa_ok = CYGACC_CALL_IF_FLASH_CFG_OP(CYGNUM_CALL_IF_FLASH_CFG_GET,         
+                                         dp->esa_key, enaddr, CONFIG_ESA);
+#endif
     // Get physical device address
-#ifdef CYGHWR_NS_DP83816_USE_EEPROM
+    // There are two different implementations due to parallel implementations.
+    // Both are included for backward compatibility, but
+    // the CYGHWR_DEVS_ETH_NS_DP83816_USE_EEPROM_ESA implementation is
+    // preferred simply because it is smaller.
+#if defined(CYGHWR_DEVS_ETH_NS_DP83816_USE_EEPROM_ESA)
+    if (!esa_ok)
+    {
+        // Read the ESA from the PMATCH receive filter register, which
+        // will have been initialised from the EEPROM.
+        cyg_uint32 rfcrdat;
+        cyg_ucount8 i;
+        for (i = 0;  i < 6;  i+=2) {
+            DP_OUT(dp->base, DP_RFCR, i);
+            DP_IN(dp->base, DP_RFDR, rfcrdat );
+            enaddr[i] = rfcrdat & 0xff;
+            enaddr[i+1] = (rfcrdat>>8) & 0xff;
+        }
+        esa_ok = true;
+    }
+#elif defined(CYGHWR_NS_DP83816_USE_EEPROM)
+    // This define (CYGHWR_NS_DP83816_USE_EEPROM) is deprecated.
     {
         cyg_uint16 t;
 
@@ -198,17 +234,6 @@ dp83816_init(struct cyg_netdevtab_entry 
         
         esa_ok =  true;
     }
-#else
-#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
 #endif
     if (esa_ok) {
         memcpy(dp->enaddr, enaddr, sizeof(enaddr));
@@ -217,8 +242,16 @@ dp83816_init(struct cyg_netdevtab_entry 
         diag_printf("DP83816 - Warning! ESA unknown\n");
     }
 
+    //    DEBUG_FUNCTION();
+
     if (!dp83816_reset(dp)) return false;
 
+#if DEBUG & 8
+    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] );
+#endif
+    
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
     cyg_drv_interrupt_create(
         dp->interrupt,
@@ -231,6 +264,8 @@ dp83816_init(struct cyg_netdevtab_entry 
 
     cyg_drv_interrupt_attach(dp->interrupt_handle);
     cyg_drv_interrupt_unmask(dp->interrupt);
+#elif defined(CYGPKG_REDBOOT)
+    cyg_drv_interrupt_unmask(dp->interrupt);    
 #endif
 
     // Initialize upper level driver
@@ -306,13 +341,27 @@ dp83816_send(struct eth_drv_sc *sc, stru
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
     int i, len;
     unsigned char *data;
-    dp83816_bd_t *bdp = dp->txfill;
+    dp83816_bd_t *bdp;
+#if 0
+    cyg_uint32 ints;
+    cyg_drv_dsr_lock();
+    HAL_DISABLE_INTERRUPTS(ints);
+#endif
+    
+    bdp= dp->txfill;
 
     DEBUG_FUNCTION();
 
     len = total_len;
     if (len < IEEE_8023_MIN_FRAME) len = IEEE_8023_MIN_FRAME;
     data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
+#if DEBUG & 1
+    if (!norecurse) {
+        norecurse=1;
+        diag_printf("send sg_len==%d, txbusy=%d, len=%d, total_len=%d\n", sg_len, dp->txbusy, len, total_len);
+        norecurse = 0;
+    }
+#endif
     for (i = 0;  i < sg_len;  i++) {
         memcpy(data, (unsigned char *)sg_list[i].buf, sg_list[i].len);
         data += sg_list[i].len;
@@ -324,6 +373,10 @@ dp83816_send(struct eth_drv_sc *sc, stru
     dp->txfill = bdp;
     // Kick the device, in case it went idle
     DP_OUT(dp->base, DP_CR, _CR_TXE);
+#if 0
+    cyg_drv_dsr_unlock();
+    HAL_RESTORE_INTERRUPTS(ints);
+#endif
 }
 
 static void
@@ -396,7 +449,8 @@ dp83816_recv(struct eth_drv_sc *sc, stru
 
     data = (unsigned char *)CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->buf));
     for (i = 0;  i < sg_len;  i++) {
-        memcpy((void *)sg_list[i].buf, data, sg_list[i].len);
+        if( sg_list[i].buf )
+            memcpy((void *)sg_list[i].buf, data, sg_list[i].len);
         data += sg_list[i].len;
     }
 }
@@ -408,6 +462,7 @@ dp83816_warm_reset(struct eth_drv_sc *sc
     dp83816_bd_t *bdp;
     int i;
 
+    DEBUG_FUNCTION();
     // Free up any active Tx buffers
     bdp = CYGARC_UNCACHED_ADDRESS(dp->txd);
     for (i = 0; i < dp->txnum; i++, bdp++) {
@@ -426,6 +481,10 @@ dp83816_poll(struct eth_drv_sc *sc)
     struct dp83816_priv_data *dp = (struct dp83816_priv_data *)sc->driver_private;
     unsigned long stat, cr_stat;
 
+#if defined(CYGPKG_REDBOOT)
+    cyg_drv_interrupt_acknowledge(dp->interrupt);
+#endif
+    
     DP_IN(dp->base, DP_ISR, stat);
     do {
         if ((stat & (_ISR_TXDESC|_ISR_TXOK)) != 0) {
@@ -436,21 +495,24 @@ dp83816_poll(struct eth_drv_sc *sc)
         }
         DP_IN(dp->base, DP_CR, cr_stat);
         if ((stat & (_ISR_HIBERR|_ISR_TXURN|_ISR_RXORN)) != 0) {            
-#if 0
+#if DEBUG & 2
             diag_printf("DP83816 - major error: %x, cmd_stat: %x\n", stat, cr_stat);
 #endif
             // Try to reset the device
             dp83816_warm_reset(sc);
         }
+#if 0
         if (((cr_stat & _CR_RXE) == 0) ||
-            ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0))) {
-#if 0
+            ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0)))
+        {
+#if DEBUG & 2
             // What happened?
-            diag_printf("DP83816 went to lunch? - stat: %x/%x, txbusy: %x\n", cr_stat, stat, dp->txbusy);
+            diag_printf("DP83816 went to lunch? - stat: %x/%x, txbusy: %x, bdstat: %x\n", cr_stat, stat, dp->txbusy, dp->txint->stat);
 #endif
             // Try to reset the device
             dp83816_warm_reset(sc);
         }
+#endif
         DP_IN(dp->base, DP_ISR, stat);
     } while (stat != 0);
 #ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED