我们来看short_kernelprobe函数如何实现由内核自动探测中断号的:
- 466void short_kernelprobe(void)
- 467{
- 468 int count = 0;
- 469 do {
- 470 unsigned long mask;
- 471
- 472 mask = probe_irq_on();
-
- 473 outb_p(0x10,short_base+2);
- 474 outb_p(0x00,short_base);
- 475 outb_p(0xFF,short_base);
- 476 outb_p(0x00,short_base+2);
-
- 477 udelay(5);
- 478 short_irq = probe_irq_off(mask);
- 479
- 480 if (short_irq == 0) {
- 481 printk(KERN_INFO "short: no irq reported by probe\n");
- 482 short_irq = -1;
- 483 }
- 484
-
-
-
-
- 489 } while (short_irq < 0 && count++ < 5);
- 490 if (short_irq < 0)
- 491 printk("short: probe failed %i times, giving up\n", count);
- 492}
Linux内核提供了探测可用中断号的接口,但这种接口只能在非共享中断模式下使用。内核提供的接口由两个函数组成:
unsigned long probe_irq_on(void);
这个函数返回一个未分配中断的位掩码,驱动程序必须保存返回的位掩码,并将它传递给probe_irq_off函数。
调用probe_irq_on函数之后,驱动程序要安排设备产生至少一次中断。
int probe_irq_off(unsigned long);
在请求设备产生中断之后,驱动程序要调用这个函数,并将前面probe_irq_on返回的位掩码作为参数传递给它。probe_irq_off返回probe_irq_on之后发生的中断编号。如果没有中断发生,就返回0。如果产生了多次中断,出现了二义性,就返回负数。
使用内核提供的接口探测中断号时,需要注意在调用probe_irq_on之后启用设备中断,在调用probe_irq_off之前禁用中断。另外,在probe_irq_off之后,需要处理设备上待处理的中断。
472行,调用probe_irq_on函数。
473行,将2号端口的第4位(0x10)设置为1,启用中断。
474行,将0号端口清0。
475行,将0号端口置1,触发中断。
476行,将2号端口的第4位(0x10)设置为0,禁用中断。
477行,延时一会,以保证中断的传递时间。
478行,调用probe_irq_off函数,并把472行probe_irq_on函数返回的位掩码传递给它。
480行,probe_irq_off函数返回0,说明没有中断发生。
489行,probe_irq_off函数返回负值,说明发生了不止一个中断,需要重新探测,这里限定最多探测5次。