This is the mail archive of the
ecos-patches@sourceware.org
mailing list for the eCos project.
NS DP83816 patches
- From: Jonathan Larmour <jifl at eCosCentric dot com>
- To: eCos Patches List <ecos-patches at ecos dot sourceware dot org>
- Date: Thu, 20 Jul 2006 16:51:56 +0100
- Subject: NS DP83816 patches
This is the first of a number of patches being submitted by eCosCentric
from our internal tree to the public tree. This is to try and bring our
sources and anoncvs into line with some of the (many) improvements we've
made in our tree. However it won't be all our changes by any means, not yet :).
In this patch for the NS DP83816 eth driver, some of our changes, and
anoncvs changes overlap, and I've retained the anoncvs implementation for
backward compatibility but deprecated.
Checked in.
Jifl
--
eCosCentric http://www.eCosCentric.com/ The eCos and RedBoot experts
------["The best things in life aren't things."]------ Opinions==mine
Index: ChangeLog
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/ns/dp83816/current/ChangeLog,v
retrieving revision 1.5
diff -u -5 -p -r1.5 ChangeLog
--- ChangeLog 21 Jul 2005 18:10:55 -0000 1.5
+++ ChangeLog 20 Jul 2006 15:48:49 -0000
@@ -11,10 +11,27 @@
2004-08-24 Gary Thomas <gary@mlbassoc.com>
* 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
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
@@ -35,10 +52,11 @@
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// 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
// Software Foundation; either version 2 or (at your option) any later version.
//
Index: src/dp83816.h
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/ns/dp83816/current/src/dp83816.h,v
retrieving revision 1.3
diff -u -5 -p -r1.3 dp83816.h
--- src/dp83816.h 21 Jul 2005 18:10:56 -0000 1.3
+++ src/dp83816.h 20 Jul 2006 15:48:50 -0000
@@ -8,10 +8,11 @@
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// 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
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -61,27 +62,27 @@
// 0 disables all debug output
// 1 for process debug output
// 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)
#define DEBUG_LINE() do {} while(0)
#endif
// ------------------------------------------------------------------------
// 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;
// ------------------------------------------------------------------------
// Private driver structure
typedef struct dp83816_priv_data {
Index: src/if_dp83816.c
===================================================================
RCS file: /cvs/ecos/ecos/packages/devs/eth/ns/dp83816/current/src/if_dp83816.c,v
retrieving revision 1.7
diff -u -5 -p -r1.7 if_dp83816.c
--- src/if_dp83816.c 21 Jul 2005 18:10:56 -0000 1.7
+++ src/if_dp83816.c 20 Jul 2006 15:48:50 -0000
@@ -8,10 +8,11 @@
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// 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
// Software Foundation; either version 2 or (at your option) any later version.
//
@@ -60,14 +61,19 @@
#include <cyg/infra/diag.h>
#include <cyg/hal/drv_api.h>
#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
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
@@ -119,10 +125,11 @@ dp83816_reset(dp83816_priv_data_t *dp)
} while (((stat & _CR_RST) != 0) && (--timeout > 0));
if (timeout == 0) {
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;
for (i = 0; i < dp->rxnum; i++, bdp++) {
bdp->next = (dp83816_bd_t *)CYG_CPU_TO_LE32(CYGARC_PHYSICAL_ADDRESS(bdp+1));
@@ -143,10 +150,11 @@ dp83816_reset(dp83816_priv_data_t *dp)
bp += _DP83816_BUFSIZE;
}
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));
dp->txbusy = 0;
// Fill in ESA
@@ -167,21 +175,49 @@ 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;
+ bool esa_ok = false;
unsigned char enaddr[6];
DEBUG_FUNCTION();
CYGHWR_NS_DP83816_PLF_INIT(dp);
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;
t = (dp83816_eeprom_read(dp, 0x0006) >> 15)
| (dp83816_eeprom_read(dp, 0x0007) << 1);
@@ -196,31 +232,28 @@ dp83816_init(struct cyg_netdevtab_entry
enaddr[4] = t & 0xFF;
enaddr[5] = t >> 8;
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));
} else {
// Can't figure out ESA
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,
0, // Priority - unused
(cyg_addrword_t)sc, // Data item passed to ISR & DSR
@@ -229,10 +262,12 @@ 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);
+#elif defined(CYGPKG_REDBOOT)
+ cyg_drv_interrupt_unmask(dp->interrupt);
#endif
// Initialize upper level driver
(sc->funs->eth_drv->init)(sc, dp->enaddr);
@@ -304,17 +339,31 @@ dp83816_send(struct eth_drv_sc *sc, stru
int total_len, unsigned long key)
{
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;
}
bdp->key = key;
@@ -322,10 +371,14 @@ dp83816_send(struct eth_drv_sc *sc, stru
dp->txbusy++;
bdp = (dp83816_bd_t *)CYGARC_UNCACHED_ADDRESS(CYGARC_VIRTUAL_ADDRESS(CYG_LE32_TO_CPU((unsigned long)bdp->next)));
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
dp83816_TxEvent(struct eth_drv_sc *sc)
{
@@ -394,11 +447,12 @@ dp83816_recv(struct eth_drv_sc *sc, stru
unsigned char *data;
int i;
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;
}
}
static void
@@ -406,10 +460,11 @@ 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 i;
+ DEBUG_FUNCTION();
// 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);
@@ -424,35 +479,42 @@ 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;
+#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) {
dp83816_TxEvent(sc);
}
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) {
-#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 (((cr_stat & _CR_RXE) == 0) ||
- ((dp->txbusy > 1) && ((cr_stat & _CR_TXE) == 0))) {
#if 0
+ if (((cr_stat & _CR_RXE) == 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
CYGHWR_NS_DP83816_PLF_INT_CLEAR(dp);
#endif