This is the mail archive of the
ecos-patches@sources.redhat.com
mailing list for the eCos project.
ne2k Ethernet fixes.
- From: David Woodhouse <dwmw2 at infradead dot org>
- To: ecos-patches at sources dot redhat dot com
- Date: Wed, 19 Nov 2003 17:40:44 +0000
- Subject: ne2k Ethernet fixes.
On the AX88796 ne2k-alike chip, you have to write to the control
register with the STOP bit set after writing to the CURP register, or
the chip just ignores what you put in CURP.
When debugging this I added sanity checks to the CURP and BNDRY handling
which showed up the fact that we currently set BNDRY to point _outside_
the ring buffer when it should point to the last page therein.
Index: ChangeLog
===================================================================
RCS file: /cvs/cvsfiles/ecc/ecc/devs/eth/ns/dp83902a/current/ChangeLog,v
retrieving revision 1.22
diff -u -p -r1.22 ChangeLog
--- ChangeLog 15 Jul 2002 15:36:35 -0000 1.22
+++ ChangeLog 19 Nov 2003 17:36:18 -0000
@@ -1,3 +1,10 @@
+2003-11-19 David Woodhouse <dwmw2@redhat.com>
+
+ * src/if_dp83902a.c: Set STOP bit in CR after setting CURP
+ register; required for AX88796 chip. Fix handling of BNDRY
+ pointer w.r.t. ring buffer wrap-around. Add extra delays
+ ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA.
+
2002-06-14 Gary Thomas <gary@chez-thomas.org>
* src/if_dp83902a.c:
Index: src/if_dp83902a.c
===================================================================
RCS file: /cvs/cvsfiles/ecc/ecc/devs/eth/ns/dp83902a/current/src/if_dp83902a.c,v
retrieving revision 1.20
diff -u -p -r1.20 if_dp83902a.c
--- src/if_dp83902a.c 15 Jul 2002 15:36:37 -0000 1.20
+++ src/if_dp83902a.c 19 Nov 2003 17:36:18 -0000
@@ -244,7 +244,7 @@ dp83902a_start(struct eth_drv_sc *sc, un
dp->rx_next = dp->rx_buf_start-1;
DP_OUT(base, DP_ISR, 0xFF); // Clear any pending interrupts
DP_OUT(base, DP_IMR, DP_IMR_All); // Enable all interrupts
- DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1); // Select page 1
+ DP_OUT(base, DP_CR, DP_CR_NODMA | DP_CR_PAGE1 | DP_CR_STOP); // Select page 1
DP_OUT(base, DP_P1_CURP, dp->rx_buf_start); // Current page - next free page for Rx
for (i = 0; i < ETHER_ADDR_LEN; i++) {
DP_OUT(base, DP_P1_PAR0+i, enaddr[i]);
@@ -498,24 +498,33 @@ dp83902a_RxEvent(struct eth_drv_sc *sc)
DP_IN(base, DP_P1_CURP, cur);
DP_OUT(base, DP_P1_CR, DP_CR_PAGE0 | DP_CR_NODMA | DP_CR_START);
DP_IN(base, DP_BNDRY, pkt);
+
pkt += 1;
+ if (pkt == dp->rx_buf_end)
+ pkt = dp->rx_buf_start;
+
if (pkt == cur) {
CR_DOWN();
break;
}
- if (pkt == dp->rx_buf_end) pkt = dp->rx_buf_start;
DP_OUT(base, DP_RBCL, sizeof(rcv_hdr));
DP_OUT(base, DP_RBCH, 0);
DP_OUT(base, DP_RSAL, 0);
DP_OUT(base, DP_RSAH, pkt);
if (dp->rx_next == pkt) {
- DP_OUT(base, DP_BNDRY, cur-1); // Update pointer
+ if (cur == dp->rx_buf_start)
+ DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
+ else
+ DP_OUT(base, DP_BNDRY, cur-1); // Update pointer
CR_DOWN();
return;
}
dp->rx_next = pkt;
DP_OUT(base, DP_ISR, DP_ISR_RDC); // Clear end of DMA
DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
+#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
+ CYGACC_CALL_IF_DELAY_US(10);
+#endif
for (i = 0; i < sizeof(rcv_hdr);) {
#ifdef CYGHWR_NS_DP83902A_PLF_16BIT_DATA
@@ -535,7 +544,10 @@ dp83902a_RxEvent(struct eth_drv_sc *sc)
#endif
len = ((rcv_hdr[3] << 8) | rcv_hdr[2]) - sizeof(rcv_hdr);
(sc->funs->eth_drv->recv)(sc, len);
- DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); // Update pointer
+ if (rcv_hdr[1] == dp->rx_buf_start)
+ DP_OUT(base, DP_BNDRY, dp->rx_buf_end-1);
+ else
+ DP_OUT(base, DP_BNDRY, rcv_hdr[1]-1); // Update pointer
}
}
@@ -581,6 +593,9 @@ dp83902a_recv(struct eth_drv_sc *sc, str
DP_OUT(base, DP_RSAH, dp->rx_next);
DP_OUT(base, DP_ISR, DP_ISR_RDC); // Clear end of DMA
DP_OUT(base, DP_CR, DP_CR_RDMA | DP_CR_START);
+#ifdef CYGHWR_NS_DP83902A_PLF_BROKEN_RX_DMA
+ CYGACC_CALL_IF_DELAY_US(10);
+#endif
saved = false;
for (i = 0; i < sg_len; i++) {
--
dwmw2