summaryrefslogtreecommitdiff
path: root/sys/dev/ic/ne2000.c
diff options
context:
space:
mode:
authorBrad Smith <brad@cvs.openbsd.org>2006-10-10 00:09:08 +0000
committerBrad Smith <brad@cvs.openbsd.org>2006-10-10 00:09:08 +0000
commitdc8d0c42a03c25fdf64c58d17fc94f81dd2782d7 (patch)
tree7035711de4c06df38dee1f8dbe133b6798372b20 /sys/dev/ic/ne2000.c
parent883652ccedcb7255aa5d5ad9048216f16d568ac3 (diff)
Add bus_space_barrier.
Add DELAY in some busy loops to allow the DMA engine to actually do something (neccessary on fast processors). From ws@ & mycroft@ NetBSD Testing by deraadt@ nick@, ok deraadt@
Diffstat (limited to 'sys/dev/ic/ne2000.c')
-rw-r--r--sys/dev/ic/ne2000.c46
1 files changed, 43 insertions, 3 deletions
diff --git a/sys/dev/ic/ne2000.c b/sys/dev/ic/ne2000.c
index 33ad2aea13c..fd5a27195ea 100644
--- a/sys/dev/ic/ne2000.c
+++ b/sys/dev/ic/ne2000.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ne2000.c,v 1.17 2006/07/29 11:31:20 miod Exp $ */
+/* $OpenBSD: ne2000.c,v 1.18 2006/10/10 00:09:07 brad Exp $ */
/* $NetBSD: ne2000.c,v 1.12 1998/06/10 01:15:50 thorpej Exp $ */
/*-
@@ -98,6 +98,10 @@ void ne2000_writemem(bus_space_tag_t, bus_space_handle_t,
void ne2000_readmem(bus_space_tag_t, bus_space_handle_t,
bus_space_tag_t, bus_space_handle_t, int, u_int8_t *, size_t, int);
+#define ASIC_BARRIER(asict, asich) \
+ bus_space_barrier((asict), (asich), 0, 0x10, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
+
struct cfdriver ne_cd = {
NULL, "ne", DV_IFNET
};
@@ -250,10 +254,13 @@ ne2000_attach(nsc, myea)
/* Read the station address. */
if (nsc->sc_type == NE2000_TYPE_AX88190) {
/* Select page 0 registers. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
/* Select word transfer. */
bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_WTS);
+ NIC_BARRIER(nict, nich);
ne2000_readmem(nict, nich, asict, asich,
NE2000_AX88190_NODEID_OFFSET,
dsc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN, useword);
@@ -273,7 +280,9 @@ ne2000_attach(nsc, myea)
bcopy(myea, dsc->sc_arpcom.ac_enaddr, ETHER_ADDR_LEN);
/* Clear any pending interrupts that might have occurred above. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_ISR, 0xff);
+ NIC_BARRIER(nict, nich);
if (dsc->sc_media_init == NULL)
dsc->sc_media_init = dp8390_media_init;
@@ -315,9 +324,11 @@ ne2000_detect(nsc)
/* Reset the board. */
#ifdef GWETHER
bus_space_write_1(asict, asich, NE2000_ASIC_RESET, 0);
+ ASIC_BARRIER(asict, asich);
delay(200);
#endif /* GWETHER */
tmp = bus_space_read_1(asict, asich, NE2000_ASIC_RESET);
+ ASIC_BARRIER(asict, asich);
delay(10000);
/*
@@ -329,6 +340,7 @@ ne2000_detect(nsc)
* the invasive thing for now. Yuck.]
*/
bus_space_write_1(asict, asich, NE2000_ASIC_RESET, tmp);
+ ASIC_BARRIER(asict, asich);
delay(5000);
/*
@@ -339,6 +351,7 @@ ne2000_detect(nsc)
*/
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_BARRIER(nict, nich);
delay(5000);
@@ -374,12 +387,14 @@ ne2000_detect(nsc)
bus_space_write_1(nict, nich,
ED_P0_CR, ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
for (i = 0; i < 100; i++) {
if ((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RST) ==
ED_ISR_RST) {
/* Ack the reset bit. */
bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RST);
+ NIC_BARRIER(nict, nich);
break;
}
delay(100);
@@ -401,6 +416,7 @@ ne2000_detect(nsc)
* the readmem routine turns on the start bit in the CR.
*/
bus_space_write_1(nict, nich, ED_P0_RCR, ED_RCR_MON);
+ NIC_BARRIER(nict, nich);
/* Temporarily initialize DCR for byte operations. */
bus_space_write_1(nict, nich, ED_P0_DCR, ED_DCR_FT1 | ED_DCR_LS);
@@ -446,6 +462,7 @@ ne2000_detect(nsc)
}
/* Clear any pending interrupts that might have occurred above. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_ISR, 0xff);
out:
@@ -475,11 +492,14 @@ ne2000_write_mbuf(sc, m, buf)
savelen = m->m_pkthdr.len;
/* Select page 0 registers. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
/* Reset remote DMA complete flag. */
bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RDC);
+ NIC_BARRIER(nict, nich);
/* Set up DMA byte count. */
bus_space_write_1(nict, nich, ED_P0_RBCR0, savelen);
@@ -490,8 +510,10 @@ ne2000_write_mbuf(sc, m, buf)
bus_space_write_1(nict, nich, ED_P0_RSAR1, buf >> 8);
/* Set remote DMA write. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich,
ED_P0_CR, ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
/*
* Transfer the mbuf chain to the NIC memory. NE2000 cards
@@ -596,6 +618,7 @@ ne2000_write_mbuf(sc, m, buf)
#endif
}
}
+ NIC_BARRIER(nict, nich);
/*
* Wait for remote DMA to complete. This is necessary because on the
@@ -605,7 +628,12 @@ ne2000_write_mbuf(sc, m, buf)
* the bus.
*/
while (((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RDC) !=
- ED_ISR_RDC) && --maxwait);
+ ED_ISR_RDC) && --maxwait) {
+ bus_space_read_1(nict, nich, ED_P0_CRDA1);
+ bus_space_read_1(nict, nich, ED_P0_CRDA0);
+ NIC_BARRIER(nict, nich);
+ DELAY(1);
+ }
if (maxwait == 0) {
log(LOG_WARNING,
@@ -699,8 +727,10 @@ ne2000_readmem(nict, nich, asict, asich, src, dst, amount, useword)
{
/* Select page 0 registers. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
/* Round up to a word. */
if (amount & 1)
@@ -714,9 +744,11 @@ ne2000_readmem(nict, nich, asict, asich, src, dst, amount, useword)
bus_space_write_1(nict, nich, ED_P0_RSAR0, src);
bus_space_write_1(nict, nich, ED_P0_RSAR1, src >> 8);
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD0 | ED_CR_PAGE_0 | ED_CR_STA);
+ ASIC_BARRIER(asict, asich);
if (useword)
#ifdef __NetBSD__
bus_space_read_multi_stream_2(asict, asich, NE2000_ASIC_DATA,
@@ -748,11 +780,14 @@ ne2000_writemem(nict, nich, asict, asich, src, dst, len, useword)
int maxwait = 100; /* about 120us */
/* Select page 0 registers. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD2 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
/* Reset remote DMA complete flag. */
bus_space_write_1(nict, nich, ED_P0_ISR, ED_ISR_RDC);
+ NIC_BARRIER(nict, nich);
/* Set up DMA byte count. */
bus_space_write_1(nict, nich, ED_P0_RBCR0, len);
@@ -763,9 +798,12 @@ ne2000_writemem(nict, nich, asict, asich, src, dst, len, useword)
bus_space_write_1(nict, nich, ED_P0_RSAR1, dst >> 8);
/* Set remote DMA write. */
+ NIC_BARRIER(nict, nich);
bus_space_write_1(nict, nich, ED_P0_CR,
ED_CR_RD1 | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(nict, nich);
+ ASIC_BARRIER(asict, asich);
if (useword)
#ifdef __NetBSD__
bus_space_write_multi_stream_2(asict, asich, NE2000_ASIC_DATA,
@@ -777,6 +815,7 @@ ne2000_writemem(nict, nich, asict, asich, src, dst, len, useword)
else
bus_space_write_multi_1(asict, asich, NE2000_ASIC_DATA,
src, len);
+ ASIC_BARRIER(asict, asich);
/*
* Wait for remote DMA to complete. This is necessary because on the
@@ -786,7 +825,8 @@ ne2000_writemem(nict, nich, asict, asich, src, dst, len, useword)
* the bus.
*/
while (((bus_space_read_1(nict, nich, ED_P0_ISR) & ED_ISR_RDC) !=
- ED_ISR_RDC) && --maxwait);
+ ED_ISR_RDC) && --maxwait)
+ DELAY(1);
}
int