diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2006-10-10 00:09:08 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2006-10-10 00:09:08 +0000 |
commit | dc8d0c42a03c25fdf64c58d17fc94f81dd2782d7 (patch) | |
tree | 7035711de4c06df38dee1f8dbe133b6798372b20 /sys/dev/ic | |
parent | 883652ccedcb7255aa5d5ad9048216f16d568ac3 (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.c | 24 | ||||
-rw-r--r-- | sys/dev/ic/dp8390var.h | 4 | ||||
-rw-r--r-- | sys/dev/ic/ne2000.c | 46 |
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 |