Example #1
0
void
imxenet_recv(struct imxenet_softc *sc)
{
	struct ifnet *ifp = &sc->sc_ac.ac_if;

	bus_dmamap_sync(sc->rbdma.dma_tag, sc->rbdma.dma_map,
	    0, sc->rbdma.dma_size,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);

	bus_dmamap_sync(sc->rxdma.dma_tag, sc->rxdma.dma_map,
	    0, sc->rxdma.dma_size,
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);

	while (!(sc->rx_desc_base[sc->cur_rx].status & ENET_RXD_EMPTY))
	{
		struct mbuf *m;
		m = imxenet_newbuf();

		if (m == NULL) {
			ifp->if_ierrors++;
			goto done;
		}

		ifp->if_ipackets++;
		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = sc->rx_desc_base[sc->cur_rx].data_length;
		m_adj(m, ETHER_ALIGN);

		memcpy(mtod(m, char *), sc->rx_buffer_base[sc->cur_rx].data,
		    sc->rx_desc_base[sc->cur_rx].data_length);

		sc->rx_desc_base[sc->cur_rx].status |= ENET_RXD_EMPTY;
		sc->rx_desc_base[sc->cur_rx].data_length = 0;

		bus_dmamap_sync(sc->rbdma.dma_tag, sc->rbdma.dma_map,
		    ENET_MAX_PKT_SIZE * sc->cur_rx, ENET_MAX_PKT_SIZE,
		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

		bus_dmamap_sync(sc->rxdma.dma_tag, sc->rxdma.dma_map,
		    sizeof(struct imxenet_buf_desc) * sc->cur_rx,
		    sizeof(struct imxenet_buf_desc),
		    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

		if (sc->rx_desc_base[sc->cur_rx].status & ENET_RXD_WRAP)
			sc->cur_rx = 0;
		else
			sc->cur_rx++;

		/* push the packet up */
#if NBPFILTER > 0
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
		ether_input_mbuf(ifp, m);
	}

done:
	/* rx descriptors are ready */
	HWRITE4(sc, ENET_RDAR, ENET_RDAR_RDAR);
}
Example #2
0
void
mace_read(struct mc_softc *sc, caddr_t pkt, int len)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	struct mbuf *m;

	if (len <= sizeof(struct ether_header) ||
	    len > ETHERMTU + sizeof(struct ether_header)) {
#ifdef MCDEBUG
		printf("%s: invalid packet size %d; dropping\n",
		    sc->sc_dev.dv_xname, len);
#endif
		ifp->if_ierrors++;
		return;
	}

	m = mace_get(sc, pkt, len);
	if (m == NULL) {
		ifp->if_ierrors++;
		return;
	}

	ifp->if_ipackets++;

#if NBPFILTER > 0
	/* Pass the packet to any BPF listeners. */
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

	/* Pass the packet up. */
	ether_input_mbuf(ifp, m);
}
Example #3
0
/*
 * Pass a packet to the higher levels.
 */
static __inline__ void
be_read(struct be_softc *sc, int idx, int len)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	struct mbuf *m;

	if (len <= sizeof(struct ether_header) ||
	    len > ETHERMTU + sizeof(struct ether_header)) {

		printf("%s: invalid packet size %d; dropping\n",
		    ifp->if_xname, len);

		ifp->if_ierrors++;
		return;
	}

	/*
	 * Pull packet off interface.
	 */
	m = be_get(sc, idx, len);
	if (m == NULL) {
		ifp->if_ierrors++;
		return;
	}
	ifp->if_ipackets++;

#if NBPFILTER > 0
	/*
	 * Check if there's a BPF listener on this interface.
	 * If so, hand off the raw packet to BPF.
	 */
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
	/* Pass the packet up. */
	ether_input_mbuf(ifp, m);
}
Example #4
0
/*
 * Receive interrupt.
 */
