summaryrefslogtreecommitdiff
path: root/sys/dev/ic/rtl81x9.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ic/rtl81x9.c')
-rw-r--r--sys/dev/ic/rtl81x9.c112
1 files changed, 81 insertions, 31 deletions
diff --git a/sys/dev/ic/rtl81x9.c b/sys/dev/ic/rtl81x9.c
index 6efc9c0cc39..164e40b9c96 100644
--- a/sys/dev/ic/rtl81x9.c
+++ b/sys/dev/ic/rtl81x9.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rtl81x9.c,v 1.30 2004/09/30 14:58:02 jason Exp $ */
+/* $OpenBSD: rtl81x9.c,v 1.31 2004/09/30 17:37:54 jason Exp $ */
/*
* Copyright (c) 1997, 1998
@@ -114,7 +114,7 @@
#include <net/bpf.h>
#endif
-#include <uvm/uvm_extern.h> /* for vtophys */
+#include <uvm/uvm_extern.h>
#include <machine/bus.h>
#include <dev/mii/mii.h>
@@ -613,6 +613,8 @@ rl_rxeof(sc)
max_bytes = limit - cur_rx;
while((CSR_READ_1(sc, RL_COMMAND) & RL_CMD_EMPTY_RXBUF) == 0) {
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);
rxbufpos = sc->rl_cdata.rl_rx_buf + cur_rx;
rxstat = *(u_int32_t *)rxbufpos;
@@ -624,12 +626,20 @@ rl_rxeof(sc)
* datasheet makes absolutely no mention of this and
* RealTek should be shot for this.
*/
- if ((u_int16_t)(rxstat >> 16) == RL_RXSTAT_UNFINISHED)
+ rxstat = htole32(rxstat);
+ if ((u_int16_t)(rxstat >> 16) == RL_RXSTAT_UNFINISHED) {
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
break;
+ }
if (!(rxstat & RL_RXSTAT_RXOK)) {
ifp->if_ierrors++;
rl_init(sc);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
return;
}
@@ -650,8 +660,12 @@ rl_rxeof(sc)
* Avoid trying to read more bytes than we know
* the chip has prepared for us.
*/
- if (rx_bytes > max_bytes)
+ if (rx_bytes > max_bytes) {
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
break;
+ }
rxbufpos = sc->rl_cdata.rl_rx_buf +
((cur_rx + sizeof(u_int32_t)) % RL_RXBUFLEN);
@@ -692,8 +706,12 @@ rl_rxeof(sc)
cur_rx = (cur_rx + 3) & ~3;
CSR_WRITE_2(sc, RL_CURRXADDR, cur_rx - 16);
- if (m == NULL)
+ if (m == NULL) {
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
continue;
+ }
ifp->if_ipackets++;
@@ -705,6 +723,9 @@ rl_rxeof(sc)
bpf_mtap(ifp->if_bpf, m);
#endif
ether_input_mbuf(ifp, m);
+
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
}
}
@@ -736,6 +757,10 @@ void rl_txeof(sc)
ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24;
if (RL_LAST_TXMBUF(sc) != NULL) {
+ bus_dmamap_sync(sc->sc_dmat, RL_LAST_TXMAP(sc),
+ 0, RL_LAST_TXMAP(sc)->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, RL_LAST_TXMAP(sc));
m_freem(RL_LAST_TXMBUF(sc));
RL_LAST_TXMBUF(sc) = NULL;
}
@@ -821,7 +846,7 @@ int rl_encap(sc, m_head)
struct rl_softc *sc;
struct mbuf *m_head;
{
- struct mbuf *m_new = NULL;
+ struct mbuf *m_new;
/*
* The RealTek is brain damaged and wants longword-aligned
@@ -842,26 +867,32 @@ int rl_encap(sc, m_head)
}
m_copydata(m_head, 0, m_head->m_pkthdr.len, mtod(m_new, caddr_t));
m_new->m_pkthdr.len = m_new->m_len = m_head->m_pkthdr.len;
- m_freem(m_head);
- m_head = m_new;
/* Pad frames to at least 60 bytes. */
- if (m_head->m_pkthdr.len < RL_MIN_FRAMELEN) {
+ if (m_new->m_pkthdr.len < RL_MIN_FRAMELEN) {
/*
* Make security-conscious people happy: zero out the
* bytes in the pad area, since we don't know what
* this mbuf cluster buffer's previous user might
* have left in it.
*/
- bzero(mtod(m_head, char *) + m_head->m_pkthdr.len,
- RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
- m_head->m_pkthdr.len +=
- (RL_MIN_FRAMELEN - m_head->m_pkthdr.len);
- m_head->m_len = m_head->m_pkthdr.len;
+ bzero(mtod(m_new, char *) + m_new->m_pkthdr.len,
+ RL_MIN_FRAMELEN - m_new->m_pkthdr.len);
+ m_new->m_pkthdr.len +=
+ (RL_MIN_FRAMELEN - m_new->m_pkthdr.len);
+ m_new->m_len = m_new->m_pkthdr.len;
}
- RL_CUR_TXMBUF(sc) = m_head;
+ if (bus_dmamap_load_mbuf(sc->sc_dmat, RL_CUR_TXMAP(sc),
+ m_new, BUS_DMA_NOWAIT) != 0) {
+ m_freem(m_new);
+ return (1);
+ }
+ m_freem(m_head);
+ RL_CUR_TXMBUF(sc) = m_new;
+ bus_dmamap_sync(sc->sc_dmat, RL_CUR_TXMAP(sc), 0,
+ RL_CUR_TXMAP(sc)->dm_mapsize, BUS_DMASYNC_PREWRITE);
return(0);
}
@@ -900,10 +931,10 @@ void rl_start(ifp)
* Transmit the frame.
*/
CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
- vtophys(mtod(RL_CUR_TXMBUF(sc), vaddr_t)));
+ RL_CUR_TXMAP(sc)->dm_segs[0].ds_addr);
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
RL_TXTHRESH(sc->rl_txthresh) |
- RL_CUR_TXMBUF(sc)->m_pkthdr.len);
+ RL_CUR_TXMAP(sc)->dm_segs[0].ds_len);
RL_INC(sc->rl_cdata.cur_tx);
}
@@ -945,7 +976,7 @@ void rl_init(xsc)
}
/* Init the RX buffer pointer register. */
- CSR_WRITE_4(sc, RL_RXADDR, vtophys((vaddr_t)sc->rl_cdata.rl_rx_buf));
+ CSR_WRITE_4(sc, RL_RXADDR, sc->rl_cdata.rl_rx_buf_pa);
/* Init TX descriptors. */
rl_list_tx_init(sc);
@@ -1153,6 +1184,12 @@ void rl_stop(sc)
*/
for (i = 0; i < RL_TX_LIST_CNT; i++) {
if (sc->rl_cdata.rl_tx_chain[i] != NULL) {
+ bus_dmamap_sync(sc->sc_dmat,
+ sc->rl_cdata.rl_tx_dmamap[i], 0,
+ sc->rl_cdata.rl_tx_dmamap[i]->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat,
+ sc->rl_cdata.rl_tx_dmamap[i]);
m_freem(sc->rl_cdata.rl_tx_chain[i]);
sc->rl_cdata.rl_tx_chain[i] = NULL;
CSR_WRITE_4(sc, RL_TXADDR0 + (i * sizeof(u_int32_t)),
@@ -1168,9 +1205,7 @@ rl_attach(sc)
struct rl_softc *sc;
{
struct ifnet *ifp = &sc->sc_arpcom.ac_if;
- bus_dma_segment_t seg;
- bus_dmamap_t dmamap;
- int rseg;
+ int rseg, i;
u_int16_t rl_id, rl_did;
caddr_t kva;
int addr_len;
@@ -1210,38 +1245,53 @@ rl_attach(sc)
}
if (bus_dmamem_alloc(sc->sc_dmat, RL_RXBUFLEN + 32, PAGE_SIZE, 0,
- &seg, 1, &rseg, BUS_DMA_NOWAIT)) {
+ &sc->sc_rx_seg, 1, &rseg, BUS_DMA_NOWAIT)) {
printf("\n%s: can't alloc rx buffers\n", sc->sc_dev.dv_xname);
return (1);
}
- if (bus_dmamem_map(sc->sc_dmat, &seg, rseg, RL_RXBUFLEN + 32, &kva,
- BUS_DMA_NOWAIT)) {
+ if (bus_dmamem_map(sc->sc_dmat, &sc->sc_rx_seg, rseg,
+ RL_RXBUFLEN + 32, &kva, BUS_DMA_NOWAIT)) {
printf("%s: can't map dma buffers (%d bytes)\n",
sc->sc_dev.dv_xname, RL_RXBUFLEN + 32);
- bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
return (1);
}
if (bus_dmamap_create(sc->sc_dmat, RL_RXBUFLEN + 32, 1,
- RL_RXBUFLEN + 32, 0, BUS_DMA_NOWAIT, &dmamap)) {
+ RL_RXBUFLEN + 32, 0, BUS_DMA_NOWAIT, &sc->sc_rx_dmamap)) {
printf("%s: can't create dma map\n", sc->sc_dev.dv_xname);
bus_dmamem_unmap(sc->sc_dmat, kva, RL_RXBUFLEN + 32);
- bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
return (1);
}
- if (bus_dmamap_load(sc->sc_dmat, dmamap, kva, RL_RXBUFLEN + 32,
- NULL, BUS_DMA_NOWAIT)) {
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_dmamap, kva,
+ RL_RXBUFLEN + 32, NULL, BUS_DMA_NOWAIT)) {
printf("%s: can't load dma map\n", sc->sc_dev.dv_xname);
- bus_dmamap_destroy(sc->sc_dmat, dmamap);
+ bus_dmamap_destroy(sc->sc_dmat, sc->sc_rx_dmamap);
bus_dmamem_unmap(sc->sc_dmat, kva, RL_RXBUFLEN + 32);
- bus_dmamem_free(sc->sc_dmat, &seg, rseg);
+ bus_dmamem_free(sc->sc_dmat, &sc->sc_rx_seg, rseg);
return (1);
}
sc->rl_cdata.rl_rx_buf = kva;
+ sc->rl_cdata.rl_rx_buf_pa = sc->sc_rx_dmamap->dm_segs[0].ds_addr;
+
bzero(sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN + 32);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_rx_dmamap,
+ 0, sc->sc_rx_dmamap->dm_mapsize, BUS_DMASYNC_PREREAD);
+
+ for (i = 0; i < RL_TX_LIST_CNT; i++) {
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
+ BUS_DMA_NOWAIT, &sc->rl_cdata.rl_tx_dmamap[i]) != 0) {
+ printf("%s: can't create tx maps\n");
+ /* XXX free any allocated... */
+ return (1);
+ }
+ }
+
/* Leave a few bytes before the start of the RX ring buffer. */
sc->rl_cdata.rl_rx_buf_ptr = sc->rl_cdata.rl_rx_buf;
sc->rl_cdata.rl_rx_buf += sizeof(u_int64_t);
+ sc->rl_cdata.rl_rx_buf_pa += sizeof(u_int64_t);
ifp->if_softc = sc;
ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;