summaryrefslogtreecommitdiffstats
path: root/sys/pci/if_xl.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/pci/if_xl.c')
-rw-r--r--sys/pci/if_xl.c418
1 files changed, 279 insertions, 139 deletions
diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c
index 9f770c4..a7f8c08 100644
--- a/sys/pci/if_xl.c
+++ b/sys/pci/if_xl.c
@@ -116,8 +116,6 @@
#include <net/bpf.h>
-#include <vm/vm.h> /* for vtophys */
-#include <vm/pmap.h> /* for vtophys */
#include <machine/bus_memio.h>
#include <machine/bus_pio.h>
#include <machine/bus.h>
@@ -263,6 +261,9 @@ static int xl_list_tx_init_90xB (struct xl_softc *);
static void xl_wait (struct xl_softc *);
static void xl_mediacheck (struct xl_softc *);
static void xl_choose_xcvr (struct xl_softc *, int);
+static void xl_dma_map_addr (void *, bus_dma_segment_t *, int, int);
+static void xl_dma_map_txbuf (void *, bus_dma_segment_t *, int, bus_size_t,
+ int);
#ifdef notdef
static void xl_testpacket (struct xl_softc *);
#endif
@@ -314,6 +315,47 @@ DRIVER_MODULE(if_xl, cardbus, xl_driver, xl_devclass, 0, 0);
DRIVER_MODULE(if_xl, pci, xl_driver, xl_devclass, 0, 0);
DRIVER_MODULE(miibus, xl, miibus_driver, miibus_devclass, 0, 0);
+static void
+xl_dma_map_addr(arg, segs, nseg, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg, error;
+{
+ u_int32_t *paddr;
+
+ paddr = arg;
+ *paddr = segs->ds_addr;
+}
+
+static void
+xl_dma_map_txbuf(arg, segs, nseg, mapsize, error)
+ void *arg;
+ bus_dma_segment_t *segs;
+ int nseg;
+ bus_size_t mapsize;
+ int error;
+{
+ struct xl_list *l;
+ int i, total_len;
+
+ if (error)
+ return;
+
+ KASSERT(nseg <= XL_MAXFRAGS, ("too many DMA segments"));
+
+ total_len = 0;
+ l = arg;
+ for (i = 0; i < nseg; i++) {
+ KASSERT(segs[i].ds_len <= MCLBYTES, ("segment size too large"));
+ l->xl_frag[i].xl_addr = segs[i].ds_addr;
+ l->xl_frag[i].xl_len = segs[i].ds_len;
+ total_len += segs[i].ds_len;
+ }
+ l->xl_frag[nseg - 1].xl_len |= XL_LAST_FRAG;
+ l->xl_status = total_len;
+ l->xl_next = 0;
+}
+
/*
* Murphy's law says that it's possible the chip can wedge and
* the 'command in progress' bit may never clear. Hence, we wait
@@ -1344,13 +1386,11 @@ xl_attach(dev)
#ifdef XL_USEIOSPACE
if (!(command & PCIM_CMD_PORTEN)) {
printf("xl%d: failed to enable I/O ports!\n", unit);
- error = ENXIO;
goto fail;
}
#else
if (!(command & PCIM_CMD_MEMEN)) {
printf("xl%d: failed to enable memory mapping!\n", unit);
- error = ENXIO;
goto fail;
}
#endif
@@ -1361,7 +1401,6 @@ xl_attach(dev)
if (sc->xl_res == NULL) {
printf ("xl%d: couldn't map ports/memory\n", unit);
- error = ENXIO;
goto fail;
}
@@ -1375,9 +1414,7 @@ xl_attach(dev)
if (sc->xl_fres == NULL) {
printf ("xl%d: couldn't map ports/memory\n", unit);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
- error = ENXIO;
- goto fail;
+ goto fail_res;
}
sc->xl_ftag = rman_get_bustag(sc->xl_fres);
@@ -1387,28 +1424,16 @@ xl_attach(dev)
rid = 0;
sc->xl_irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1,
RF_SHAREABLE | RF_ACTIVE);
-
if (sc->xl_irq == NULL) {
printf("xl%d: couldn't map interrupt\n", unit);
- if (sc->xl_fres != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- XL_PCI_FUNCMEM, sc->xl_fres);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
- error = ENXIO;
- goto fail;
+ goto fail_fres;
}
error = bus_setup_intr(dev, sc->xl_irq, INTR_TYPE_NET,
xl_intr, sc, &sc->xl_intrhand);
-
if (error) {
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq);
- if (sc->xl_fres != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- XL_PCI_FUNCMEM, sc->xl_fres);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
printf("xl%d: couldn't set up irq\n", unit);
- goto fail;
+ goto fail_irq;
}
/* Reset the adapter. */
@@ -1419,14 +1444,7 @@ xl_attach(dev)
*/
if (xl_read_eeprom(sc, (caddr_t)&eaddr, XL_EE_OEM_ADR0, 3, 1)) {
printf("xl%d: failed to read station address\n", sc->xl_unit);
- bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq);
- if (sc->xl_fres != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- XL_PCI_FUNCMEM, sc->xl_fres);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
- error = ENXIO;
- goto fail;
+ goto fail_irq_setup;
}
/*
@@ -1438,22 +1456,74 @@ xl_attach(dev)
callout_handle_init(&sc->xl_stat_ch);
bcopy(eaddr, (char *)&sc->arpcom.ac_enaddr, ETHER_ADDR_LEN);
- sc->xl_ldata = contigmalloc(sizeof(struct xl_list_data), M_DEVBUF,
- M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0);
+ /*
+ * 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(NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ XL_RX_LIST_SZ, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->xl_ldata.xl_rx_tag);
+ if (error) {
+ printf("xl%d: failed to allocate dma tag\n", unit);
+ goto fail_irq_setup;
+ }
+
+ error = bus_dma_tag_create(NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
+ XL_TX_LIST_SZ, 1, BUS_SPACE_MAXSIZE_32BIT, 0,
+ &sc->xl_ldata.xl_tx_tag);
+ if (error) {
+ printf("xl%d: failed to allocate dma tag\n", unit);
+ goto fail_rxtag;
+ }
- if (sc->xl_ldata == NULL) {
+ /*
+ * Allocate a DMA tag for the mapping of mbufs.
+ */
+ error = bus_dma_tag_create(NULL, 1, 0,
+ BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
+ XL_MAXFRAGS, BUS_SPACE_MAXSIZE_32BIT, 0, &sc->xl_mtag);
+ if (error) {
+ printf("xl%d: failed to allocate dma tag\n", unit);
+ goto fail_txtag;
+ }
+
+ /*
+ * Now allocate a chunk of DMA-able memory based on the
+ * tag we just created.
+ */
+ error = bus_dmamem_alloc(sc->xl_ldata.xl_tx_tag,
+ (void **)&sc->xl_ldata.xl_tx_list, BUS_DMA_NOWAIT,
+ &sc->xl_ldata.xl_tx_dmamap);
+ if (error) {
printf("xl%d: no memory for list buffers!\n", unit);
- bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq);
- if (sc->xl_fres != NULL)
- bus_release_resource(dev, SYS_RES_MEMORY,
- XL_PCI_FUNCMEM, sc->xl_fres);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
- error = ENXIO;
- goto fail;
+ goto fail_mtag;
+ }
+
+ error = bus_dmamem_alloc(sc->xl_ldata.xl_rx_tag,
+ (void **)&sc->xl_ldata.xl_rx_list, BUS_DMA_NOWAIT,
+ &sc->xl_ldata.xl_rx_dmamap);
+ if (error) {
+ printf("xl%d: no memory for list buffers!\n", unit);
+ goto fail_txmem;
}
- bzero(sc->xl_ldata, sizeof(struct xl_list_data));
+ bzero(sc->xl_ldata.xl_tx_list, XL_TX_LIST_SZ);
+ bzero(sc->xl_ldata.xl_rx_list, XL_RX_LIST_SZ);
+
+ /*
+ * Obtain the DMA address of the RX ring which we'll need later.
+ */
+ error = bus_dmamap_load(sc->xl_ldata.xl_rx_tag,
+ sc->xl_ldata.xl_rx_dmamap, &(sc->xl_ldata.xl_rx_list[0]),
+ sizeof(struct xl_list_onefrag), xl_dma_map_addr,
+ &sc->xl_ldata.xl_rx_dmaaddr, 0);
+ if (error) {
+ printf("xl%d: cannot get dma address of the rx ring!\n", unit);
+ goto fail_rxmem;
+ }
/*
* Figure out the card type. 3c905B adapters have the
@@ -1511,13 +1581,7 @@ xl_attach(dev)
if (mii_phy_probe(dev, &sc->xl_miibus,
xl_ifmedia_upd, xl_ifmedia_sts)) {
printf("xl%d: no PHY found!\n", sc->xl_unit);
- bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand);
- bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq);
- bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
- contigfree(sc->xl_ldata,
- sizeof(struct xl_list_data), M_DEVBUF);
- error = ENXIO;
- goto fail;
+ goto fail_rxmem;
}
goto done;
@@ -1637,11 +1701,33 @@ done:
XL_UNLOCK(sc);
return(0);
+fail_rxmem:
+ bus_dmamem_free(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_list,
+ sc->xl_ldata.xl_rx_dmamap);
+fail_txmem:
+ bus_dmamem_free(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_list,
+ sc->xl_ldata.xl_tx_dmamap);
+fail_mtag:
+ bus_dma_tag_destroy(sc->xl_mtag);
+fail_txtag:
+ bus_dma_tag_destroy(sc->xl_ldata.xl_tx_tag);
+fail_rxtag:
+ bus_dma_tag_destroy(sc->xl_ldata.xl_rx_tag);
+fail_irq_setup:
+ bus_teardown_intr(dev, sc->xl_irq, sc->xl_intrhand);
+fail_irq:
+ bus_release_resource(dev, SYS_RES_IRQ, 0, sc->xl_irq);
+fail_fres:
+ if (sc->xl_fres != NULL)
+ bus_release_resource(dev, SYS_RES_MEMORY, XL_PCI_FUNCMEM,
+ sc->xl_fres);
+fail_res:
+ bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
fail:
XL_UNLOCK(sc);
mtx_destroy(&sc->xl_mtx);
- return(error);
+ return(ENXIO);
}
static int
@@ -1671,9 +1757,16 @@ xl_detach(dev)
bus_release_resource(dev, SYS_RES_MEMORY,
XL_PCI_FUNCMEM, sc->xl_fres);
bus_release_resource(dev, XL_RES, XL_RID, sc->xl_res);
-
+ bus_dmamap_unload(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_dmamap);
+ bus_dmamap_unload(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_dmamap);
+ bus_dmamem_free(sc->xl_ldata.xl_rx_tag, sc->xl_ldata.xl_rx_list,
+ sc->xl_ldata.xl_rx_dmamap);
+ bus_dmamem_free(sc->xl_ldata.xl_tx_tag, sc->xl_ldata.xl_tx_list,
+ sc->xl_ldata.xl_tx_dmamap);
+ bus_dma_tag_destroy(sc->xl_ldata.xl_rx_tag);
+ bus_dma_tag_destroy(sc->xl_ldata.xl_tx_tag);
+ bus_dma_tag_destroy(sc->xl_mtag);
ifmedia_removeall(&sc->ifmedia);
- contigfree(sc->xl_ldata, sizeof(struct xl_list_data), M_DEVBUF);
XL_UNLOCK(sc);
mtx_destroy(&sc->xl_mtx);
@@ -1690,12 +1783,21 @@ xl_list_tx_init(sc)
{
struct xl_chain_data *cd;
struct xl_list_data *ld;
- int i;
+ int error, i;
cd = &sc->xl_cdata;
- ld = sc->xl_ldata;
+ ld = &sc->xl_ldata;
for (i = 0; i < XL_TX_LIST_CNT; i++) {
cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
+ error = bus_dmamap_create(sc->xl_mtag, 0,
+ &cd->xl_tx_chain[i].xl_map);
+ if (error)
+ return(error);
+ error = bus_dmamap_load(ld->xl_tx_tag, ld->xl_tx_dmamap,
+ &ld->xl_tx_list[i], sizeof(struct xl_list),
+ xl_dma_map_addr, &cd->xl_tx_chain[i].xl_phys, 0);
+ if (error)
+ return(error);
if (i == (XL_TX_LIST_CNT - 1))
cd->xl_tx_chain[i].xl_next = NULL;
else
@@ -1705,24 +1807,34 @@ xl_list_tx_init(sc)
cd->xl_tx_free = &cd->xl_tx_chain[0];
cd->xl_tx_tail = cd->xl_tx_head = NULL;
+ bus_dmamap_sync(ld->xl_tx_tag, ld->xl_tx_dmamap, BUS_DMASYNC_PREWRITE);
return(0);
}
/*
* Initialize the transmit descriptors.
*/
-static int xl_list_tx_init_90xB(sc)
+static int
+xl_list_tx_init_90xB(sc)
struct xl_softc *sc;
{
struct xl_chain_data *cd;
struct xl_list_data *ld;
- int i;
+ int error, i;
cd = &sc->xl_cdata;
- ld = sc->xl_ldata;
+ ld = &sc->xl_ldata;
for (i = 0; i < XL_TX_LIST_CNT; i++) {
cd->xl_tx_chain[i].xl_ptr = &ld->xl_tx_list[i];
- cd->xl_tx_chain[i].xl_phys = vtophys(&ld->xl_tx_list[i]);
+ error = bus_dmamap_create(sc->xl_mtag, 0,
+ &cd->xl_tx_chain[i].xl_map);
+ if (error)
+ return(error);
+ error = bus_dmamap_load(ld->xl_tx_tag, ld->xl_tx_dmamap,
+ &ld->xl_tx_list[i], sizeof(struct xl_list),
+ xl_dma_map_addr, &cd->xl_tx_chain[i].xl_phys, 0);
+ if (error)
+ return(error);
if (i == (XL_TX_LIST_CNT - 1))
cd->xl_tx_chain[i].xl_next = &cd->xl_tx_chain[0];
else
@@ -1735,14 +1847,14 @@ static int xl_list_tx_init_90xB(sc)
&cd->xl_tx_chain[i - 1];
}
- bzero((char *)ld->xl_tx_list,
- sizeof(struct xl_list) * XL_TX_LIST_CNT);
+ bzero(ld->xl_tx_list, XL_TX_LIST_SZ);
ld->xl_tx_list[0].xl_status = XL_TXSTAT_EMPTY;
cd->xl_tx_prod = 1;
cd->xl_tx_cons = 1;
cd->xl_tx_cnt = 0;
+ bus_dmamap_sync(ld->xl_tx_tag, ld->xl_tx_dmamap, BUS_DMASYNC_PREWRITE);
return(0);
}
@@ -1757,27 +1869,39 @@ xl_list_rx_init(sc)
{
struct xl_chain_data *cd;
struct xl_list_data *ld;
- int i;
+ int error, i;
cd = &sc->xl_cdata;
- ld = sc->xl_ldata;
+ ld = &sc->xl_ldata;
for (i = 0; i < XL_RX_LIST_CNT; i++) {
- cd->xl_rx_chain[i].xl_ptr =
- (struct xl_list_onefrag *)&ld->xl_rx_list[i];
- if (xl_newbuf(sc, &cd->xl_rx_chain[i]) == ENOBUFS)
- return(ENOBUFS);
+ cd->xl_rx_chain[i].xl_ptr = &ld->xl_rx_list[i];
+ error = bus_dmamap_create(sc->xl_mtag, 0,
+ &cd->xl_rx_chain[i].xl_map);
+ if (error)
+ return(error);
+ error = xl_newbuf(sc, &cd->xl_rx_chain[i]);
+ if (error)
+ return(error);
if (i == (XL_RX_LIST_CNT - 1)) {
cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[0];
- ld->xl_rx_list[i].xl_next =
- vtophys(&ld->xl_rx_list[0]);
+ error = bus_dmamap_load(ld->xl_rx_tag, ld->xl_rx_dmamap,
+ &ld->xl_rx_list[0], sizeof(struct xl_list_onefrag),
+ xl_dma_map_addr, &ld->xl_rx_list[i].xl_next, 0);
+ if (error)
+ return(error);
} else {
cd->xl_rx_chain[i].xl_next = &cd->xl_rx_chain[i + 1];
- ld->xl_rx_list[i].xl_next =
- vtophys(&ld->xl_rx_list[i + 1]);
+ error = bus_dmamap_load(ld->xl_rx_tag, ld->xl_rx_dmamap,
+ &ld->xl_rx_list[i + 1],
+ sizeof(struct xl_list_onefrag), xl_dma_map_addr,
+ &ld->xl_rx_list[i].xl_next, 0);
+ if (error)
+ return(error);
}
}
+ bus_dmamap_sync(ld->xl_rx_tag, ld->xl_rx_dmamap, BUS_DMASYNC_PREWRITE);
cd->xl_rx_head = &cd->xl_rx_chain[0];
return(0);
@@ -1792,6 +1916,7 @@ xl_newbuf(sc, c)
struct xl_chain_onefrag *c;
{
struct mbuf *m_new = NULL;
+ int error;
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
if (m_new == NULL)
@@ -1809,10 +1934,17 @@ xl_newbuf(sc, c)
m_adj(m_new, ETHER_ALIGN);
c->xl_mbuf = m_new;
- c->xl_ptr->xl_frag.xl_addr = vtophys(mtod(m_new, caddr_t));
c->xl_ptr->xl_frag.xl_len = MCLBYTES | XL_LAST_FRAG;
c->xl_ptr->xl_status = 0;
+ error = bus_dmamap_load(sc->xl_mtag, c->xl_map, mtod(m_new, void *),
+ MCLBYTES, xl_dma_map_addr, &c->xl_ptr->xl_frag.xl_addr, 0);
+ if (error) {
+ m_freem(m_new);
+ printf("xl%d: can't map mbuf\n", sc->xl_unit);
+ return(error);
+ }
+ bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREWRITE);
return(0);
}
@@ -1887,6 +2019,9 @@ again:
}
/* No errors; receive the packet. */
+ bus_dmamap_sync(sc->xl_mtag, cur_rx->xl_map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->xl_mtag, cur_rx->xl_map);
m = cur_rx->xl_mbuf;
total_len = cur_rx->xl_ptr->xl_status & XL_RXSTAT_LENMASK;
@@ -1897,7 +2032,7 @@ again:
* result in a lost packet, but there's little else we
* can do in this situation.
*/
- if (xl_newbuf(sc, cur_rx) == ENOBUFS) {
+ if (xl_newbuf(sc, cur_rx)) {
ifp->if_ierrors++;
cur_rx->xl_ptr->xl_status = 0;
continue;
@@ -1942,8 +2077,7 @@ again:
CSR_READ_4(sc, XL_UPLIST_STATUS) & XL_PKTSTAT_UP_STALLED) {
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
xl_wait(sc);
- CSR_WRITE_4(sc, XL_UPLIST_PTR,
- vtophys(&sc->xl_ldata->xl_rx_list[0]));
+ CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->xl_ldata.xl_rx_dmaaddr);
sc->xl_cdata.xl_rx_head = &sc->xl_cdata.xl_rx_chain[0];
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
goto again;
@@ -1984,6 +2118,9 @@ xl_txeof(sc)
break;
sc->xl_cdata.xl_tx_head = cur_tx->xl_next;
+ bus_dmamap_sync(sc->xl_mtag, cur_tx->xl_map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->xl_mtag, cur_tx->xl_map);
m_freem(cur_tx->xl_mbuf);
cur_tx->xl_mbuf = NULL;
ifp->if_opackets++;
@@ -1999,7 +2136,7 @@ xl_txeof(sc)
if (CSR_READ_4(sc, XL_DMACTL) & XL_DMACTL_DOWN_STALLED ||
!CSR_READ_4(sc, XL_DOWNLIST_PTR)) {
CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
- vtophys(sc->xl_cdata.xl_tx_head->xl_ptr));
+ sc->xl_cdata.xl_tx_head->xl_phys);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
}
}
@@ -2007,7 +2144,8 @@ xl_txeof(sc)
return;
}
-static void xl_txeof_90xB(sc)
+static void
+xl_txeof_90xB(sc)
struct xl_softc *sc;
{
struct xl_chain *cur_tx = NULL;
@@ -2025,6 +2163,9 @@ static void xl_txeof_90xB(sc)
break;
if (cur_tx->xl_mbuf != NULL) {
+ bus_dmamap_sync(sc->xl_mtag, cur_tx->xl_map,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->xl_mtag, cur_tx->xl_map);
m_freem(cur_tx->xl_mbuf);
cur_tx->xl_mbuf = NULL;
}
@@ -2076,7 +2217,7 @@ xl_txeoc(sc)
} else {
if (sc->xl_cdata.xl_tx_head != NULL)
CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
- vtophys(sc->xl_cdata.xl_tx_head->xl_ptr));
+ sc->xl_cdata.xl_tx_head->xl_phys);
}
/*
* Remember to set this for the
@@ -2234,30 +2375,17 @@ xl_encap(sc, c, m_head)
struct xl_chain *c;
struct mbuf *m_head;
{
- int frag = 0;
struct xl_frag *f = NULL;
- int total_len;
- struct mbuf *m;
+ int error;
/*
* Start packing the mbufs in this chain into
* the fragment pointers. Stop when we run out
* of fragments or hit the end of the mbuf chain.
*/
- m = m_head;
- total_len = 0;
- for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
- if (m->m_len != 0) {
- if (frag == XL_MAXFRAGS)
- break;
- total_len+= m->m_len;
- c->xl_ptr->xl_frag[frag].xl_addr =
- vtophys(mtod(m, vm_offset_t));
- c->xl_ptr->xl_frag[frag].xl_len = m->m_len;
- frag++;
- }
- }
+ error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map, m_head,
+ xl_dma_map_txbuf, c->xl_ptr, 0);
/*
* Handle special case: we used up all 63 fragments,
@@ -2267,7 +2395,11 @@ xl_encap(sc, c, m_head)
* pointers/counters; it wouldn't gain us anything,
* and would waste cycles.
*/
- if (m != NULL) {
+ /*
+ * XXX It's not really possible to tell if the error
+ * we got was because we had more than 63 mbufs.
+ */
+ if (error) {
struct mbuf *m_new = NULL;
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
@@ -2290,16 +2422,21 @@ xl_encap(sc, c, m_head)
m_freem(m_head);
m_head = m_new;
f = &c->xl_ptr->xl_frag[0];
- f->xl_addr = vtophys(mtod(m_new, caddr_t));
- f->xl_len = total_len = m_new->m_len;
- frag = 1;
+ error = bus_dmamap_load(sc->xl_mtag, c->xl_map,
+ mtod(m_new, void *), MCLBYTES, xl_dma_map_addr,
+ &f->xl_addr, 0);
+ if (error) {
+ m_freem(m_new);
+ printf("xl%d: can't map mbuf\n", sc->xl_unit);
+ return(1);
+ }
+ f->xl_len = m_new->m_len | XL_LAST_FRAG;
+ c->xl_ptr->xl_status = m_new->m_len;
+ c->xl_ptr->xl_next = 0;
}
c->xl_mbuf = m_head;
- c->xl_ptr->xl_frag[frag - 1].xl_len |= XL_LAST_FRAG;
- c->xl_ptr->xl_status = total_len;
- c->xl_ptr->xl_next = 0;
-
+ bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREREAD);
return(0);
}
@@ -2352,7 +2489,7 @@ xl_start(ifp)
/* Chain it together. */
if (prev != NULL) {
prev->xl_next = cur_tx;
- prev->xl_ptr->xl_next = vtophys(cur_tx->xl_ptr);
+ prev->xl_ptr->xl_next = cur_tx->xl_phys;
}
prev = cur_tx;
@@ -2389,8 +2526,7 @@ xl_start(ifp)
if (sc->xl_cdata.xl_tx_head != NULL) {
sc->xl_cdata.xl_tx_tail->xl_next = start_tx;
- sc->xl_cdata.xl_tx_tail->xl_ptr->xl_next =
- vtophys(start_tx->xl_ptr);
+ sc->xl_cdata.xl_tx_tail->xl_ptr->xl_next = start_tx->xl_phys;
sc->xl_cdata.xl_tx_tail->xl_ptr->xl_status &=
~XL_TXSTAT_DL_INTR;
sc->xl_cdata.xl_tx_tail = cur_tx;
@@ -2399,7 +2535,7 @@ xl_start(ifp)
sc->xl_cdata.xl_tx_tail = cur_tx;
}
if (!CSR_READ_4(sc, XL_DOWNLIST_PTR))
- CSR_WRITE_4(sc, XL_DOWNLIST_PTR, vtophys(start_tx->xl_ptr));
+ CSR_WRITE_4(sc, XL_DOWNLIST_PTR, start_tx->xl_phys);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
@@ -2432,38 +2568,27 @@ xl_start(ifp)
return;
}
-static int xl_encap_90xB(sc, c, m_head)
+static int
+xl_encap_90xB(sc, c, m_head)
struct xl_softc *sc;
struct xl_chain *c;
struct mbuf *m_head;
{
- int frag = 0;
- struct xl_frag *f = NULL;
- struct mbuf *m;
- struct xl_list *d;
+ int error;
/*
* Start packing the mbufs in this chain into
- * the fragment pointers. Stop when we run out
- * of fragments or hit the end of the mbuf chain.
+ * the fragment pointers.
*/
- d = c->xl_ptr;
- d->xl_status = 0;
- d->xl_next = 0;
-
- for (m = m_head, frag = 0; m != NULL; m = m->m_next) {
- if (m->m_len != 0) {
- if (frag == XL_MAXFRAGS)
- break;
- f = &d->xl_frag[frag];
- f->xl_addr = vtophys(mtod(m, vm_offset_t));
- f->xl_len = m->m_len;
- frag++;
- }
+ error = bus_dmamap_load_mbuf(sc->xl_mtag, c->xl_map, m_head,
+ xl_dma_map_txbuf, c->xl_ptr, 0);
+ if (error) {
+ m_freem(m_head);
+ printf("xl%d: can't map mbuf\n", sc->xl_unit);
+ return(1);
}
c->xl_mbuf = m_head;
- c->xl_ptr->xl_frag[frag - 1].xl_len |= XL_LAST_FRAG;
c->xl_ptr->xl_status = XL_TXSTAT_RND_DEFEAT;
if (m_head->m_pkthdr.csum_flags) {
@@ -2474,10 +2599,12 @@ static int xl_encap_90xB(sc, c, m_head)
if (m_head->m_pkthdr.csum_flags & CSUM_UDP)
c->xl_ptr->xl_status |= XL_TXSTAT_UDPCKSUM;
}
+ bus_dmamap_sync(sc->xl_mtag, c->xl_map, BUS_DMASYNC_PREREAD);
return(0);
}
-static void xl_start_90xB(ifp)
+static void
+xl_start_90xB(ifp)
struct ifnet *ifp;
{
struct xl_softc *sc;
@@ -2564,7 +2691,7 @@ xl_init(xsc)
{
struct xl_softc *sc = xsc;
struct ifnet *ifp = &sc->arpcom.ac_if;
- int i;
+ int error, i;
u_int16_t rxfilt = 0;
struct mii_data *mii = NULL;
@@ -2604,9 +2731,10 @@ xl_init(xsc)
xl_wait(sc);
#endif
/* Init circular RX list. */
- if (xl_list_rx_init(sc) == ENOBUFS) {
- printf("xl%d: initialization failed: no "
- "memory for rx buffers\n", sc->xl_unit);
+ error = xl_list_rx_init(sc);
+ if (error) {
+ printf("xl%d: initialization of the rx ring failed (%d)\n",
+ sc->xl_unit, error);
xl_stop(sc);
XL_UNLOCK(sc);
return;
@@ -2614,9 +2742,15 @@ xl_init(xsc)
/* Init TX descriptors. */
if (sc->xl_type == XL_TYPE_905B)
- xl_list_tx_init_90xB(sc);
+ error = xl_list_tx_init_90xB(sc);
else
- xl_list_tx_init(sc);
+ error = xl_list_tx_init(sc);
+ if (error) {
+ printf("xl%d: initialization of the tx ring failed (%d)\n",
+ sc->xl_unit, error);
+ xl_stop(sc);
+ XL_UNLOCK(sc);
+ }
/*
* Set the TX freethresh value.
@@ -2691,7 +2825,7 @@ xl_init(xsc)
*/
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_STALL);
xl_wait(sc);
- CSR_WRITE_4(sc, XL_UPLIST_PTR, vtophys(&sc->xl_ldata->xl_rx_list[0]));
+ CSR_WRITE_4(sc, XL_UPLIST_PTR, sc->xl_ldata.xl_rx_dmaaddr);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_UP_UNSTALL);
xl_wait(sc);
@@ -2703,7 +2837,7 @@ xl_init(xsc)
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_STALL);
xl_wait(sc);
CSR_WRITE_4(sc, XL_DOWNLIST_PTR,
- vtophys(&sc->xl_ldata->xl_tx_list[0]));
+ sc->xl_cdata.xl_tx_chain[0].xl_phys);
CSR_WRITE_2(sc, XL_COMMAND, XL_CMD_DOWN_UNSTALL);
xl_wait(sc);
}
@@ -3023,23 +3157,29 @@ xl_stop(sc)
*/
for (i = 0; i < XL_RX_LIST_CNT; i++) {
if (sc->xl_cdata.xl_rx_chain[i].xl_mbuf != NULL) {
+ bus_dmamap_unload(sc->xl_mtag,
+ sc->xl_cdata.xl_tx_chain[i].xl_map);
+ bus_dmamap_destroy(sc->xl_mtag,
+ sc->xl_cdata.xl_tx_chain[i].xl_map);
m_freem(sc->xl_cdata.xl_rx_chain[i].xl_mbuf);
sc->xl_cdata.xl_rx_chain[i].xl_mbuf = NULL;
}
}
- bzero((char *)&sc->xl_ldata->xl_rx_list,
- sizeof(sc->xl_ldata->xl_rx_list));
+ bzero(sc->xl_ldata.xl_rx_list, XL_RX_LIST_SZ);
/*
* Free the TX list buffers.
*/
for (i = 0; i < XL_TX_LIST_CNT; i++) {
if (sc->xl_cdata.xl_tx_chain[i].xl_mbuf != NULL) {
+ bus_dmamap_unload(sc->xl_mtag,
+ sc->xl_cdata.xl_tx_chain[i].xl_map);
+ bus_dmamap_destroy(sc->xl_mtag,
+ sc->xl_cdata.xl_tx_chain[i].xl_map);
m_freem(sc->xl_cdata.xl_tx_chain[i].xl_mbuf);
sc->xl_cdata.xl_tx_chain[i].xl_mbuf = NULL;
}
}
- bzero((char *)&sc->xl_ldata->xl_tx_list,
- sizeof(sc->xl_ldata->xl_tx_list));
+ bzero(sc->xl_ldata.xl_tx_list, XL_TX_LIST_SZ);
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
OpenPOWER on IntegriCloud