zoukankan      html  css  js  c++  java
  • dm9000

    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);
    }

    网络设备的MAC地址

  • 相关阅读:
    instanceof操作符判断对象类型
    继承
    题解 P3943 星空
    NOIP 模拟 10 考试总结
    题解 P3942 将军令
    题解 P3941 入阵曲
    题解 P3191 [HNOI2007]紧急疏散EVACUATE
    NOIP 模拟 9 考试总结
    NOIP 模拟 9 分组
    NOIP 模拟 9 数颜色
  • 原文地址:https://www.cnblogs.com/dream397/p/15124651.html
Copyright © 2011-2022 走看看