"); //-->
作者:下家山(请尊重原创,转载请注明) http://www.xiajiashan.com
四:当中断发生时,kernel是怎么找到这个句柄
第二个问题,我们调用register_irq 函数时注册的句柄,当中断发生时,kernel是怎么找到这个句柄,继而执行我们驱动里的函数的???
4.1 关于s3c_init_irq函数在asm_do_IRQ执行时,调用了desc_handle_irq(irq, desc);此函数调用了一个回调函数irq_desc->handle_irq,这一回调函数是在s3c_init_irq(位于/arch/arm/plat-s3c24xx/irq-pl192.c中)中设置的,其原型为:
/* --------------------------------------------------
* s3c_init_irq
*
* Initialise s3c6400 IRQ system
* --------------------------------------------------
*/
/*这个函数是在内核启动时被执行的,通过它来初始化irq_desc结构体数组,这样后续的驱动如果要注册中断就填充到这个数组中来*/
void __init s3c_init_irq(void)
{
int irqno;
int irqindex = 0;
irqdbf("s3c_init_irq: clearing interrupt status flags\n");
/* first, clear all interrupts pending... */
/* clear external interrupts */
__raw_writel(0xFFFFFFFF, S3C_EINTPEND);
/* clear all vector interrupts */
__raw_writel(0x00000000, S3C_VIC0ADDRESS);
__raw_writel(0x00000000, S3C_VIC1ADDRESS);
/* For writing the IRQ number into the VICVECTADDR */
for (irqno = IRQ_EINT0_3; irqno <= IRQ_LCD_SYSTEM; irqno++) {
__raw_writel(irqno, S3C_VIC0VECTADDR0 + irqindex);
irqindex = irqindex + 4;
}/*初始化第一组(0~31)中断源的向量地址*/
irqindex = 0;
for (irqno = IRQ_EINT12_19; irqno <= IRQ_ADC; irqno++) {
__raw_writel(irqno, S3C_VIC1VECTADDR0 + irqindex);
irqindex = irqindex + 4;
}/*初始化第二组(32~63)中断源的向量地址*/
/* register the main interrupts */
irqdbf("s3c6400_init_irq: registering mDirac-III interrupt handlers\n");
/*下面的for循环设置63个中断源的中断服务例程(中断服务函数或中断句柄),状态,标志,中断服务例程处理时的回调函数*/
for (irqno = IRQ_EINT0_3; irqno <= IRQ_ADC; irqno++) {
switch (irqno) {
/* deal with the special IRQs in ext (cascaded) */
case IRQ_EINT0_3:
set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
break; /*设置第一组外部中断中断源的中断服务例程(中断服务函数或中断句柄) */
case IRQ_EINT4_11:
set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
break; /*设置第二组外部中断中断源的中断服务例程(中断服务函数或中断句柄) */
case IRQ_EINT12_19:
set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
break; /*设置第三组外部中断中断源的中断服务例程(中断服务函数或中断句柄) */
case IRQ_EINT20_27:
set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
break; /*设置第四组外部中断中断源的中断服务例程(中断服务函数或中断句柄) */
default:
irqdbf("registering irq %d (s3c irq)\n", irqno);
set_irq_chip(irqno, &s3c_irq_level_chip);/* 设置内部中断中断源的irq_desc结构体回调函数*/
//set_irq_handler(irqno, do_level_IRQ);
set_irq_handler(irqno, handle_level_irq); /*设置内部中断中断源的中断服务例程(中断服务函数或中断句柄) */
set_irq_flags(irqno, IRQF_VALID); /*设置内部中断中断源的irq_desc结构体中断标志*/
break;
}
}
for (irqno = IRQ_EINT0; irqno <= IRQ_EINT27; irqno++) {
irqdbf("registering irq %d (extended s3c irq)\n", irqno);
set_irq_chip(irqno, &s3c_irqext_chip); /* 设置外部中断中断源的irq_desc结构体回调函数*/
//set_irq_handler(irqno, do_level_IRQ);
set_irq_handler(irqno, handle_level_irq); /*设置外部中断中断源的中断服务例程(中断服务函数或中断句柄) */
set_irq_flags(irqno, IRQF_VALID); /*设置外部中断中断源的irq_desc结构体中断标志*/
}
irqdbf("s3c6400: registered interrupt handlers\n");
}
下面对
set_irq_chip();//见kernel/irq/chip.c
set_irq_handler();//见include/linux/irq.h->见kernel/irq/chip.c
set_irq_flags();//见arch/arm/kernel/irq.c
这三个函数分别展开
4.1.1 关于 set_irq_chip()函数/**
* set_irq_chip - set the irq chip for an irq
* @irq: irq number
* @chip: pointer to irq chip description structure
*/
int set_irq_chip(unsigned int irq, struct irq_chip *chip)
{
struct irq_desc *desc;
unsigned long flags;
if (irq >= NR_IRQS) {
printk(KERN_ERR "Trying to install chip for IRQ%d\n", irq);
WARN_ON(1);
return -EINVAL;
}
if (!chip)
chip = &no_irq_chip;
desc = irq_desc + irq;
spin_lock_irqsave(&desc->lock, flags);
irq_chip_set_defaults(chip);/*会调用到irq_chip_set_defaults函数*/
desc->chip = chip;
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
}
4.1.2 关于 irq_chip_set_defaults函数
下面是irq_chip_set_defaults函数的原型(见当前页)
/*
* Fixup enable/disable function pointers
*/
void irq_chip_set_defaults(struct irq_chip *chip)
{
if (!chip->enable)
chip->enable = default_enable;/* 见当前页*/
if (!chip->disable)
chip->disable = default_disable; /* 见当前页*/
if (!chip->startup)
chip->startup = default_startup; /* 见当前页*/
if (!chip->shutdown)
chip->shutdown = chip->disable; /* 见当前页*/
if (!chip->name)
chip->name = chip->typename;
if (!chip->end)
chip->end = dummy_irq_chip.end;
}
2009-2-13 下家山 写于上海.漕河泾
有什么问题可以给我邮件ximenpiaoxue4016@sina.com或加我群198204885
*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。
eleaction01 阅读:4490