diff options
author | Brad Smith <brad@cvs.openbsd.org> | 2005-11-05 11:49:02 +0000 |
---|---|---|
committer | Brad Smith <brad@cvs.openbsd.org> | 2005-11-05 11:49:02 +0000 |
commit | f43d63d8ec76b40ecd312f784f636a0fd96a7308 (patch) | |
tree | a685542b46db89eb11396916d5b41b9730ab25ae | |
parent | a83a75f3cdc91a1e05b70efee323ff59f74fdce3 (diff) |
add bus_dma and big endian support.
From NetBSD
Thanks to Jason Ackley for testing on i386/amd64/sparc64
with both T1 and T3 cards.
"looks ok" dlg@
-rw-r--r-- | sys/dev/pci/if_lmc.c | 357 | ||||
-rw-r--r-- | sys/dev/pci/if_lmc_common.c | 39 | ||||
-rw-r--r-- | sys/dev/pci/if_lmc_media.c | 6 | ||||
-rw-r--r-- | sys/dev/pci/if_lmc_obsd.c | 116 | ||||
-rw-r--r-- | sys/dev/pci/if_lmc_types.h | 18 | ||||
-rw-r--r-- | sys/dev/pci/if_lmcioctl.h | 6 | ||||
-rw-r--r-- | sys/dev/pci/if_lmcvar.h | 138 |
7 files changed, 505 insertions, 175 deletions
diff --git a/sys/dev/pci/if_lmc.c b/sys/dev/pci/if_lmc.c index 6399154f598..1105c903fe7 100644 --- a/sys/dev/pci/if_lmc.c +++ b/sys/dev/pci/if_lmc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lmc.c,v 1.18 2004/11/28 23:39:45 canacar Exp $ */ +/* $OpenBSD: if_lmc.c,v 1.19 2005/11/05 11:49:01 brad Exp $ */ /* $NetBSD: if_lmc.c,v 1.1 1999/03/25 03:32:43 explorer Exp $ */ /*- @@ -116,8 +116,6 @@ #include <net/bpf.h> #endif -#include <uvm/uvm_extern.h> - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <net/if_sppp.h> #endif @@ -169,12 +167,6 @@ #define INCLUDE_PATH_PREFIX "dev/pci/" #endif /* __NetBSD__ */ -#if defined(__OpenBSD__) -#define d_length1 u.bd_length1 -#define d_length2 u.bd_length2 -#define d_flag u.bd_flag -#endif - /* * Sigh. Every OS puts these in different places. NetBSD and FreeBSD use * a C preprocessor that allows this hack, but BSDI does not. Grr. @@ -441,7 +433,6 @@ lmc_watchdog(int unit) /* Is the transmit clock still available? */ ticks = LMC_CSR_READ (sc, csr_gp_timer); ticks = 0x0000ffff - (ticks & 0x0000ffff); - if (ticks == 0) { /* no clock found ? */ @@ -555,6 +546,7 @@ lmc_ifup(lmc_softc_t * const sc) */ sc->lmc_intrmask |= (TULIP_STS_NORMALINTR | TULIP_STS_RXINTR + | TULIP_STS_RXNOBUF | TULIP_STS_TXINTR | TULIP_STS_ABNRMLINTR | TULIP_STS_SYSERROR @@ -594,15 +586,18 @@ lmc_rx_intr(lmc_softc_t * const sc) { lmc_ringinfo_t * const ri = &sc->lmc_rxinfo; struct ifnet * const ifp = &sc->lmc_if; + u_int32_t status; int fillok = 1; sc->lmc_rxtick++; for (;;) { - tulip_desc_t *eop = ri->ri_nextin; + lmc_desc_t *eop = ri->ri_nextin; int total_len = 0, last_offset = 0; struct mbuf *ms = NULL, *me = NULL; int accept = 0; + bus_dmamap_t map; + int error; if (fillok && sc->lmc_rxq.ifq_len < LMC_RXQ_TARGET) goto queue_mbuf; @@ -618,14 +613,18 @@ lmc_rx_intr(lmc_softc_t * const sc) * 90% of the packets will fit in one descriptor. So we * optimize for that case. */ - if ((((volatile tulip_desc_t *) eop)->d_status & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) { + LMC_RXDESC_POSTSYNC(sc, eop, sizeof(*eop)); + status = letoh32(((volatile lmc_desc_t *) eop)->d_status); + if ((status & + (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == + (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) { IF_DEQUEUE(&sc->lmc_rxq, ms); me = ms; } else { /* * If still owned by the TULIP, don't touch it. */ - if (((volatile tulip_desc_t *)eop)->d_status & TULIP_DSTS_OWNER) + if (status & TULIP_DSTS_OWNER) break; /* @@ -634,10 +633,14 @@ lmc_rx_intr(lmc_softc_t * const sc) * for a received packet to cross more than one * receive descriptor. */ - while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) { + while ((status & TULIP_DSTS_RxLASTDESC) == 0) { if (++eop == ri->ri_last) eop = ri->ri_first; - if (eop == ri->ri_nextout || ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER))) { + LMC_RXDESC_POSTSYNC(sc, eop, sizeof(*eop)); + status = letoh32(((volatile lmc_desc_t *) + eop)->d_status); + if (eop == ri->ri_nextout || + (status & TULIP_DSTS_OWNER)) { return; } total_len++; @@ -658,6 +661,13 @@ lmc_rx_intr(lmc_softc_t * const sc) */ IF_DEQUEUE(&sc->lmc_rxq, ms); for (me = ms; total_len > 0; total_len--) { + map = LMC_GETCTX(me, bus_dmamap_t); + LMC_RXMAP_POSTSYNC(sc, map); + bus_dmamap_unload(sc->lmc_dmatag, map); + sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map; +#if defined(DIAGNOSTIC) + LMC_SETCTX(me, NULL); +#endif me->m_len = LMC_RX_BUFLEN; last_offset += LMC_RX_BUFLEN; IF_DEQUEUE(&sc->lmc_rxq, me->m_next); @@ -668,19 +678,29 @@ lmc_rx_intr(lmc_softc_t * const sc) /* * Now get the size of received packet (minus the CRC). */ - total_len = ((eop->d_status >> 16) & 0x7FFF); + total_len = ((status >> 16) & 0x7FFF); if (sc->ictl.crc_length == 16) total_len -= 2; else total_len -= 4; if ((sc->lmc_flags & LMC_RXIGNORE) == 0 - && ((eop->d_status & LMC_DSTS_ERRSUM) == 0 + && ((status & LMC_DSTS_ERRSUM) == 0 #ifdef BIG_PACKET || (total_len <= sc->lmc_if.if_mtu + PPP_HEADER_LEN - && (eop->d_status & TULIP_DSTS_RxOVERFLOW) == 0) + && (status & TULIP_DSTS_RxOVERFLOW) == 0) #endif )) { + + map = LMC_GETCTX(me, bus_dmamap_t); + bus_dmamap_sync(sc->lmc_dmatag, map, 0, me->m_len, + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->lmc_dmatag, map); + sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map; +#if defined(DIAGNOSTIC) + LMC_SETCTX(me, NULL); +#endif + me->m_len = total_len - last_offset; #if NBPFILTER > 0 if (sc->lmc_bpf != NULL) { @@ -694,9 +714,15 @@ lmc_rx_intr(lmc_softc_t * const sc) accept = 1; } else { ifp->if_ierrors++; - if (eop->d_status & TULIP_DSTS_RxOVERFLOW) { + if (status & TULIP_DSTS_RxOVERFLOW) { sc->lmc_dot3stats.dot3StatsInternalMacReceiveErrors++; } + map = LMC_GETCTX(me, bus_dmamap_t); + bus_dmamap_unload(sc->lmc_dmatag, map); + sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map; +#if defined(DIAGNOSTIC) + LMC_SETCTX(me, NULL); +#endif } ifp->if_ipackets++; @@ -754,9 +780,52 @@ lmc_rx_intr(lmc_softc_t * const sc) * receive queue. */ do { - ri->ri_nextout->d_length1 = LMC_RX_BUFLEN; - ri->ri_nextout->d_addr1 = LMC_KVATOPHYS(sc, mtod(ms, caddr_t)); - ri->ri_nextout->d_status = TULIP_DSTS_OWNER; + u_int32_t ctl; + lmc_desc_t * const nextout = ri->ri_nextout; + + if (sc->lmc_rxmaps_free > 0) { + map = sc->lmc_rxmaps[--sc->lmc_rxmaps_free]; + } else { + m_freem(ms); + sc->lmc_flags |= LMC_RXBUFSLOW; +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_rxlowbufs++; +#endif + break; + } + LMC_SETCTX(ms, map); + error = bus_dmamap_load(sc->lmc_dmatag, map, + mtod(ms, void *), LMC_RX_BUFLEN, + NULL, BUS_DMA_NOWAIT); + if (error) { + printf(LMC_PRINTF_FMT + ": unable to load rx map, " + "error = %d\n", + LMC_PRINTF_ARGS, error); + panic("lmc_rx_intr"); /* XXX */ + } + + ctl = letoh32(nextout->d_ctl); + /* For some weird reason we lose TULIP_DFLAG_ENDRING */ + if ((nextout+1) == ri->ri_last) + ctl = LMC_CTL(LMC_CTL_FLGS(ctl)| + TULIP_DFLAG_ENDRING, 0, 0); + nextout->d_addr1 = htole32(map->dm_segs[0].ds_addr); + if (map->dm_nsegs == 2) { + nextout->d_addr2 = htole32(map->dm_segs[1].ds_addr); + nextout->d_ctl = + htole32(LMC_CTL(LMC_CTL_FLGS(ctl), + map->dm_segs[0].ds_len, + map->dm_segs[1].ds_len)); + } else { + nextout->d_addr2 = 0; + nextout->d_ctl = + htole32(LMC_CTL(LMC_CTL_FLGS(ctl), + map->dm_segs[0].ds_len, 0)); + } + LMC_RXDESC_POSTSYNC(sc, nextout, sizeof(*nextout)); + ri->ri_nextout->d_status = htole32(TULIP_DSTS_OWNER); + LMC_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; @@ -776,29 +845,25 @@ lmc_tx_intr(lmc_softc_t * const sc) struct mbuf *m; int xmits = 0; int descs = 0; + u_int32_t d_status; sc->lmc_txtick++; while (ri->ri_free < ri->ri_max) { -#ifdef __OpenBSD__ - u_int32_t duh_flag; -#else - u_int32_t d_flag; -#endif + u_int32_t flag; - if (((volatile tulip_desc_t *) ri->ri_nextin)->d_status & TULIP_DSTS_OWNER) + LMC_TXDESC_POSTSYNC(sc, ri->ri_nextin, sizeof(*ri->ri_nextin)); + d_status = letoh32(((volatile lmc_desc_t *) ri->ri_nextin)->d_status); + if (d_status & TULIP_DSTS_OWNER) break; -#ifdef __OpenBSD__ - duh_flag = ri->ri_nextin->d_flag; - if (duh_flag & TULIP_DFLAG_TxLASTSEG) { -#else - d_flag = ri->ri_nextin->d_flag; - if (d_flag & TULIP_DFLAG_TxLASTSEG) { -#endif - const u_int32_t d_status = ri->ri_nextin->d_status; + flag = LMC_CTL_FLGS(letoh32(ri->ri_nextin->d_ctl)); + if (flag & TULIP_DFLAG_TxLASTSEG) { IF_DEQUEUE(&sc->lmc_txq, m); if (m != NULL) { + bus_dmamap_t map = LMC_GETCTX(m, bus_dmamap_t); + LMC_TXMAP_POSTSYNC(sc, map); + sc->lmc_txmaps[sc->lmc_txmaps_free++] = map; #if NBPFILTER > 0 if (sc->lmc_bpf != NULL) LMC_BPF_MTAP(sc, m); @@ -812,11 +877,13 @@ lmc_tx_intr(lmc_softc_t * const sc) xmits++; if (d_status & LMC_DSTS_ERRSUM) { sc->lmc_if.if_oerrors++; - if (d_status & TULIP_DSTS_TxUNDERFLOW) + if (d_status & TULIP_DSTS_TxUNDERFLOW) { sc->lmc_dot3stats.dot3StatsInternalTransmitUnderflows++; + } } else { - if (d_status & TULIP_DSTS_TxDEFERRED) + if (d_status & TULIP_DSTS_TxDEFERRED) { sc->lmc_dot3stats.dot3StatsDeferredTransmissions++; + } } } @@ -1006,10 +1073,11 @@ static struct mbuf * lmc_txput(lmc_softc_t * const sc, struct mbuf *m) { lmc_ringinfo_t * const ri = &sc->lmc_txinfo; - tulip_desc_t *eop, *nextout; + lmc_desc_t *eop, *nextout; int segcnt, free; - u_int32_t d_status; - struct mbuf *m0; + u_int32_t d_status, ctl; + bus_dmamap_t map; + int error; #if defined(LMC_DEBUG) if ((sc->lmc_cmdmode & TULIP_CMD_TXRUN) == 0) { @@ -1037,84 +1105,113 @@ lmc_txput(lmc_softc_t * const sc, struct mbuf *m) * case we will just wait for the ring to empty. In the * latter case we have to recopy. */ - again: d_status = 0; eop = nextout = ri->ri_nextout; - m0 = m; segcnt = 0; free = ri->ri_free; - do { - int len = m0->m_len; - caddr_t addr = mtod(m0, caddr_t); - unsigned clsize = PAGE_SIZE - (((u_long) addr) & PAGE_MASK); - - while (len > 0) { - unsigned slen = min(len, clsize); -#ifdef BIG_PACKET - int partial = 0; - if (slen >= 2048) - slen = 2040, partial = 1; + /* + * Reclaim some DMA maps from if we are out. + */ + if (sc->lmc_txmaps_free == 0) { +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_no_txmaps++; #endif - segcnt++; - if (segcnt > LMC_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. - */ - m = lmc_mbuf_compress(m); - if (m == NULL) - goto finish; - goto again; - } - if (segcnt & 1) { - if (--free == 0) { - /* - * See if there's any unclaimed space - * in the transmit ring. - */ - if ((free += lmc_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->lmc_flags |= LMC_WANTTXSTART; - goto finish; - } - } - eop = nextout; - if (++nextout == ri->ri_last) - nextout = ri->ri_first; - eop->d_flag &= TULIP_DFLAG_ENDRING; - eop->d_flag |= TULIP_DFLAG_TxNOPADDING; - if (sc->ictl.crc_length == 16) - eop->d_flag |= TULIP_DFLAG_TxHASCRC; - eop->d_status = d_status; - eop->d_addr1 = LMC_KVATOPHYS(sc, addr); - eop->d_length1 = slen; - } else { - /* - * Fill in second half of descriptor - */ - eop->d_addr2 = LMC_KVATOPHYS(sc, addr); - eop->d_length2 = slen; + free += lmc_tx_intr(sc); + } + if (sc->lmc_txmaps_free > 0) { + map = sc->lmc_txmaps[sc->lmc_txmaps_free-1]; + } else { + sc->lmc_flags |= LMC_WANTTXSTART; +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_txput_finishes[1]++; +#endif + goto finish; + } + error = bus_dmamap_load_mbuf(sc->lmc_dmatag, map, m, BUS_DMA_NOWAIT); + if (error != 0) { + if (error == EFBIG) { + /* + * The packet exceeds the number of transmit buffer + * entries that we can use for one packet, so we have + * to recopy it into one mbuf and then try again. + */ + m = lmc_mbuf_compress(m); + if (m == NULL) { +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_txput_finishes[2]++; +#endif + goto finish; } - d_status = TULIP_DSTS_OWNER; - len -= slen; - addr += slen; -#ifdef BIG_PACKET - if (partial) - continue; + error = bus_dmamap_load_mbuf(sc->lmc_dmatag, map, m, + BUS_DMA_NOWAIT); + } + if (error != 0) { + printf(LMC_PRINTF_FMT ": unable to load tx map, " + "error = %d\n", LMC_PRINTF_ARGS, error); +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_txput_finishes[3]++; #endif - clsize = PAGE_SIZE; + goto finish; } - } while ((m0 = m0->m_next) != NULL); + } + if ((free -= (map->dm_nsegs + 1) / 2) <= 0 + /* + * See if there's any unclaimed space in the transmit ring. + */ + && (free += lmc_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->lmc_flags |= LMC_WANTTXSTART; +#if defined(LMC_DEBUG) + sc->lmc_dbg.dbg_txput_finishes[4]++; +#endif + bus_dmamap_unload(sc->lmc_dmatag, map); + goto finish; + } + for (; map->dm_nsegs - segcnt > 1; segcnt += 2) { + int flg; + eop = nextout; + flg = LMC_CTL_FLGS(letoh32(eop->d_ctl)); + flg &= TULIP_DFLAG_ENDRING; + flg |= TULIP_DFLAG_TxNOPADDING; + if (sc->ictl.crc_length == 16) + flg |= TULIP_DFLAG_TxHASCRC; + eop->d_status = htole32(d_status); + eop->d_addr1 = htole32(map->dm_segs[segcnt].ds_addr); + eop->d_addr2 = htole32(map->dm_segs[segcnt+1].ds_addr); + eop->d_ctl = htole32(LMC_CTL(flg, + map->dm_segs[segcnt].ds_len, + 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) { + int flg; + + eop = nextout; + flg = LMC_CTL_FLGS(letoh32(eop->d_ctl)); + flg &= TULIP_DFLAG_ENDRING; + flg |= TULIP_DFLAG_TxNOPADDING; + if (sc->ictl.crc_length == 16) + flg |= TULIP_DFLAG_TxHASCRC; + eop->d_status = htole32(d_status); + eop->d_addr1 = htole32(map->dm_segs[segcnt].ds_addr); + eop->d_addr2 = 0; + eop->d_ctl = htole32(LMC_CTL(flg, + map->dm_segs[segcnt].ds_len, 0)); + if (++nextout == ri->ri_last) + nextout = ri->ri_first; + } + LMC_TXMAP_PRESYNC(sc, map); + LMC_SETCTX(m, map); + map = NULL; + --sc->lmc_txmaps_free; /* commit to using the dmamap */ /* * The descriptors have been filled in. Now get ready @@ -1129,29 +1226,39 @@ lmc_txput(lmc_softc_t * const sc, struct mbuf *m) * of room in the ring. */ nextout->d_status = 0; - - /* - * If we only used the first segment of the last descriptor, - * make sure the second segment will not be used. - */ - if (segcnt & 1) { - eop->d_addr2 = 0; - eop->d_length2 = 0; - } + LMC_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t)); /* * Mark the last and first segments, indicate we want a transmit * complete interrupt, and tell it to transmit! */ - eop->d_flag |= TULIP_DFLAG_TxLASTSEG | TULIP_DFLAG_TxWANTINTR; + ctl = letoh32(eop->d_ctl); + eop->d_ctl = htole32(LMC_CTL( + LMC_CTL_FLGS(ctl)|TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR, + LMC_CTL_LEN1(ctl), + LMC_CTL_LEN2(ctl))); /* * Note that ri->ri_nextout is still the start of the packet * and until we set the OWNER bit, we can still back out of * everything we have done. */ - ri->ri_nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG; - ri->ri_nextout->d_status = TULIP_DSTS_OWNER; + ctl = letoh32(ri->ri_nextout->d_ctl); + ri->ri_nextout->d_ctl = htole32(LMC_CTL( + LMC_CTL_FLGS(ctl)|TULIP_DFLAG_TxFIRSTSEG, + LMC_CTL_LEN1(ctl), + LMC_CTL_LEN2(ctl))); + if (eop < ri->ri_nextout) { + LMC_TXDESC_PRESYNC(sc, ri->ri_nextout, + (caddr_t) ri->ri_last - (caddr_t) ri->ri_nextout); + LMC_TXDESC_PRESYNC(sc, ri->ri_first, + (caddr_t) (eop + 1) - (caddr_t) ri->ri_first); + } else { + LMC_TXDESC_PRESYNC(sc, ri->ri_nextout, + (caddr_t) (eop + 1) - (caddr_t) ri->ri_nextout); + } + ri->ri_nextout->d_status = htole32(TULIP_DSTS_OWNER); + LMC_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t)); LMC_CSR_WRITE(sc, csr_txpoll, 1); @@ -1481,14 +1588,14 @@ lmc_attach(lmc_softc_t * const sc) else lmc_led_on (sc, LMC_MII16_LED0 | LMC_MII16_LED2); } - + void lmc_initring(lmc_softc_t * const sc, lmc_ringinfo_t * const ri, - tulip_desc_t *descs, int ndescs) + lmc_desc_t *descs, int ndescs) { ri->ri_max = ndescs; ri->ri_first = descs; ri->ri_last = ri->ri_first + ri->ri_max; bzero((caddr_t) ri->ri_first, sizeof(ri->ri_first[0]) * ri->ri_max); - ri->ri_last[-1].d_flag = TULIP_DFLAG_ENDRING; + ri->ri_last[-1].d_ctl = htole32(LMC_CTL(TULIP_DFLAG_ENDRING, 0, 0)); } diff --git a/sys/dev/pci/if_lmc_common.c b/sys/dev/pci/if_lmc_common.c index d422d626a9f..3f2ecc72e38 100644 --- a/sys/dev/pci/if_lmc_common.c +++ b/sys/dev/pci/if_lmc_common.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lmc_common.c,v 1.9 2004/05/12 06:35:11 tedu Exp $ */ +/* $OpenBSD: if_lmc_common.c,v 1.10 2005/11/05 11:49:01 brad Exp $ */ /* $NetBSD: if_lmc_common.c,v 1.1 1999/03/25 03:32:43 explorer Exp $ */ /*- @@ -100,8 +100,6 @@ #include <net/bpf.h> #endif -#include <uvm/uvm_extern.h> - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <net/if_sppp.h> #endif @@ -253,7 +251,7 @@ lmc_dec_reset(lmc_softc_t * const sc) { #ifndef __linux__ lmc_ringinfo_t *ri; - tulip_desc_t *di; + lmc_desc_t *di; #endif u_int32_t val; @@ -329,15 +327,12 @@ lmc_dec_reset(lmc_softc_t * const sc) /* * reprogram the tx desc, rx desc, and PCI bus options */ - LMC_CSR_WRITE(sc, csr_txlist, - LMC_KVATOPHYS(sc, &sc->lmc_txinfo.ri_first[0])); - LMC_CSR_WRITE(sc, csr_rxlist, - LMC_KVATOPHYS(sc, &sc->lmc_rxinfo.ri_first[0])); + LMC_CSR_WRITE(sc, csr_txlist, sc->lmc_txdescmap->dm_segs[0].ds_addr); + LMC_CSR_WRITE(sc, csr_rxlist, sc->lmc_rxdescmap->dm_segs[0].ds_addr); LMC_CSR_WRITE(sc, csr_busmode, - (1 << (LMC_BURSTSIZE(sc->lmc_unit) + 8)) - |TULIP_BUSMODE_CACHE_ALIGN8 - |TULIP_BUSMODE_READMULTIPLE - |(BYTE_ORDER != LITTLE_ENDIAN ? TULIP_BUSMODE_BIGENDIAN : 0)); + (1 << (LMC_BURSTSIZE(sc->lmc_unit) + 8)) + |TULIP_BUSMODE_CACHE_ALIGN8 + |TULIP_BUSMODE_READMULTIPLE); sc->lmc_txq.ifq_maxlen = LMC_TXDESCS; @@ -345,11 +340,15 @@ lmc_dec_reset(lmc_softc_t * const sc) * Free all the mbufs that were on the transmit ring. */ for (;;) { + bus_dmamap_t map; struct mbuf *m; IF_DEQUEUE(&sc->lmc_txq, m); if (m == NULL) break; + map = LMC_GETCTX(m, bus_dmamap_t); + bus_dmamap_unload(sc->lmc_dmatag, map); + sc->lmc_txmaps[sc->lmc_txmaps_free++] = map; m_freem(m); } @@ -361,6 +360,9 @@ lmc_dec_reset(lmc_softc_t * const sc) ri->ri_free = ri->ri_max; for (di = ri->ri_first; di < ri->ri_last; di++) di->d_status = 0; + bus_dmamap_sync(sc->lmc_dmatag, sc->lmc_txdescmap, + 0, sc->lmc_txdescmap->dm_mapsize, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); /* * We need to collect all the mbufs were on the @@ -372,15 +374,24 @@ lmc_dec_reset(lmc_softc_t * const sc) ri->ri_nextin = ri->ri_nextout = ri->ri_first; ri->ri_free = ri->ri_max; for (di = ri->ri_first; di < ri->ri_last; di++) { + u_int32_t ctl = di->d_ctl; di->d_status = 0; - di->d_length1 = 0; di->d_addr1 = 0; - di->d_length2 = 0; di->d_addr2 = 0; + di->d_ctl = LMC_CTL(LMC_CTL_FLGS(ctl),0,0); + di->d_addr1 = 0; + di->d_addr2 = 0; } + bus_dmamap_sync(sc->lmc_dmatag, sc->lmc_rxdescmap, + 0, sc->lmc_rxdescmap->dm_mapsize, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); for (;;) { + bus_dmamap_t map; struct mbuf *m; IF_DEQUEUE(&sc->lmc_rxq, m); if (m == NULL) break; + map = LMC_GETCTX(m, bus_dmamap_t); + bus_dmamap_unload(sc->lmc_dmatag, map); + sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map; m_freem(m); } #endif diff --git a/sys/dev/pci/if_lmc_media.c b/sys/dev/pci/if_lmc_media.c index c03f514554a..548a2fc344b 100644 --- a/sys/dev/pci/if_lmc_media.c +++ b/sys/dev/pci/if_lmc_media.c @@ -1,5 +1,5 @@ -/* $OpenBSD: if_lmc_media.c,v 1.14 2004/05/12 06:35:11 tedu Exp $ */ -/* $Id: if_lmc_media.c,v 1.14 2004/05/12 06:35:11 tedu Exp $ */ +/* $OpenBSD: if_lmc_media.c,v 1.15 2005/11/05 11:49:01 brad Exp $ */ +/* $Id: if_lmc_media.c,v 1.15 2005/11/05 11:49:01 brad Exp $ */ /*- * Copyright (c) 1997-1999 LAN Media Corporation (LMC) @@ -76,8 +76,6 @@ #include <net/bpf.h> #endif -#include <uvm/uvm_extern.h> - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <net/if_sppp.h> #endif diff --git a/sys/dev/pci/if_lmc_obsd.c b/sys/dev/pci/if_lmc_obsd.c index b08b5c8dda1..70c5fc97761 100644 --- a/sys/dev/pci/if_lmc_obsd.c +++ b/sys/dev/pci/if_lmc_obsd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lmc_obsd.c,v 1.16 2005/08/09 04:10:12 mickey Exp $ */ +/* $OpenBSD: if_lmc_obsd.c,v 1.17 2005/11/05 11:49:01 brad Exp $ */ /* $NetBSD: if_lmc_nbsd.c,v 1.1 1999/03/25 03:32:43 explorer Exp $ */ /*- @@ -100,8 +100,6 @@ #include <net/bpf.h> #endif -#include <uvm/uvm_extern.h> - #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) #include <net/if_sppp.h> #endif @@ -176,6 +174,9 @@ */ static void lmc_shutdown(void *arg); +static int lmc_busdma_init(lmc_softc_t * const sc); +static int lmc_busdma_allocmem(lmc_softc_t * const sc, size_t size, + bus_dmamap_t *map_p, lmc_desc_t **desc_p); static int lmc_pci_probe(struct device *parent, @@ -210,7 +211,7 @@ lmc_pci_probe(struct device *parent, && (PCI_CHIPID(id) != PCI_PRODUCT_LMC_DS1)) return 0; - return 10; /* must be > than any other tulip driver */ + return 20; /* must be > than any other tulip driver */ } static void lmc_pci_attach(struct device * const parent, @@ -231,9 +232,6 @@ lmc_pci_attach(struct device * const parent, u_int32_t revinfo, cfdainfo, id, ssid; pci_intr_handle_t intrhandle; const char *intrstr; -#if 0 - vm_offset_t pa_csrs; -#endif unsigned csroffset = LMC_PCI_CSROFFSET; unsigned csrsize = LMC_PCI_CSRSIZE; lmc_csrptr_t csr_base; @@ -320,6 +318,12 @@ lmc_pci_attach(struct device * const parent, } } + sc->lmc_dmatag = pa->pa_dmat; + if ((lmc_busdma_init(sc)) != 0) { + printf("error initing bus_dma\n"); + return; + } + lmc_initcsrs(sc, csr_base + csroffset, csrsize); lmc_initring(sc, &sc->lmc_rxinfo, sc->lmc_rxdescs, LMC_RXDESCS); @@ -398,3 +402,101 @@ lmc_shutdown(void *arg) sc->lmc_miireg16 = 0; /* deassert ready, and all others too */ lmc_led_on(sc, LMC_MII16_LED_ALL); } + +static int +lmc_busdma_allocmem( + lmc_softc_t * const sc, + size_t size, + bus_dmamap_t *map_p, + lmc_desc_t **desc_p) +{ + bus_dma_segment_t segs[1]; + int nsegs, error; + error = bus_dmamem_alloc(sc->lmc_dmatag, size, 1, NBPG, + segs, sizeof(segs)/sizeof(segs[0]), + &nsegs, BUS_DMA_NOWAIT); + if (error == 0) { + void *desc; + error = bus_dmamem_map(sc->lmc_dmatag, segs, nsegs, size, + (void *) &desc, BUS_DMA_NOWAIT|BUS_DMA_COHERENT); + if (error == 0) { + bus_dmamap_t map; + error = bus_dmamap_create(sc->lmc_dmatag, size, 1, size, 0, + BUS_DMA_NOWAIT, &map); + if (error == 0) { + error = bus_dmamap_load(sc->lmc_dmatag, map, desc, + size, NULL, BUS_DMA_NOWAIT); + if (error) + bus_dmamap_destroy(sc->lmc_dmatag, map); + else + *map_p = map; + } + if (error) + bus_dmamem_unmap(sc->lmc_dmatag, desc, size); + } + if (error) + bus_dmamem_free(sc->lmc_dmatag, segs, nsegs); + else + *desc_p = desc; + } + return error; +} + +static int +lmc_busdma_init( + lmc_softc_t * const sc) +{ + int error = 0; + + /* + * Allocate space and dmamap for transmit ring + */ + if (error == 0) { + error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_TXDESCS, + &sc->lmc_txdescmap, + &sc->lmc_txdescs); + } + + /* + * Allocate dmamaps for each transmit descriptors + */ + if (error == 0) { + while (error == 0 && sc->lmc_txmaps_free < LMC_TXDESCS) { + bus_dmamap_t map; + if ((error = LMC_TXMAP_CREATE(sc, &map)) == 0) + sc->lmc_txmaps[sc->lmc_txmaps_free++] = map; + } + if (error) { + while (sc->lmc_txmaps_free > 0) + bus_dmamap_destroy(sc->lmc_dmatag, + sc->lmc_txmaps[--sc->lmc_txmaps_free]); + } + } + + /* + * Allocate space and dmamap for receive ring + */ + if (error == 0) { + error = lmc_busdma_allocmem(sc, sizeof(lmc_desc_t) * LMC_RXDESCS, + &sc->lmc_rxdescmap, + &sc->lmc_rxdescs); + } + + /* + * Allocate dmamaps for each receive descriptors + */ + if (error == 0) { + while (error == 0 && sc->lmc_rxmaps_free < LMC_RXDESCS) { + bus_dmamap_t map; + if ((error = LMC_RXMAP_CREATE(sc, &map)) == 0) + sc->lmc_rxmaps[sc->lmc_rxmaps_free++] = map; + } + if (error) { + while (sc->lmc_rxmaps_free > 0) + bus_dmamap_destroy(sc->lmc_dmatag, + sc->lmc_rxmaps[--sc->lmc_rxmaps_free]); + } + } + + return error; +} diff --git a/sys/dev/pci/if_lmc_types.h b/sys/dev/pci/if_lmc_types.h index db468cfaee5..674a5690e9b 100644 --- a/sys/dev/pci/if_lmc_types.h +++ b/sys/dev/pci/if_lmc_types.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lmc_types.h,v 1.2 2000/02/01 18:01:42 chris Exp $ */ +/* $OpenBSD: if_lmc_types.h,v 1.3 2005/11/05 11:49:01 brad Exp $ */ /* $NetBSD: if_lmc_types.h,v 1.2 1999/03/25 04:09:33 explorer Exp $ */ /*- @@ -56,6 +56,22 @@ #endif #if defined(LMC_IS_KERNEL) + +/* + * LMC has weird endianness issues, so we can't use the tulip_desc_t. + */ +typedef struct { + u_int32_t d_status; + u_int32_t d_ctl; + u_int32_t d_addr1; + u_int32_t d_addr2; +} lmc_desc_t; + +#define LMC_CTL_FLGS(x) (((x)>>22)&0x3ff) +#define LMC_CTL_LEN2(x) (((x)>>11)&0x7ff) +#define LMC_CTL_LEN1(x) ((x)&0x7ff) +#define LMC_CTL(f,l1,l2) ((((f)&0x3ff)<<22)|(((l2)&0x7ff)<<11)|((l1)&0x7ff)) + #if defined(__NetBSD__) || defined(__OpenBSD__) typedef bus_addr_t lmc_csrptr_t; #else diff --git a/sys/dev/pci/if_lmcioctl.h b/sys/dev/pci/if_lmcioctl.h index 7c3c2bbd14a..679d5e95d72 100644 --- a/sys/dev/pci/if_lmcioctl.h +++ b/sys/dev/pci/if_lmcioctl.h @@ -1,5 +1,5 @@ -/* $OpenBSD: if_lmcioctl.h,v 1.4 2000/11/10 15:33:09 provos Exp $ */ -/* $Id: if_lmcioctl.h,v 1.4 2000/11/10 15:33:09 provos Exp $ */ +/* $OpenBSD: if_lmcioctl.h,v 1.5 2005/11/05 11:49:01 brad Exp $ */ +/* $Id: if_lmcioctl.h,v 1.5 2005/11/05 11:49:01 brad Exp $ */ /* * Copyright (c) 1997-1999 LAN Media Corporation (LMC) @@ -328,5 +328,5 @@ lmc_intrfunc_t lmc_intr_normal(void *); int lmc_read_macaddr(lmc_softc_t * const sc); void lmc_attach(lmc_softc_t * const sc); void lmc_initring(lmc_softc_t * const sc, lmc_ringinfo_t * const ri, - tulip_desc_t *descs, int ndescs); + lmc_desc_t *descs, int ndescs); #endif /* LMC_IS_KERNEL */ diff --git a/sys/dev/pci/if_lmcvar.h b/sys/dev/pci/if_lmcvar.h index de226048d2b..2b4d064b4f7 100644 --- a/sys/dev/pci/if_lmcvar.h +++ b/sys/dev/pci/if_lmcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_lmcvar.h,v 1.6 2002/06/02 22:50:00 deraadt Exp $ */ +/* $OpenBSD: if_lmcvar.h,v 1.7 2005/11/05 11:49:01 brad Exp $ */ /* $NetBSD: if_lmcvar.h,v 1.1 1999/03/25 03:32:43 explorer Exp $ */ /*- @@ -66,6 +66,7 @@ #define LMC_MTU 1500 #define PPP_HEADER_LEN 4 #define BIG_PACKET +#define LMC_DATA_PER_DESC 2032 /* * This turns on all sort of debugging stuff and make the @@ -73,6 +74,32 @@ */ #if 0 #define LMC_DEBUG +typedef enum { + LMC_21040_GENERIC, /* Generic 21040 (works with most any board) */ + LMC_21140_ISV, /* Digital Semicondutor 21140 ISV SROM Format */ + LMC_21142_ISV, /* Digital Semicondutor 21142 ISV SROM Format */ + LMC_21143_ISV, /* Digital Semicondutor 21143 ISV SROM Format */ + LMC_21140_DEC_EB, /* Digital Semicondutor 21140 Evaluation Board */ + LMC_21140_MII, /* 21140[A] with MII */ + LMC_21140_DEC_DE500, /* Digital DE500-?? 10/100 */ + LMC_21140_SMC_9332, /* SMC 9332 */ + LMC_21140_COGENT_EM100, /* Cogent EM100 100 only */ + LMC_21140_ZNYX_ZX34X, /* ZNYX ZX342 10/100 */ + LMC_21140_ASANTE, /* AsanteFast 10/100 */ + LMC_21140_EN1207, /* Accton EN2107 10/100 BNC */ + LMC_21041_GENERIC /* Generic 21041 card */ +} lmc_board_t; + +typedef enum { + LMC_MEDIAPOLL_TIMER, /* 100ms timer fired */ + LMC_MEDIAPOLL_FASTTIMER, /* <100ms timer fired */ + LMC_MEDIAPOLL_LINKFAIL, /* called from interrupt routine */ + LMC_MEDIAPOLL_LINKPASS, /* called from interrupt routine */ + LMC_MEDIAPOLL_START, /* start a media probe (called from reset) */ + LMC_MEDIAPOLL_TXPROBE_OK, /* txprobe succeeded */ + LMC_MEDIAPOLL_TXPROBE_FAILED, /* txprobe failed */ + LMC_MEDIAPOLL_MAX +} lmc_mediapoll_event_t; #define DP(x) printf x #else #define DP(x) @@ -194,10 +221,10 @@ typedef struct { * traditional FIFO ring. */ struct lmc_ringinfo { - tulip_desc_t *ri_first; /* first entry in ring */ - tulip_desc_t *ri_last; /* one after last entry */ - tulip_desc_t *ri_nextin; /* next to processed by host */ - tulip_desc_t *ri_nextout; /* next to processed by adapter */ + lmc_desc_t *ri_first; /* first entry in ring */ + lmc_desc_t *ri_last; /* one after last entry */ + lmc_desc_t *ri_nextin; /* next to processed by host */ + lmc_desc_t *ri_nextout; /* next to processed by adapter */ int ri_max; int ri_free; }; @@ -331,19 +358,23 @@ struct lmc___softc { lmc_media_t *lmc_media; lmc_ctl_t ictl; + bus_dma_tag_t lmc_dmatag; /* bus DMA tag */ + bus_dmamap_t lmc_setupmap; + bus_dmamap_t lmc_txdescmap; + bus_dmamap_t lmc_txmaps[LMC_TXDESCS]; + unsigned lmc_txmaps_free; + bus_dmamap_t lmc_rxdescmap; + bus_dmamap_t lmc_rxmaps[LMC_RXDESCS]; + unsigned lmc_rxmaps_free; + #if defined(__NetBSD__) || defined(__OpenBSD__) struct device *lmc_pci_busno; /* needed for multiport boards */ #else u_int8_t lmc_pci_busno; /* needed for multiport boards */ #endif u_int8_t lmc_pci_devno; /* needed for multiport boards */ -#if defined(__FreeBSD__) - tulip_desc_t *lmc_rxdescs; - tulip_desc_t *lmc_txdescs; -#else - tulip_desc_t lmc_rxdescs[LMC_RXDESCS]; - tulip_desc_t lmc_txdescs[LMC_TXDESCS]; -#endif + lmc_desc_t *lmc_rxdescs; + lmc_desc_t *lmc_txdescs; #if defined(__NetBSD__) && NRND > 0 rndsource_element_t lmc_rndsource; #endif @@ -354,6 +385,36 @@ struct lmc___softc { char lmc_timing; /* for HSSI and SSI */ u_int16_t t1_alarm1_status; u_int16_t t1_alarm2_status; +#if defined(LMC_DEBUG) + /* + * Debugging/Statistical information + */ + struct { + lmc_media_t dbg_last_media; + u_int32_t dbg_intrs; + u_int32_t dbg_media_probes; + u_int32_t dbg_txprobe_nocarr; + u_int32_t dbg_txprobe_exccoll; + u_int32_t dbg_link_downed; + u_int32_t dbg_link_suspected; + u_int32_t dbg_link_intrs; + u_int32_t dbg_link_pollintrs; + u_int32_t dbg_link_failures; + u_int32_t dbg_nway_starts; + u_int32_t dbg_nway_failures; + u_int16_t dbg_phyregs[32][4]; + u_int32_t dbg_rxlowbufs; + u_int32_t dbg_rxintrs; + u_int32_t dbg_last_rxintrs; + u_int32_t dbg_high_rxintrs_hz; + u_int32_t dbg_no_txmaps; + u_int32_t dbg_txput_finishes[8]; + u_int32_t dbg_txprobes_ok; + u_int32_t dbg_txprobes_failed; + u_int32_t dbg_events[LMC_MEDIAPOLL_MAX]; + u_int32_t dbg_rxpktsperintr[LMC_RXDESCS]; + } lmc_dbg; +#endif }; /* @@ -424,6 +485,7 @@ static const char * const lmc_system_errors[] = { "reserved #7", }; +#if 0 static const char * const lmc_status_bits[] = { NULL, "transmit process stopped", @@ -444,12 +506,51 @@ static const char * const lmc_status_bits[] = { NULL, NULL, }; +#endif /* * This driver supports a maximum of 32 devices. */ #define LMC_MAX_DEVICES 32 +#define LMC_RXDESC_PRESYNC(sc, di, s) \ + bus_dmamap_sync((sc)->lmc_dmatag, (sc)->lmc_rxdescmap, \ + (caddr_t) di - (caddr_t) (sc)->lmc_rxdescs, \ + (s), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define LMC_RXDESC_POSTSYNC(sc, di, s) \ + bus_dmamap_sync((sc)->lmc_dmatag, (sc)->lmc_rxdescmap, \ + (caddr_t) di - (caddr_t) (sc)->lmc_rxdescs, \ + (s), BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define LMC_RXMAP_PRESYNC(sc, map) \ + bus_dmamap_sync((sc)->lmc_dmatag, (map), 0, (map)->dm_mapsize, \ + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define LMC_RXMAP_POSTSYNC(sc, map) \ + bus_dmamap_sync((sc)->lmc_dmatag, (map), 0, (map)->dm_mapsize, \ + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define LMC_RXMAP_CREATE(sc, mapp) \ + bus_dmamap_create((sc)->lmc_dmatag, LMC_RX_BUFLEN, 2, \ + LMC_DATA_PER_DESC, 0, \ + BUS_DMA_NOWAIT|BUS_DMA_ALLOCNOW, (mapp)) + +#define LMC_TXDESC_PRESYNC(sc, di, s) \ + bus_dmamap_sync((sc)->lmc_dmatag, (sc)->lmc_txdescmap, \ + (caddr_t) di - (caddr_t) (sc)->lmc_txdescs, \ + (s), BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define LMC_TXDESC_POSTSYNC(sc, di, s) \ + bus_dmamap_sync((sc)->lmc_dmatag, (sc)->lmc_txdescmap, \ + (caddr_t) di - (caddr_t) (sc)->lmc_txdescs, \ + (s), BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define LMC_TXMAP_PRESYNC(sc, map) \ + bus_dmamap_sync((sc)->lmc_dmatag, (map), 0, (map)->dm_mapsize, \ + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define LMC_TXMAP_POSTSYNC(sc, map) \ + bus_dmamap_sync((sc)->lmc_dmatag, (map), 0, (map)->dm_mapsize, \ + BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define LMC_TXMAP_CREATE(sc, mapp) \ + bus_dmamap_create((sc)->lmc_dmatag, LMC_DATA_PER_DESC, \ + LMC_MAX_TXSEG, LMC_DATA_PER_DESC, \ + 0, BUS_DMA_NOWAIT, (mapp)) + #if defined(__FreeBSD__) typedef void ifnet_ret_t; typedef int ioctl_cmd_t; @@ -507,10 +608,6 @@ extern struct cfdriver lmc_cd; #define loudprintf printf #define LMC_PRINTF_FMT "%s" #define LMC_PRINTF_ARGS sc->lmc_xname -#if defined(__alpha__) -/* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */ -#define LMC_KVATOPHYS(sc, va) alpha_XXX_dmamap((vm_offset_t)(va)) -#endif #endif /* __NetBSD__ */ #ifndef LMC_PRINTF_FMT @@ -541,12 +638,8 @@ extern struct cfdriver lmc_cd; #endif #endif -#if !defined(LMC_KVATOPHYS) -#define LMC_KVATOPHYS(sc, va) vtophys(va) -#endif - #ifndef LMC_RAISESPL -#define LMC_RAISESPL() splimp() +#define LMC_RAISESPL() splnet() #endif #ifndef LMC_RAISESOFTSPL #define LMC_RAISESOFTSPL() splnet() @@ -586,3 +679,6 @@ extern struct cfdriver lmc_cd; && ((u_int16_t *)a1)[2] == 0xFFFFU) typedef int lmc_spl_t; + +#define LMC_GETCTX(m, t) ((t) (m)->m_pkthdr.rcvif + 0) +#define LMC_SETCTX(m, c) ((void) ((m)->m_pkthdr.rcvif = (void *) (c))) |