This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
ETH - improve error handling on NS/DP83816
- From: Gary Thomas <gary at mlbassoc dot com>
- To: eCos patches <ecos-patches at ecos dot sourceware dot org>
- Date: 14 Oct 2003 07:45:23 -0600
- Subject: ETH - improve error handling on NS/DP83816
- Organization: MLB Associates
Somewhat - it still sometimes just stops and has to be reset.
--
Gary Thomas <gary@mlbassoc.com>
MLB Associates
Index: devs/eth/ns/dp83816/current/ChangeLog
===================================================================
RCS file: /misc/cvsfiles/ecos/packages/devs/eth/ns/dp83816/current/ChangeLog,v
retrieving revision 1.2
diff -u -5 -p -r1.2 ChangeLog
--- devs/eth/ns/dp83816/current/ChangeLog 2 Oct 2003 20:11:57 -0000 1.2
+++ devs/eth/ns/dp83816/current/ChangeLog 14 Oct 2003 13:24:43 -0000
@@ -1,5 +1,12 @@
+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
easily set it a runtime.
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.2
diff -u -5 -p -r1.2 if_dp83816.c
--- devs/eth/ns/dp83816/current/src/if_dp83816.c 30 Sep 2003 21:10:11 -0000 1.2
+++ devs/eth/ns/dp83816/current/src/if_dp83816.c 14 Oct 2003 13:25:29 -0000
@@ -328,16 +328,20 @@ 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;
+ 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);
bdp->stat = _h2le(BD_INTR | _DP83816_BUFSIZE); // Give back buffer
}
@@ -369,53 +373,57 @@ dp83816_recv(struct eth_drv_sc *sc, stru
data += sg_list[i].len;
}
}
static void
-dp83816_poll(struct eth_drv_sc *sc)
+dp83816_warm_reset(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 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;
+
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);
#ifdef CYGINT_IO_ETH_INT_SUPPORT_REQUIRED
CYGHWR_NS_DP83816_PLF_INT_CLEAR(dp);