int
cas_rint(struct cas_softc *sc)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	bus_space_tag_t t = sc->sc_memt;
	bus_space_handle_t h = sc->sc_memh;
	struct cas_rxsoft *rxs;
	struct mbuf *m;
	u_int64_t word[4];
	int len, off, idx;
	int i, skip;
	caddr_t cp;

	for (i = sc->sc_rxptr;; i = CAS_NEXTRX(i + skip)) {
		CAS_CDRXCSYNC(sc, i,
		    BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE);

		word[0] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[0]);
		word[1] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[1]);
		word[2] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[2]);
		word[3] = CAS_DMA_READ(sc->sc_rxcomps[i].cc_word[3]);

		/* Stop if the hardware still owns the descriptor. */
		if ((word[0] & CAS_RC0_TYPE) == 0 || word[3] & CAS_RC3_OWN)
			break;

		len = CAS_RC1_HDR_LEN(word[1]);
		if (len > 0) {
			off = CAS_RC1_HDR_OFF(word[1]);
			idx = CAS_RC1_HDR_IDX(word[1]);
			rxs = &sc->sc_rxsoft[idx];

			DPRINTF(sc, ("hdr at idx %d, off %d, len %d\n",
			    idx, off, len));

			bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0,
			    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);

			cp = rxs->rxs_kva + off * 256;
			m = m_devget(cp, len + ETHER_ALIGN, 0, ifp, NULL);
			
			if (word[0] & CAS_RC0_RELEASE_HDR)
				cas_add_rxbuf(sc, idx);

			if (m != NULL) {
				m_adj(m, ETHER_ALIGN);

#if NBPFILTER > 0
				/*
				 * Pass this up to any BPF listeners, but only
				 * pass it up the stack if its for us.
				 */
				if (ifp->if_bpf)
					bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif /* NBPFILTER > 0 */

				ifp->if_ipackets++;
				ether_input_mbuf(ifp, m);
			} else
				ifp->if_ierrors++;
		}

		len = CAS_RC0_DATA_LEN(word[0]);
		if (len > 0) {
			off = CAS_RC0_DATA_OFF(word[0]);
			idx = CAS_RC0_DATA_IDX(word[0]);
			rxs = &sc->sc_rxsoft[idx];

			DPRINTF(sc, ("data at idx %d, off %d, len %d\n",
			    idx, off, len));

			bus_dmamap_sync(sc->sc_dmatag, rxs->rxs_dmamap, 0,
			    rxs->rxs_dmamap->dm_mapsize, BUS_DMASYNC_POSTREAD);

			/* XXX We should not be copying the packet here. */
			cp = rxs->rxs_kva + off;
			m = m_devget(cp, len + ETHER_ALIGN, 0, ifp, NULL);

			if (word[0] & CAS_RC0_RELEASE_DATA)
				cas_add_rxbuf(sc, idx);

			if (m != NULL) {
				m_adj(m, ETHER_ALIGN);

#if NBPFILTER > 0
				/*
				 * Pass this up to any BPF listeners, but only
				 * pass it up the stack if its for us.
				 */
				if (ifp->if_bpf)
					bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif /* NBPFILTER > 0 */

				ifp->if_ipackets++;
				ether_input_mbuf(ifp, m);
			} else
				ifp->if_ierrors++;
		}

		if (word[0] & CAS_RC0_SPLIT)
			printf("split packet\n");

		skip = CAS_RC0_SKIP(word[0]);
	}

	while (sc->sc_rxptr != i) {
		sc->sc_rxcomps[sc->sc_rxptr].cc_word[0] = 0;
		sc->sc_rxcomps[sc->sc_rxptr].cc_word[1] = 0;
		sc->sc_rxcomps[sc->sc_rxptr].cc_word[2] = 0;
		sc->sc_rxcomps[sc->sc_rxptr].cc_word[3] =
		    CAS_DMA_WRITE(CAS_RC3_OWN);
		CAS_CDRXCSYNC(sc, sc->sc_rxptr,
		    BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);

		sc->sc_rxptr = CAS_NEXTRX(sc->sc_rxptr);
	}

	bus_space_write_4(t, h, CAS_RX_COMP_TAIL, sc->sc_rxptr);

	DPRINTF(sc, ("cas_rint: done sc->rxptr %d, complete %d\n",
		sc->sc_rxptr, bus_space_read_4(t, h, CAS_RX_COMPLETION)));

	return (1);
}
Example #5
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
void
kue_rxeof(usbd_xfer_handle xfer, usbd_private_handle priv, usbd_status status)
{
	struct kue_chain	*c = priv;
	struct kue_softc	*sc = c->kue_sc;
	struct ifnet		*ifp = GET_IFP(sc);
	struct mbuf		*m;
	int			total_len = 0;
	int			s;

	DPRINTFN(10,("%s: %s: enter status=%d\n", sc->kue_dev.dv_xname,
		     __func__, status));

	if (sc->kue_dying)
		return;

	if (!(ifp->if_flags & IFF_RUNNING))
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		sc->kue_rx_errs++;
		if (usbd_ratecheck(&sc->kue_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			    sc->kue_dev.dv_xname, sc->kue_rx_errs,
			    usbd_errstr(status));
			sc->kue_rx_errs = 0;
		}
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(sc->kue_ep[KUE_ENDPT_RX]);
		goto done;
	}

	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);

	DPRINTFN(10,("%s: %s: total_len=%d len=%d\n", sc->kue_dev.dv_xname,
		     __func__, total_len,
		     UGETW(mtod(c->kue_mbuf, u_int8_t *))));

	if (total_len <= 1)
		goto done;

	m = c->kue_mbuf;
	/* copy data to mbuf */
	memcpy(mtod(m, char *), c->kue_buf, total_len);

	/* No errors; receive the packet. */
	total_len = UGETW(mtod(m, u_int8_t *));
	m_adj(m, sizeof(u_int16_t));

	if (total_len < sizeof(struct ether_header)) {
		ifp->if_ierrors++;
		goto done;
	}

	ifp->if_ipackets++;
	m->m_pkthdr.len = m->m_len = total_len;

	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	/* XXX ugly */
	if (kue_newbuf(sc, c, NULL) == ENOBUFS) {
		ifp->if_ierrors++;
		goto done1;
	}

