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); }
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); }
/* * 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); }
/* * 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); }
/* * 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__)); }
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 {
/* 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; }
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); }
/* * 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; }
/* * 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__)); }
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])); } }
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); }
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); }
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); }