Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1419448
  • 博文数量: 1334
  • 博客积分: 645
  • 博客等级: 上士
  • 技术积分: 5762
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-25 16:56
文章分类

全部博文(1334)

文章存档

2014年(108)

2013年(1059)

2012年(169)

分类: LINUX

2014-03-27 13:35:57

原文地址:dm9000网卡驱动分析4 作者:zhongli_i

11.中断处理函数
网络设备接收数据的主要方法是有中断引发设备的中断处理函数,中断处理函数判断中断的类型,如果为接收中断,则读取接收到的数据,分配sk_buff数据结构和数据缓冲区,将接收到的数据复制到数据缓冲区中,并调用netif_rx()函数将sk_buff传递给上层协议。

点击(此处)折叠或打开

  1. static irqreturn_t dm9000_interrupt(int irq, void *dev_id)
  2. {
  3.     struct net_device *dev = dev_id;
  4.     board_info_t *db = netdev_priv(dev);
  5.     int int_status;
  6.     unsigned long flags;
  7.     u8 reg_save;

  8.     dm9000_dbg(db, 3, "entering %s\n", __func__);

  9.     /* A real interrupt coming */

  10.     /* holders of db->lock must always block IRQs */
  11.     spin_lock_irqsave(&db->lock, flags);

  12.     /* Save previous register address */
  13.     reg_save = readb(db->io_addr);

  14.     /* Disable all interrupts */
  15.     iow(db, DM9000_IMR, IMR_PAR);

  16.     /* Got DM9000 interrupt status */ //获取中断类型
  17.     int_status = ior(db, DM9000_ISR);    /* Got ISR */
  18.     iow(db, DM9000_ISR, int_status);    /* Clear ISR status */

  19.     if (netif_msg_intr(db))
  20.         dev_dbg(db->dev, "interrupt status %02x\n", int_status);

  21.     /* Received the coming packet */ //接收到一个数据包
  22.     if (int_status & ISR_PRS)
  23.         dm9000_rx(dev); //调用数据接收函数

  24.     /* Trnasmit Interrupt check */ //发送一个数据包
  25.     if (int_status & ISR_PTS)
  26.         dm9000_tx_done(dev, db); //调用数据发送函数

  27.     if (db->type != TYPE_DM9000E) {
  28.         if (int_status & ISR_LNKCHNG) {
  29.             /* fire a link-change request */
  30.             schedule_delayed_work(&db->phy_poll, 1);
  31.         }
  32.     }

  33.     /* Re-enable interrupt mask */
  34.     iow(db, DM9000_IMR, db->imr_all);

  35.     /* Restore previous register address */
  36.     writeb(reg_save, db->io_addr);

  37.     spin_unlock_irqrestore(&db->lock, flags);

  38.     return IRQ_HANDLED;
  39. }

12.接收数据
接收数据函数主要将接收到的数据包传递给上层。

