--- //depot/vendor/freebsd/src/sys/pci/if_de.c 2005/08/17 17:50:43 +++ //depot/user/jhb/acpipci/pci/if_de.c 2005/08/17 19:40:59 @@ -39,10 +39,14 @@ __FBSDID("$FreeBSD: src/sys/pci/if_de.c,v 1.170 2005/08/17 17:46:51 jhb Exp $"); #define TULIP_HDR_DATA +//#define TULIP_BUS_DMA + +#include "opt_ddb.h" #include #include #include +#include #include #include #include @@ -51,6 +55,9 @@ #include #include #include +#ifdef TULIP_BUS_DMA +#include +#endif #include #include #include @@ -77,6 +84,10 @@ #include #include +#ifdef DDB +#include +#endif + /* * Intel CPUs should use I/O mapped access. */ @@ -84,6 +95,13 @@ #define TULIP_IOMAPPED #endif +#if 1 +/* This enables KTR traces at KTR_DEV. */ +#define KTR_TULIP KTR_DEV +#else +#define KTR_TULIP 0 +#endif + #if 0 /* * This turns on all sort of debugging stuff and make the @@ -100,6 +118,10 @@ #include +#define SYNC_NONE 0 +#define SYNC_RX 1 +#define SYNC_TX 2 + /* * This module supports * the DEC 21040 PCI Ethernet Controller. @@ -126,13 +148,86 @@ static void tulip_mii_writereg(tulip_softc_t * const sc, unsigned devaddr, unsigned regno, unsigned data); static void tulip_reset(tulip_softc_t * const sc); +#ifdef INVARIANTS +static int tulip_ring_free(tulip_ringinfo_t *ri); +#endif static void tulip_rx_intr(tulip_softc_t * const sc); static int tulip_srom_decode(tulip_softc_t * const sc); static void tulip_start(tulip_softc_t * const sc); static struct mbuf * tulip_txput(tulip_softc_t * const sc, struct mbuf *m); static void tulip_txput_setup(tulip_softc_t * const sc); +struct mbuf * tulip_dequeue_mbuf(tulip_ringinfo_t *ri, tulip_descinfo_t *di, + int sync); +#ifdef TULIP_BUS_DMA +static void tulip_dma_map_addr(void *, bus_dma_segment_t *, int, int); +static void tulip_dma_map_rxbuf(void *, bus_dma_segment_t *, int, + bus_size_t, int); +#endif + +#ifdef TULIP_BUS_DMA +static void +tulip_dma_map_addr(void *arg, bus_dma_segment_t *segs, int nseg, int error) +{ + u_int32_t *paddr; + + if (error) + return; + + paddr = arg; + *paddr = segs->ds_addr; +} + +static void +tulip_dma_map_rxbuf(void *arg, bus_dma_segment_t *segs, int nseg, + bus_size_t mapsize, int error) +{ + tulip_desc_t *desc; + + if (error) + return; + + desc = arg; + KASSERT(nseg == 1, ("too many DMA segments")); + KASSERT(segs[0].ds_len >= TULIP_RX_BUFLEN, ("receive buffer too small")); + + desc->d_addr1 = segs[0].ds_addr; + desc->d_length1 = TULIP_RX_BUFLEN; +#ifdef not_needed + /* These should already always be zero. */ + desc->d_addr2 = 0; + desc->d_length2 = 0; +#endif +} +#endif +struct mbuf * +tulip_dequeue_mbuf(tulip_ringinfo_t *ri, tulip_descinfo_t *di, int sync) +{ + struct mbuf *m; + + m = di->di_mbuf; + if (m != NULL) { + switch (sync) { + case SYNC_NONE: + break; + case SYNC_RX: + TULIP_RXMAP_POSTSYNC(ri, di); + break; + case SYNC_TX: + TULIP_TXMAP_POSTSYNC(ri, di); + break; + default: + panic("bad sync flag: %d", sync); + } +#ifdef TULIP_BUS_DMA + bus_dmamap_unload(ri->ri_data_tag, *di->di_map); +#endif + di->di_mbuf = NULL; + } + return (m); +} + static void tulip_timeout_callback( void *arg) @@ -140,14 +235,13 @@ tulip_softc_t * const sc = arg; TULIP_PERFSTART(timeout) - TULIP_LOCK(sc); + TULIP_LOCK_ASSERT(sc); sc->tulip_flags &= ~TULIP_TIMEOUTPENDING; sc->tulip_probe_timeout -= 1000 / TULIP_HZ; (sc->tulip_boardsw->bd_media_poll)(sc, TULIP_MEDIAPOLL_TIMER); TULIP_PERFEND(timeout); - TULIP_UNLOCK(sc); } static void @@ -1354,6 +1448,7 @@ ifp->if_xname, phyaddr); sc->tulip_flags &= ~TULIP_TXPROBE_ACTIVE; sc->tulip_probe_state = TULIP_PROBE_FAILED; + /* XXX: ifnet locking */ sc->tulip_ifp->if_flags &= ~IFF_UP; sc->tulip_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; return; @@ -2314,6 +2409,10 @@ * All 4 chips on these boards share an interrupt. This code * copied from tulip_read_macaddr. */ + /* + * XXX: Need to lock the slave list here, maybe using the root_sc's + * lock? + */ sc->tulip_features |= TULIP_HAVE_SHAREDINTR; for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) { root_sc = tulips[root_unit]; @@ -2841,6 +2940,7 @@ if (idx == sizeof(sc->tulip_rombuf)) { int root_unit; tulip_softc_t *root_sc = NULL; + /* XXX: root_sc locking again */ for (root_unit = sc->tulip_unit - 1; root_unit >= 0; root_unit--) { root_sc = tulips[root_unit]; if (root_sc == NULL || (root_sc->tulip_features & (TULIP_HAVE_OKROM|TULIP_HAVE_SLAVEDROM)) == TULIP_HAVE_OKROM) @@ -3150,11 +3250,14 @@ tulip_softc_t * const sc) { tulip_ringinfo_t *ri; - tulip_desc_t *di; + tulip_descinfo_t *di; + struct mbuf *m; u_int32_t inreset = (sc->tulip_flags & TULIP_INRESET); TULIP_LOCK_ASSERT(sc); + CTR1(KTR_TULIP, "tulip_reset: inreset %d", inreset); + /* * Brilliant. Simply brilliant. When switching modes/speeds * on a 2114*, you need to set the appriopriate MII/PCS/SCL/PS @@ -3177,15 +3280,12 @@ sc->tulip_ifp->if_drv_flags &= ~IFF_DRV_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); +#if defined(TULIP_BUS_DMA) + TULIP_CSR_WRITE(sc, csr_txlist, sc->tulip_txinfo.ri_dma_addr); + TULIP_CSR_WRITE(sc, csr_rxlist, sc->tulip_rxinfo.ri_dma_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])); + TULIP_CSR_WRITE(sc, csr_txlist, TULIP_KVATOPHYS(sc, sc->tulip_txinfo.ri_descs)); + TULIP_CSR_WRITE(sc, csr_rxlist, TULIP_KVATOPHYS(sc, sc->tulip_rxinfo.ri_descs)); #endif TULIP_CSR_WRITE(sc, csr_busmode, (1 << (3 /*pci_max_burst_len*/ + 8)) @@ -3195,74 +3295,46 @@ TULIP_BUSMODE_DESC_BIGENDIAN : 0)); sc->tulip_txtimer = 0; - sc->tulip_txq.ifq_maxlen = TULIP_TXDESCS; /* * 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); - sc->tulip_txmaps[sc->tulip_txmaps_free++] = map; -#endif - m_freem(m); + CTR0(KTR_TULIP, "tulip_reset: drain transmit ring"); + ri = &sc->tulip_txinfo; + for (di = ri->ri_first; di < ri->ri_last; di++) { + m = tulip_dequeue_mbuf(ri, di, SYNC_NONE); + if (m != NULL) + m_freem(m); + di->di_desc->d_status = 0; } - ri = &sc->tulip_txinfo; 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++) - 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 + TULIP_TXDESC_PRESYNC(ri); /* - * We need to collect all the mbufs were on the + * We need to collect all the mbufs that were on the * receive ring before we reinit it either to put * them back on or to know if we have to allocate * more. */ + CTR0(KTR_TULIP, "tulip_reset: drain receive ring"); ri = &sc->tulip_rxinfo; 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++) { - di->d_status = 0; - di->d_length1 = 0; di->d_addr1 = 0; - di->d_length2 = 0; di->d_addr2 = 0; + di->di_desc->d_status = 0; + di->di_desc->d_length1 = 0; di->di_desc->d_addr1 = 0; + di->di_desc->d_length2 = 0; di->di_desc->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); - sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map; -#endif - m_freem(m); + TULIP_RXDESC_PRESYNC(ri); + for (di = ri->ri_first; di < ri->ri_last; di++) { + m = tulip_dequeue_mbuf(ri, di, SYNC_NONE); + if (m != NULL) + m_freem(m); } /* - * If tulip_reset is being called recurisvely, exit quickly knowing + * If tulip_reset is being called recursively, exit quickly knowing * that when the outer tulip_reset returns all the right stuff will * have happened. */ @@ -3307,9 +3379,11 @@ tulip_init( tulip_softc_t * const sc) { + CTR0(KTR_TULIP, "tulip_init"); if (sc->tulip_ifp->if_flags & IFF_UP) { if ((sc->tulip_ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { /* initialize the media */ + CTR0(KTR_TULIP, "tulip_init: up but not running, reset chip"); tulip_reset(sc); } sc->tulip_ifp->if_drv_flags |= IFF_DRV_RUNNING; @@ -3336,16 +3410,38 @@ sc->tulip_cmdmode &= ~TULIP_CMD_RXRUN; sc->tulip_intrmask &= ~TULIP_STS_RXSTOPPED; } + CTR2(KTR_TULIP, "tulip_init: intr mask %08x cmdmode %08x", + sc->tulip_intrmask, sc->tulip_cmdmode); TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode); + CTR1(KTR_TULIP, "tulip_init: status %08x\n", + TULIP_CSR_READ(sc, csr_status)); if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) tulip_txput_setup(sc); } else { + CTR0(KTR_TULIP, "tulip_init: not up, reset chip"); sc->tulip_ifp->if_drv_flags &= ~IFF_DRV_RUNNING; tulip_reset(sc); } } +#define DESC_STATUS(di) (((volatile tulip_desc_t *)((di)->di_desc))->d_status) +#define DESC_FLAG(di) ((di)->di_desc->d_flag) + +#ifdef INVARIANTS +/* Return the number of descriptors in this ring that are free. */ +static int +tulip_ring_free(tulip_ringinfo_t *ri) +{ + int len; + + len = ri->ri_nextin - ri->ri_nextout; + if (len < 0) + len += ri->ri_max; + return (len); +} +#endif + static void tulip_rx_intr( tulip_softc_t * const sc) @@ -3359,18 +3455,18 @@ #endif TULIP_LOCK_ASSERT(sc); + CTR0(KTR_TULIP, "tulip_rx_intr: start"); for (;;) { TULIP_PERFSTART(rxget) - tulip_desc_t *eop = ri->ri_nextin; + tulip_descinfo_t *eop = ri->ri_nextin, *dip; 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; +#if defined(TULIP_BUS_DMA) int error; #endif - if (fillok && sc->tulip_rxq.ifq_len < TULIP_RXQ_TARGET) + if (fillok && (ri->ri_max - ri->ri_free) < TULIP_RXQ_TARGET) goto queue_mbuf; #if defined(TULIP_DEBUG) @@ -3388,30 +3484,41 @@ * 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); + TULIP_RXDESC_POSTSYNC(ri); + if ((DESC_STATUS(eop) & (TULIP_DSTS_OWNER|TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) == (TULIP_DSTS_RxFIRSTDESC|TULIP_DSTS_RxLASTDESC)) { + ms = tulip_dequeue_mbuf(ri, eop, SYNC_RX); + CTR2(KTR_TULIP, + "tulip_rx_intr: single packet mbuf %p from descriptor %td", ms, + eop - ri->ri_first); me = ms; + ri->ri_free++; } else { /* * If still owned by the TULIP, don't touch it. */ - if (((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_OWNER) + if (DESC_STATUS(eop) & TULIP_DSTS_OWNER) break; /* * It is possible (though improbable unless MCLBYTES < 1518) for - * a received packet to cross more than one receive descriptor. + * a received packet to cross more than one receive descriptor. + * We first loop through the descriptor ring making sure we have + * received a complete packet. If not, we bail until the next + * interrupt. */ - while ((((volatile tulip_desc_t *) eop)->d_status & TULIP_DSTS_RxLASTDESC) == 0) { + dip = eop; + while ((DESC_STATUS(eop) & 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))) { + TULIP_RXDESC_POSTSYNC(ri); + if (eop == ri->ri_nextout || DESC_STATUS(eop) & TULIP_DSTS_OWNER) { #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_rxintrs++; sc->tulip_dbg.dbg_rxpktsperintr[cnt]++; #endif + KASSERT(tulip_ring_free(ri) == ri->ri_free, + ("free out of sync1, actual %d, free %d", + tulip_ring_free(ri), ri->ri_free)); TULIP_PERFEND(rxget); TULIP_PERFEND(rxintr); return; @@ -3429,61 +3536,55 @@ * won't go into the loop and thereby saving ourselves from * doing a multiplication by 0 in the normal case). */ - _IF_DEQUEUE(&sc->tulip_rxq, ms); + ms = tulip_dequeue_mbuf(ri, dip, SYNC_RX); + CTR2(KTR_TULIP, + "tulip_rx_intr: start packet mbuf %p from descriptor %td", ms, + dip - ri->ri_first); + ri->ri_free++; 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); - sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = 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); + if (++dip == ri->ri_last) + dip = ri->ri_first; + me->m_next = tulip_dequeue_mbuf(ri, dip, SYNC_RX); + ri->ri_free++; me = me->m_next; + CTR2(KTR_TULIP, + "tulip_rx_intr: cont packet mbuf %p from descriptor %td", + me, dip - ri->ri_first); } + KASSERT(dip == eop, ("mismatched descinfo structs")); } /* * Now get the size of received packet (minus the CRC). */ - total_len = ((eop->d_status >> 16) & 0x7FFF) - 4; + total_len = ((DESC_STATUS(eop) >> 16) & 0x7FFF) - 4; if ((sc->tulip_flags & TULIP_RXIGNORE) == 0 - && ((eop->d_status & TULIP_DSTS_ERRSUM) == 0)) { + && ((DESC_STATUS(eop) & TULIP_DSTS_ERRSUM) == 0)) { 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); - sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map; -#if defined(DIAGNOSTIC) - M_SETCTX(me, NULL); -#endif -#endif /* TULIP_BUS_DMA */ - sc->tulip_flags |= TULIP_RXACT; accept = 1; + CTR1(KTR_TULIP, "tulip_rx_intr: good packet; length %d", + total_len); } else { + CTR1(KTR_TULIP, "tulip_rx_intr: bad packet; status %08x", + DESC_STATUS(eop)); ifp->if_ierrors++; - if (eop->d_status & (TULIP_DSTS_RxBADLENGTH|TULIP_DSTS_RxOVERFLOW|TULIP_DSTS_RxWATCHDOG)) { + if (DESC_STATUS(eop) & (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) { + if (DESC_STATUS(eop) & 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) { + if (DESC_STATUS(eop) & TULIP_DSTS_RxBADCRC) { + if (DESC_STATUS(eop) & TULIP_DSTS_RxDRBBLBIT) { sc->tulip_dot3stats.dot3StatsAlignmentErrors++; #if defined(TULIP_VERBOSE) error = "alignment error"; @@ -3505,14 +3606,6 @@ #endif } -#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NORX) - map = M_GETCTX(me, bus_dmamap_t); - bus_dmamap_unload(sc->tulip_dmatag, map); - sc->tulip_rxmaps[sc->tulip_rxmaps_free++] = map; -#if defined(DIAGNOSTIC) - M_SETCTX(me, NULL); -#endif -#endif /* TULIP_BUS_DMA */ } #if defined(TULIP_DEBUG) cnt++; @@ -3521,6 +3614,9 @@ if (++eop == ri->ri_last) eop = ri->ri_first; ri->ri_nextin = eop; + KASSERT(tulip_ring_free(ri) == ri->ri_free, + ("free out of sync2, actual %d, free %d", tulip_ring_free(ri), + ri->ri_free)); queue_mbuf: /* * Either we are priming the TULIP with mbufs (m == NULL) @@ -3532,45 +3628,39 @@ * * Note that if this packet crossed multiple descriptors * we don't even try to reallocate all the mbufs here. - * Instead we rely on the test of the beginning of + * Instead we rely on the test at the beginning of * the loop to refill for the extra consumed mbufs. */ if (accept || ms == NULL) { struct mbuf *m0; - MGETHDR(m0, M_DONTWAIT, MT_DATA); - if (m0 != NULL) { + #if defined(TULIP_COPY_RXDATA) - if (!accept || total_len >= (MHLEN - 2)) { -#endif - MCLGET(m0, M_DONTWAIT); - if ((m0->m_flags & M_EXT) == 0) { - m_freem(m0); - m0 = NULL; - } -#if defined(TULIP_COPY_RXDATA) - } -#endif - } - if (accept -#if defined(TULIP_COPY_RXDATA) - && m0 != NULL -#endif - ) { + if (!accept || total_len >= (MHLEN - 2)) + m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + else + MGETHDR(m0, M_DONTWAIT, MT_DATA); + if (accept && m0 != NULL) { TULIP_UNLOCK(sc); -#if !defined(TULIP_COPY_RXDATA) - ms->m_pkthdr.len = total_len; - ms->m_pkthdr.rcvif = ifp; - (*ifp->if_input)(ifp, ms); -#else m0->m_data += 2; /* align data after header */ m_copydata(ms, 0, total_len, mtod(m0, caddr_t)); m0->m_len = m0->m_pkthdr.len = total_len; m0->m_pkthdr.rcvif = ifp; + CTR1(KTR_TULIP, "tulip_rx_intr: passing %p to upper layer", m0); (*ifp->if_input)(ifp, m0); m0 = ms; -#endif /* ! TULIP_COPY_RXDATA */ + TULIP_LOCK(sc); + } +#else /* TULIP_COPY_RXDATA */ + m0 = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR); + if (accept) { + TULIP_UNLOCK(sc); + ms->m_pkthdr.len = total_len; + ms->m_pkthdr.rcvif = ifp; + CTR1(KTR_TULIP, "tulip_rx_intr: passing %p to upper layer", ms); + (*ifp->if_input)(ifp, ms); TULIP_LOCK(sc); } +#endif /* TULIP_COPY_RXDATA */ ms = m0; } if (ms == NULL) { @@ -3591,50 +3681,42 @@ * receive queue. */ do { - 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 { - m_freem(ms); - sc->tulip_flags |= TULIP_RXBUFSLOW; -#if defined(TULIP_DEBUG) - sc->tulip_dbg.dbg_rxlowbufs++; -#endif - break; - } - M_SETCTX(ms, map); - error = bus_dmamap_load(sc->tulip_dmatag, map, mtod(ms, void *), - TULIP_RX_BUFLEN, NULL, BUS_DMA_NOWAIT); + tulip_descinfo_t * const nextout = ri->ri_nextout; + + M_ASSERTPKTHDR(ms); + KASSERT(ms->m_data == ms->m_ext.ext_buf, + ("rx mbuf data doesn't point to cluster")); +#ifdef TULIP_BUS_DMA + ms->m_len = ms->m_pkthdr.len = MCLBYTES; + error = bus_dmamap_load_mbuf(ri->ri_data_tag, *nextout->di_map, ms, + tulip_dma_map_rxbuf, nextout->di_desc, BUS_DMA_NOWAIT); if (error) { if_printf(sc->tulip_ifp, "unable to load rx map, error = %d\n", error); + printf("mbuf: %p, len %d\n", ms, ms->m_pkthdr.len); panic("tulip_rx_intr"); /* XXX */ } - 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; + nextout->di_desc->d_addr1 = TULIP_KVATOPHYS(sc, mtod(ms, caddr_t)); + nextout->di_desc->d_length1 = TULIP_RX_BUFLEN; #endif /* TULIP_BUS_DMA */ - nextout->d_status = TULIP_DSTS_OWNER; - TULIP_RXDESC_POSTSYNC(sc, nextout, sizeof(u_int32_t)); + nextout->di_desc->d_status = TULIP_DSTS_OWNER; + KASSERT(nextout->di_mbuf == NULL, ("clobbering earlier rx mbuf")); + nextout->di_mbuf = ms; + CTR2(KTR_TULIP, "tulip_rx_intr: enqueued mbuf %p to descriptor %td", + ms, nextout - ri->ri_first); + TULIP_RXDESC_POSTSYNC(ri); if (++ri->ri_nextout == ri->ri_last) ri->ri_nextout = ri->ri_first; + ri->ri_free--; me = ms->m_next; ms->m_next = NULL; - _IF_ENQUEUE(&sc->tulip_rxq, ms); } while ((ms = me) != NULL); - if (sc->tulip_rxq.ifq_len >= TULIP_RXQ_TARGET) + KASSERT(tulip_ring_free(ri) == ri->ri_free, + ("free out of sync3, actual %d, free %d", tulip_ring_free(ri), + ri->ri_free)); + if ((ri->ri_max - ri->ri_free) >= TULIP_RXQ_TARGET) sc->tulip_flags &= ~TULIP_RXBUFSLOW; TULIP_PERFEND(rxget); } @@ -3643,6 +3725,9 @@ sc->tulip_dbg.dbg_rxintrs++; sc->tulip_dbg.dbg_rxpktsperintr[cnt]++; #endif + KASSERT(tulip_ring_free(ri) == ri->ri_free, + ("free out of sync4, actual %d, free %d", tulip_ring_free(ri), + ri->ri_free)); TULIP_PERFEND(rxintr); } @@ -3650,25 +3735,29 @@ tulip_tx_intr( tulip_softc_t * const sc) { - TULIP_PERFSTART(txintr) + TULIP_PERFSTART(txintr) tulip_ringinfo_t * const ri = &sc->tulip_txinfo; struct mbuf *m; int xmits = 0; int descs = 0; + CTR0(KTR_TULIP, "tulip_tx_intr: start"); TULIP_LOCK_ASSERT(sc); 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) + TULIP_TXDESC_POSTSYNC(ri); + if (DESC_STATUS(ri->ri_nextin) & TULIP_DSTS_OWNER) break; ri->ri_free++; descs++; - d_flag = ri->ri_nextin->d_flag; + d_flag = DESC_FLAG(ri->ri_nextin); if (d_flag & TULIP_DFLAG_TxLASTSEG) { if (d_flag & TULIP_DFLAG_TxSETUPPKT) { + CTR2(KTR_TULIP, + "tulip_tx_intr: setup packet from descriptor %td: %08x", + ri->ri_nextin - ri->ri_first, DESC_STATUS(ri->ri_nextin)); /* * We've just finished processing a setup packet. * Mark that we finished it. If there's not @@ -3676,27 +3765,34 @@ * Make sure we ack the RXSTOPPED so we won't get * an abormal interrupt indication. */ +#ifdef TULIP_BUS_DMA + bus_dmamap_sync(sc->tulip_setup_tag, sc->tulip_setup_map, + BUS_DMASYNC_POSTWRITE); +#else TULIP_TXMAP_POSTSYNC(sc, sc->tulip_setupmap); +#endif sc->tulip_flags &= ~(TULIP_DOINGSETUP|TULIP_HASHONLY); - if (ri->ri_nextin->d_flag & TULIP_DFLAG_TxINVRSFILT) + if (DESC_FLAG(ri->ri_nextin) & TULIP_DFLAG_TxINVRSFILT) sc->tulip_flags |= TULIP_HASHONLY; if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == 0) { tulip_rx_intr(sc); sc->tulip_cmdmode |= TULIP_CMD_RXRUN; sc->tulip_intrmask |= TULIP_STS_RXSTOPPED; + CTR2(KTR_TULIP, + "tulip_tx_intr: intr mask %08x cmdmode %08x", + sc->tulip_intrmask, sc->tulip_cmdmode); TULIP_CSR_WRITE(sc, csr_status, TULIP_STS_RXSTOPPED); TULIP_CSR_WRITE(sc, csr_intr, sc->tulip_intrmask); TULIP_CSR_WRITE(sc, csr_command, sc->tulip_cmdmode); } } else { - const u_int32_t d_status = ri->ri_nextin->d_status; - _IF_DEQUEUE(&sc->tulip_txq, m); + const u_int32_t d_status = DESC_STATUS(ri->ri_nextin); + + m = tulip_dequeue_mbuf(ri, ri->ri_nextin, SYNC_TX); + CTR2(KTR_TULIP, + "tulip_tx_intr: data packet %p from descriptor %td", m, + ri->ri_nextin - ri->ri_first); 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); - sc->tulip_txmaps[sc->tulip_txmaps_free++] = map; -#endif /* TULIP_BUS_DMA */ m_freem(m); #if defined(TULIP_DEBUG) } else { @@ -3723,6 +3819,8 @@ } else { xmits++; if (d_status & TULIP_DSTS_ERRSUM) { + CTR1(KTR_TULIP, "tulip_tx_intr: output error: %08x", + d_status); sc->tulip_ifp->if_oerrors++; if (d_status & TULIP_DSTS_TxEXCCOLL) sc->tulip_dot3stats.dot3StatsExcessiveCollisions++; @@ -3740,6 +3838,10 @@ u_int32_t collisions = (d_status & TULIP_DSTS_TxCOLLMASK) >> TULIP_DSTS_V_TxCOLLCNT; + + CTR2(KTR_TULIP, + "tulip_tx_intr: output ok, collisions %d, status %08x", + collisions, d_status); sc->tulip_ifp->if_collisions += collisions; if (collisions == 1) sc->tulip_dot3stats.dot3StatsSingleCollisionFrames++; @@ -3817,6 +3919,7 @@ TULIP_PERFSTART(intr) u_int32_t csr; + CTR0(KTR_TULIP, "tulip_intr_handler invoked"); TULIP_LOCK_ASSERT(sc); while ((csr = TULIP_CSR_READ(sc, csr_status)) & sc->tulip_intrmask) { TULIP_CSR_WRITE(sc, csr_status, csr); @@ -3913,6 +4016,7 @@ { tulip_softc_t * sc = arg; + /* XXX: have to do locking for slave lists */ for (; sc != NULL; sc = sc->tulip_slaves) { TULIP_LOCK(sc); #if defined(TULIP_DEBUG) @@ -4002,15 +4106,19 @@ { TULIP_PERFSTART(txput) tulip_ringinfo_t * const ri = &sc->tulip_txinfo; - tulip_desc_t *eop, *nextout; + tulip_descinfo_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; - int error; +#if defined(TULIP_BUS_DMA) + bus_dma_segment_t segs[TULIP_MAX_TXSEG]; + bus_dmamap_t *map; + int error, nsegs; #else struct mbuf *m0; #endif +#if defined(KTR) && KTR_TULIP + struct mbuf *m1; +#endif TULIP_LOCK_ASSERT(sc); #if defined(TULIP_DEBUG) @@ -4040,35 +4148,44 @@ * 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) +#if !defined(TULIP_BUS_DMA) again: m0 = m; #endif +#if defined(KTR) && KTR_TULIP + segcnt = 1; + m1 = m; + while (m1->m_next != NULL) { + segcnt++; + m1 = m1->m_next; + } +#endif + CTR2(KTR_TULIP, "tulip_txput: sending packet %p (%d chunks)", m, segcnt); d_status = 0; eop = nextout = ri->ri_nextout; segcnt = 0; free = ri->ri_free; -#if defined(TULIP_BUS_DMA) && !defined(TULIP_BUS_DMA_NOTX) +#if defined(TULIP_BUS_DMA) /* * Reclaim some dma maps from if we are out. + * XXX? */ - if (sc->tulip_txmaps_free == 0) { + if (free == 0) { #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_no_txmaps++; #endif free += tulip_tx_intr(sc); } - if (sc->tulip_txmaps_free > 0) { - map = sc->tulip_txmaps[sc->tulip_txmaps_free-1]; - } else { + if (free == 0) { sc->tulip_flags |= TULIP_WANTTXSTART; #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_txput_finishes[1]++; #endif goto finish; } - error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf_sg(ri->ri_data_tag, *eop->di_map, m, segs, + &nsegs, BUS_DMA_NOWAIT); if (error != 0) { if (error == EFBIG) { /* @@ -4083,7 +4200,8 @@ #endif goto finish; } - error = bus_dmamap_load_mbuf(sc->tulip_dmatag, map, m, BUS_DMA_NOWAIT); + error = bus_dmamap_load_mbuf_sg(ri->ri_data_tag, *eop->di_map, m, + segs, &nsegs, BUS_DMA_NOWAIT); } if (error != 0) { if_printf(sc->tulip_ifp, @@ -4094,7 +4212,11 @@ goto finish; } } - if ((free -= (map->dm_nsegs + 1) / 2) <= 0 + CTR1(KTR_TULIP, "tulip_txput: nsegs %d", nsegs); + /* Currently I don't allow more than 2 frags per descriptor. That is + probably bad for performance. */ + /* XXX: that's all the hardware allows for - jhb */ + if ((free -= (nsegs + 1) / 2) <= 0 /* * See if there's any unclaimed space in the transmit ring. */ @@ -4109,37 +4231,46 @@ #if defined(TULIP_DEBUG) sc->tulip_dbg.dbg_txput_finishes[4]++; #endif - bus_dmamap_unload(sc->tulip_dmatag, map); + bus_dmamap_unload(ri->ri_data_tag, *eop->di_map); goto finish; } - for (; map->dm_nsegs - segcnt > 1; segcnt += 2) { + for (; 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; + eop->di_desc->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + eop->di_desc->d_status = d_status; + eop->di_desc->d_addr1 = segs[segcnt].ds_addr; + eop->di_desc->d_length1 = segs[segcnt].ds_len; + eop->di_desc->d_addr2 = segs[segcnt+1].ds_addr; + eop->di_desc->d_length2 = segs[segcnt+1].ds_len; d_status = TULIP_DSTS_OWNER; if (++nextout == ri->ri_last) nextout = ri->ri_first; } - if (segcnt < map->dm_nsegs) { + if (segcnt < 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; + eop->di_desc->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + eop->di_desc->d_status = d_status; + eop->di_desc->d_addr1 = segs[segcnt].ds_addr; + eop->di_desc->d_length1 = segs[segcnt].ds_len; + eop->di_desc->d_addr2 = 0; + eop->di_desc->d_length2 = 0; if (++nextout == ri->ri_last) nextout = ri->ri_first; } - TULIP_TXMAP_PRESYNC(sc, map); - M_SETCTX(m, map); - map = NULL; - --sc->tulip_txmaps_free; /* commit to using the dmamap */ + /* + * tulip_tx_intr() harvests the mbuf from the last descriptor in the + * frame. We just used the dmamap in the first descriptor for the + * load operation however. Thus, to let the tulip_dequeue_mbuf() call + * in tulip_tx_intr() unload the correct dmamap, we swap the dmamap + * pointers in the two descriptors if this is a multiple-descriptor + * packet. + */ + if (eop != ri->ri_nextout) { + map = eop->di_map; + eop->di_map = ri->ri_nextout->di_map; + ri->ri_nextout->di_map = map; + } #else /* !TULIP_BUS_DMA */ do { @@ -4156,6 +4287,7 @@ * entries that we can use for one packet, so we have * recopy it into one mbuf and then try again. */ + CTR0(KTR_TULIP, "tulip_txput: compressing mbuf"); m = tulip_mbuf_compress(m); if (m == NULL) goto finish; @@ -4184,16 +4316,16 @@ eop = nextout; if (++nextout == ri->ri_last) nextout = ri->ri_first; - eop->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; - eop->d_status = d_status; - eop->d_addr1 = TULIP_KVATOPHYS(sc, addr); - eop->d_length1 = slen; + eop->di_desc->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; + eop->di_desc->d_status = d_status; + eop->di_desc->d_addr1 = TULIP_KVATOPHYS(sc, addr); + eop->di_desc->d_length1 = slen; } else { /* * Fill in second half of descriptor */ - eop->d_addr2 = TULIP_KVATOPHYS(sc, addr); - eop->d_length2 = slen; + eop->di_desc->d_addr2 = TULIP_KVATOPHYS(sc, addr); + eop->di_desc->d_length2 = slen; } d_status = TULIP_DSTS_OWNER; len -= slen; @@ -4201,6 +4333,8 @@ clsize = PAGE_SIZE; } } while ((m0 = m0->m_next) != NULL); + + CTR1(KTR_TULIP, "tulip_txput: nsegs %d", segcnt); #endif /* TULIP_BUS_DMA */ /* @@ -4212,7 +4346,11 @@ * The descriptors have been filled in. Now get ready * to transmit. */ - _IF_ENQUEUE(&sc->tulip_txq, m); + CTR3(KTR_TULIP, "tulip_txput: enqueued mbuf %p to descriptors %td - %td", + m, ri->ri_nextout - ri->ri_first, eop - ri->ri_first); + KASSERT(eop->di_mbuf == NULL, ("clobbering earlier tx mbuf")); + eop->di_mbuf = m; + TULIP_TXMAP_PRESYNC(ri, ri->ri_nextout); m = NULL; /* @@ -4220,17 +4358,17 @@ * by us since it may have been set up above if we ran out * of room in the ring. */ - nextout->d_status = 0; - TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t)); + nextout->di_desc->d_status = 0; + TULIP_TXDESC_PRESYNC(ri); -#if !defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NOTX) +#if !defined(TULIP_BUS_DMA) /* * 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; + eop->di_desc->d_addr2 = 0; + eop->di_desc->d_length2 = 0; } #endif /* TULIP_BUS_DMA */ @@ -4238,27 +4376,17 @@ * 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; + eop->di_desc->d_flag |= TULIP_DFLAG_TxLASTSEG|TULIP_DFLAG_TxWANTINTR; /* * 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; -#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)); + ri->ri_nextout->di_desc->d_flag |= TULIP_DFLAG_TxFIRSTSEG; + TULIP_TXDESC_PRESYNC(ri); + ri->ri_nextout->di_desc->d_status = TULIP_DSTS_OWNER; + TULIP_TXDESC_PRESYNC(ri); /* * This advances the ring for us. @@ -4345,14 +4473,14 @@ return; } bcopy(sc->tulip_setupdata, sc->tulip_setupbuf, - sizeof(sc->tulip_setupbuf)); + sizeof(sc->tulip_setupdata)); /* - * Clear WANTSETUP and set DOINGSETUP. Set know that WANTSETUP is + * Clear WANTSETUP and set DOINGSETUP. Since we know that WANTSETUP is * set and DOINGSETUP is clear doing an XOR of the two will DTRT. */ sc->tulip_flags ^= TULIP_WANTSETUP|TULIP_DOINGSETUP; ri->ri_free--; - nextout = ri->ri_nextout; + nextout = ri->ri_nextout->di_desc; nextout->d_flag &= TULIP_DFLAG_ENDRING|TULIP_DFLAG_CHAIN; nextout->d_flag |= TULIP_DFLAG_TxFIRSTSEG|TULIP_DFLAG_TxLASTSEG |TULIP_DFLAG_TxSETUPPKT|TULIP_DFLAG_TxWANTINTR; @@ -4363,19 +4491,17 @@ 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)); + nextout->d_length1 = sizeof(sc->tulip_setupdata); +#if defined(TULIP_BUS_DMA) + nextout->d_addr1 = sc->tulip_setup_dma_addr; + bus_dmamap_sync(sc->tulip_setup_tag, sc->tulip_setup_map, + BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE); #else - nextout->d_length1 = sizeof(sc->tulip_setupbuf); nextout->d_addr1 = TULIP_KVATOPHYS(sc, sc->tulip_setupbuf); #endif + TULIP_TXDESC_PRESYNC(ri); + CTR1(KTR_TULIP, "tulip_txput_setup: using descriptor %td", + ri->ri_nextout - ri->ri_first); /* * Advance the ring for the next transmit packet. @@ -4388,13 +4514,13 @@ * may have been set up above if we ran out of room in the * ring. */ - ri->ri_nextout->d_status = 0; - TULIP_TXDESC_PRESYNC(sc, ri->ri_nextout, sizeof(u_int32_t)); + ri->ri_nextout->di_desc->d_status = 0; + TULIP_TXDESC_PRESYNC(ri); nextout->d_status = TULIP_DSTS_OWNER; /* * Flush the ownwership of the current descriptor */ - TULIP_TXDESC_PRESYNC(sc, nextout, sizeof(u_int32_t)); + TULIP_TXDESC_PRESYNC(ri); TULIP_CSR_WRITE(sc, csr_txpoll, 1); if ((sc->tulip_intrmask & TULIP_STS_TXINTR) == 0) { sc->tulip_intrmask |= TULIP_STS_TXINTR; @@ -4451,6 +4577,7 @@ error = EINVAL; break; } + /* XXX: ifnet locking? */ ifp->if_mtu = ifr->ifr_mtu; TULIP_UNLOCK(sc); break; @@ -4483,11 +4610,15 @@ { TULIP_PERFSTART(ifstart) tulip_softc_t * const sc = (tulip_softc_t *)ifp->if_softc; + static int foo; if (ifp->if_drv_flags & IFF_DRV_RUNNING) { TULIP_LOCK(sc); tulip_start(sc); TULIP_UNLOCK(sc); + } else if (foo < 10) { + if_printf(ifp, "tulip_ifstart when not running\n"); + foo++; } TULIP_PERFEND(ifstart); @@ -4500,9 +4631,12 @@ TULIP_LOCK_ASSERT(sc); + CTR0(KTR_TULIP, "tulip_start invoked"); if ((sc->tulip_flags & (TULIP_WANTSETUP|TULIP_TXPROBE_ACTIVE)) == TULIP_WANTSETUP) tulip_txput_setup(sc); + CTR1(KTR_TULIP, "tulip_start: %d tx packets pending", + sc->tulip_ifp->if_snd.ifq_len); while (!IFQ_DRV_IS_EMPTY(&sc->tulip_ifp->if_snd)) { IFQ_DRV_DEQUEUE(&sc->tulip_ifp->if_snd, m); if(m == NULL) @@ -4539,6 +4673,7 @@ sc->tulip_dbg.dbg_last_rxintrs = sc->tulip_dbg.dbg_rxintrs; #endif /* TULIP_DEBUG */ + /* XXX: ifnet locking */ sc->tulip_ifp->if_timer = 1; /* * These should be rare so do a bulk test up front so we can just skip @@ -4661,130 +4796,193 @@ } #if defined(TULIP_BUS_DMA) -#if !defined(TULIP_BUS_DMA_NOTX) || !defined(TULIP_BUS_DMA_NORX) +/* Release memory for a single descriptor ring. */ +static void +tulip_busdma_freering(tulip_ringinfo_t *ri) +{ + int i; + + /* Release the DMA maps and tag for data buffers. */ + if (ri->ri_data_maps != NULL) { + for (i = 0; i < ri->ri_max; i++) { + if (ri->ri_data_maps[i] != NULL) { + bus_dmamap_destroy(ri->ri_data_tag, ri->ri_data_maps[i]); + ri->ri_data_maps[i] = NULL; + } + } + free(ri->ri_data_maps, M_DEVBUF); + ri->ri_data_maps = NULL; + } + if (ri->ri_data_tag != NULL) { + bus_dma_tag_destroy(ri->ri_data_tag); + ri->ri_data_tag = NULL; + } + + /* Release the DMA memory and tag for the ring descriptors. */ + if (ri->ri_dma_addr != 0) { + bus_dmamap_unload(ri->ri_ring_tag, ri->ri_ring_map); + ri->ri_dma_addr = 0; + } + if (ri->ri_descs != NULL) { + bus_dmamem_free(ri->ri_ring_tag, ri->ri_descs, ri->ri_ring_map); + ri->ri_ring_map = NULL; + ri->ri_descs = NULL; + } + if (ri->ri_ring_tag != NULL) { + bus_dma_tag_destroy(ri->ri_ring_tag); + ri->ri_ring_tag = NULL; + } +} + +/* Allocate memory for a single descriptor ring. */ static int -tulip_busdma_allocmem( +tulip_busdma_allocring( + device_t dev, tulip_softc_t * const sc, - size_t size, - bus_dmamap_t *map_p, - tulip_desc_t **desc_p) + size_t count, + bus_size_t maxsize, + int nsegs, + tulip_ringinfo_t *ri, + const char *name) { - bus_dma_segment_t segs[1]; - int nsegs, error; - error = bus_dmamem_alloc(sc->tulip_dmatag, size, 1, PAGE_SIZE, - 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_NOWAIT, &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); + size_t size; + int error, i; + + /* First, setup a tag. */ + ri->ri_max = count; + size = count * sizeof(tulip_desc_t); + error = bus_dma_tag_create(NULL, PAGE_SIZE, 0, BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, size, 1, size, 0, NULL, NULL, + &ri->ri_ring_tag); + if (error) { + device_printf(dev, "failed to allocate %s descriptor ring dma tag\n", + name); + return (error); + } + + /* Next, allocate memory for the descriptors. */ + error = bus_dmamem_alloc(ri->ri_ring_tag, (void **)&ri->ri_descs, + BUS_DMA_NOWAIT | BUS_DMA_ZERO, &ri->ri_ring_map); + if (error) { + device_printf(dev, "failed to allocate memory for %s descriptor ring\n", + name); + return (error); + } + + /* Map the descriptors. */ + error = bus_dmamap_load(ri->ri_ring_tag, ri->ri_ring_map, ri->ri_descs, + size, tulip_dma_map_addr, &ri->ri_dma_addr, BUS_DMA_NOWAIT); + if (error) { + device_printf(dev, "failed to get dma address for %s descriptor ring\n", + name); + return (error); + } + + /* Allocate a tag for the data buffers. */ + error = bus_dma_tag_create(NULL, 4, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + maxsize, nsegs, TULIP_DATA_PER_DESC, 0, NULL, NULL, &ri->ri_data_tag); + if (error) { + device_printf(dev, "failed to allocate %s buffer dma tag\n", name); + return (error); + } + + /* Allocate maps for the data buffers. */ + ri->ri_data_maps = malloc(sizeof(bus_dmamap_t) * count, M_DEVBUF, + M_WAITOK | M_ZERO); + for (i = 0; i < count; i++) { + error = bus_dmamap_create(ri->ri_data_tag, 0, &ri->ri_data_maps[i]); + if (error) { + device_printf(dev, "failed to create map for %s buffer %d\n", + name, i); + return (error); } - if (error) - bus_dmamem_free(sc->tulip_dmatag, segs, nsegs); - else - *desc_p = desc; } - return error; + + return (0); } -#endif + +/* Release busdma maps, tags, and memory. */ +static void +tulip_busdma_cleanup(tulip_softc_t * const sc) +{ + + /* Release resources for the setup descriptor. */ + if (sc->tulip_setup_dma_addr != 0) { + bus_dmamap_unload(sc->tulip_setup_tag, sc->tulip_setup_map); + sc->tulip_setup_dma_addr = 0; + } + if (sc->tulip_setupbuf != NULL) { + bus_dmamem_free(sc->tulip_setup_tag, sc->tulip_setupdata, + sc->tulip_setup_map); + sc->tulip_setup_map = NULL; + sc->tulip_setupbuf = NULL; + } + if (sc->tulip_setup_tag != NULL) { + bus_dma_tag_destroy(sc->tulip_setup_tag); + sc->tulip_setup_tag = NULL; + } + + /* Release the transmit ring. */ + tulip_busdma_freering(&sc->tulip_txinfo); + + /* Release the receive ring. */ + tulip_busdma_freering(&sc->tulip_rxinfo); +} + static int tulip_busdma_init( + device_t dev, tulip_softc_t * const sc) { - int error = 0; + int error; -#if !defined(TULIP_BUS_DMA_NOTX) /* - * Allocate dmamap for setup descriptor + * Allocate space and dmamap for transmit ring. */ - error = bus_dmamap_create(sc->tulip_dmatag, sizeof(sc->tulip_setupbuf), 2, - sizeof(sc->tulip_setupbuf), 0, BUS_DMA_NOWAIT, - &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); - } + error = tulip_busdma_allocring(dev, sc, TULIP_TXDESCS, TULIP_DATA_PER_DESC, + TULIP_MAX_TXSEG, &sc->tulip_txinfo, "transmit"); + if (error) + return (error); + /* - * Allocate space and dmamap for transmit ring + * Allocate space and dmamap for receive ring. We tell bus_dma that + * we can map MCLBYTES so that it will accept a full MCLBYTES cluster, + * but we will only map the first TULIP_RX_BUFLEN bytes. This is not + * a waste in practice though as an ethernet frame can easily fit + * in TULIP_RX_BUFLEN bytes nowadays. */ - if (error == 0) { - error = tulip_busdma_allocmem(sc, sizeof(tulip_desc_t) * TULIP_TXDESCS, - &sc->tulip_txdescmap, - &sc->tulip_txdescs); - } + error = tulip_busdma_allocring(dev, sc, TULIP_RXDESCS, MCLBYTES, 1, + &sc->tulip_rxinfo, "receive"); + if (error) + return (error); /* - * Allocate dmamaps for each transmit descriptors + * Allocate a DMA tag, memory, and map for setup descriptor */ - if (error == 0) { - while (error == 0 && sc->tulip_txmaps_free < TULIP_TXDESCS) { - 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]); - } + error = bus_dma_tag_create(NULL, 4, 0, + BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, + sizeof(sc->tulip_setupdata), 1, sizeof(sc->tulip_setupdata), 0, + NULL, NULL, &sc->tulip_setup_tag); + if (error) { + device_printf(dev, "failed to allocate setup descriptor dma tag\n"); + return (error); } -#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; + error = bus_dmamem_alloc(sc->tulip_setup_tag, (void **)&sc->tulip_setupbuf, + BUS_DMA_NOWAIT | BUS_DMA_ZERO, &sc->tulip_setup_map); + if (error) { + device_printf(dev, "failed to allocate memory for setup descriptor\n"); + return (error); } -#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); + error = bus_dmamap_load(sc->tulip_setup_tag, sc->tulip_setup_map, + sc->tulip_setupbuf, sizeof(sc->tulip_setupdata), + tulip_dma_map_addr, &sc->tulip_setup_dma_addr, BUS_DMA_NOWAIT); + if (error) { + device_printf(dev, "failed to get dma address for setup descriptor\n"); + return (error); } - /* - * Allocate dmamaps for each receive descriptors - */ - if (error == 0) { - while (error == 0 && sc->tulip_rxmaps_free < TULIP_RXDESCS) { - 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 */ @@ -4813,18 +5011,29 @@ sc->tulip_csrs.csr_15 = csr_base + 15 * csr_size; } -static void +static int tulip_initring( + device_t dev, tulip_softc_t * const sc, tulip_ringinfo_t * const ri, - tulip_desc_t *descs, int ndescs) { + int i; + + ri->ri_descinfo = malloc(sizeof(tulip_descinfo_t) * ndescs, M_DEVBUF, + M_WAITOK | M_ZERO); + for (i = 0; i < ndescs; i++) { + ri->ri_descinfo[i].di_desc = &ri->ri_descs[i]; +#ifdef TULIP_BUS_DMA + ri->ri_descinfo[i].di_map = &ri->ri_data_maps[i]; +#endif + } + ri->ri_first = ri->ri_descinfo; 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; + bzero(ri->ri_descs, sizeof(tulip_desc_t) * ri->ri_max); + ri->ri_last[-1].di_desc->d_flag = TULIP_DFLAG_ENDRING; + return (0); } /* @@ -5007,33 +5216,49 @@ mtx_init(TULIP_MUTEX(sc), MTX_NETWORK_LOCK, device_get_nameunit(dev), MTX_DEF); - callout_init(&sc->tulip_callout, CALLOUT_MPSAFE); + callout_init_mtx(&sc->tulip_callout, TULIP_MUTEX(sc), 0); tulips[unit] = sc; tulip_initcsrs(sc, csr_base + csroffset, csrsize); #if defined(TULIP_BUS_DMA) - if ((retval = tulip_busdma_init(sc)) != 0) { + if ((retval = tulip_busdma_init(dev, sc)) != 0) { printf("error initing bus_dma: %d\n", retval); + tulip_busdma_cleanup(sc); mtx_destroy(TULIP_MUTEX(sc)); return ENXIO; } + #else - sc->tulip_rxdescs = (tulip_desc_t *) malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, M_DEVBUF, M_NOWAIT); - sc->tulip_txdescs = (tulip_desc_t *) malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, M_DEVBUF, M_NOWAIT); - if (sc->tulip_rxdescs == NULL || sc->tulip_txdescs == NULL) { + sc->tulip_rxinfo.ri_descs = malloc(sizeof(tulip_desc_t) * TULIP_RXDESCS, + M_DEVBUF, M_NOWAIT); + sc->tulip_txinfo.ri_descs = malloc(sizeof(tulip_desc_t) * TULIP_TXDESCS, + M_DEVBUF, M_NOWAIT); + if (sc->tulip_rxinfo.ri_descs == NULL || + sc->tulip_txinfo.ri_descs == NULL) { device_printf(dev, "malloc failed\n"); - if (sc->tulip_rxdescs) - free((caddr_t) sc->tulip_rxdescs, M_DEVBUF); - if (sc->tulip_txdescs) - free((caddr_t) sc->tulip_txdescs, M_DEVBUF); + if (sc->tulip_rxinfo.ri_descs) + free(sc->tulip_rxinfo.ri_descs, M_DEVBUF); + if (sc->tulip_txinfo.ri_descs) + free(sc->tulip_txinfo.ri_descs, M_DEVBUF); mtx_destroy(TULIP_MUTEX(sc)); return ENXIO; } #endif - tulip_initring(sc, &sc->tulip_rxinfo, sc->tulip_rxdescs, TULIP_RXDESCS); - tulip_initring(sc, &sc->tulip_txinfo, sc->tulip_txdescs, TULIP_TXDESCS); + retval = tulip_initring(dev, sc, &sc->tulip_rxinfo, TULIP_RXDESCS); + if (retval == 0) + retval = tulip_initring(dev, sc, &sc->tulip_txinfo, TULIP_TXDESCS); + if (retval) { +#ifndef TULIP_BUS_DMA + free(sc->tulip_rxinfo.ri_descs, M_DEVBUF); + free(sc->tulip_txinfo.ri_descs, M_DEVBUF); +#else + tulip_busdma_cleanup(sc); +#endif + mtx_destroy(TULIP_MUTEX(sc)); + return retval; + } /* * Make sure there won't be any interrupts or such... @@ -5076,8 +5301,12 @@ if (res == 0 || bus_setup_intr(dev, res, INTR_TYPE_NET | INTR_MPSAFE, intr_rtn, sc, &ih)) { device_printf(dev, "couldn't map interrupt\n"); - free((caddr_t) sc->tulip_rxdescs, M_DEVBUF); - free((caddr_t) sc->tulip_txdescs, M_DEVBUF); +#ifndef TULIP_BUS_DMA + free(sc->tulip_rxinfo.ri_descs, M_DEVBUF); + free(sc->tulip_txinfo.ri_descs, M_DEVBUF); +#else + tulip_busdma_cleanup(sc); +#endif ether_ifdetach(sc->tulip_ifp); if_free(sc->tulip_ifp); mtx_destroy(TULIP_MUTEX(sc)); @@ -5109,3 +5338,118 @@ }; static devclass_t tulip_devclass; DRIVER_MODULE(de, pci, tulip_pci_driver, tulip_devclass, 0, 0); + +#ifdef DDB +void tulip_dumpring(int unit, int ring); +void tulip_dumpdesc(int unit, int ring, int desc); +void tulip_status(int unit); + +void +tulip_dumpring(int unit, int ring) +{ + tulip_softc_t *sc; + tulip_ringinfo_t *ri; + tulip_descinfo_t *di; + + if (unit < 0 || unit >= TULIP_MAX_DEVICES) { + db_printf("invalid unit %d\n", unit); + return; + } + sc = tulips[unit]; + if (sc == NULL) { + db_printf("unit %d not present\n", unit); + return; + } + + switch (ring) { + case 0: + db_printf("receive ring:\n"); + ri = &sc->tulip_rxinfo; + break; + case 1: + db_printf("transmit ring:\n"); + ri = &sc->tulip_txinfo; + break; + default: + db_printf("invalid ring %d\n", ring); + return; + } + + db_printf(" nextin: %td, nextout: %td, max: %d, free: %d\n", + ri->ri_nextin - ri->ri_first, ri->ri_nextout - ri->ri_first, + ri->ri_max, ri->ri_free); + for (di = ri->ri_first; di != ri->ri_last; di++) { + if (di->di_mbuf != NULL) + db_printf(" descriptor %td: mbuf %p\n", di - ri->ri_first, + di->di_mbuf); + else if (di->di_desc->d_flag & TULIP_DFLAG_TxSETUPPKT) + db_printf(" descriptor %td: setup packet\n", di - ri->ri_first); + } +} + +void +tulip_dumpdesc(int unit, int ring, int desc) +{ + tulip_softc_t *sc; + tulip_ringinfo_t *ri; + tulip_descinfo_t *di; + char *s; + + if (unit < 0 || unit >= TULIP_MAX_DEVICES) { + db_printf("invalid unit %d\n", unit); + return; + } + sc = tulips[unit]; + if (sc == NULL) { + db_printf("unit %d not present\n", unit); + return; + } + + switch (ring) { + case 0: + s = "receive"; + ri = &sc->tulip_rxinfo; + break; + case 1: + s = "transmit"; + ri = &sc->tulip_txinfo; + break; + default: + db_printf("invalid ring %d\n", ring); + return; + } + + if (desc < 0 || desc >= ri->ri_max) { + db_printf("invalid descriptor %d\n", desc); + return; + } + + db_printf("%s descriptor %d:\n", s, desc); + di = &ri->ri_first[desc]; + db_printf(" mbuf: %p\n", di->di_mbuf); + db_printf(" status: %08x flag: %03x\n", di->di_desc->d_status, + di->di_desc->d_flag); + db_printf(" addr1: %08x len1: %03x\n", di->di_desc->d_addr1, + di->di_desc->d_length1); + db_printf(" addr2: %08x len2: %03x\n", di->di_desc->d_addr2, + di->di_desc->d_length2); +} + +void +tulip_status(int unit) +{ + tulip_softc_t *sc; + + if (unit < 0 || unit >= TULIP_MAX_DEVICES) { + db_printf("invalid unit %d\n", unit); + return; + } + sc = tulips[unit]; + if (sc == NULL) { + db_printf("unit %d not present\n", unit); + return; + } + + db_printf("chip status: %08x\n", TULIP_CSR_READ(sc, csr_status)); +} +#endif --- //depot/vendor/freebsd/src/sys/pci/if_devar.h 2005/08/17 17:50:43 +++ //depot/user/jhb/acpipci/pci/if_devar.h 2005/08/17 19:40:59 @@ -88,12 +88,29 @@ * traditional FIFO ring. */ typedef struct { - 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 */ + tulip_desc_t *di_desc; + struct mbuf *di_mbuf; +#ifdef TULIP_BUS_DMA + bus_dmamap_t *di_map; +#endif +} tulip_descinfo_t; + +typedef struct { + tulip_descinfo_t *ri_first; /* first entry in ring */ + tulip_descinfo_t *ri_last; /* one after last entry */ + tulip_descinfo_t *ri_nextin; /* next to processed by host */ + tulip_descinfo_t *ri_nextout; /* next to processed by adapter */ int ri_max; int ri_free; + tulip_desc_t *ri_descs; + tulip_descinfo_t *ri_descinfo; +#ifdef TULIP_BUS_DMA + bus_dma_tag_t ri_ring_tag; + bus_dmamap_t ri_ring_map; + uint32_t ri_dma_addr; + bus_dma_tag_t ri_data_tag; + bus_dmamap_t *ri_data_maps; +#endif } tulip_ringinfo_t; /* @@ -496,20 +513,6 @@ struct tulip_softc { struct ifmedia tulip_ifmedia; int tulip_unit; -#if defined(TULIP_BUS_DMA) - bus_dma_tag_t tulip_dmatag; -#if !defined(TULIP_BUS_DMA_NOTX) - bus_dmamap_t tulip_setupmap; - bus_dmamap_t tulip_txdescmap; - bus_dmamap_t tulip_txmaps[TULIP_TXDESCS]; - unsigned int tulip_txmaps_free; -#endif -#if !defined(TULIP_BUS_DMA_NORX) - bus_dmamap_t tulip_rxdescmap; - bus_dmamap_t tulip_rxmaps[TULIP_RXDESCS]; - unsigned int tulip_rxmaps_free; -#endif -#endif struct ifnet *tulip_ifp; u_char tulip_enaddr[6]; bus_space_tag_t tulip_csrs_bst; @@ -550,8 +553,6 @@ #if defined(TULIP_PERFSTATS) struct tulip_perfstat tulip_perfstats[TULIP_PERF_MAX]; #endif - struct ifqueue tulip_txq; - struct ifqueue tulip_rxq; tulip_dot3_stats_t tulip_dot3stats; tulip_ringinfo_t tulip_rxinfo; tulip_ringinfo_t tulip_txinfo; @@ -560,7 +561,14 @@ * The setup buffers for sending the setup frame to the chip. one is * the one being sent while the other is the one being filled. */ +#ifdef TULIP_BUS_DMA + bus_dma_tag_t tulip_setup_tag; + bus_dmamap_t tulip_setup_map; + uint32_t tulip_setup_dma_addr; + u_int32_t *tulip_setupbuf; +#else u_int32_t tulip_setupbuf[192 / sizeof(u_int32_t)]; +#endif u_int32_t tulip_setupdata[192 / sizeof(u_int32_t)]; char tulip_boardid[24]; u_int8_t tulip_rombuf[128]; /* must be aligned */ @@ -571,8 +579,6 @@ u_int8_t tulip_connidx; tulip_srom_connection_t tulip_conntype; - tulip_desc_t *tulip_rxdescs; - tulip_desc_t *tulip_txdescs; struct callout tulip_callout; struct mtx tulip_mutex; }; @@ -838,73 +844,44 @@ */ #define TULIP_MAX_DEVICES 32 -#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_NOWAIT|BUS_DMA_ALLOCNOW, (mapp)) +#if defined(TULIP_BUS_DMA) +#define _TULIP_DESC_SYNC(ri, op) \ + bus_dmamap_sync((ri)->ri_ring_tag, (ri)->ri_ring_map, (op)) +#define _TULIP_MAP_SYNC(ri, di, op) \ + bus_dmamap_sync((ri)->ri_data_tag, *(di)->di_map, (op)) #else #ifdef __alpha__ -#define TULIP_RXDESC_PRESYNC(sc, di, s) alpha_mb() -#define TULIP_RXDESC_POSTSYNC(sc, di, s) alpha_mb() -#define TULIP_RXMAP_PRESYNC(sc, map) alpha_mb() -#define TULIP_RXMAP_POSTSYNC(sc, map) alpha_mb() +#define _TULIP_DESC_SYNC(ri, op) alpha_mb() +#define _TULIP_MAP_SYNC(ri, di, op) alpha_mb() #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_DESC_SYNC(ri, op) do { } while (0) +#define _TULIP_MAP_SYNC(ri, di, op) do { } while (0) #endif -#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_NOWAIT, (mapp)) -#else -#ifdef __alpha__ -#define TULIP_TXDESC_PRESYNC(sc, di, s) alpha_mb() -#define TULIP_TXDESC_POSTSYNC(sc, di, s) alpha_mb() -#define TULIP_TXMAP_PRESYNC(sc, map) alpha_mb() -#define TULIP_TXMAP_POSTSYNC(sc, map) alpha_mb() -#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) -#endif -#define TULIP_TXMAP_CREATE(sc, mapp) do { } while (0) -#endif +/* + * Descriptors are both read from and written to by the card (corresponding + * to DMA WRITE and READ operations in bus-dma backwards-speak). Receive + * maps are written to by the card (a DMA READ operation in bus-dma) and + * transmit buffers are read from by the card (a DMA WRITE operation in + * bus-dma). + */ +#define TULIP_RXDESC_PRESYNC(ri) \ + _TULIP_DESC_SYNC(ri, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define TULIP_RXDESC_POSTSYNC(ri) \ + _TULIP_DESC_SYNC(ri, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define TULIP_RXMAP_PRESYNC(ri, di) \ + _TULIP_MAP_SYNC(ri, di, BUS_DMASYNC_PREREAD) +#define TULIP_RXMAP_POSTSYNC(ri, di) \ + _TULIP_MAP_SYNC(ri, di, BUS_DMASYNC_POSTREAD) +#define TULIP_TXDESC_PRESYNC(ri) \ + _TULIP_DESC_SYNC(ri, BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE) +#define TULIP_TXDESC_POSTSYNC(ri) \ + _TULIP_DESC_SYNC(ri, BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE) +#define TULIP_TXMAP_PRESYNC(ri, di) \ + _TULIP_MAP_SYNC(ri, di, BUS_DMASYNC_PREWRITE) +#define TULIP_TXMAP_POSTSYNC(ri, di) \ + _TULIP_MAP_SYNC(ri, di, BUS_DMASYNC_POSTWRITE) #ifdef notyet #define SIOCGADDRROM _IOW('i', 240, struct ifreq) /* get 128 bytes of ROM */ @@ -917,7 +894,7 @@ #define loudprintf if (bootverbose) printf -#if !defined(TULIP_KVATOPHYS) && (!defined(TULIP_BUS_DMA) || defined(TULIP_BUS_DMA_NORX) || defined(TULIP_BUS_DMA_NOTX)) +#if !defined(TULIP_KVATOPHYS) && !defined(TULIP_BUS_DMA) #if defined(__alpha__) /* XXX XXX NEED REAL DMA MAPPING SUPPORT XXX XXX */ #define vtobus(va) alpha_XXX_dmamap((vm_offset_t)va) @@ -958,6 +935,7 @@ #define TULIP_CRC32_POLY 0xEDB88320UL /* CRC-32 Poly -- Little * Endian */ #define TULIP_MAX_TXSEG 30 +#define TULIP_MAX_FRAGS 2 #define TULIP_ADDREQUAL(a1, a2) \ (((u_int16_t *)a1)[0] == ((u_int16_t *)a2)[0] \