#if NBPFILTER > 0
	/*
	 * Handle BPF listeners. Let the BPF user see the packet, but
	 * don't pass it up to the ether_input() layer unless it's
	 * a broadcast packet, multicast packet, matches our ethernet
	 * address or the interface is in promiscuous mode.
	 */
	if (ifp->if_bpf)
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

	DPRINTFN(10,("%s: %s: deliver %d\n", sc->kue_dev.dv_xname,
		    __func__, m->m_len));
	ether_input_mbuf(ifp, m);
 done1:
	splx(s);

 done:

	/* Setup new transfer. */
	usbd_setup_xfer(c->kue_xfer, sc->kue_ep[KUE_ENDPT_RX],
	    c, c->kue_buf, KUE_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, kue_rxeof);
	usbd_transfer(c->kue_xfer);

	DPRINTFN(10,("%s: %s: start rx\n", sc->kue_dev.dv_xname,
		    __func__));
}
Example #6
0
void
nfe_rxeof(struct nfe_softc *sc)
{
	struct ifnet *ifp = &sc->sc_arpcom.ac_if;
	struct nfe_desc32 *desc32;
	struct nfe_desc64 *desc64;
	struct nfe_rx_data *data;
	struct nfe_jbuf *jbuf;
	struct mbuf *m, *mnew;
	bus_addr_t physaddr;
	uint16_t flags;
	int error, len;

	for (;;) {
		data = &sc->rxq.data[sc->rxq.cur];

		if (sc->sc_flags & NFE_40BIT_ADDR) {
			desc64 = &sc->rxq.desc64[sc->rxq.cur];
			nfe_rxdesc64_sync(sc, desc64, BUS_DMASYNC_POSTREAD);

			flags = letoh16(desc64->flags);
			len = letoh16(desc64->length) & 0x3fff;
		} else {
			desc32 = &sc->rxq.desc32[sc->rxq.cur];
			nfe_rxdesc32_sync(sc, desc32, BUS_DMASYNC_POSTREAD);

			flags = letoh16(desc32->flags);
			len = letoh16(desc32->length) & 0x3fff;
		}

		if (flags & NFE_RX_READY)
			break;

		if ((sc->sc_flags & (NFE_JUMBO_SUP | NFE_40BIT_ADDR)) == 0) {
			if (!(flags & NFE_RX_VALID_V1))
				goto skip;

			if ((flags & NFE_RX_FIXME_V1) == NFE_RX_FIXME_V1) {
				flags &= ~NFE_RX_ERROR;
				len--;	/* fix buffer length */
			}
		} else {
			if (!(flags & NFE_RX_VALID_V2))
				goto skip;

			if ((flags & NFE_RX_FIXME_V2) == NFE_RX_FIXME_V2) {
				flags &= ~NFE_RX_ERROR;
				len--;	/* fix buffer length */
			}
		}

		if (flags & NFE_RX_ERROR) {
			ifp->if_ierrors++;
			goto skip;
		}

		/*
		 * Try to allocate a new mbuf for this ring element and load
		 * it before processing the current mbuf. If the ring element
		 * cannot be loaded, drop the received packet and reuse the
		 * old mbuf. In the unlikely case that the old mbuf can't be
		 * reloaded either, explicitly panic.
		 */
		MGETHDR(mnew, M_DONTWAIT, MT_DATA);
		if (mnew == NULL) {
			ifp->if_ierrors++;
			goto skip;
		}

		if (sc->sc_flags & NFE_USE_JUMBO) {
			if ((jbuf = nfe_jalloc(sc)) == NULL) {
				m_freem(mnew);
				ifp->if_ierrors++;
				goto skip;
			}
			MEXTADD(mnew, jbuf->buf, NFE_JBYTES, 0, nfe_jfree, sc);

			bus_dmamap_sync(sc->sc_dmat, sc->rxq.jmap,
			    mtod(data->m, caddr_t) - sc->rxq.jpool, NFE_JBYTES,
			    BUS_DMASYNC_POSTREAD);

			physaddr = jbuf->physaddr;
		} else {
			MCLGET(mnew, M_DONTWAIT);
			if (!(mnew->m_flags & M_EXT)) {
				m_freem(mnew);
				ifp->if_ierrors++;
				goto skip;
			}

			bus_dmamap_sync(sc->sc_dmat, data->map, 0,
			    data->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
			bus_dmamap_unload(sc->sc_dmat, data->map);

			error = bus_dmamap_load(sc->sc_dmat, data->map,
			    mtod(mnew, void *), MCLBYTES, NULL,
			    BUS_DMA_READ | BUS_DMA_NOWAIT);
			if (error != 0) {
				m_freem(mnew);

				/* try to reload the old mbuf */
				error = bus_dmamap_load(sc->sc_dmat, data->map,
				    mtod(data->m, void *), MCLBYTES, NULL,
				    BUS_DMA_READ | BUS_DMA_NOWAIT);
				if (error != 0) {
					/* very unlikely that it will fail.. */
					panic("%s: could not load old rx mbuf",
					    sc->sc_dev.dv_xname);
				}
				ifp->if_ierrors++;
				goto skip;
			}
			physaddr = data->map->dm_segs[0].ds_addr;
		}

		/*
		 * New mbuf successfully loaded, update Rx ring and continue
		 * processing.
		 */
		m = data->m;
		data->m = mnew;

		/* finalize mbuf */
		m->m_pkthdr.len = m->m_len = len;
		m->m_pkthdr.rcvif = ifp;

		if ((sc->sc_flags & NFE_HW_CSUM) &&
		    (flags & NFE_RX_IP_CSUMOK)) {
			m->m_pkthdr.csum_flags |= M_IPV4_CSUM_IN_OK;
			if (flags & NFE_RX_UDP_CSUMOK)
				m->m_pkthdr.csum_flags |= M_UDP_CSUM_IN_OK;
			if (flags & NFE_RX_TCP_CSUMOK)
				m->m_pkthdr.csum_flags |= M_TCP_CSUM_IN_OK;
		}

#if NBPFILTER > 0
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
		ifp->if_ipackets++;
		ether_input_mbuf(ifp, m);

		/* update mapping address in h/w descriptor */
		if (sc->sc_flags & NFE_40BIT_ADDR) {
#if defined(__LP64__)
			desc64->physaddr[0] = htole32(physaddr >> 32);
#endif
			desc64->physaddr[1] = htole32(physaddr & 0xffffffff);
		} else {
Example #7
0
/* Receive interrupt handler */
void
bce_rxintr(struct bce_softc *sc)
{
	struct ifnet   *ifp = &sc->bce_ac.ac_if;
	struct rx_pph  *pph;
	struct mbuf    *m;
	int             curr;
	int             len;
	int             i;

	/* get pointer to active receive slot */
	curr = bus_space_read_4(sc->bce_btag, sc->bce_bhandle, BCE_DMA_RXSTATUS)
	    & RS_CD_MASK;
	curr = curr / sizeof(struct bce_dma_slot);
	if (curr >= BCE_NRXDESC)
		curr = BCE_NRXDESC - 1;

	/* process packets up to but not current packet being worked on */
	for (i = sc->bce_rxin; i != curr;
	    i + 1 > BCE_NRXDESC - 1 ? i = 0 : i++) {
		/* complete any post dma memory ops on packet */
		bus_dmamap_sync(sc->bce_dmatag, sc->bce_cdata.bce_rx_map[i], 0,
		    sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
		    BUS_DMASYNC_POSTREAD);

		/*
		 * If the packet had an error, simply recycle the buffer,
		 * resetting the len, and flags.
		 */
		pph = mtod(sc->bce_cdata.bce_rx_chain[i], struct rx_pph *);
		if (pph->flags & (RXF_NO | RXF_RXER | RXF_CRC | RXF_OV)) {
			ifp->if_ierrors++;
			pph->len = 0;
			pph->flags = 0;
			continue;
		}
		/* receive the packet */
		len = pph->len;
		if (len == 0)
			continue;	/* no packet if empty */
		pph->len = 0;
		pph->flags = 0;
		/* bump past pre header to packet */
		sc->bce_cdata.bce_rx_chain[i]->m_data +=
			BCE_PREPKT_HEADER_SIZE;

 		/*
		 * The chip includes the CRC with every packet.  Trim
		 * it off here.
		 */
		len -= ETHER_CRC_LEN;

		/*
		 * If the packet is small enough to fit in a
		 * single header mbuf, allocate one and copy
		 * the data into it.  This greatly reduces
		 * memory consumption when receiving lots
		 * of small packets.
		 *
		 * Otherwise, add a new buffer to the receive
		 * chain.  If this fails, drop the packet and
		 * recycle the old buffer.
		 */
		if (len <= (MHLEN - 2)) {
			MGETHDR(m, M_DONTWAIT, MT_DATA);
			if (m == NULL)
				goto dropit;
			m->m_data += 2;
			memcpy(mtod(m, caddr_t),
			 mtod(sc->bce_cdata.bce_rx_chain[i], caddr_t), len);
			sc->bce_cdata.bce_rx_chain[i]->m_data -=
				BCE_PREPKT_HEADER_SIZE;
		} else {
			m = sc->bce_cdata.bce_rx_chain[i];
			if (bce_add_rxbuf(sc, i) != 0) {
		dropit:
				ifp->if_ierrors++;
				/* continue to use old buffer */
				sc->bce_cdata.bce_rx_chain[i]->m_data -=
					BCE_PREPKT_HEADER_SIZE;
				bus_dmamap_sync(sc->bce_dmatag,
				    sc->bce_cdata.bce_rx_map[i], 0,
				    sc->bce_cdata.bce_rx_map[i]->dm_mapsize,
				    BUS_DMASYNC_PREREAD);
				continue;
			}
		}

		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = len;
		ifp->if_ipackets++;

#if NBPFILTER > 0
		/*
		 * Pass this up to any BPF listeners, but only
		 * pass it up the stack if it's for us.
		 */
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif				/* NBPFILTER > 0 */

		/* Pass it on. */
		ether_input_mbuf(ifp, m);

		/* re-check current in case it changed */
		curr = (bus_space_read_4(sc->bce_btag, sc->bce_bhandle,
		    BCE_DMA_RXSTATUS) & RS_CD_MASK) /
		    sizeof(struct bce_dma_slot);
		if (curr >= BCE_NRXDESC)
			curr = BCE_NRXDESC - 1;
	}
	sc->bce_rxin = curr;
}
Example #8
0
void
mec_rxintr(struct mec_softc *sc, uint32_t stat)
{
	bus_space_tag_t st = sc->sc_st;
	bus_space_handle_t sh = sc->sc_sh;
	struct ifnet *ifp = &sc->sc_ac.ac_if;
	struct mbuf *m;
	struct mec_rxdesc *rxd;
	uint64_t rxstat;
	u_int len;
	int i, last;

	DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: called\n"));

	bus_space_write_8(st, sh, MEC_RX_ALIAS, 0);

	last = (stat & MEC_INT_RX_MCL_FIFO_ALIAS) >> 8;
	/* XXX does alias count mod 32 even if 16 descs are set up? */
	last &= MEC_NRXDESC_MASK;

	if (stat & MEC_INT_RX_FIFO_UNDERFLOW)
		last = (last - 1) & MEC_NRXDESC_MASK;

	DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: rxptr %d last %d\n",
	    sc->sc_rxptr, last));
	for (i = sc->sc_rxptr; i != last; i = MEC_NEXTRX(i)) {

		MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_POSTREAD);
		rxd = &sc->sc_rxdesc[i];
		rxstat = rxd->rxd_stat;

		DPRINTF(MEC_DEBUG_RXINTR,
		    ("mec_rxintr: rxstat = 0x%llx, rxptr = %d\n",
		    rxstat, i));
		DPRINTF(MEC_DEBUG_RXINTR, ("mec_rxintr: rxfifo = 0x%x\n",
		    (u_int)bus_space_read_8(st, sh, MEC_RX_FIFO)));

		if ((rxstat & MEC_RXSTAT_RECEIVED) == 0) {
			/* Status not received but FIFO counted? Drop it! */
			goto dropit;
		}

		len = rxstat & MEC_RXSTAT_LEN;

		if (len < ETHER_MIN_LEN ||
		    len > ETHER_MAX_LEN) {
			/* Invalid length packet; drop it. */
			DPRINTF(MEC_DEBUG_RXINTR,
			    ("mec_rxintr: wrong packet\n"));
 dropit:
			ifp->if_ierrors++;
			rxd->rxd_stat = 0;
			MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD);
			bus_space_write_8(st, sh, MEC_MCL_RX_FIFO,
			    MEC_CDRXADDR(sc, i));
			continue;
		}

		if (rxstat &
		    (MEC_RXSTAT_BADPACKET |
		     MEC_RXSTAT_LONGEVENT |
		     MEC_RXSTAT_INVALID   |
		     MEC_RXSTAT_CRCERROR  |
		     MEC_RXSTAT_VIOLATION)) {
			printf("%s: mec_rxintr: status = 0x%llx\n",
			    sc->sc_dev.dv_xname, rxstat);
			goto dropit;
		}

		/*
		 * Now allocate an mbuf (and possibly a cluster) to hold
		 * the received packet.
		 */
		MGETHDR(m, M_DONTWAIT, MT_DATA);
		if (m == NULL) {
			printf("%s: unable to allocate RX mbuf\n",
			    sc->sc_dev.dv_xname);
			goto dropit;
		}
		if (len > (MHLEN - ETHER_ALIGN)) {
			MCLGET(m, M_DONTWAIT);
			if ((m->m_flags & M_EXT) == 0) {
				printf("%s: unable to allocate RX cluster\n",
				    sc->sc_dev.dv_xname);
				m_freem(m);
				m = NULL;
				goto dropit;
			}
		}

		/*
		 * Note MEC chip seems to insert 2 byte padding at the start of
		 * RX buffer, but we copy whole buffer to avoid unaligned copy.
		 */
		MEC_RXBUFSYNC(sc, i, len + ETHER_ALIGN, BUS_DMASYNC_POSTREAD);
		memcpy(mtod(m, caddr_t), rxd->rxd_buf,
		    ETHER_ALIGN + len - ETHER_CRC_LEN);
		MEC_RXBUFSYNC(sc, i, ETHER_MAX_LEN, BUS_DMASYNC_PREREAD);
		m->m_data += ETHER_ALIGN;

		/* Put RX buffer into FIFO again. */
		rxd->rxd_stat = 0;
		MEC_RXSTATSYNC(sc, i, BUS_DMASYNC_PREREAD);
		bus_space_write_8(st, sh, MEC_MCL_RX_FIFO, MEC_CDRXADDR(sc, i));

		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = len - ETHER_CRC_LEN;

		ifp->if_ipackets++;

#if NBPFILTER > 0
		/*
		 * Pass this up to any BPF listeners, but only
		 * pass it up the stack if it is for us.
		 */
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

		/* Pass it on. */
		ether_input_mbuf(ifp, m);
	}

	/* Update RX pointer. */
	sc->sc_rxptr = i;

	bus_space_write_8(st, sh, MEC_RX_ALIAS,
	    (MEC_NRXDESC << MEC_DMA_RX_INT_THRESH_SHIFT) |
	    MEC_DMA_RX_INT_ENABLE);
}
Example #9
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
void
ste_rxeof(struct ste_softc *sc)
{
        struct mbuf		*m;
        struct ifnet		*ifp;
	struct ste_chain_onefrag	*cur_rx;
	int			total_len = 0, count=0;
	u_int32_t		rxstat;

	ifp = &sc->arpcom.ac_if;

	while((rxstat = sc->ste_cdata.ste_rx_head->ste_ptr->ste_status)
	      & STE_RXSTAT_DMADONE) {
		if ((STE_RX_LIST_CNT - count) < 3)
			break;

		cur_rx = sc->ste_cdata.ste_rx_head;
		sc->ste_cdata.ste_rx_head = cur_rx->ste_next;

		/*
		 * If an error occurs, update stats, clear the
		 * status word and leave the mbuf cluster in place:
		 * it should simply get re-used next time this descriptor
	 	 * comes up in the ring.
		 */
		if (rxstat & STE_RXSTAT_FRAME_ERR) {
			ifp->if_ierrors++;
			cur_rx->ste_ptr->ste_status = 0;
			continue;
		}

		/*
		 * If there error bit was not set, the upload complete
		 * bit should be set which means we have a valid packet.
		 * If not, something truly strange has happened.
		 */
		if (!(rxstat & STE_RXSTAT_DMADONE)) {
			printf("%s: bad receive status -- packet dropped",
				sc->sc_dev.dv_xname);
			ifp->if_ierrors++;
			cur_rx->ste_ptr->ste_status = 0;
			continue;
		}

		/* No errors; receive the packet. */	
		m = cur_rx->ste_mbuf;
		total_len = cur_rx->ste_ptr->ste_status & STE_RXSTAT_FRAMELEN;

		/*
		 * Try to conjure up a new mbuf cluster. If that
		 * fails, it means we have an out of memory condition and
		 * should leave the buffer in place and continue. This will
		 * result in a lost packet, but there's little else we
		 * can do in this situation.
		 */
		if (ste_newbuf(sc, cur_rx, NULL) == ENOBUFS) {
			ifp->if_ierrors++;
			cur_rx->ste_ptr->ste_status = 0;
			continue;
		}

		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = total_len;

		ifp->if_ipackets++;

#if NBPFILTER > 0
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

		/* pass it on. */
		ether_input_mbuf(ifp, m);

		cur_rx->ste_ptr->ste_status = 0;
		count++;
	}

	return;
}
Example #10
0
/*
 * A frame has been uploaded: pass the resulting mbuf chain up to
 * the higher level protocols.
 */
