dm9000驱动中一共包含两个中断
//这个中断函数主要做的事情是读dm9000寄存器NSR,WCR,根据读到的内容 //作出相应提示 static irqreturn_t dm9000_wol_interrupt(int irq, void *dev_id) { struct net_device *dev = dev_id; board_info_t *db = netdev_priv(dev); unsigned long flags; unsigned nsr, wcr; //关中断,获得自旋锁 spin_lock_irqsave(&db->lock, flags); nsr = ior(db, DM9000_NSR); wcr = ior(db, DM9000_WCR); dev_dbg(db->dev, "%s: NSR=0x%02x, WCR=0x%02x\n", __func__, nsr, wcr); if (nsr & NSR_WAKEST) { /* clear, so we can avoid */ iow(db, DM9000_NSR, NSR_WAKEST); if (wcr & WCR_LINKST) dev_info(db->dev, "wake by link status change\n"); if (wcr & WCR_SAMPLEST) dev_info(db->dev, "wake by sample packet\n"); if (wcr & WCR_MAGICST ) dev_info(db->dev, "wake by magic packet\n"); if (!(wcr & (WCR_LINKST | WCR_SAMPLEST | WCR_MAGICST))) dev_err(db->dev, "wake signalled with no reason? " "NSR=0x%02x, WSR=0x%02x\n", nsr, wcr); } //释放自旋锁,恢复本地中断 spin_unlock_irqrestore(&db->lock, flags); return (nsr & NSR_WAKEST) ? IRQ_HANDLED : IRQ_NONE; } 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); //通过读DM9000中断寄存器,判断是哪种类型中断,并作出相应处理 /* 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 */ //如果是接收中断,读取接收的数据并存入skbuff,并提交协议上一层 if (int_status & ISR_PRS) dm9000_rx(dev); /* Trnasmit Interrupt check */ //发送中断,如果还有包未发完,继续发送。 if (int_status & ISR_PTS) dm9000_tx_done(dev, db); //如果是DM9000E系列的芯片,作特别处理。 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; }