static void ffec_rxfinish_locked(struct ffec_softc *sc) { struct ffec_hwdesc *desc; int len; boolean_t produced_empty_buffer; FFEC_ASSERT_LOCKED(sc); produced_empty_buffer = false; for (;;) { desc = &sc->rxdesc_ring[sc->rx_idx]; if (desc->flags_len & FEC_RXDESC_EMPTY) break; produced_empty_buffer = true; len = (desc->flags_len & FEC_RXDESC_LEN_MASK); if (len < 64) { /* * Just recycle the descriptor and continue. . */ ffec_setup_rxdesc(sc, sc->rx_idx, sc->rxdesc_ring[sc->rx_idx].buf_paddr); } else if ((desc->flags_len & FEC_RXDESC_L) == 0) { /* * The entire frame is not in this buffer. Impossible. * Recycle the descriptor and continue. * * XXX what's the right way to handle this? Probably we * should stop/init the hardware because this should * just really never happen when we have buffers bigger * than the maximum frame size. */ device_printf(sc->dev, "fec_rxfinish: received frame without LAST bit set"); ffec_setup_rxdesc(sc, sc->rx_idx, sc->rxdesc_ring[sc->rx_idx].buf_paddr); } else if (desc->flags_len & FEC_RXDESC_ERROR_BITS) { /* * Something went wrong with receiving the frame, we * don't care what (the hardware has counted the error * in the stats registers already), we just reuse the * same mbuf, which is still dma-mapped, by resetting * the rx descriptor. */ ffec_setup_rxdesc(sc, sc->rx_idx, sc->rxdesc_ring[sc->rx_idx].buf_paddr); } else { /* * Normal case: a good frame all in one buffer. */ ffec_rxfinish_onebuf(sc, len); } sc->rx_idx = next_rxidx(sc, sc->rx_idx); } if (produced_empty_buffer) { WR4(sc, FEC_RDAR_REG, FEC_RDAR_RDAR); } }
inline static uint32_t ffec_setup_rxdesc(struct ffec_softc *sc, int idx, bus_addr_t paddr) { uint32_t nidx; /* * The hardware requires 32-bit physical addresses. We set up the dma * tag to indicate that, so the cast to uint32_t should never lose * significant bits. */ nidx = next_rxidx(sc, idx); sc->rxdesc_ring[idx].buf_paddr = (uint32_t)paddr; sc->rxdesc_ring[idx].flags_len = FEC_RXDESC_EMPTY | ((nidx == 0) ? FEC_RXDESC_WRAP : 0); return (nidx); }