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和数据段缓冲区,读取硬件接收的数据放入缓冲区中,解析上层协议类型,将数据包交给上层]
更多细节参考
阅读(5006) | 评论(0) | 转发(7) |