static int rtl8139_rx(struct net_device *dev, struct rtl8139_private *tp, int budget) { void *ioaddr = tp->mmio_addr; int received = 0; unsigned char *rx_ring = tp->rx_ring; // / 网卡不断的把数据放进环形接收缓冲区, CPU 读出来的时候,读到
哪里的顺序需要自己维护, //tp−>c u r r x 记录上次读到哪里,这里将接着从上一次的地方拷贝。/
unsigned int cur_rx = tp->cur_rx; DPRINTK ("%s: In rtl8139_rx(), current %4.4x BufAddr %4.4x," " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); //轮询寄存器,当ChipCmd RxBufEmpty 位没被网卡设置的时候,
//则说明环形缓冲区中有接收到的数据等待处理。
while (netif_running(dev) && received < budget && (RTL_R8 (ChipCmd) & RxBufEmpty) == 0) { u32 ring_offset = cur_rx % RX_BUF_LEN; u32 rx_status; unsigned int rx_size; unsigned int pkt_size; struct sk_buff *skb; u16 status; rmb(); /* read size+status of next frame from DMA ring buffer */ rx_status = le32_to_cpu (*(u32 *) (rx_ring + ring_offset)); rx_size = rx_status >> 16; pkt_size = rx_size - 4; if (netif_msg_rx_status(tp)) printk(KERN_DEBUG "%s: rtl8139_rx() status %4.4x, size %4.4x," " cur %4.4x.\n", dev->name, rx_status, rx_size, cur_rx); #if RTL8139_DEBUG > 2 { int i; DPRINTK ("%s: Frame contents ", dev->name); for (i = 0; i < 70; i++) printk (" %2.2x", rx_ring[ring_offset + i]); printk (".\n"); } #endif /* Packet copy from FIFO still in progress. * Theoretically, this should never happen * since EarlyRx is disabled. */ //当EarlyRX 允许的时候,可能会发生这种情况,一个完整的数据包
的一部分已经通过DMA //传送到了内存中,而另外一部分还在网卡内部FIFO 中,网卡的DMA
操作还在进行中。 if (unlikely(rx_size == 0xfff0)) { tp->xstats.early_rx++; goto done; } /* If Rx err or invalid rx_size/rx_status received * (which happens if we get lost in the ring), * Rx process gets reset, so we abort any further * Rx processing. */ if (unlikely((rx_size > (MAX_ETH_FRAME_SIZE+4)) || (rx_size < 8) || (!(rx_status & RxStatusOK)))) { rtl8139_rx_err (rx_status, dev, tp, ioaddr); return -1; } /* Malloc up new buffer, compatible with net-2e. */ /* Omit the four octet CRC from the length. */ // / 把数据拷贝到SKB 中来。/
skb = dev_alloc_skb (pkt_size + 2); if (likely(skb)) { skb->dev = dev; skb_reserve (skb, 2); /* 16 byte align the IP fields. */ #if RX_BUF_IDX == 3 wrap_copy(skb, rx_ring, ring_offset+4, pkt_size); #else eth_copy_and_sum (skb, &rx_ring[ring_offset + 4], pkt_size, 0); #endif skb_put (skb, pkt_size); // / 判断包的协议。/
skb->protocol = eth_type_trans (skb, dev); dev->last_rx = jiffies; // / 更新统计信息,这些信息就是我们用i f c o n f i g 命
令看到的。􀗛/ tp->stats.rx_bytes += pkt_size; tp->stats.rx_packets++; //调用系统函数通知上层协议驱动数据包的到来
netif_receive_skb (skb); } else { if (net_ratelimit()) printk (KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name); tp->stats.rx_dropped++; } received++; cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; RTL_W16 (RxBufPtr, (u16) (cur_rx - 16)); /* Clear out errors and receive interrupts */ status = RTL_R16 (IntrStatus) & RxAckBits; if (likely(status != 0)) { if (unlikely(status & (RxFIFOOver | RxOverflow))) { tp->stats.rx_errors++; if (status & RxFIFOOver) tp->stats.rx_fifo_errors++; } RTL_W16_F (IntrStatus, RxAckBits); } } done: #if RTL8139_DEBUG > 1 DPRINTK ("%s: Done rtl8139_rx(), current %4.4x BufAddr %4.4x," " free to %4.4x, Cmd %2.2x.\n", dev->name, cur_rx, RTL_R16 (RxBufAddr), RTL_R16 (RxBufPtr), RTL_R8 (ChipCmd)); #endif tp->cur_rx = cur_rx; return received; }
|