int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *devname, void *dev_id) { struct irq_node *node; int res;
node = new_irq_node(); if (!node) return -ENOMEM;
node->handler = handler; node->flags = flags; node->dev_id = dev_id; node->devname = devname;
res = setup_irq(irq, node); if (res) node->handler = NULL;
return res; }
|
irq_node 处理中断的结构体链表
先定义一个node结构体
通过 node = new_irq_node();分配并初始化node,主要是寻找node表中的未分配的一个
node->handler = handler;指定中断服务程序
node->flags = flags;
node->dev_id = dev_id;用于共享中断信号线的指针。它是唯一的标识,在中断线空闲时可以使用它,驱动程序也可以用它来指向自己的私有数据区(来标识哪个设备产生中断)。若中断没有被共享,dev_id 可以设置为 NULL,但推荐用它指向设备的数据结构。
node->devname = devname;设备名
这四句赋值
最后设置 setup_irq
void free_irq(unsigned int irq, void *dev_id) { struct irq_controller *contr; struct irq_node **p, *node; unsigned long flags;
if (irq >= NR_IRQS || !(contr = irq_controller[irq])) { printk("%s: Incorrect IRQ %d\n", __func__, irq); return; }
spin_lock_irqsave(&contr->lock, flags);
p = irq_list + irq; while ((node = *p)) { if (node->dev_id == dev_id) break; p = &node->next; }
if (node) { *p = node->next; node->handler = NULL; } else printk("%s: Removing probably wrong IRQ %d\n", __func__, irq);
if (!irq_list[irq]) { if (contr->shutdown) contr->shutdown(irq); else contr->disable(irq); }
spin_unlock_irqrestore(&contr->lock, flags); }
|
红色部分搞不懂,可能是dev_id没理解。
一种用户数据类型(驱动程序可用的私有数据),传递给 request_irq的 void* 参数,会在中断发生时作为参数传给处理例程。我们通常传递一个指向设备数据结构的指针到 dev_id 中,这样一个管理若干相同设备的驱动在中断处理例程中不需要任何额外的代码,就可以找出哪个设备产生了当前的中断事件。
*p = node->next;这一句可以去掉吧
阅读(1417) | 评论(0) | 转发(0) |