void
ugl_rxeof(struct usbd_xfer *xfer, void *priv, usbd_status status)
{
	struct ugl_chain	*c = priv;
	struct ugl_softc	*sc = c->ugl_sc;
	struct ifnet		*ifp = GET_IFP(sc);
	struct mbuf		*m;
	int			total_len = 0;
	unsigned int		packet_len, packet_count;
	int			s;

	if (usbd_is_dying(sc->sc_udev))
		return;

	if (!(ifp->if_flags & IFF_RUNNING))
		return;

	if (status != USBD_NORMAL_COMPLETION) {
		if (status == USBD_NOT_STARTED || status == USBD_CANCELLED)
			return;
		sc->sc_rx_errs++;
		if (usbd_ratecheck(&sc->sc_rx_notice)) {
			printf("%s: %u usb errors on rx: %s\n",
			    sc->sc_dev.dv_xname, sc->sc_rx_errs,
			    usbd_errstr(status));
			sc->sc_rx_errs = 0;
		}
		if (status == USBD_STALLED)
			usbd_clear_endpoint_stall_async(sc->sc_ep[UGL_ENDPT_RX]);
		goto done;
	}

	usbd_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);

	DPRINTFN(9,("%s: %s: enter status=%d length=%d\n",
		    sc->sc_dev.dv_xname, __func__, status, total_len));

	if (total_len < offsetof(struct ugl_packet, pkt_data)) {
		printf("%s: bad header (length=%d)\n",
		    sc->sc_dev.dv_xname, total_len);

		goto done;
	}

	packet_count = UGETDW(c->ugl_buf->pkt_count);
	if (packet_count != UGL_RX_FRAMES) {
		printf("%s: bad packet count (%d)\n",
		    sc->sc_dev.dv_xname, packet_count);

		if (packet_count == 0)
			goto done;
	}

	packet_len = UGETDW(c->ugl_buf->pkt_length);
	if (total_len < packet_len) {
		printf("%s: bad packet size(%d), length=%d\n",
		    sc->sc_dev.dv_xname, packet_len, total_len);

		if (packet_len == 0)
			goto done;
	}

	m = c->ugl_mbuf;
	memcpy(mtod(c->ugl_mbuf, char *), c->ugl_buf->pkt_data, packet_len);

	ifp->if_ipackets++;
	m->m_pkthdr.len = m->m_len = packet_len;

	m->m_pkthdr.rcvif = ifp;

	s = splnet();

	/* XXX ugly */
	if (ugl_newbuf(sc, c, NULL) == ENOBUFS) {
		ifp->if_ierrors++;
		goto done1;
	}

