A version of the de driver which does bus_dma. Note that it has not been

tested on any other platform other than i386.  Use of bus_dma(9) can be
turned by defining TULIP_BUS_DMA_NOTX and TULIP_BUS_DMA_NORX.  These allow
one to determine if the problem is in the transmit or receive path.
A problem reported by mycroft is also fixed.
This commit is contained in:
matt 1998-02-06 20:57:12 +00:00
parent a66f53e128
commit 8098a443f0
2 changed files with 494 additions and 16 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_de.c,v 1.58 1998/01/12 09:39:58 thorpej Exp $ */
/* $NetBSD: if_de.c,v 1.59 1998/02/06 20:57:12 matt Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -437,8 +437,8 @@ tulip_linkup(
* No reason to change media if we have the right media.
*/
tulip_reset(sc);
tulip_init(sc);
}
tulip_init(sc);
}
static void
@ -2242,8 +2242,13 @@ tulip_identify_cogent_nic(
strcpy(sc->tulip_boardid, "Cogent ");
if (sc->tulip_chipid == TULIP_21140 || sc->tulip_chipid == TULIP_21140A) {
if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100TX_ID) {
strcat(sc->tulip_boardid, "EM100FX ");
strcat(sc->tulip_boardid, "EM100TX ");
sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
#if defined(TULIP_COGENT_EM110TX_ID)
} else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM110TX_ID) {
strcat(sc->tulip_boardid, "EM110TX ");
sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
#endif
} else if (sc->tulip_rombuf[32] == TULIP_COGENT_EM100FX_ID) {
strcat(sc->tulip_boardid, "EM100FX ");
sc->tulip_boardsw = &tulip_21140_cogent_em100_boardsw;
@ -3160,8 +3165,16 @@ tulip_reset(
sc->tulip_if.if_flags &= ~IFF_OACTIVE;
}
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txdescmap->dm_segs[0].ds_addr);
#else
TULIP_CSR_WRITE(sc, csr_txlist, TULIP_KVATOPHYS(sc, &sc->tulip_txinfo.ri_first[0]));
#endif
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxdescmap->dm_segs[0].ds_addr);
#else
TULIP_CSR_WRITE(sc, csr_rxlist, TULIP_KVATOPHYS(sc, &sc->tulip_rxinfo.ri_first[0]));
#endif
TULIP_CSR_WRITE(sc, csr_busmode,
(1 << (TULIP_BURSTSIZE(sc->tulip_unit) + 8))
|TULIP_BUSMODE_CACHE_ALIGN8
@ -3174,10 +3187,22 @@ tulip_reset(
* Free all the mbufs that were on the transmit ring.
*/
for (;;) {
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t map;
#endif
struct mbuf *m;
IF_DEQUEUE(&sc->tulip_txq, m);
if (m == NULL)
break;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
map = M_GETCTX(m, bus_dmamap_t);
bus_dmamap_unload(sc->tulip_dmatag, map);
if (sc->tulip_txmaps_free < TULIP_TXQ_TARGET) {
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
} else {
bus_dmamap_destroy(sc->tulip_dmatag, map);
}
#endif
m_freem(m);
}
@ -3186,6 +3211,11 @@ tulip_reset(
ri->ri_free = ri->ri_max;
for (di = ri->ri_first; di < ri->ri_last; di++)
di->d_status = 0;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_txdescmap,
0, sc->tulip_txdescmap->dm_mapsize,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#endif
/*
* We need to collect all the mbufs were on the
@ -3201,11 +3231,28 @@ tulip_reset(
di->d_length1 = 0; di->d_addr1 = 0;
di->d_length2 = 0; di->d_addr2 = 0;
}
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
bus_dmamap_sync(sc->tulip_dmatag, sc->tulip_rxdescmap,
0, sc->tulip_rxdescmap->dm_mapsize,
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
#endif
for (;;) {
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
bus_dmamap_t map;
#endif
struct mbuf *m;
IF_DEQUEUE(&sc->tulip_rxq, m);
if (m == NULL)
break;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
map = M_GETCTX(m, bus_dmamap_t);
bus_dmamap_unload(sc->tulip_dmatag, map);
if (sc->tulip_rxmaps_free < TULIP_RXQ_TARGET) {
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
} else {
bus_dmamap_destroy(sc->tulip_dmatag, map);
}
#endif
m_freem(m);
}
@ -3300,6 +3347,9 @@ tulip_rx_intr(
int total_len = 0, last_offset = 0;
struct mbuf *ms = NULL, *me = NULL;
int accept = 0;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
bus_dmamap_t map;
#endif
if (fillok && sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET)
goto queue_mbuf;
@ -3314,11 +3364,12 @@ tulip_rx_intr(
*/
if (eop == ri->ri_nextout)
break;
/*
* 90% of the packets will fit in one descriptor. So we optimize
* for that case.
*/
TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
if ((((volatile tulip_desc_t *) eop)->d_status & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) {
IF_DEQUEUE(&sc->tulip_rxq, ms);
me = ms;
@ -3337,6 +3388,7 @@ tulip_rx_intr(
while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) {
if (++eop == ri->ri_last)
eop = ri->ri_first;
TULIP_RXDESC_POSTSYNC(sc, eop, sizeof(*eop));
if (eop == ri->ri_nextout || ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER))) {
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_rxintrs++;
@ -3361,6 +3413,19 @@ tulip_rx_intr(
*/
IF_DEQUEUE(&sc->tulip_rxq, ms);
for (me = ms; total_len > 0; total_len--) {
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
map = M_GETCTX(me, bus_dmamap_t);
TULIP_RXMAP_POSTSYNC(sc, map);
bus_dmamap_unload(sc->tulip_dmatag, map);
if (sc->tulip_rxmaps_free < TULIP_RXDESCS) {
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
} else {
bus_dmamap_destroy(sc->tulip_dmatag, map);
}
#if defined(DIAGNOSTIC)
M_SETCTX(me, NULL);
#endif
#endif /* TULIP_BUS_DMA */
me->m_len = TULIP_RX_BUFLEN;
last_offset += TULIP_RX_BUFLEN;
IF_DEQUEUE(&sc->tulip_rxq, me->m_next);
@ -3382,6 +3447,22 @@ tulip_rx_intr(
#endif
)) {
me->m_len = total_len - last_offset;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
map = M_GETCTX(me, bus_dmamap_t);
bus_dmamap_sync(sc->tulip_dmatag, map, 0, me->m_len,
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(sc->tulip_dmatag, map);
if (sc->tulip_rxmaps_free < TULIP_RXDESCS) {
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
} else {
bus_dmamap_destroy(sc->tulip_dmatag, map);
}
#if defined(DIAGNOSTIC)
M_SETCTX(me, NULL);
#endif
#endif /* TULIP_BUS_DMA */
eh = *mtod(ms, struct ether_header *);
#if NBPFILTER > 0
if (sc->tulip_bpf != NULL)
@ -3402,20 +3483,29 @@ tulip_rx_intr(
if (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxOVERFLOW|TULIP_DSTS_RxWATCHDOG)) {
sc->tulip_dot3stats.dot3StatsInternalMacReceiveErrors++;
} else {
#if defined(TULIP_VERBOSE)
const char *error = NULL;
#endif
if (eop->d_status & TULIP_DSTS_RxTOOLONG) {
sc->tulip_dot3stats.dot3StatsFrameTooLongs++;
#if defined(TULIP_VERBOSE)
error = "frame too long";
#endif
}
if (eop->d_status & TULIP_DSTS_RxBADCRC) {
if (eop->d_status & TULIP_DSTS_RxDRBBLBIT) {
sc->tulip_dot3stats.dot3StatsAlignmentErrors++;
#if defined(TULIP_VERBOSE)
error = "alignment error";
#endif
} else {
sc->tulip_dot3stats.dot3StatsFCSErrors++;
#if defined(TULIP_VERBOSE)
error = "bad crc";
#endif
}
}
#if defined(TULIP_VERBOSE)
if (error != NULL && (sc->tulip_flags & TULIP_NOMESSAGES) == 0) {
printf(TULIP_PRINTF_FMT ": receive: " TULIP_EADDR_FMT ": %s\n",
TULIP_PRINTF_ARGS,
@ -3423,6 +3513,7 @@ tulip_rx_intr(
error);
sc->tulip_flags |= TULIP_NOMESSAGES;
}
#endif
}
}
next:
@ -3512,9 +3603,39 @@ tulip_rx_intr(
* receive queue.
*/
do {
ri->ri_nextout->d_length1 = TULIP_RX_BUFLEN;
ri->ri_nextout->d_addr1 = TULIP_KVATOPHYS(sc, mtod(ms, caddr_t));
ri->ri_nextout->d_status = TULIP_DSTS_OWNER;
tulip_desc_t * const nextout = ri->ri_nextout;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
if (sc->tulip_rxmaps_free > 0) {
map = sc->tulip_rxmaps[--sc->tulip_rxmaps_free];
} else {
if (TULIP_RXMAP_CREATE(sc, &map) != 0) {
m_freem(ms);
sc->tulip_flags |= TULIP_RXBUFSLOW;
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_rxlowbufs++;
#endif
break;
}
}
M_SETCTX(ms, map);
bus_dmamap_load(sc->tulip_dmatag, map, mtod(ms, void *),
TULIP_RX_BUFLEN, NULL, BUS_DMA_NOWAIT);
nextout->d_addr1 = map->dm_segs[0].ds_addr;
nextout->d_length1 = map->dm_segs[0].ds_len;
if (map->dm_nsegs == 2) {
nextout->d_addr2 = map->dm_segs[1].ds_addr;
nextout->d_length2 = map->dm_segs[1].ds_len;
} else {
nextout->d_addr2 = 0;
nextout->d_length2 = 0;
}
TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(*nextout));
#else /* TULIP_BUS_DMA */
nextout->d_addr1 = TULIP_KVATOPHYS(sc, mtod(ms, caddr_t));
nextout->d_length1 = TULIP_RX_BUFLEN;
#endif /* TULIP_BUS_DMA */
nextout->d_status = TULIP_DSTS_OWNER;
TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t));
if (++ri->ri_nextout == ri->ri_last)
ri->ri_nextout = ri->ri_first;
me = ms->m_next;
@ -3527,6 +3648,17 @@ tulip_rx_intr(
TULIP_PERFEND(rxget);
}
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
/*
* Free any excess dmamaps
*/
while (sc->tulip_rxmaps_free > TULIP_RXQ_TARGET) {
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_rxmaps[--sc->tulip_rxmaps_free]);
}
#endif
#if defined(TULIP_DEBUG)
sc->tulip_dbg.dbg_rxintrs++;
sc->tulip_dbg.dbg_rxpktsperintr[cnt]++;
@ -3546,6 +3678,8 @@ tulip_tx_intr(
while (ri->ri_free < ri->ri_max) {
u_int32_t d_flag;
TULIP_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin));
if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER)
break;
@ -3559,6 +3693,7 @@ tulip_tx_intr(
* Make sure we ack the RXSTOPPED so we won't get
* an abormal interrupt indication.
*/
TULIP_TXMAP_POSTSYNC(sc, sc->tulip_setupmap);
sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_HASHONLY);
if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxINVRSFILT)
sc->tulip_flags |= TULIP_HASHONLY;
@ -3574,6 +3709,15 @@ tulip_tx_intr(
const u_int32_t d_status = ri->ri_nextin->d_status;
IF_DEQUEUE(&sc->tulip_txq, m);
if (m != NULL) {
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t map = M_GETCTX(m, bus_dmamap_t);
TULIP_TXMAP_POSTSYNC(sc, map);
if (sc->tulip_txmaps_free < TULIP_TXQ_HIGHWATER) {
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
} else {
bus_dmamap_destroy(sc->tulip_dmatag, map);
}
#endif /* TULIP_BUS_DMA */
#if NBPFILTER > 0
if (sc->tulip_bpf != NULL)
TULIP_BPF_MTAP(sc, m);
@ -4025,7 +4169,11 @@ tulip_txput(
tulip_desc_t *eop, *nextout;
int segcnt, free;
u_int32_t d_status;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t map;
#else
struct mbuf *m0;
#endif
#if defined(TULIP_DEBUG)
if ((sc->tulip_cmdmode & TULIP_CMD_TXRUN) == 0) {
@ -4054,12 +4202,79 @@ tulip_txput(
* case we will just wait for the ring to empty. In the
* latter case we have to recopy.
*/
#if !defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NOTX)
m0 = m;
again:
#endif
d_status = 0;
eop = nextout = ri->ri_nextout;
m0 = m;
segcnt = 0;
free = ri->ri_free;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
if (sc->tulip_txmaps_free > 0) {
map = sc->tulip_txmaps[--sc->tulip_txmaps_free];
} else if (TULIP_TXMAP_CREATE(sc, &map) != 0) {
sc->tulip_flags |= TULIP_WANTTXSTART;
goto finish;
}
if (bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT)
|| map->dm_nsegs > TULIP_MAX_TXSEG) {
/*
* The packet exceeds the number of transmit buffer
* entries that we can use for one packet, so we have
* recopy it into one mbuf and then try again.
*/
if (map->dm_nsegs > 0)
bus_dmamap_unload(sc->tulip_dmatag, map);
m = tulip_mbuf_compress(m);
if (m == NULL)
goto finish;
bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT);
}
if ((free -= (map->dm_nsegs + 1) / 2) <= 0
/*
* See if there's any unclaimed space in the transmit ring.
*/
|| (free += tulip_tx_intr(sc)) <= 0) {
/*
* There's no more room but since nothing
* has been committed at this point, just
* show output is active, put back the
* mbuf and return.
*/
sc->tulip_flags |= TULIP_WANTTXSTART;
goto finish;
}
for (; map->dm_nsegs - segcnt > 1; segcnt += 2) {
eop = nextout;
eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
eop->d_status = d_status;
eop->d_addr1 = map->dm_segs[segcnt].ds_addr;
eop->d_length1 = map->dm_segs[segcnt].ds_len;
eop->d_addr2 = map->dm_segs[segcnt+1].ds_addr;
eop->d_length2 = map->dm_segs[segcnt+1].ds_len;
d_status = TULIP_DSTS_OWNER;
if (++nextout == ri->ri_last)
nextout = ri->ri_first;
}
if (segcnt < map->dm_nsegs) {
eop = nextout;
eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN;
eop->d_status = d_status;
eop->d_addr1 = map->dm_segs[segcnt].ds_addr;
eop->d_length1 = map->dm_segs[segcnt].ds_len;
eop->d_addr2 = 0;
eop->d_length2 = 0;
if (++nextout == ri->ri_last)
nextout = ri->ri_first;
}
TULIP_TXMAP_PRESYNC(sc, map);
M_SETCTX(m, map);
map = NULL;
#else /* !TULIP_BUS_DMA */
do {
int len = m0->m_len;
caddr_t addr = mtod(m0, caddr_t);
@ -4125,7 +4340,7 @@ tulip_txput(
clsize = CLBYTES;
}
} while ((m0 = m0->m_next) != NULL);
#endif /* TULIP_BUS_DMA */
/*
* The descriptors have been filled in. Now get ready
@ -4140,7 +4355,9 @@ tulip_txput(
* of room in the ring.
*/
nextout->d_status = 0;
TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
#if !defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NOTX)
/*
* If we only used the first segment of the last descriptor,
* make sure the second segment will not be used.
@ -4149,6 +4366,7 @@ tulip_txput(
eop->d_addr2 = 0;
eop->d_length2 = 0;
}
#endif /* TULIP_BUS_DMA */
/*
* Mark the last and first segments, indicate we want a transmit
@ -4162,7 +4380,19 @@ tulip_txput(
* everything we have done.
*/
ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG;
#if defined(TULIP_BUS_MAP) && !defined(TULIP_BUS_DMA_NOTX)
if (eop < ri->ri_nextout) {
TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
(caddr_t) ri->ri_last - (caddr_t) ri->ri_nextout);
TULIP_TXDESC_PRESYNC(sc, ri->ri_first,
(caddr_t) (eop + 1) - (caddr_t) ri->ri_first);
} else {
TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout,
(caddr_t) (eop + 1) - (caddr_t) ri->ri_nextout);
}
#endif
ri->ri_nextout->d_status = TULIP_DSTS_OWNER;
TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
TULIP_CSR_WRITE(sc, csr_txpoll, 1);
@ -4262,10 +4492,21 @@ tulip_txput_setup(
else if (sc->tulip_flags & TULIP_WANTHASHONLY)
nextout->d_flag |= TULIP_DFLAG_TxHASHFILT|TULIP_DFLAG_TxINVRSFILT;
nextout->d_length1 = sizeof(sc->tulip_setupbuf);
nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf);
nextout->d_length2 = 0;
nextout->d_addr2 = 0;
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
nextout->d_length1 = sc->tulip_setupmap->dm_segs[0].ds_len;
nextout->d_addr1 = sc->tulip_setupmap->dm_segs[0].ds_addr;
if (sc->tulip_setupmap->dm_nsegs == 2) {
nextout->d_length2 = sc->tulip_setupmap->dm_segs[1].ds_len;
nextout->d_addr2 = sc->tulip_setupmap->dm_segs[1].ds_addr;
}
TULIP_TXMAP_PRESYNC(sc, sc->tulip_setupmap);
TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(*nextout));
#else
nextout->d_length1 = sizeof(sc->tulip_setupbuf);
nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf);
#endif
/*
* Advance the ring for the next transmit packet.
@ -4279,7 +4520,12 @@ tulip_txput_setup(
* ring.
*/
ri->ri_nextout->d_status = 0;
TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t));
nextout->d_status = TULIP_DSTS_OWNER;
/*
* Flush the ownwership of the current descriptor
*/
TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t));
TULIP_CSR_WRITE(sc, csr_txpoll, 1);
if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) {
sc->tulip_intrmask |= TULIP_STS_TXINTR;
@ -4571,6 +4817,17 @@ tulip_ifwatchdog(
tulip_init(sc);
}
#if defined(TULIP_BUS_DMA) & !defined(TULIP_BUS_DMA_NOTX)
/*
* If we had a sudden increase in transmit dmamaps,
* free them slowly...
*/
if (sc->tulip_txmaps_free > TULIP_TXQ_TARGET) {
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_txmaps[--sc->tulip_txmaps_free]);
}
#endif
TULIP_PERFEND(ifwatchdog);
TULIP_PERFMERGE(sc, perf_intr_cycles);
TULIP_PERFMERGE(sc, perf_ifstart_cycles);
@ -4721,6 +4978,135 @@ tulip_attach(
#endif
}
#if defined(TULIP_BUS_DMA)
#if !defined(TULIP_BUS_DMA_NOTX) || !defined(TULIP_BUS_DMA_NORX)
static int
tulip_busdma_allocmem(
tulip_softc_t * const sc,
size_t size,
bus_dmamap_t *map_p,
tulip_desc_t **desc_p)
{
bus_dma_segment_t segs[1];
int nsegs, error;
error = bus_dmamem_alloc(sc->tulip_dmatag, size, 1, CLBYTES,
segs, sizeof(segs)/sizeof(segs[0]),
&nsegs, BUS_DMA_NOWAIT);
if (error == 0) {
void *desc;
error = bus_dmamem_map(sc->tulip_dmatag, segs, nsegs, size,
(void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT);
if (error == 0) {
bus_dmamap_t map;
error = bus_dmamap_create(sc->tulip_dmatag, size, 1, size, 0,
BUS_DMA_ALLOCNOW, &map);
if (error == 0) {
error = bus_dmamap_load(sc->tulip_dmatag, map, desc,
size, NULL, BUS_DMA_NOWAIT);
if (error)
bus_dmamap_destroy(sc->tulip_dmatag, map);
else
*map_p = map;
}
if (error)
bus_dmamem_unmap(sc->tulip_dmatag, desc, size);
}
if (error)
bus_dmamem_free(sc->tulip_dmatag, segs, nsegs);
else
*desc_p = desc;
}
return error;
}
#endif
static int
tulip_busdma_init(
tulip_softc_t * const sc)
{
int error = 0;
#if !defined(TULIP_BUS_DMA_NOTX)
/*
* Allocate dmamap for setup descriptor
*/
error = bus_dmamap_create(sc->tulip_dmatag, sizeof(sc->tulip_setupbuf), 2,
sizeof(sc->tulip_setupbuf), 0, BUS_DMA_ALLOCNOW,
&sc->tulip_setupmap);
if (error == 0) {
error = bus_dmamap_load(sc->tulip_dmatag, sc->tulip_setupmap,
sc->tulip_setupbuf, sizeof(sc->tulip_setupbuf),
NULL, BUS_DMA_NOWAIT);
if (error)
bus_dmamap_destroy(sc->tulip_dmatag, sc->tulip_setupmap);
}
/*
* Allocate space and dmamap for transmit ring
*/
if (error == 0) {
error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_TXDESCS,
&sc->tulip_txdescmap,
&sc->tulip_txdescs);
}
/*
* Allocate dmamaps for each transmit descriptors
*/
if (error == 0) {
while (error == 0 && sc->tulip_txmaps_free < TULIP_TXQ_TARGET) {
bus_dmamap_t map;
if ((error = TULIP_TXMAP_CREATE(sc, &map)) == 0)
sc->tulip_txmaps[sc->tulip_txmaps_free++] = map;
}
if (error) {
while (sc->tulip_txmaps_free > 0)
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_txmaps[--sc->tulip_txmaps_free]);
}
}
#else
if (error == 0) {
sc->tulip_txdescs = (tulip_desc_t *) malloc(TULIP_TXDESCS * sizeof(tulip_desc_t), M_DEVBUF, M_NOWAIT);
if (sc->tulip_txdescs == NULL)
error = ENOMEM;
}
#endif
#if !defined(TULIP_BUS_DMA_NORX)
/*
* Allocate space and dmamap for receive ring
*/
if (error == 0) {
error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_RXDESCS,
&sc->tulip_rxdescmap,
&sc->tulip_rxdescs);
}
/*
* Allocate dmamaps for each receive descriptors
*/
if (error == 0) {
while (error == 0 && sc->tulip_rxmaps_free < TULIP_RXQ_TARGET) {
bus_dmamap_t map;
if ((error = TULIP_RXMAP_CREATE(sc, &map)) == 0)
sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map;
}
if (error) {
while (sc->tulip_rxmaps_free > 0)
bus_dmamap_destroy(sc->tulip_dmatag,
sc->tulip_rxmaps[--sc->tulip_rxmaps_free]);
}
}
#else
if (error == 0) {
sc->tulip_rxdescs = (tulip_desc_t *) malloc(TULIP_RXDESCS * sizeof(tulip_desc_t), M_DEVBUF, M_NOWAIT);
if (sc->tulip_rxdescs == NULL)
error = ENOMEM;
}
#endif
return error;
}
#endif /* TULIP_BUS_DMA */
static void
tulip_initcsrs(
tulip_softc_t * const sc,
@ -5198,6 +5584,9 @@ tulip_pci_attach(
bcopy(self->dv_xname, sc->tulip_if.if_xname, IFNAMSIZ);
sc->tulip_if.if_softc = sc;
sc->tulip_pc = pa->pa_pc;
#if defined(TULIP_BUS_DMA)
sc->tulip_dmatag = pa->pa_dmat;
#endif
#else
sc->tulip_unit = unit;
sc->tulip_name = "de";
@ -5255,6 +5644,17 @@ tulip_pci_attach(
#endif /* __NetBSD__ */
tulip_initcsrs(sc, csr_base + csroffset, csrsize);
#if defined(TULIP_BUS_DMA)
if ((retval = tulip_busdma_init(sc)) != 0) {
printf("error initing bus_dma: %d\n", retval);
return;
}
#else
sc->tulip_txdescs = (tulip_desc_t *) malloc((TULIP_TXDESCS+TULIP_RXDESCS)*sizeof(tulip_desc_t), M_DEVBUF, M_WAITOK);
sc->tulip_rxdescs = sc->tulip_txdescs + TULIP_TXDESCS;
#endif
tulip_initring(sc, &sc->tulip_rxinfo, sc->tulip_rxdescs, TULIP_RXDESCS);
tulip_initring(sc, &sc->tulip_txinfo, sc->tulip_txdescs, TULIP_TXDESCS);

View File

@ -1,4 +1,4 @@
/* $NetBSD: if_devar.h,v 1.22 1997/10/20 14:33:01 matt Exp $ */
/* $NetBSD: if_devar.h,v 1.23 1998/02/06 20:57:19 matt Exp $ */
/*-
* Copyright (c) 1994-1997 Matt Thomas (matt@3am-software.com)
@ -36,6 +36,12 @@
#include <sys/rnd.h>
#endif
#if NetBSD >= 199803
#define TULIP_BUS_DMA 1
/* #define TULIP_BUS_DMA_NORX 1 */
/* #define TULIP_BUS_DMA_NOTX 1 */
#endif
typedef bus_addr_t tulip_csrptr_t;
#define TULIP_CSR_READ(sc, csr) \
@ -164,10 +170,13 @@ typedef struct {
#define TULIP_COPY_RXDATA 1
#endif
#define TULIP_DATA_PER_DESC 2032
#define TULIP_TXTIMER 4
#define TULIP_RXDESCS 48
#define TULIP_TXDESCS 32
#define TULIP_RXQ_TARGET 32
#define TULIP_TXQ_TARGET 4
#define TULIP_TXQ_HIGHWATER 12
#if TULIP_RXQ_TARGET >= TULIP_RXDESCS
#error TULIP_RXQ_TARGET must be less than TULIP_RXDESCS
#endif
@ -495,6 +504,20 @@ struct _tulip_softc_t {
#if !defined(tulip_ifmedia) && defined(IFM_ETHER)
struct ifmedia tulip_ifmedia;
#endif
#if defined(TULIP_BUS_DMA)
bus_dma_tag_t tulip_dmatag; /* bus DMA tag */
#if !defined(TULIP_BUS_DMA_NOTX)
bus_dmamap_t tulip_setupmap;
bus_dmamap_t tulip_txdescmap;
bus_dmamap_t tulip_txmaps[TULIP_TXDESCS];
unsigned tulip_txmaps_free;
#endif
#if !defined(TULIP_BUS_DMA_NORX)
bus_dmamap_t tulip_rxdescmap;
bus_dmamap_t tulip_rxmaps[TULIP_RXDESCS];
unsigned tulip_rxmaps_free;
#endif
#endif
#if !defined(__NetBSD__)
struct arpcom tulip_ac;
#endif
@ -667,8 +690,8 @@ struct _tulip_softc_t {
u_int8_t tulip_pci_devno; /* needed for multiport boards */
u_int8_t tulip_connidx;
tulip_srom_connection_t tulip_conntype;
tulip_desc_t tulip_rxdescs[TULIP_RXDESCS];
tulip_desc_t tulip_txdescs[TULIP_TXDESCS];
tulip_desc_t *tulip_rxdescs;
tulip_desc_t *tulip_txdescs;
#if defined(__NetBSD__) && NRND > 0
rndsource_element_t tulip_rndsource;
#endif
@ -830,6 +853,59 @@ static int tulip_softintr_max_unit;
static void tulip_softintr(void);
#endif
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX)
#define TULIP_RXDESC_PRESYNC(sc, di, s) \
bus_dmamap_sync((sc)->tulip_dmatag, (sc)->tulip_rxdescmap, \
(caddr_t) di - (caddr_t) (sc)->tulip_rxdescs, \
(s), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
#define TULIP_RXDESC_POSTSYNC(sc, di, s) \
bus_dmamap_sync((sc)->tulip_dmatag, (sc)->tulip_rxdescmap, \
(caddr_t) di - (caddr_t) (sc)->tulip_rxdescs, \
(s), BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
#define TULIP_RXMAP_PRESYNC(sc, map) \
bus_dmamap_sync((sc)->tulip_dmatag, (map), 0, (map)->dm_mapsize, \
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
#define TULIP_RXMAP_POSTSYNC(sc, map) \
bus_dmamap_sync((sc)->tulip_dmatag, (map), 0, (map)->dm_mapsize, \
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
#define TULIP_RXMAP_CREATE(sc, mapp) \
bus_dmamap_create((sc)->tulip_dmatag, TULIP_RX_BUFLEN, 2, \
TULIP_DATA_PER_DESC, 0, BUS_DMA_ALLOCNOW, (mapp))
#else
#define TULIP_RXDESC_PRESYNC(sc, di, s) do { } while (0)
#define TULIP_RXDESC_POSTSYNC(sc, di, s) do { } while (0)
#define TULIP_RXMAP_PRESYNC(sc, map) do { } while (0)
#define TULIP_RXMAP_POSTSYNC(sc, map) do { } while (0)
#define TULIP_RXMAP_CREATE(sc, mapp) do { } while (0)
#endif
#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX)
#define TULIP_TXDESC_PRESYNC(sc, di, s) \
bus_dmamap_sync((sc)->tulip_dmatag, (sc)->tulip_txdescmap, \
(caddr_t) di - (caddr_t) (sc)->tulip_txdescs, \
(s), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
#define TULIP_TXDESC_POSTSYNC(sc, di, s) \
bus_dmamap_sync((sc)->tulip_dmatag, (sc)->tulip_txdescmap, \
(caddr_t) di - (caddr_t) (sc)->tulip_txdescs, \
(s), BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
#define TULIP_TXMAP_PRESYNC(sc, map) \
bus_dmamap_sync((sc)->tulip_dmatag, (map), 0, (map)->dm_mapsize, \
BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)
#define TULIP_TXMAP_POSTSYNC(sc, map) \
bus_dmamap_sync((sc)->tulip_dmatag, (map), 0, (map)->dm_mapsize, \
BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)
#define TULIP_TXMAP_CREATE(sc, mapp) \
bus_dmamap_create((sc)->tulip_dmatag, TULIP_DATA_PER_DESC, \
TULIP_MAX_TXSEG, TULIP_DATA_PER_DESC, \
0, BUS_DMA_ALLOCNOW, (mapp))
#else
#define TULIP_TXDESC_PRESYNC(sc, di, s) do { } while (0)
#define TULIP_TXDESC_POSTSYNC(sc, di, s) do { } while (0)
#define TULIP_TXMAP_PRESYNC(sc, map) do { } while (0)
#define TULIP_TXMAP_POSTSYNC(sc, map) do { } while (0)
#define TULIP_TXMAP_CREATE(sc, mapp) do { } while (0)
#endif
#ifdef notyet
#define SIOCGADDRROM _IOW('i', 240, struct ifreq) /* get 128 bytes of ROM */
#define SIOCGCHIPID _IOWR('i', 241, struct ifreq) /* get chipid */
@ -920,10 +996,12 @@ extern struct cfdriver de_cd;
#define loudprintf printf
#define TULIP_PRINTF_FMT "%s"
#define TULIP_PRINTF_ARGS sc->tulip_xname
#if !defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NORX) || defined(TULIP_BUS_DMA_NOTX)
#if defined(__alpha__)
/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */
#define TULIP_KVATOPHYS(sc, va) alpha_XXX_dmamap((vm_offset_t)(va))
#endif
#endif
#endif /* __NetBSD__ */
#ifndef TULIP_PRINTF_FMT
@ -971,8 +1049,8 @@ extern struct cfdriver de_cd;
#define tulip_intrfunc_t int
#endif
#if !defined(TULIP_KVATOPHYS)
#define TULIP_KVATOPHYS(sc, va) vtophys(va)
#if !defined(TULIP_KVATOPHYS) && (!defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NORX) || defined(TULIP_BUS_DMA_NOTX))
#define TULIP_KVATOPHYS(sc, va) vtophys(va)
#endif
#ifndef TULIP_RAISESPL