summaryrefslogtreecommitdiff
path: root/sys/dev/ic
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
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')
-rw-r--r--sys/dev/ic/dp8390.c24
-rw-r--r--sys/dev/ic/dp8390var.h4
-rw-r--r--sys/dev/ic/ne2000.c46
3 files changed, 68 insertions, 6 deletions
diff --git a/sys/dev/ic/dp8390.c b/sys/dev/ic/dp8390.c
index 109bc698208..23397fe9680 100644
--- a/sys/dev/ic/dp8390.c
+++ b/sys/dev/ic/dp8390.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dp8390.c,v 1.35 2006/10/07 22:08:19 brad Exp $ */
+/* $OpenBSD: dp8390.c,v 1.36 2006/10/10 00:09:07 brad Exp $ */
/* $NetBSD: dp8390.c,v 1.13 1998/07/05 06:49:11 jonathan Exp $ */
/*
@@ -205,8 +205,10 @@ dp8390_stop(sc)
int n = 5000;
/* Stop everything on the interface, and select page 0 registers. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_BARRIER(regt, regh);
/*
* Wait for interface to enter stopped state, but limit # of checks to
@@ -215,7 +217,7 @@ dp8390_stop(sc)
*/
while (((NIC_GET(regt, regh,
ED_P0_ISR) & ED_ISR_RST) == 0) && --n)
- ;
+ DELAY(1);
if (sc->stop_card != NULL)
(*sc->stop_card)(sc);
@@ -265,8 +267,10 @@ dp8390_init(sc)
sc->txb_next_tx = 0;
/* Set interface for page 0, remote DMA complete, stopped. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_BARRIER(regt, regh);
if (sc->dcr_reg & ED_DCR_LS) {
NIC_PUT(regt, regh, ED_P0_DCR, sc->dcr_reg);
@@ -314,8 +318,10 @@ dp8390_init(sc)
NIC_PUT(regt, regh, ED_P0_ISR, 0xff);
/* Program command register for page 1. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STP);
+ NIC_BARRIER(regt, regh);
/* Copy out our station address. */
for (i = 0; i < ETHER_ADDR_LEN; ++i)
@@ -335,8 +341,10 @@ dp8390_init(sc)
NIC_PUT(regt, regh, ED_P1_CURR, sc->next_packet);
/* Program command register for page 0. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P1_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STP);
+ NIC_BARRIER(regt, regh);
/* Accept broadcast and multicast packets by default. */
i = ED_RCR_AB | ED_RCR_AM | sc->rcr_proto;
@@ -357,6 +365,7 @@ dp8390_init(sc)
(*sc->init_card)(sc);
/* Fire up the interface. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
@@ -392,8 +401,10 @@ dp8390_xmit(sc)
len = sc->txb_len[sc->txb_next_tx];
/* Set NIC for page 0 register access. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(regt, regh);
/* Set TX buffer start page. */
NIC_PUT(regt, regh, ED_P0_TPSR, sc->tx_page_start +
@@ -404,6 +415,7 @@ dp8390_xmit(sc)
NIC_PUT(regt, regh, ED_P0_TBCR1, len >> 8);
/* Set page 0, remote DMA complete, transmit packet, and *start*. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_TXP | ED_CR_STA);
@@ -498,8 +510,10 @@ dp8390_rint(sc)
loop:
/* Set NIC to page 1 registers to get 'current' pointer. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_1 | ED_CR_STA);
+ NIC_BARRIER(regt, regh);
/*
* 'sc->next_packet' is the logical beginning of the ring-buffer - i.e.
@@ -514,8 +528,10 @@ loop:
return;
/* Set NIC to page 0 registers to update boundary register. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P1_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(regt, regh);
do {
/* Get pointer to this buffer's header structure. */
@@ -613,8 +629,10 @@ dp8390_intr(arg)
return (0);
/* Set NIC to page 0 registers. */
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(regt, regh);
isr = NIC_GET(regt, regh, ED_P0_ISR);
if (!isr)
@@ -771,8 +789,10 @@ dp8390_intr(arg)
* set in the transmit routine, is *okay* - it is 'edge'
* triggered from low to high).
*/
+ NIC_BARRIER(regt, regh);
NIC_PUT(regt, regh, ED_P0_CR,
sc->cr_proto | ED_CR_PAGE_0 | ED_CR_STA);
+ NIC_BARRIER(regt, regh);
/*
* If the Network Talley Counters overflow, read them to reset
diff --git a/sys/dev/ic/dp8390var.h b/sys/dev/ic/dp8390var.h
index 8c104034933..b37bf9b41f8 100644
--- a/sys/dev/ic/dp8390var.h
+++ b/sys/dev/ic/dp8390var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dp8390var.h,v 1.9 2003/10/21 18:58:49 jmc Exp $ */
+/* $OpenBSD: dp8390var.h,v 1.10 2006/10/10 00:09:07 brad Exp $ */
/* $NetBSD: dp8390var.h,v 1.8 1998/08/12 07:19:09 scottr Exp $ */
/*
@@ -141,6 +141,8 @@ struct dp8390_softc {
((sc)->sc_reg_map[reg]))
#define NIC_PUT(t, h, reg, val) bus_space_write_1(t, h, \
((sc)->sc_reg_map[reg]), (val))
+#define NIC_BARRIER(t, h) bus_space_barrier(t, h, 0, 0x10, \
+ BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE)
int dp8390_config(struct dp8390_softc *);
int dp8390_intr(void *);
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