void snull_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int statusword; struct snull_priv *privptr; /* * As usual, check the "device" pointer for shared handlers. * Then assign "struct device *dev" */ struct net_device *dev = (struct net_device *)dev_id; /* ... and check with hw if it's really ours */ if (!dev /*paranoid*/ ) return; /* Lock the device */ privptr = (struct snull_priv *)(dev->priv); spin_lock(&privptr->lock); /* retrieve statusword: real netdevices use I/O instructions */ statusword = privptr->status; if (statusword & SNULL_RX_INTR) { /* send it to snull_rx for handling */ snull_rx(dev, privptr->rx_packetlen, privptr->rx_packetdata); } if (statusword & SNULL_TX_INTR) { /* a transmission is over: free the skb */ privptr->stats.tx_packets++; privptr->stats.tx_bytes += privptr->tx_packetlen; dev_kfree_skb(privptr->skb); } /* Unlock the device and we are done */ spin_unlock(&privptr->lock); return; }
void snull_interrupt(int irq, void *dev_id, struct pt_regs *regs) { int statusword; struct snull_priv *privptr; /* * As usual, check the "device" pointer for shared handlers. * Then assign "struct device *dev" */ #if 0 && defined(LINUX_20) /* This is the way to do things for non-shared handlers */ struct device *dev = (struct device *)(irq2dev_map[irq]); #else /* Otherwise use this SA_SHIRQ-safe approach */ struct net_device *dev = (struct net_device *)dev_id; /* ... and check with hw if it's really ours */ #endif if (!dev /*paranoid*/ ) return; /* Lock the device */ privptr = (struct snull_priv *)(dev->priv); spin_lock(&privptr->lock); dev->interrupt = 1; /* retrieve statusword: real netdevices use inb() or inw() */ statusword = privptr->status; if (statusword & SNULL_RX_INTR) { /* send it to snull_rx for handling */ snull_rx(dev, privptr->rx_packetlen, privptr->rx_packetdata); } if (statusword & SNULL_TX_INTR) { /* a transmission is over: tell we are no more busy */ privptr->stats.tx_packets++; #ifndef LINUX_20 privptr->stats.tx_bytes += privptr->tx_packetlen; #endif dev_kfree_skb(privptr->skb); } spin_unlock(&privptr->lock); dev->interrupt = 0; return; }
/* 中断处理,此程序中没有硬件,因此,没有真正的硬件中断,只是模拟中断,在发送完网络数据包之后,会产生中断 用来通知内核已经发送完数据包,当新的数据包到达网络接口时,会发生中断,通知新的数据包已经到来了 */ void snull_interrupt(int irq, void *dev_id, struct pt_regs *regs) { printk("snull_interrupt\n"); int statusword;//用来标识是发送完毕还是接收到新的数据包 struct net_device *dev = (struct net_device *)dev_id; struct snull_priv *priv = netdev_priv(dev); /* 检查这个设备的真伪 */ if (!dev) { return; } /* 自旋锁上锁 */ spin_lock(&priv->lock); /* 获取中断类型 */ statusword = priv->status; priv->status = 0; //如果是接收 if (statusword & SNULL_RX_INTR) { /* 调用上层函数处理 */ snull_rx(dev, priv->rx_packetlen, priv->rx_packetdata); } //如果发送完毕 if (statusword & SNULL_TX_INTR) { /* 更新计数信息 */ priv->stats.tx_packets++; priv->stats.tx_bytes += priv->tx_packetlen; dev_kfree_skb(priv->skb);//释放skb套接字缓冲区 } /* 释放自旋锁 */ spin_unlock(&priv->lock); return; }