DM9000驱动理解三(中断函数)

来源:互联网 发布:怎样才能加入淘宝客 编辑:程序博客网 时间:2024/05/21 19:10

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;}