summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_rl.c
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2001-08-15 17:38:43 +0000
committerwpaul <wpaul@FreeBSD.org>2001-08-15 17:38:43 +0000
commit3420b9251b1fde96009222c3335489d8f34edcee (patch)
treed02c2e7dcb5460927414e17349bd92e6b0abbd0a /sys/pci/if_rl.c
parentbf74860be15599f1e7ef46c085c1c5d2b291c23d (diff)
downloadFreeBSD-src-3420b9251b1fde96009222c3335489d8f34edcee.zip
FreeBSD-src-3420b9251b1fde96009222c3335489d8f34edcee.tar.gz
Convert the if_sis and if_rl drivers to use the bus_dma API instead of
calling vtophys() and contigmalloc()/contigfree() directly. Hopefully, I have shaken out all of the problems with busdma on the alpha now. (Everything seems to work as expected.) Also, change the max RX DMA limit to 1024 bytes instead of "unlimited," as the latter seems not to work correctly on the alpha that I tested. (At 100Mbps, all attempts to receive frames yield RX errors.)
Diffstat (limited to 'sys/pci/if_rl.c')
-rw-r--r--sys/pci/if_rl.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/sys/pci/if_rl.c b/sys/pci/if_rl.c
index 5b70c08..3502f20 100644
--- a/sys/pci/if_rl.c
+++ b/sys/pci/if_rl.c
@@ -99,8 +99,6 @@
#include <net/bpf.h>
-#include <vm/vm.h> /* for vtophys */
-#include <vm/pmap.h> /* for vtophys */
#include <machine/bus_pio.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
@@ -194,6 +192,11 @@ static void rl_setmulti __P((struct rl_softc *));
static void rl_reset __P((struct rl_softc *));
static int rl_list_tx_init __P((struct rl_softc *));
+static void rl_dma_map_rxbuf __P((void *, bus_dma_segment_t *,
+ int, int));
+static void rl_dma_map_txbuf __P((void *, bus_dma_segment_t *,
+ int, int));
+
#ifdef RL_USEIOSPACE
#define RL_RES SYS_RES_IOPORT
#define RL_RID RL_PCI_LOIO
@@ -241,6 +244,34 @@ DRIVER_MODULE(miibus, rl, miibus_driver, miibus_devclass, 0, 0);
CSR_WRITE_1(sc, RL_EECMD, \
CSR_READ_1(sc, RL_EECMD) & ~x)
+static void
+rl_dma_map_rxbuf(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg, error;
+{
+ struct rl_softc *sc;
+
+ sc = arg;
+ CSR_WRITE_4(sc, RL_RXADDR, segs->ds_addr & 0xFFFFFFFF);
+
+ return;
+}
+
+static void
+rl_dma_map_txbuf(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg, error;
+{
+ struct rl_softc *sc;
+
+ sc = arg;
+ CSR_WRITE_4(sc, RL_CUR_TXADDR(sc), segs->ds_addr & 0xFFFFFFFF);
+
+ return;
+}
+
/*
* Send a read command and address to the EEPROM, check for ACK.
*/
@@ -940,14 +971,49 @@ static int rl_attach(dev)
goto fail;
}
- sc->rl_cdata.rl_rx_buf = contigmalloc(RL_RXBUFLEN + 1518, M_DEVBUF,
- M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
+ /*
+ * Allocate the parent bus DMA tag appropriate for PCI.
+ */
+#define RL_NSEG_NEW 32
+ error = bus_dma_tag_create(NULL, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR_32BIT,/* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ MAXBSIZE, RL_NSEG_NEW, /* maxsize, nsegments */
+ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+ BUS_DMA_ALLOCNOW, /* flags */
+ &sc->rl_parent_tag);
+
+ /*
+ * Now allocate a tag for the DMA descriptor lists.
+ * All of our lists are allocated as a contiguous block
+ * of memory.
+ */
+ error = bus_dma_tag_create(sc->rl_parent_tag, /* parent */
+ 1, 0, /* alignment, boundary */
+ BUS_SPACE_MAXADDR, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* highaddr */
+ NULL, NULL, /* filter, filterarg */
+ RL_RXBUFLEN + 1518, 1, /* maxsize,nsegments */
+ BUS_SPACE_MAXSIZE_32BIT,/* maxsegsize */
+ 0, /* flags */
+ &sc->rl_tag);
+
+ /*
+ * Now allocate a chunk of DMA-able memory based on the
+ * tag we just created.
+ */
+ error = bus_dmamem_alloc(sc->rl_tag,
+ (void **)&sc->rl_cdata.rl_rx_buf, BUS_DMA_NOWAIT,
+ &sc->rl_cdata.rl_rx_dmamap);
if (sc->rl_cdata.rl_rx_buf == NULL) {
printf("rl%d: no memory for list buffers!\n", unit);
bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq);
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
+ bus_dma_tag_destroy(sc->rl_tag);
error = ENXIO;
goto fail;
}
@@ -963,7 +1029,9 @@ static int rl_attach(dev)
bus_teardown_intr(dev, sc->rl_irq, sc->rl_intrhand);
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq);
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
- free(sc->rl_cdata.rl_rx_buf, M_DEVBUF);
+ bus_dmamem_free(sc->rl_tag,
+ sc->rl_cdata.rl_rx_buf, sc->rl_cdata.rl_rx_dmamap);
+ bus_dma_tag_destroy(sc->rl_tag);
error = ENXIO;
goto fail;
}
@@ -1015,7 +1083,11 @@ static int rl_detach(dev)
bus_release_resource(dev, SYS_RES_IRQ, 0, sc->rl_irq);
bus_release_resource(dev, RL_RES, RL_RID, sc->rl_res);
- contigfree(sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN + 32, M_DEVBUF);
+ bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap);
+ bus_dmamem_free(sc->rl_tag, sc->rl_cdata.rl_rx_buf,
+ sc->rl_cdata.rl_rx_dmamap);
+ bus_dma_tag_destroy(sc->rl_tag);
+ bus_dma_tag_destroy(sc->rl_parent_tag);
RL_UNLOCK(sc);
mtx_destroy(&sc->rl_mtx);
@@ -1082,6 +1154,9 @@ static void rl_rxeof(sc)
ifp = &sc->arpcom.ac_if;
+ bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
+ BUS_DMASYNC_POSTWRITE);
+
cur_rx = (CSR_READ_2(sc, RL_CURRXADDR) + 16) % RL_RXBUFLEN;
/* Do not try to read past this point. */
@@ -1212,6 +1287,8 @@ static void rl_txeof(sc)
ifp->if_collisions += (txstat & RL_TXSTAT_COLLCNT) >> 24;
if (RL_LAST_TXMBUF(sc) != NULL) {
+ bus_dmamap_unload(sc->rl_tag, RL_LAST_DMAMAP(sc));
+ bus_dmamap_destroy(sc->rl_tag, RL_LAST_DMAMAP(sc));
m_freem(RL_LAST_TXMBUF(sc));
RL_LAST_TXMBUF(sc) = NULL;
}
@@ -1399,8 +1476,12 @@ static void rl_start(ifp)
/*
* Transmit the frame.
*/
- CSR_WRITE_4(sc, RL_CUR_TXADDR(sc),
- vtophys(mtod(RL_CUR_TXMBUF(sc), caddr_t)));
+ bus_dmamap_create(sc->rl_tag, 0, &RL_CUR_DMAMAP(sc));
+ bus_dmamap_load(sc->rl_tag, RL_CUR_DMAMAP(sc),
+ mtod(RL_CUR_TXMBUF(sc), void *),
+ RL_CUR_TXMBUF(sc)->m_pkthdr.len, rl_dma_map_txbuf, sc, 0);
+ bus_dmamap_sync(sc->rl_tag, RL_CUR_DMAMAP(sc),
+ BUS_DMASYNC_PREREAD);
CSR_WRITE_4(sc, RL_CUR_TXSTAT(sc),
RL_TXTHRESH(sc->rl_txthresh) |
RL_CUR_TXMBUF(sc)->m_pkthdr.len);
@@ -1448,7 +1529,10 @@ static void rl_init(xsc)
}
/* Init the RX buffer pointer register. */
- CSR_WRITE_4(sc, RL_RXADDR, vtophys(sc->rl_cdata.rl_rx_buf));
+ bus_dmamap_load(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
+ sc->rl_cdata.rl_rx_buf, RL_RXBUFLEN, rl_dma_map_rxbuf, sc, 0);
+ bus_dmamap_sync(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap,
+ BUS_DMASYNC_PREWRITE);
/* Init TX descriptors. */
rl_list_tx_init(sc);
@@ -1639,12 +1723,17 @@ static void rl_stop(sc)
CSR_WRITE_1(sc, RL_COMMAND, 0x00);
CSR_WRITE_2(sc, RL_IMR, 0x0000);
+ bus_dmamap_unload(sc->rl_tag, sc->rl_cdata.rl_rx_dmamap);
/*
* Free the TX list buffers.
*/
for (i = 0; i < RL_TX_LIST_CNT; i++) {
if (sc->rl_cdata.rl_tx_chain[i] != NULL) {
+ bus_dmamap_unload(sc->rl_tag,
+ sc->rl_cdata.rl_tx_dmamap[i]);
+ bus_dmamap_destroy(sc->rl_tag,
+ 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, 0x0000000);
OpenPOWER on IntegriCloud