点击(此处)折叠或打开

  1. dm9000_rx(struct net_device *dev)
  2. {
  3.     board_info_t *db = netdev_priv(dev); //获得网卡私有数据首地址
  4.     struct dm9000_rxhdr rxhdr;
  5.     struct sk_buff *skb;
  6.     u8 rxbyte, *rdptr;
  7.     bool GoodPacket;
  8.     int RxLen;

  9.     /* Check packet ready or not */
  10.     do {//存储器地址不变的读数据
  11.         ior(db, DM9000_MRCMDX);    /* Dummy read */ //MRCMDX是内存数据预取读命令
  12.  
  13.         /* Get most updated data */
  14.         rxbyte = readb(db->io_data);

  15.         /* Status check: this byte must be 0 or 1 */ //0、1为正确,2表示接收出错
  16.         if (rxbyte & DM9000_PKT_ERR) {
  17.             dev_warn(db->dev, "status check fail: %d\n", rxbyte);
  18.             iow(db, DM9000_RCR, 0x00);    /* Stop Device */ //关闭设备 并停止中断请求
  19.             iow(db, DM9000_ISR, IMR_PAR);    /* Stop INT request */
  20.             return;
  21.         }

  22.         if (!(rxbyte & DM9000_PKT_RDY)) // 0x01没准备好,直接返回
  23.             return;

  24.         /* A packet ready now & Get status/length */
  25.         GoodPacket = true;
  26.         writeb(DM9000_MRCMD, db->io_addr);
  27.       //读取数据,从RX_SRAM读取到rxhdr中
  28.         (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr))

  29.         RxLen = le16_to_cpu(rxhdr.RxLen);

  30.         if (netif_msg_rx_status(db))
  31.             dev_dbg(db->dev, "RX: status %02x, length %04x\n",
  32.                 rxhdr.RxStatus, RxLen);

  33.         /* Packet Status check */ //检查包得完整性
  34.         if (RxLen < 0x40) {
  35.             GoodPacket = false;
  36.             if (netif_msg_rx_err(db))
  37.                 dev_dbg(db->dev, "RX: Bad Packet (runt)\n");
  38.         }

  39.         if (RxLen > DM9000_PKT_MAX) {
  40.             dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen);
  41.         }

  42.         /* rxhdr.RxStatus is identical to RSR register. */
  43.         if (rxhdr.RxStatus & (RSR_FOE | RSR_CE | RSR_AE |
  44.                  RSR_PLE | RSR_RWTO |
  45.                  RSR_LCS | RSR_RF)) {
  46.             GoodPacket = false;
  47.             if (rxhdr.RxStatus & RSR_FOE) {
  48.                 if (netif_msg_rx_err(db))
  49.                     dev_dbg(db->dev, "fifo error\n");
  50.                 dev->stats.rx_fifo_errors++;
  51.             }
  52.             if (rxhdr.RxStatus & RSR_CE) {
  53.                 if (netif_msg_rx_err(db))
  54.                     dev_dbg(db->dev, "crc error\n");
  55.                 dev->stats.rx_crc_errors++;
  56.             }
  57.             if (rxhdr.RxStatus & RSR_RF) {
  58.                 if (netif_msg_rx_err(db))
  59.                     dev_dbg(db->dev, "length error\n");
  60.                 dev->stats.rx_length_errors++;
  61.             }
  62.         }

  63.         /* Move data from DM9000 */ //从DM9000获取数据
  64.         if (GoodPacket && //分配SKB
  65.          ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) {
  66.             skb_reserve(skb, 2);
  67.             rdptr = (u8 *) skb_put(skb, RxLen - 4);

  68.             /* Read received packet from RX SRAM */
  69.        //读取数据 从RX SRAM 到sk_buff中
  70.             (db->inblk)(db->io_data, rdptr, RxLen);
  71.             dev->stats.rx_bytes += RxLen;

  72.             /* Pass to upper layer */ //获取上层协议类型
  73.             skb->protocol = eth_type_trans(skb, dev);
  74.             if (db->rx_csum) {
  75.                 if ((((rxbyte & 0x1c) << 3) & rxbyte) == 0)
  76.                     skb->ip_summed = CHECKSUM_UNNECESSARY;
  77.                 else
  78.                     skb->ip_summed = CHECKSUM_NONE;
  79.             }
  80.             netif_rx(skb); //把数据包交给上层
  81.             dev->stats.rx_packets++;

  82.         } else {
  83.             /* need to dump the packet's data */

  84.             (db->dumpblk)(db->io_data, RxLen);
  85.         }
  86.     } while (rxbyte & DM9000_PKT_RDY);
  87. }
可以看出接收数据主要包括:
判断为接收数据中断----dm9000_rx()完成更深入的数据包接收工作[获取数据包长度,分配sk_buff和数据段缓冲区,读取硬件接收的数据放入缓冲区中,解析上层协议类型,将数据包交给上层]

更多细节参考
阅读(345) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~