11.中断处理函数
网络设备接收数据的主要方法是有中断引发设备的中断处理函数,中断处理函数判断中断的类型,如果为接收中断,则读取接收到的数据,分配sk_buff数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区中,并调用netif_rx()函数将sk_buff传递给上层协议。
点击(此处)折叠或打开
- static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
- {
-     struct net_device *dev = dev_id;
-     board_info_t *db = netdev_priv(dev);
-     int int_status;
-     unsigned long flags;
-     u8 reg_save;
-     dm9000_dbg(db, 3, "entering %s\n", __func__);
-     /* A real interrupt coming */
-     /* holders of db->lock must always block IRQs */
-     spin_lock_irqsave(&db->lock, flags);
-     /* Save previous register address */
-     reg_save = readb(db->io_addr);
-     /* Disable all interrupts */
-     iow(db, DM9000_IMR, IMR_PAR);
-     /* Got DM9000 interrupt status */ //获取中断类型
-     int_status = ior(db, DM9000_ISR);    /* Got ISR */
-     iow(db, DM9000_ISR, int_status);    /* Clear ISR status */
-     if (netif_msg_intr(db))
-         dev_dbg(db->dev, "interrupt status %02x\n", int_status);
-     /* Received the coming packet */ //接收到一个数据包
-     if (int_status & ISR_PRS)
-         dm9000_rx(dev); //调用数据接收函数
-     /* Trnasmit Interrupt check */ //发送一个数据包
-     if (int_status & ISR_PTS)
-         dm9000_tx_done(dev, db); //调用数据发送函数
-     if (db->type != TYPE_DM9000E) {
-         if (int_status & ISR_LNKCHNG) {
-             /* fire a link-change request */
-             schedule_delayed_work(&db->phy_poll, 1);
-         }
-     }
-     /* Re-enable interrupt mask */
-     iow(db, DM9000_IMR, db->imr_all);
-     /* Restore previous register address */
-     writeb(reg_save, db->io_addr);
-     spin_unlock_irqrestore(&db->lock, flags);
-     return IRQ_HANDLED;
- }
12.接收数据
接收数据函数主要将接收到的数据包传递给上层。
可以看出接收数据主要包括:
点击(此处)折叠或打开
- dm9000_rx(struct net_device *dev)
- {
-     board_info_t *db = netdev_priv(dev); //获得网卡私有数据首地址
-     struct dm9000_rxhdr rxhdr;
-     struct sk_buff *skb;
-     u8 rxbyte, *rdptr;
-     bool GoodPacket;
-     int RxLen;
-     /* Check packet ready or not */
-     do {//存储器地址不变的读数据
-         ior(db, DM9000_MRCMDX);    /* Dummy read */ //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\n", 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);
- //读取数据,从RX_SRAM读取到rxhdr中
-         (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); 
-         RxLen = le16_to_cpu(rxhdr.RxLen);
-         if (netif_msg_rx_status(db))
-             dev_dbg(db->dev, "RX: status %02x, length %04x\n",
-                 rxhdr.RxStatus, RxLen);
-         /* Packet Status check */ //检查包得完整性
-         if (RxLen < 0x40) {
-             GoodPacket = false;
-             if (netif_msg_rx_err(db))
-                 dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
-         }
-         if (RxLen > DM9000_PKT_MAX) {
-             dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
-         }
-         /* rxhdr.RxStatus is identical to RSR register. */
-         if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
-                       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\n");
-                 dev->stats.rx_fifo_errors++;
-             }
-             if (rxhdr.RxStatus & RSR_CE) {
-                 if (netif_msg_rx_err(db))
-                     dev_dbg(db->dev, "crc error\n");
-                 dev->stats.rx_crc_errors++;
-             }
-             if (rxhdr.RxStatus & RSR_RF) {
-                 if (netif_msg_rx_err(db))
-                     dev_dbg(db->dev, "length error\n");
-                 dev->stats.rx_length_errors++;
-             }
-         }
-         /* Move data from DM9000 */ //从DM9000获取数据
-         if (GoodPacket && //分配SKB
-             ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
-             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);
-             if (db->rx_csum) {
-                 if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
-                     skb->ip_summed = CHECKSUM_UNNECESSARY;
-                 else
-                     skb->ip_summed = CHECKSUM_NONE;
-             }
-             netif_rx(skb); //把数据包交给上层
-             dev->stats.rx_packets++;
-         } else {
-             /* need to dump the packet's data */
-             (db->dumpblk)(db->io_data, RxLen);
-         }
-     } while (rxbyte & DM9000_PKT_RDY);
- }
判断为接收数据中断----dm9000_rx()完成更深入的数据包接收工作[获取数据包长度,分配sk_buff和数据段缓冲区,读取硬件接收的数据放入缓冲区中,解析上层协议类型,将数据包交给上层]
更多细节参考
