- 2.4 内核
- 2.6 内核
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags, const char *name, void *dev);
参数说明:
irq----是要申请的硬件中断号。
handler---是向系统注册的中断处理函数的函数指针,我们需要自己定义这个函数并把函数指针做为参数传到这里,中断发生时,系统会调用这个函数,dev_id参数将被传递给它。
irqflags---是中断处理的属性,若设置了IRQF_DISABLED,则表示中断处理程序是快速处理程序,快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽;若设置了 IRQF_SHARED,则表示多个设备共享中断(多个中断服务程序将注册到这个中断号上),若设置了IRQF_SAMPLE_RANDOM,表示对系统熵有贡献,对系统获取随机数有好处。这几个flag是可以通过或的方式同时使用的。
dev_id---在中断共享时会用到,一般设置为这个设备的设备结构体或者NULL。这个参数一般设为设备结构体,这样方便我们把设备有关信息传给该设备的中断处理程序,在使用到共享中断时,该参数必须设置,因为free_irq(unsigned int irq, void *dev_id) 这个函数中,需要根据这个参数来判断要释放共享上的哪个中断。在共享中断里,每个中断服务程序需要读取中断寄存器来判断是否是自己的中断,是的则执行相应代码,不是的则马上返回。
其中irqreturn_t为一个类型定义,
typedef irqreturn_t (*irq_handler_t)(int, void *);
在linux-2.6.32.2/include/linux/interrupt.h中定义的request_irq()函数如下:
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
{
return request_threaded_irq(irq, handler, NULL, flags, name, dev);
}
- int request_threaded_irq(unsigned int irq,
- irq_handler_t handler,
- irq_handler_t thread_fn,
- unsigned long irqflags,
- const char *devname,
- void *dev_id )
- {
- 。。。
- /*获得一个irq_desc对象*/
- desc = irq_to_desc(irq);
- 。。。。
- /*向内核申请一个中断反应对象并根据传进来的参数初始化*/
- action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
- if (!action)
- return -ENOMEM;
- action->handler = handler;
- action->thread_fn = thread_fn;
- action->flags = irqflags;
- action->name = devname;
- action->dev_id = dev_id;
- /*处理这个中断服务,如将这个中断添加到中断服务链表中等
- 后面我们将仔细分析__setup_irq这个函数
- */
- chip_bus_lock(irq, desc);
- retval = __setup_irq(irq, desc, action);
- chip_bus_sync_unlock(irq, desc);
- 。。。
- }
__setup_irq来完成注册函数处理,将action注册到desc[irq]中。
- static int setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
- {
- 。。。。
- /* add new interrupt at end of irq queue */
- old_ptr = &desc->action;
old = *old_ptr; - if (old) {
- do {
- old_ptr = &old->next;
-
- old = *old_ptr;
- } while (old);
- shared = 1;
- }
- 。。。
- new->irq = irq;
*old_ptr = new; - 。。。
- }
while(old)循环使得old_ptr存放desc->action最后一个action的地址(即最后一个action存放nex的地址),且最后一个action->next的指针指向为空。最后,将要插入的新的action放到连尾。