static void dm9000_rx(struct net_device *dev) { board_info_t *db = netdev_priv(dev); struct dm9000_rxhdr rxhdr; /* 该结构体按照DM9000的接收格式封装了dm9000接收的数据包信息 */ struct sk_buff *skb; u8 rxbyte, *rdptr; bool GoodPacket; int RxLen; /* Check packet ready or not 判断包是否已经接收过来了。需要用到MRCMDX寄存器。*/ do { ior(db, DM9000_MRCMDX); /* Dummy read. MRCMDX : memory data read command without address increment register*/ //MRCMDX寄存器是存储数据读命令寄存器(地址不增加) /* Get most updated data */ rxbyte = readb(db->io_data); /* Status check: this byte must be 0 or 1 */ //0、1为正确,2表示接收出错 if (rxbyte & DM9000_PKT_ERR) { dev_warn(db->dev, "status check fail: %d ", rxbyte); iow(db, DM9000_RCR, 0x00); /* Stop Device */ iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ return; } if (!(rxbyte & DM9000_PKT_RDY)) //0x01 没有准备好,直接返回*/ return; /* A packet ready now & Get status/length */ GoodPacket = true; writeb(DM9000_MRCMD, db->io_addr); /* MRCMD是地址增加的数据读取命令 读指针自动增加*/ (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); //一次性读入四个字节的内容到rxhdr变量 //这四个字节是存储在RX_SRAM中的每个包的信息头 RxLen = le16_to_cpu(rxhdr.RxLen); if (netif_msg_rx_status(db)) dev_dbg(db->dev, "RX: status %02x, length %04x ", rxhdr.RxStatus, RxLen); /* Packet Status check */ //检查包的完整性,需要用到MRCMD寄存器, if (RxLen < 0x40) { //因为数据读取到struct dm9000_rxhdr rxhdr;中,RXLEn为其成员 GoodPacket = false; if (netif_msg_rx_err(db)) dev_dbg(db->dev, "RX: Bad Packet (runt) "); } if (RxLen > DM9000_PKT_MAX) { //同上,检查包的大小如果数据长度大于DM9000_PKT_MAX ,即 1536 dev_dbg(db->dev, "RST: RX Len:%x ", RxLen); } /* rxhdr.RxStatus is identical to RSR register. */ //也是检查包 if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE | //这里是RSR寄存器中各位对接收的校验 RSR_PLE | RSR_RWTO | RSR_LCS | RSR_RF)) { GoodPacket = false; if (rxhdr.RxStatus & RSR_FOE) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "fifo error "); dev->stats.rx_fifo_errors++; } if (rxhdr.RxStatus & RSR_CE) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "crc error "); dev->stats.rx_crc_errors++; } if (rxhdr.RxStatus & RSR_RF) { if (netif_msg_rx_err(db)) dev_dbg(db->dev, "length error "); dev->stats.rx_length_errors++; } } /* Move data from DM9000 */ /*关键的代码就是这里。使用到了上面提到的sk_buff。将RX SRAM中的 data段数据放入sk_buff,然后发送给上层,至于怎么发送,不用去驱动 操心了。sk_buff的protocol全部搞定*/ if (GoodPacket && ((skb = netdev_alloc_skb(dev, RxLen + 4)) != NULL)) { //分配一个skbuff给网络设备的接收 skb_reserve(skb, 2); rdptr = (u8 *) skb_put(skb, RxLen - 4); /* Read received packet from RX SRAM */ //读取数据 从RX SRAM 到sk_buff中 (db->inblk)(db->io_data, rdptr, RxLen); dev->stats.rx_bytes += RxLen; /* Pass to upper layer */ //获取上层协议类型 skb->protocol = eth_type_trans(skb, dev); //eth_type_trans判断数据帧的类型,及协议类型 if (dev->features & NETIF_F_RXCSUM) { if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0) skb->ip_summed = CHECKSUM_UNNECESSARY; else skb_checksum_none_assert(skb); } netif_rx(skb); //将skbuff结构体交给上层 dev->stats.rx_packets++; //计数加1 } else { // 坏包,丢弃 /* need to dump the packet's data */ (db->dumpblk)(db->io_data, RxLen); } } while (rxbyte & DM9000_PKT_RDY); }
单播MAC地址
单播MAC地址保存在net_device结构体的uc链表中,函数dev_uc_add负责添加单播MAC地址。由其在内核代码的调用可以看到目前vlan设备、macvlan设备、ipvlan设备与macsec设备等在添加单播MAC地址。
无论是单播MAC还是多播MAC都是用作MAC地址的接收过滤来使用,具体由函数__dev_set_rx_mode进行设置。将需要过滤的MAC地址下发到网驱动处理,例如e1000驱动中的e1000_set_rx_mode函数。但是,对于不支持单播过滤的网卡,有两种处理情况:1)如果存在MAC地址需要过滤,打开设备的混杂接收模式;2)如果没有MAC地址需过滤,关闭混杂模式。
非混杂模式下,仅接收目的MAC与net_device结构中dev_addr值相同的数据包。
int dev_uc_add(struct net_device *dev, const unsigned char *addr) { err = __hw_addr_add(&dev->uc, addr, dev->addr_len, NETDEV_HW_ADDR_T_UNICAST); if (!err) __dev_set_rx_mode(dev); }
多播MAC地址
多播MAC地址保存在net_device结构体的mc链表中,由函数dev_mc_add负责添加多播MAC地址。与单播MAC地址相同,通过__dev_set_rx_mode函数可以设置网卡的多播地址接收过滤功能。
static int __dev_mc_add(struct net_device *dev, const unsigned char *addr, bool global) { err = __hw_addr_add_ex(&dev->mc, addr, dev->addr_len, NETDEV_HW_ADDR_T_MULTICAST, global, false, 0); if (!err) __dev_set_rx_mode(dev); }