FreeBSD/sys/mips/idt/if_kr.c
/*
 * Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
 * pointers to the fragment pointers.
 */
Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
pointers to the fragment pointers.
Encapsulate an mbuf chain in a descriptor by coupling the mbuf data pointers to the fragment pointers .
static int
kr_encap(struct kr_softc *sc, struct mbuf **m_head)
{
	struct kr_txdesc	*txd;
	struct kr_desc		*desc, *prev_desc;
	bus_dma_segment_t	txsegs[KR_MAXFRAGS];
	uint32_t		link_addr;
	int			error, i, nsegs, prod, si, prev_prod;
	KR_LOCK_ASSERT(sc);
	prod = sc->kr_cdata.kr_tx_prod;
	txd = &sc->kr_cdata.kr_txdesc[prod];
	error = bus_dmamap_load_mbuf_sg(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap,
	    *m_head, txsegs, &nsegs, BUS_DMA_NOWAIT);
	if (error == EFBIG) {
		panic("EFBIG");
	} else if (error != 0)
		return (error);
	if (nsegs == 0) {
		m_freem(*m_head);
		*m_head = NULL;
		return (EIO);
	}
	if (sc->kr_cdata.kr_tx_cnt + nsegs >= (KR_TX_RING_CNT - 1)) {
		bus_dmamap_unload(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap);
		return (ENOBUFS);
	}
	txd->tx_m = *m_head;
	bus_dmamap_sync(sc->kr_cdata.kr_tx_tag, txd->tx_dmamap,
	    BUS_DMASYNC_PREWRITE);
	si = prod;
	prev_prod = prod;
	desc = prev_desc = NULL;
	for (i = 0; i < nsegs; i++) {
		desc = &sc->kr_rdata.kr_tx_ring[prod];
		desc->kr_ctl = KR_DMASIZE(txsegs[i].ds_len) | KR_CTL_IOF;
		if (i == 0)
			desc->kr_devcs = KR_DMATX_DEVCS_FD;
		desc->kr_ca = txsegs[i].ds_addr;
		desc->kr_link = 0;
		if (prev_desc)
			prev_desc->kr_link = KR_TX_RING_ADDR(sc, prod);
		sc->kr_cdata.kr_tx_cnt++;
		prev_desc = desc;
		KR_INC(prod, KR_TX_RING_CNT);
	}
	if (desc) {
		desc->kr_ctl |=  KR_CTL_COF;
		desc->kr_devcs |= KR_DMATX_DEVCS_LD;
	}
	sc->kr_cdata.kr_tx_prod = prod;
	bus_dmamap_sync(sc->kr_cdata.kr_tx_ring_tag,
	    sc->kr_cdata.kr_tx_ring_map,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
	if (KR_DMA_READ_REG(KR_DMA_TXCHAN, DMA_NDPTR) == 0) {
		KR_DMA_WRITE_REG(KR_DMA_TXCHAN, DMA_NDPTR, 
		    KR_TX_RING_ADDR(sc, si));
	}
	else {
		link_addr = KR_TX_RING_ADDR(sc, si);
		si = (si + KR_TX_RING_CNT - 1) % KR_TX_RING_CNT;
		desc = &sc->kr_rdata.kr_tx_ring[si];
		desc->kr_link = link_addr;
	}
	return (0);
}
static int kr_encap ( struct kr_softc * sc , struct mbuf * * m_head ) { struct kr_txdesc * txd ; struct kr_desc * desc , * prev_desc ; bus_dma_segment_t txsegs [ KR_MAXFRAGS ] ; uint32_t link_addr ; int error , i , nsegs , prod , si , prev_prod ; KR_LOCK_ASSERT ( sc ) ; prod = sc -> kr_cdata . kr_tx_prod ; txd = & sc -> kr_cdata . kr_txdesc [ prod ] ; error = bus_dmamap_load_mbuf_sg ( sc -> kr_cdata . kr_tx_tag , txd -> tx_dmamap , * m_head , txsegs , & nsegs , BUS_DMA_NOWAIT ) ; if ( error == EFBIG ) { panic ( " " ) ; } else if ( error != 0 ) return ( error ) ; if ( nsegs == 0 ) { m_freem ( * m_head ) ; * m_head = NULL ; return ( EIO ) ; } if ( sc -> kr_cdata . kr_tx_cnt + nsegs >= ( KR_TX_RING_CNT - 1 ) ) { bus_dmamap_unload ( sc -> kr_cdata . kr_tx_tag , txd -> tx_dmamap ) ; return ( ENOBUFS ) ; } txd -> tx_m = * m_head ; bus_dmamap_sync ( sc -> kr_cdata . kr_tx_tag , txd -> tx_dmamap , BUS_DMASYNC_PREWRITE ) ; si = prod ; prev_prod = prod ; desc = prev_desc = NULL ; for ( i = 0 ; i < nsegs ; i ++ ) { desc = & sc -> kr_rdata . kr_tx_ring [ prod ] ; desc -> kr_ctl = KR_DMASIZE ( txsegs [ i ] . ds_len ) | KR_CTL_IOF ; if ( i == 0 ) desc -> kr_devcs = KR_DMATX_DEVCS_FD ; desc -> kr_ca = txsegs [ i ] . ds_addr ; desc -> kr_link = 0 ; if ( prev_desc ) prev_desc -> kr_link = KR_TX_RING_ADDR ( sc , prod ) ; sc -> kr_cdata . kr_tx_cnt ++ ; prev_desc = desc ; KR_INC ( prod , KR_TX_RING_CNT ) ; } if ( desc ) { desc -> kr_ctl |= KR_CTL_COF ; desc -> kr_devcs |= KR_DMATX_DEVCS_LD ; } sc -> kr_cdata . kr_tx_prod = prod ; bus_dmamap_sync ( sc -> kr_cdata . kr_tx_ring_tag , sc -> kr_cdata . kr_tx_ring_map , BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE ) ; if ( KR_DMA_READ_REG ( KR_DMA_TXCHAN , DMA_NDPTR ) == 0 ) { KR_DMA_WRITE_REG ( KR_DMA_TXCHAN , DMA_NDPTR , KR_TX_RING_ADDR ( sc , si ) ) ; } else { link_addr = KR_TX_RING_ADDR ( sc , si ) ; si = ( si + KR_TX_RING_CNT - 1 ) % KR_TX_RING_CNT ; desc = & sc -> kr_rdata . kr_tx_ring [ si ] ; desc -> kr_link = link_addr ; } return ( 0 ) ; }
Encapsulate an mbuf chain in a descriptor by coupling the mbuf data
 pointers to the fragment pointers.
Encapsulate an mbuf chain in a descriptor by coupling the mbuf data pointers to the fragment pointers .
/* Check number of available descriptors. */ /* 
	 * Make a list of descriptors for this packet. DMA controller will
	 * walk through it while kr_link is not zero. The last one should
	 * have COF flag set, to pickup next chain from NDPTR
	 */ /* link with previous descriptor */ /* 
	 * Set COF for last descriptor and mark last fragment with LD flag
	 */ /* Update producer index. */ /* Sync descriptors. */ /* Start transmitting */ /* Check if new list is queued in NDPTR */ /* NDPTR is not busy - start new list */ /* Get previous descriptor */