}
2:中断的申请
在__ath_attach()有如下中断申请代码
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,20)
if (request_irq(dev->irq, ath_isr, SA_SHIRQ, dev->name, dev)) {
#else
#ifdef ATH_AHB
if (request_irq(dev->irq, ath_isr, IRQF_DISABLED, dev->name, dev)) {
#else
if (request_irq(dev->irq, ath_isr, IRQF_SHARED, dev->name, dev)) {
#endif
#endif
printk(KERN_WARNING "%s: request_irq failed\n", dev->name);
error = -EIO;
goto bad3;
} 由此可知,中断处理函数为:
ath_isr(int irq, void *dev_id, struct pt_regs *regs)
{
do_ath_isr(irq,dev_id,regs);
}
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
#define do_ath_isr(_irq,_dev_id) do{ return ath_isr_generic(_irq,_dev_id);}while(0)
#else
#define do_ath_isr(_irq,_dev_id,_regs) do{ return ath_isr_generic(_irq,_dev_id,_regs);}while(0)
#endif //if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,19)
irqreturn_t ath_isr_generic(int irq, void *dev_id, struct pt_regs *regs)
#endif
{
struct net_device *dev = dev_id;
struct ath_softc_net80211 *scn = ath_netdev_priv(dev);
int sched, needmark = 0;
/* always acknowledge the interrupt */
sched = scn->sc_ops->isr(scn->sc_dev);
switch(sched)
{
case ATH_ISR_NOSCHED:
return IRQ_HANDLED;
case ATH_ISR_NOTMINE:
return IRQ_NONE;
default:
if ((dev->flags & (IFF_RUNNING|IFF_UP)) != (IFF_RUNNING|IFF_UP))
{
DPRINTF_INTSAFE(scn, ATH_DEBUG_INTR, "%s: flags 0x%x\n", __func__, dev->flags);
scn->sc_ops->disable_interrupt(scn->sc_dev); /* disable further intr's */
return IRQ_HANDLED;
}
}
/*
** See if the transmit queue processing needs to be scheduled
*/
ATH_SCHEDULE_TQUEUE(&scn->sc_osdev->intr_tq, &needmark);
if (needmark)
mark_bh(IMMEDIATE_BH);
return IRQ_HANDLED;
}上面已经说明了在中断处理函数中对tasklet或者workqueue的调度。
3:代码执行流程
其代码执行过程如下:
当数据数据之后,会交给函数ieee80211_input(),在测函数中会处理80211的三大数据包类似,数据帧,管理帧和控制帧。