#if NBPFILTER > 0
	/*
	 * Handle BPF listeners. Let the BPF user see the packet, but
	 * don't pass it up to the ether_input() layer unless it's
	 * a broadcast packet, multicast packet, matches our ethernet
	 * address or the interface is in promiscuous mode.
	 */
	if (ifp->if_bpf) {
		bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
	}
#endif

	DPRINTFN(10,("%s: %s: deliver %d\n", sc->sc_dev.dv_xname,
		    __func__, m->m_len));

	ether_input_mbuf(ifp, m);

 done1:
	splx(s);

 done:
	/* Setup new transfer. */
	usbd_setup_xfer(c->ugl_xfer, sc->sc_ep[UGL_ENDPT_RX],
	    c, c->ugl_buf, UGL_BUFSZ, USBD_SHORT_XFER_OK | USBD_NO_COPY,
	    USBD_NO_TIMEOUT, ugl_rxeof);
	usbd_transfer(c->ugl_xfer);

	DPRINTFN(10,("%s: %s: start rx\n", sc->sc_dev.dv_xname,
		    __func__));
}
Example #11
0
static void
qeintr(void *arg)
{
	struct qe_softc *sc = arg;
	struct qe_cdata *qc = sc->sc_qedata;
	struct ifnet *ifp = &sc->sc_if;
	struct ether_header *eh;
	struct mbuf *m;
	int csr, status1, status2, len;

	csr = QE_RCSR(QE_CSR_CSR);

	QE_WCSR(QE_CSR_CSR, QE_RCV_ENABLE | QE_INT_ENABLE | QE_XMIT_INT |
	    QE_RCV_INT | QE_ILOOP);

	if (csr & QE_RCV_INT)
		while (qc->qc_recv[sc->sc_nextrx].qe_status1 != QE_NOTYET) {
			status1 = qc->qc_recv[sc->sc_nextrx].qe_status1;
			status2 = qc->qc_recv[sc->sc_nextrx].qe_status2;

			m = sc->sc_rxmbuf[sc->sc_nextrx];
			len = ((status1 & QE_RBL_HI) |
			    (status2 & QE_RBL_LO)) + 60;
			qe_add_rxbuf(sc, sc->sc_nextrx);
			m->m_pkthdr.rcvif = ifp;
			m->m_pkthdr.len = m->m_len = len;
			if (++sc->sc_nextrx == RXDESCS)
				sc->sc_nextrx = 0;
			eh = mtod(m, struct ether_header *);
#if NBPFILTER > 0
			if (ifp->if_bpf) {
				bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
				if ((ifp->if_flags & IFF_PROMISC) != 0 &&
				    bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
				    ETHER_ADDR_LEN) != 0 &&
				    ((eh->ether_dhost[0] & 1) == 0)) {
					m_freem(m);
					continue;
				}
			}
#endif
			/*
			 * ALLMULTI means PROMISC in this driver.
			 */
			if ((ifp->if_flags & IFF_ALLMULTI) &&
			    ((eh->ether_dhost[0] & 1) == 0) &&
			    bcmp(sc->sc_ac.ac_enaddr, eh->ether_dhost,
			    ETHER_ADDR_LEN)) {
				m_freem(m);
				continue;
			}

			if ((status1 & QE_ESETUP) == 0)
				ether_input_mbuf(ifp, m);
			else
				m_freem(m);
		}

	if (csr & (QE_XMIT_INT|QE_XL_INVALID)) {
		while (qc->qc_xmit[sc->sc_lastack].qe_status1 != QE_NOTYET) {
			int idx = sc->sc_lastack;

			sc->sc_inq--;
			if (++sc->sc_lastack == TXDESCS)
				sc->sc_lastack = 0;

			/* XXX collect statistics */
			qc->qc_xmit[idx].qe_addr_hi &= ~QE_VALID;
			qc->qc_xmit[idx].qe_status1 =
			    qc->qc_xmit[idx].qe_flag = QE_NOTYET;

			if (qc->qc_xmit[idx].qe_addr_hi & QE_SETUP)
				continue;
			bus_dmamap_unload(sc->sc_dmat, sc->sc_xmtmap[idx]);
			if (sc->sc_txmbuf[idx]) {
				m_freem(sc->sc_txmbuf[idx]);
				sc->sc_txmbuf[idx] = 0;
			}
		}
		ifp->if_timer = 0;
		ifp->if_flags &= ~IFF_OACTIVE;
		qestart(ifp); /* Put in more in queue */
	}
	/*
	 * How can the receive list get invalid???
	 * Verified that it happens anyway.
	 */
	if ((qc->qc_recv[sc->sc_nextrx].qe_status1 == QE_NOTYET) &&
	    (QE_RCSR(QE_CSR_CSR) & QE_RL_INVALID)) {
		QE_WCSR(QE_CSR_RCLL,
		    LOWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
		QE_WCSR(QE_CSR_RCLH,
		    HIWORD(&sc->sc_pqedata->qc_recv[sc->sc_nextrx]));
	}
}
Example #12
0
int
bmac_rint(void *v)
{
	struct bmac_softc *sc = v;
	struct ifnet *ifp = &sc->arpcom.ac_if;
	struct mbuf *m;
	dbdma_command_t *cmd;
	int status, resid, count, datalen;
	int i, n;
	void *data;
#ifdef BMAC_DEBUG
	printf("bmac_rint() called\n");
#endif

	i = sc->sc_rxlast;
	for (n = 0; n < BMAC_RXBUFS; n++, i++) {
		if (i == BMAC_RXBUFS)
			i = 0;
		cmd = &sc->sc_rxcmd[i];
		status = dbdma_ld16(&cmd->d_status);
		resid = dbdma_ld16(&cmd->d_resid);

#ifdef BMAC_DEBUG
		if (status != 0 && status != 0x8440 && status != 0x9440)
			printf("bmac_rint status = 0x%x\n", status);
#endif

		if ((status & DBDMA_CNTRL_ACTIVE) == 0)	/* 0x9440 | 0x8440 */
			continue;
		count = dbdma_ld16(&cmd->d_count);
		datalen = count - resid;		/* 2 == framelen */
		if (datalen < sizeof(struct ether_header)) {
			printf("%s: short packet len = %d\n",
				ifp->if_xname, datalen);
			goto next;
		}
		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_STOP, 0, 0, 0, 0);
		data = sc->sc_rxbuf + BMAC_BUFLEN * i;

		/* XXX Sometimes bmac reads one extra byte. */
		if (datalen == ETHER_MAX_LEN + 1)
			datalen--;

		/* Trim the CRC. */
		datalen -= ETHER_CRC_LEN;

		m = bmac_get(sc, data, datalen);
		if (m == NULL) {
			ifp->if_ierrors++;
			goto next;
		}

#if NBPFILTER > 0
		/*
		 * Check if there's a BPF listener on this interface.
		 * If so, hand off the raw packet to BPF.
		 */
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif
		ether_input_mbuf(ifp, m);
		ifp->if_ipackets++;

next:
		DBDMA_BUILD_CMD(cmd, DBDMA_CMD_IN_LAST, 0, DBDMA_INT_ALWAYS,
			DBDMA_WAIT_NEVER, DBDMA_BRANCH_NEVER);

		cmd->d_status = 0;
		cmd->d_resid = 0;
		sc->sc_rxlast = i + 1;
	}
	dbdma_continue(sc->sc_rxdma);

	return (1);
}
Example #13
0
void
cdcef_rxeof(struct usbf_xfer *xfer, void *priv,
            usbf_status status)
{
    struct cdcef_softc	*sc = priv;
    int total_len = 0;
    struct ifnet		*ifp = GET_IFP(sc);
    struct mbuf		*m = NULL;


    int s;

#if 0
    printf("cdcef_rxeof: xfer=%p, priv=%p, %s\n", xfer, priv,
           usbf_errstr(status));
#endif

    if (status != USBF_NORMAL_COMPLETION) {
        if (status == USBF_NOT_STARTED || status == USBF_CANCELLED)
            return;
        if (sc->sc_rxeof_errors == 0)
            printf("%s: usb error on rx: %s\n",
                   DEVNAME(sc), usbf_errstr(status));
        /* XXX - no stalls on client */
        if (sc->sc_rxeof_errors++ > 10) {
            printf("%s: too many errors, disabling\n",
                   DEVNAME(sc));
        }
        goto done;
    }
    sc->sc_rxeof_errors = 0;

    /* upon first incoming packet we know the host is listening */
    if (sc->sc_listening == 0) {
        sc->sc_listening = 1;
    }


    usbf_get_xfer_status(xfer, NULL, NULL, &total_len, NULL);

    /* total_len -= 4; Strip off CRC added for Zaurus - XXX*/
    if (total_len <= 1)
        goto done;

    if (total_len < sizeof(struct ether_header)) {
        ifp->if_ierrors++;
        goto done;
    }

    s = splnet();
    if (ifp->if_flags & IFF_RUNNING) {
        m = cdcef_newbuf();
        if (m == NULL) {
            /* message? */
            ifp->if_ierrors++;
            goto done1;
        }

        m->m_pkthdr.len = m->m_len = total_len;
        bcopy(sc->sc_buffer_out, mtod(m, char *), total_len);
        m->m_pkthdr.rcvif = ifp;

        ifp->if_ipackets++;

#if NBPFILTER > 0
        if (ifp->if_bpf)
            bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

        ether_input_mbuf(ifp, m);
    }
Example #14
0
void
tsec_rx_proc(struct tsec_softc *sc)
{
	struct ifnet *ifp = &sc->sc_ac.ac_if;
	struct tsec_desc *rxd;
	struct tsec_buf *rxb;
	struct mbuf *m;
	int idx, len;

	if ((ifp->if_flags & IFF_RUNNING) == 0)
		return;

	bus_dmamap_sync(sc->sc_dmat, TSEC_DMA_MAP(sc->sc_rxring), 0,
	    TSEC_DMA_LEN(sc->sc_rxring),
	    BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);

	while (sc->sc_rx_cnt > 0) {
		idx = sc->sc_rx_cons;
		KASSERT(idx < TSEC_NRXDESC);

		rxd = &sc->sc_rxdesc[idx];
		if (rxd->td_status & TSEC_RX_E)
			break;

		len = rxd->td_len;
		rxb = &sc->sc_rxbuf[idx];
		KASSERT(rxb->tb_m);

		bus_dmamap_sync(sc->sc_dmat, rxb->tb_map, 0,
		    len, BUS_DMASYNC_POSTREAD);
		bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);

		/* Strip off CRC. */
		len -= ETHER_CRC_LEN;
		KASSERT(len > 0);

		m = rxb->tb_m;
		rxb->tb_m = NULL;
		m->m_pkthdr.rcvif = ifp;
		m->m_pkthdr.len = m->m_len = len;

		ifp->if_ipackets++;

#if NBPFILTER > 0
		if (ifp->if_bpf)
			bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
#endif

		ether_input_mbuf(ifp, m);

		sc->sc_rx_cnt--;
		if (rxd->td_status & TSEC_RX_W)
			sc->sc_rx_cons = 0;
		else
			sc->sc_rx_cons++;
	}

	tsec_fill_rx_ring(sc);

	bus_dmamap_sync(sc->sc_dmat, TSEC_DMA_MAP(sc->sc_rxring), 0,
	    TSEC_DMA_LEN(sc->sc_rxring),
	    BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
}