static int macb_recv(struct eth_device *netdev) { struct macb_device *macb = to_macb(netdev); unsigned int rx_tail = macb->rx_tail; void *buffer; int length; int wrapped = 0; u32 status; for (;;) { macb_invalidate_ring_desc(macb, RX); if (!(macb->rx_ring[rx_tail].addr & RXADDR_USED)) return -1; status = macb->rx_ring[rx_tail].ctrl; if (status & RXBUF_FRAME_START) { if (rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, rx_tail); wrapped = 0; } if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; macb_invalidate_rx_buffer(macb); if (wrapped) { unsigned int headlen, taillen; headlen = 128 * (MACB_RX_RING_SIZE - macb->rx_tail); taillen = length - headlen; memcpy((void *)NetRxPackets[0], buffer, headlen); memcpy((void *)NetRxPackets[0] + headlen, macb->rx_buffer, taillen); buffer = (void *)NetRxPackets[0]; } NetReceive(buffer, length); if (++rx_tail >= MACB_RX_RING_SIZE) rx_tail = 0; reclaim_rx_buffers(macb, rx_tail); } else { if (++rx_tail >= MACB_RX_RING_SIZE) { wrapped = 1; rx_tail = 0; } } barrier(); } return 0; }
static int _macb_recv(struct macb_device *macb, uchar **packetp) { unsigned int next_rx_tail = macb->next_rx_tail; void *buffer; int length; u32 status; macb->wrapped = false; for (;;) { macb_invalidate_ring_desc(macb, RX); if (!(macb->rx_ring[next_rx_tail].addr & RXADDR_USED)) return -EAGAIN; status = macb->rx_ring[next_rx_tail].ctrl; if (status & RXBUF_FRAME_START) { if (next_rx_tail != macb->rx_tail) reclaim_rx_buffers(macb, next_rx_tail); macb->wrapped = false; } if (status & RXBUF_FRAME_END) { buffer = macb->rx_buffer + 128 * macb->rx_tail; length = status & RXBUF_FRMLEN_MASK; macb_invalidate_rx_buffer(macb); if (macb->wrapped) { unsigned int headlen, taillen; headlen = 128 * (MACB_RX_RING_SIZE - macb->rx_tail); taillen = length - headlen; memcpy((void *)net_rx_packets[0], buffer, headlen); memcpy((void *)net_rx_packets[0] + headlen, macb->rx_buffer, taillen); *packetp = (void *)net_rx_packets[0]; } else { *packetp = buffer; } if (++next_rx_tail >= MACB_RX_RING_SIZE) next_rx_tail = 0; macb->next_rx_tail = next_rx_tail; return length; } else { if (++next_rx_tail >= MACB_RX_RING_SIZE) { macb->wrapped = true; next_rx_tail = 0; } } barrier(); } }