summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorAaron Campbell <aaron@cvs.openbsd.org>2002-07-02 16:44:26 +0000
committerAaron Campbell <aaron@cvs.openbsd.org>2002-07-02 16:44:26 +0000
commit3aca8249d13a32de42bfae96a88149bea16f20e0 (patch)
treea1c7c0af8fb95d292d1816ab682bf03841606ab4 /sys
parent7960893b2808b040982b3f9394a88a28c046e06d (diff)
bus_dma'ify, works on an SiS900 and a Netgear FA411. Thanks to wilfried@ for
testing.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/pci/if_sis.c220
-rw-r--r--sys/dev/pci/if_sisreg.h16
2 files changed, 176 insertions, 60 deletions
diff --git a/sys/dev/pci/if_sis.c b/sys/dev/pci/if_sis.c
index fdfb542de5f..ebe68ada4a6 100644
--- a/sys/dev/pci/if_sis.c
+++ b/sys/dev/pci/if_sis.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sis.c,v 1.23 2002/03/25 20:28:06 mickey Exp $ */
+/* $OpenBSD: if_sis.c,v 1.24 2002/07/02 16:44:25 aaron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
@@ -90,8 +90,6 @@
#include <net/bpf.h>
#endif
-#include <uvm/uvm_extern.h> /* for vtophys */
-
#include <sys/device.h>
#include <dev/mii/mii.h>
@@ -640,7 +638,7 @@ void sis_attach(parent, self, aux)
struct device *parent, *self;
void *aux;
{
- int s;
+ int i, s;
const char *intrstr = NULL;
u_int32_t command;
struct sis_softc *sc = (struct sis_softc *)self;
@@ -831,16 +829,61 @@ void sis_attach(parent, self, aux)
printf(" address %s\n", ether_sprintf(sc->arpcom.ac_enaddr));
- sc->sis_ldata_ptr = malloc(sizeof(struct sis_list_data) + 8,
- M_DEVBUF, M_NOWAIT);
- if (sc->sis_ldata_ptr == NULL) {
- printf("%s: no memory for list buffers!\n", sc->sis_unit);
- goto fail;
- }
+ sc->sc_dmat = pa->pa_dmat;
- sc->sis_ldata = (struct sis_list_data *)sc->sis_ldata_ptr;
+ if (bus_dmamem_alloc(sc->sc_dmat, sizeof(struct sis_list_data),
+ PAGE_SIZE, 0, sc->sc_listseg, 1, &sc->sc_listnseg,
+ BUS_DMA_NOWAIT) != 0) {
+ printf(": can't alloc list mem\n");
+ return;
+ }
+ if (bus_dmamem_map(sc->sc_dmat, sc->sc_listseg, sc->sc_listnseg,
+ sizeof(struct sis_list_data), &sc->sc_listkva,
+ BUS_DMA_NOWAIT) != 0) {
+ printf(": can't map list mem\n");
+ return;
+ }
+ if (bus_dmamap_create(sc->sc_dmat, sizeof(struct sis_list_data), 1,
+ sizeof(struct sis_list_data), 0, BUS_DMA_NOWAIT,
+ &sc->sc_listmap) != 0) {
+ printf(": can't alloc list map\n");
+ return;
+ }
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_listmap, sc->sc_listkva,
+ sizeof(struct sis_list_data), NULL, BUS_DMA_NOWAIT) != 0) {
+ printf(": can't load list map\n");
+ return;
+ }
+ sc->sis_ldata = (struct sis_list_data *)sc->sc_listkva;
bzero(sc->sis_ldata, sizeof(struct sis_list_data));
+ for (i = 0; i < SIS_RX_LIST_CNT; i++) {
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
+ BUS_DMA_NOWAIT, &sc->sis_ldata->sis_rx_list[i].map) != 0) {
+ printf(": can't create rx map\n");
+ return;
+ }
+ }
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, 1, MCLBYTES, 0,
+ BUS_DMA_NOWAIT, &sc->sc_rx_sparemap) != 0) {
+ printf(": can't create rx spare map\n");
+ return;
+ }
+
+ for (i = 0; i < SIS_TX_LIST_CNT; i++) {
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES,
+ SIS_TX_LIST_CNT - 3, MCLBYTES, 0, BUS_DMA_NOWAIT,
+ &sc->sis_ldata->sis_tx_list[i].map) != 0) {
+ printf(": can't create tx map\n");
+ return;
+ }
+ }
+ if (bus_dmamap_create(sc->sc_dmat, MCLBYTES, SIS_TX_LIST_CNT - 3,
+ MCLBYTES, 0, BUS_DMA_NOWAIT, &sc->sc_tx_sparemap) != 0) {
+ printf(": can't create tx spare map\n");
+ return;
+ }
+
ifp = &sc->arpcom.ac_if;
ifp->if_softc = sc;
ifp->if_mtu = ETHERMTU;
@@ -892,17 +935,26 @@ int sis_list_tx_init(sc)
{
struct sis_list_data *ld;
struct sis_ring_data *cd;
- int i, nexti;
+ int i;
+ bus_addr_t next;
cd = &sc->sis_cdata;
ld = sc->sis_ldata;
for (i = 0; i < SIS_TX_LIST_CNT; i++) {
- nexti = (i == (SIS_TX_LIST_CNT - 1)) ? 0 : i+1;
- ld->sis_tx_list[i].sis_nextdesc =
- &ld->sis_tx_list[nexti];
- ld->sis_tx_list[i].sis_next =
- vtophys(&ld->sis_tx_list[nexti]);
+ next = sc->sc_listmap->dm_segs[0].ds_addr;
+ if (i == (SIS_TX_LIST_CNT - 1)) {
+ ld->sis_tx_list[i].sis_nextdesc =
+ &ld->sis_tx_list[0];
+ next +=
+ offsetof(struct sis_list_data, sis_tx_list[0]);
+ } else {
+ ld->sis_tx_list[i].sis_nextdesc =
+ &ld->sis_tx_list[i+1];
+ next +=
+ offsetof(struct sis_list_data, sis_tx_list[i+1]);
+ }
+ ld->sis_tx_list[i].sis_next = next;
ld->sis_tx_list[i].sis_mbuf = NULL;
ld->sis_tx_list[i].sis_ptr = 0;
ld->sis_tx_list[i].sis_ctl = 0;
@@ -924,7 +976,8 @@ int sis_list_rx_init(sc)
{
struct sis_list_data *ld;
struct sis_ring_data *cd;
- int i, nexti;
+ int i;
+ bus_addr_t next;
ld = sc->sis_ldata;
cd = &sc->sis_cdata;
@@ -932,11 +985,17 @@ int sis_list_rx_init(sc)
for (i = 0; i < SIS_RX_LIST_CNT; i++) {
if (sis_newbuf(sc, &ld->sis_rx_list[i], NULL) == ENOBUFS)
return(ENOBUFS);
- nexti = (i == (SIS_RX_LIST_CNT - 1)) ? 0 : i+1;
- ld->sis_rx_list[i].sis_nextdesc =
- &ld->sis_rx_list[nexti];
- ld->sis_rx_list[i].sis_next =
- vtophys(&ld->sis_rx_list[nexti]);
+ next = sc->sc_listmap->dm_segs[0].ds_addr;
+ if (i == (SIS_RX_LIST_CNT - 1)) {
+ ld->sis_rx_list[i].sis_nextdesc = &ld->sis_rx_list[0];
+ next +=
+ offsetof(struct sis_list_data, sis_rx_list[0]);
+ } else {
+ ld->sis_rx_list[i].sis_nextdesc = &ld->sis_rx_list[i+1];
+ next +=
+ offsetof(struct sis_list_data, sis_rx_list[i+1]);
+ }
+ ld->sis_rx_list[i].sis_next = next;
}
cd->sis_rx_prod = 0;
@@ -953,6 +1012,7 @@ int sis_newbuf(sc, c, m)
struct mbuf *m;
{
struct mbuf *m_new = NULL;
+ bus_dmamap_t map;
if (m == NULL) {
MGETHDR(m_new, M_DONTWAIT, MT_DATA);
@@ -976,12 +1036,29 @@ int sis_newbuf(sc, c, m)
m_new->m_data = m_new->m_ext.ext_buf;
}
+ if (bus_dmamap_load(sc->sc_dmat, sc->sc_rx_sparemap,
+ mtod(m_new, caddr_t), MCLBYTES, NULL, BUS_DMA_NOWAIT) != 0) {
+ printf("%s: rx load failed\n", sc->sc_dev.dv_xname);
+ m_freem(m_new);
+ return (ENOBUFS);
+ }
+ map = c->map;
+ c->map = sc->sc_rx_sparemap;
+ sc->sc_rx_sparemap = map;
+
+ bus_dmamap_sync(sc->sc_dmat, c->map, 0, c->map->dm_mapsize,
+ BUS_DMASYNC_PREREAD);
+
m_adj(m_new, sizeof(u_int64_t));
c->sis_mbuf = m_new;
- c->sis_ptr = vtophys(mtod(m_new, caddr_t));
+ c->sis_ptr = c->map->dm_segs[0].ds_addr + sizeof(u_int64_t);
c->sis_ctl = SIS_RXLEN;
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ ((caddr_t)c->sis_ptr - sc->sc_listkva), sizeof(struct sis_desc),
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
return(0);
}
@@ -1010,6 +1087,11 @@ void sis_rxeof(sc)
total_len = SIS_RXBYTES(cur_rx);
SIS_INC(i, SIS_RX_LIST_CNT);
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ ((caddr_t)cur_rx->sis_ptr - sc->sc_listkva),
+ sizeof(struct sis_desc),
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
/*
* If an error occurs, update stats, clear the
* status word and leave the mbuf cluster in place:
@@ -1025,6 +1107,8 @@ void sis_rxeof(sc)
}
/* No errors; receive the packet. */
+ bus_dmamap_sync(sc->sc_dmat, cur_rx->map, 0,
+ cur_rx->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
#ifndef __STRICT_ALIGNMENT
/*
* On some architectures, we do not have alignment problems,
@@ -1102,6 +1186,11 @@ void sis_txeof(sc)
while (idx != sc->sis_cdata.sis_tx_prod) {
cur_tx = &sc->sis_ldata->sis_tx_list[idx];
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ ((caddr_t)cur_tx->sis_ptr - sc->sc_listkva),
+ sizeof(struct sis_desc),
+ BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
+
if (SIS_OWNDESC(cur_tx))
break;
@@ -1123,6 +1212,13 @@ void sis_txeof(sc)
(cur_tx->sis_txstat & SIS_TXSTAT_COLLCNT) >> 16;
ifp->if_opackets++;
+ if (cur_tx->map->dm_nsegs != 0) {
+ bus_dmamap_t map = cur_tx->map;
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
if (cur_tx->sis_mbuf != NULL) {
m_freem(cur_tx->sis_mbuf);
cur_tx->sis_mbuf = NULL;
@@ -1241,42 +1337,47 @@ int sis_encap(sc, m_head, txidx)
u_int32_t *txidx;
{
struct sis_desc *f = NULL;
- struct mbuf *m;
- int frag, cur, cnt = 0;
+ int frag, cur, i;
+ bus_dmamap_t map;
+
+ map = sc->sc_tx_sparemap;
+ if (bus_dmamap_load_mbuf(sc->sc_dmat, map,
+ m_head, BUS_DMA_NOWAIT) != 0)
+ return (ENOBUFS);
/*
* 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;
cur = frag = *txidx;
- for (m = m_head; m != NULL; m = m->m_next) {
- if (m->m_len != 0) {
- if ((SIS_TX_LIST_CNT -
- (sc->sis_cdata.sis_tx_cnt + cnt)) < 2)
- return(ENOBUFS);
- f = &sc->sis_ldata->sis_tx_list[frag];
- f->sis_ctl = SIS_CMDSTS_MORE | m->m_len;
- f->sis_ptr = vtophys(mtod(m, vm_offset_t));
- if (cnt != 0)
- f->sis_ctl |= SIS_CMDSTS_OWN;
- cur = frag;
- SIS_INC(frag, SIS_TX_LIST_CNT);
- cnt++;
- }
+ for (i = 0; i < map->dm_nsegs; i++) {
+ if ((SIS_TX_LIST_CNT - (sc->sis_cdata.sis_tx_cnt + i)) < 2)
+ return(ENOBUFS);
+ f = &sc->sis_ldata->sis_tx_list[frag];
+ f->sis_ctl = SIS_CMDSTS_MORE | map->dm_segs[i].ds_len;
+ f->sis_ptr = map->dm_segs[i].ds_addr;
+ if (i != 0)
+ f->sis_ctl |= SIS_CMDSTS_OWN;
+ cur = frag;
+ SIS_INC(frag, SIS_TX_LIST_CNT);
}
- if (m != NULL)
- return(ENOBUFS);
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_PREWRITE);
sc->sis_ldata->sis_tx_list[cur].sis_mbuf = m_head;
sc->sis_ldata->sis_tx_list[cur].sis_ctl &= ~SIS_CMDSTS_MORE;
sc->sis_ldata->sis_tx_list[*txidx].sis_ctl |= SIS_CMDSTS_OWN;
- sc->sis_cdata.sis_tx_cnt += cnt;
+ sc->sis_cdata.sis_tx_cnt += i - 1;
*txidx = frag;
+ bus_dmamap_sync(sc->sc_dmat, sc->sc_listmap,
+ offsetof(struct sis_list_data, sis_tx_list[0]),
+ sizeof(struct sis_desc) * SIS_TX_LIST_CNT,
+ BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
+
return(0);
}
@@ -1436,10 +1537,10 @@ void sis_init(xsc)
/*
* Load the address of the RX and TX lists.
*/
- CSR_WRITE_4(sc, SIS_RX_LISTPTR,
- vtophys(&sc->sis_ldata->sis_rx_list[0]));
- CSR_WRITE_4(sc, SIS_TX_LISTPTR,
- vtophys(&sc->sis_ldata->sis_tx_list[0]));
+ CSR_WRITE_4(sc, SIS_RX_LISTPTR, sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct sis_list_data, sis_rx_list[0]));
+ CSR_WRITE_4(sc, SIS_TX_LISTPTR, sc->sc_listmap->dm_segs[0].ds_addr +
+ offsetof(struct sis_list_data, sis_tx_list[0]));
/* Set RX configuration */
CSR_WRITE_4(sc, SIS_RX_CFG, SIS_RXCFG);
@@ -1670,27 +1771,40 @@ void sis_stop(sc)
* Free data in the RX lists.
*/
for (i = 0; i < SIS_RX_LIST_CNT; i++) {
+ if (sc->sis_ldata->sis_rx_list[i].map->dm_nsegs != 0) {
+ bus_dmamap_t map = sc->sis_ldata->sis_rx_list[i].map;
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTREAD);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
if (sc->sis_ldata->sis_rx_list[i].sis_mbuf != NULL) {
m_freem(sc->sis_ldata->sis_rx_list[i].sis_mbuf);
sc->sis_ldata->sis_rx_list[i].sis_mbuf = NULL;
}
+ bzero((char *)&sc->sis_ldata->sis_rx_list[i],
+ sizeof(struct sis_desc) - sizeof(bus_dmamap_t));
}
- bzero((char *)&sc->sis_ldata->sis_rx_list,
- sizeof(sc->sis_ldata->sis_rx_list));
/*
* Free the TX list buffers.
*/
for (i = 0; i < SIS_TX_LIST_CNT; i++) {
+ if (sc->sis_ldata->sis_tx_list[i].map->dm_nsegs != 0) {
+ bus_dmamap_t map = sc->sis_ldata->sis_tx_list[i].map;
+
+ bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(sc->sc_dmat, map);
+ }
if (sc->sis_ldata->sis_tx_list[i].sis_mbuf != NULL) {
m_freem(sc->sis_ldata->sis_tx_list[i].sis_mbuf);
sc->sis_ldata->sis_tx_list[i].sis_mbuf = NULL;
}
+ bzero((char *)&sc->sis_ldata->sis_tx_list[i],
+ sizeof(struct sis_desc) - sizeof(bus_dmamap_t));
}
- bzero((char *)&sc->sis_ldata->sis_tx_list,
- sizeof(sc->sis_ldata->sis_tx_list));
-
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
return;
diff --git a/sys/dev/pci/if_sisreg.h b/sys/dev/pci/if_sisreg.h
index 4c2be26037f..8eb9711a478 100644
--- a/sys/dev/pci/if_sisreg.h
+++ b/sys/dev/pci/if_sisreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_sisreg.h,v 1.9 2002/03/25 20:28:06 mickey Exp $ */
+/* $OpenBSD: if_sisreg.h,v 1.10 2002/07/02 16:44:25 aaron Exp $ */
/*
* Copyright (c) 1997, 1998, 1999
* Bill Paul <wpaul@ee.columbia.edu>. All rights reserved.
@@ -297,6 +297,7 @@ struct sis_desc {
/* Driver software section */
struct mbuf *sis_mbuf;
struct sis_desc *sis_nextdesc;
+ bus_dmamap_t map;
};
#define SIS_CMDSTS_BUFLEN 0x00000FFF
@@ -393,9 +394,15 @@ struct sis_softc {
u_int8_t sis_type;
u_int8_t sis_link;
struct sis_list_data *sis_ldata;
- caddr_t sis_ldata_ptr;
struct sis_ring_data sis_cdata;
struct timeout sis_timeout;
+ bus_dma_tag_t sc_dmat;
+ bus_dmamap_t sc_listmap;
+ bus_dma_segment_t sc_listseg[1];
+ int sc_listnseg;
+ caddr_t sc_listkva;
+ bus_dmamap_t sc_rx_sparemap;
+ bus_dmamap_t sc_tx_sparemap;
};
/*
@@ -449,8 +456,3 @@ struct sis_softc {
#define SIS_PSTATE_D3 0x0003
#define SIS_PME_EN 0x0010
#define SIS_PME_STATUS 0x8000
-
-#ifdef __alpha__
-#undef vtophys
-#define vtophys(va) alpha_XXX_dmamap((vm_offset_t)va)
-#endif