FreeBSD/sys/dev/rt/if_rt.c
/*
 * rt_rx_eof - check for frames that done by DMA engine and pass it into
 * network subsystem.
 */
check for frames that done by DMA engine and pass it into
network subsystem.
check for frames that done by DMA engine and pass it into network subsystem .
static int
rt_rx_eof(struct rt_softc *sc, struct rt_softc_rx_ring *ring, int limit)
{
	struct ifnet *ifp;
	struct rt_rxdesc *desc;
	struct rt_softc_rx_data *data;
	struct mbuf *m, *mnew;
	bus_dma_segment_t segs[1];
	bus_dmamap_t dma_map;
	uint32_t index, desc_flags;
	int error, nsegs, len, nframes;
	ifp = sc->ifp;
	nframes = 0;
	while (limit != 0) {
		index = RT_READ(sc, sc->rx_drx_idx[0]);
		if (ring->cur == index)
			break;
		desc = &ring->desc[ring->cur];
		data = &ring->data[ring->cur];
		bus_dmamap_sync(ring->desc_dma_tag, ring->desc_dma_map,
		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
#ifdef IF_RT_DEBUG
		if ( sc->debug & RT_DEBUG_RX ) {
			printf("\nRX Descriptor[%#08x] dump:\n", (u_int)desc);
		        hexdump(desc, 16, 0, 0);
			printf("-----------------------------------\n");
		}
#endif
#ifdef DDONE_FIXED
		if (!(desc->sdl0 & htole16(RT_RXDESC_SDL0_DDONE))) {
			RT_DPRINTF(sc, RT_DEBUG_RX, "DDONE=0, try next\n");
			break;
		}
#endif
		len = le16toh(desc->sdl0) & 0x3fff;
		RT_DPRINTF(sc, RT_DEBUG_RX, "new frame len=%d\n", len);
		nframes++;
		mnew = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
		    MJUMPAGESIZE);
		if (mnew == NULL) {
			sc->rx_mbuf_alloc_errors++;
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
			goto skip;
		}
		mnew->m_len = mnew->m_pkthdr.len = MJUMPAGESIZE;
		error = bus_dmamap_load_mbuf_sg(ring->data_dma_tag,
		    ring->spare_dma_map, mnew, segs, &nsegs, BUS_DMA_NOWAIT);
		if (error != 0) {
			RT_DPRINTF(sc, RT_DEBUG_RX,
			    "could not load Rx mbuf DMA map: "
			    "error=%d, nsegs=%d\n",
			    error, nsegs);
			m_freem(mnew);
			sc->rx_mbuf_dmamap_errors++;
			if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
			goto skip;
		}
		KASSERT(nsegs == 1, ("%s: too many DMA segments",
			device_get_nameunit(sc->dev)));
		bus_dmamap_sync(ring->data_dma_tag, data->dma_map,
			BUS_DMASYNC_POSTREAD);
		bus_dmamap_unload(ring->data_dma_tag, data->dma_map);
		dma_map = data->dma_map;
		data->dma_map = ring->spare_dma_map;
		ring->spare_dma_map = dma_map;
		bus_dmamap_sync(ring->data_dma_tag, data->dma_map,
			BUS_DMASYNC_PREREAD);
		m = data->m;
		desc_flags = desc->word3;
		data->m = mnew;
		desc->sdp0 = htole32(segs[0].ds_addr+2);
		desc->sdl0 = htole32(segs[0].ds_len-2);
		desc->word3 = 0;
		RT_DPRINTF(sc, RT_DEBUG_RX,
		    "Rx frame: rxdesc flags=0x%08x\n", desc_flags);
		m->m_pkthdr.rcvif = ifp;
		m->m_data += 2;
		m->m_pkthdr.len = m->m_len = len;
		if ((ifp->if_capenable & IFCAP_RXCSUM) != 0) {
			if (desc_flags & (sc->csum_fail_ip|sc->csum_fail_l4)) {
				RT_DPRINTF(sc, RT_DEBUG_RX,
				    "rxdesc: crc error\n");
				if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
				if (!(ifp->if_flags & IFF_PROMISC)) {
				    m_freem(m);
				    goto skip;
				}
			}
			if ((desc_flags & sc->csum_fail_ip) == 0) {
				m->m_pkthdr.csum_flags |= CSUM_IP_CHECKED;
				m->m_pkthdr.csum_flags |= CSUM_IP_VALID;
				m->m_pkthdr.csum_data = 0xffff;
			}
			m->m_flags &= ~M_HASFCS;
		}
		(*ifp->if_input)(ifp, m);
skip:
		desc->sdl0 &= ~htole16(RT_RXDESC_SDL0_DDONE);
		bus_dmamap_sync(ring->desc_dma_tag, ring->desc_dma_map,
			BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
		ring->cur = (ring->cur + 1) % RT_SOFTC_RX_RING_DATA_COUNT;
		limit--;
	}
	if (ring->cur == 0)
		RT_WRITE(sc, sc->rx_calc_idx[0],
			RT_SOFTC_RX_RING_DATA_COUNT - 1);
	else
		RT_WRITE(sc, sc->rx_calc_idx[0],
			ring->cur - 1);
	RT_DPRINTF(sc, RT_DEBUG_RX, "Rx eof: nframes=%d\n", nframes);
	sc->rx_packets += nframes;
	return (limit == 0);
}
static int rt_rx_eof ( struct rt_softc * sc , struct rt_softc_rx_ring * ring , int limit ) { struct ifnet * ifp ; struct rt_rxdesc * desc ; struct rt_softc_rx_data * data ; struct mbuf * m , * mnew ; bus_dma_segment_t segs [ 1 ] ; bus_dmamap_t dma_map ; uint32_t index , desc_flags ; int error , nsegs , len , nframes ; ifp = sc -> ifp ; nframes = 0 ; while ( limit != 0 ) { index = RT_READ ( sc , sc -> rx_drx_idx [ 0 ] ) ; if ( ring -> cur == index ) break ; desc = & ring -> desc [ ring -> cur ] ; data = & ring -> data [ ring -> cur ] ; bus_dmamap_sync ( ring -> desc_dma_tag , ring -> desc_dma_map , BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE ) ; #ifdef IF_RT_DEBUG if ( sc -> debug & RT_DEBUG_RX ) { printf ( " \n \n " , ( u_int ) desc ) ; hexdump ( desc , 16 , 0 , 0 ) ; printf ( " \n " ) ; } #endif #ifdef DDONE_FIXED if ( ! ( desc -> sdl0 & htole16 ( RT_RXDESC_SDL0_DDONE ) ) ) { RT_DPRINTF ( sc , RT_DEBUG_RX , " \n " ) ; break ; } #endif len = le16toh ( desc -> sdl0 ) & 0x3fff ; RT_DPRINTF ( sc , RT_DEBUG_RX , " \n " , len ) ; nframes ++ ; mnew = m_getjcl ( M_NOWAIT , MT_DATA , M_PKTHDR , MJUMPAGESIZE ) ; if ( mnew == NULL ) { sc -> rx_mbuf_alloc_errors ++ ; if_inc_counter ( ifp , IFCOUNTER_IERRORS , 1 ) ; goto skip ; } mnew -> m_len = mnew -> m_pkthdr . len = MJUMPAGESIZE ; error = bus_dmamap_load_mbuf_sg ( ring -> data_dma_tag , ring -> spare_dma_map , mnew , segs , & nsegs , BUS_DMA_NOWAIT ) ; if ( error != 0 ) { RT_DPRINTF ( sc , RT_DEBUG_RX , " " " \n " , error , nsegs ) ; m_freem ( mnew ) ; sc -> rx_mbuf_dmamap_errors ++ ; if_inc_counter ( ifp , IFCOUNTER_IERRORS , 1 ) ; goto skip ; } KASSERT ( nsegs == 1 , ( " " , device_get_nameunit ( sc -> dev ) ) ) ; bus_dmamap_sync ( ring -> data_dma_tag , data -> dma_map , BUS_DMASYNC_POSTREAD ) ; bus_dmamap_unload ( ring -> data_dma_tag , data -> dma_map ) ; dma_map = data -> dma_map ; data -> dma_map = ring -> spare_dma_map ; ring -> spare_dma_map = dma_map ; bus_dmamap_sync ( ring -> data_dma_tag , data -> dma_map , BUS_DMASYNC_PREREAD ) ; m = data -> m ; desc_flags = desc -> word3 ; data -> m = mnew ; desc -> sdp0 = htole32 ( segs [ 0 ] . ds_addr + 2 ) ; desc -> sdl0 = htole32 ( segs [ 0 ] . ds_len - 2 ) ; desc -> word3 = 0 ; RT_DPRINTF ( sc , RT_DEBUG_RX , " \n " , desc_flags ) ; m -> m_pkthdr . rcvif = ifp ; m -> m_data += 2 ; m -> m_pkthdr . len = m -> m_len = len ; if ( ( ifp -> if_capenable & IFCAP_RXCSUM ) != 0 ) { if ( desc_flags & ( sc -> csum_fail_ip | sc -> csum_fail_l4 ) ) { RT_DPRINTF ( sc , RT_DEBUG_RX , " \n " ) ; if_inc_counter ( ifp , IFCOUNTER_IERRORS , 1 ) ; if ( ! ( ifp -> if_flags & IFF_PROMISC ) ) { m_freem ( m ) ; goto skip ; } } if ( ( desc_flags & sc -> csum_fail_ip ) == 0 ) { m -> m_pkthdr . csum_flags |= CSUM_IP_CHECKED ; m -> m_pkthdr . csum_flags |= CSUM_IP_VALID ; m -> m_pkthdr . csum_data = 0xffff ; } m -> m_flags &= ~ M_HASFCS ; } ( * ifp -> if_input ) ( ifp , m ) ; skip : desc -> sdl0 &= ~ htole16 ( RT_RXDESC_SDL0_DDONE ) ; bus_dmamap_sync ( ring -> desc_dma_tag , ring -> desc_dma_map , BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE ) ; ring -> cur = ( ring -> cur + 1 ) % RT_SOFTC_RX_RING_DATA_COUNT ; limit -- ; } if ( ring -> cur == 0 ) RT_WRITE ( sc , sc -> rx_calc_idx [ 0 ] , RT_SOFTC_RX_RING_DATA_COUNT - 1 ) ; else RT_WRITE ( sc , sc -> rx_calc_idx [ 0 ] , ring -> cur - 1 ) ; RT_DPRINTF ( sc , RT_DEBUG_RX , " \n " , nframes ) ; sc -> rx_packets += nframes ; return ( limit == 0 ) ; }
rt_rx_eof - check for frames that done by DMA engine and pass it into
 network subsystem.
rt_rx_eof - check for frames that done by DMA engine and pass it into network subsystem .
/*	struct rt_softc_rx_ring *ring; */ /*	ring = &sc->rx_ring[0]; */ /* XXX Sometime device don`t set DDONE bit */ /* Add 2 for proper align of RX IP header */ /* Add 2 to fix data align, after sdp0 = addr + 2 */ /* check for crc errors */ /*check for valid checksum*/