当有中断产生时,中断处理代码将读取这两个中断状态寄存器(ISR)。它将0x20中的ISR看成一个16位中断寄存器的低8位而将0xA0中的ISR看成其高8位。这样0xA0中ISR第1位上的中断将被视作系统中断9。PIC1 上的第二位由于被用来级连PIC2所以不能作其它用处,PIC2上的任何中断将导致PIC1的第二位被置位。
7.2 初始化中断处理数据结构核心的中断处理数据结构在设备驱动请求系统中断控制时建立。为完成此项工作,设备驱动使用一组Linux核心函数来请求中断,使能中断和屏蔽中断。
每个设备驱动将调用这些过程来注册其中断处理例程地址。
有些中断由于传统的PC体系结构被固定下来,所以驱动仅需要在其初始化时请求它的中断。软盘设备驱动正是使用的这种方式;它的中断号总为6。有时设备驱动也可能不知道设备使用的中断号。对PCI设备驱动来说这不是什么大问题,它们总是可以知道其中断号。但对于ISA设备驱动则没有取得中断号的方便方式。Linux通过让设备驱动检测它们的中断号来解决这个问题。
设备驱动首先迫使设备引起一个中断。系统中所有未被分配的中断都被使能。此时设备引发的中断可以通过可编程中断控制器来发送出去。Linux再读取中断状态寄存器并将其内容返回给设备驱动。非0结果则表示在此次检测中有一个或多个中断发生。设备驱动然后将关闭检测并将所有未分配中断屏蔽掉。
如果ISA设备驱动成功找到了设备的IRQ号,就可以象平常一样请求对设备的控制。
基于PCI系统比基于ISA系统有更多的动态性。ISA设备使用的中断引脚通常是通过硬件设备上的跳线来设置并固定在设备驱动中。PCI设备在系统启动与初始化PCI时由PCI BIOS或PCI子系统来分配中断。每个PCI设备可以使用A,B,C或D之中的任意中断。这个中断在设备建立时确定且通常多数设备的缺省中断为 A。PCI槽中的PCI中断连线A,B,C和D被正确路由到中断控制器中。所以PCI槽4上的引脚A可能被路由到中断控制器上的引脚6,PCI槽7上的引脚B被路由到中断控制器上的引脚7等等。
如何路由PCI中断完全取决于特定的系统,一般设置代码能理解PCI中断路由拓扑。在基于Intel的PC上由系统BIOS代码在启动时作这些设置而在不带BIOS(如Alpha AXP)系统中由Linux核心来完成这个任务。
PCI设置代码将每个设备对应的中断控制器的引脚号写入PCI配置头中。通过得到PCI中断路由拓扑及设备的PCI槽号和PCI中断引脚设置代码可以确定其对应的中断引脚(或IRQ)号。设备使用的中断引脚被保存在此设备的PCI配置头中为此目的保留的中断连线域中。当运行设备驱动时这些信息被读出并用来控制来自Linux核心的中断请求。
系统中可能存在许多PCI中断源,比如在使用PCI-PCI桥接器时。这些中断源的个数可能将超出系统可编程中断控制器的引脚数。此时PCI设备必须共享中断号-中断控制器上的一个引脚可能被多个PCI设备同时使用。Linux让中断的第一个请求者申明此中断是否可以共享。中断的共享将导致irq_action数组中的一个入口同时指向几个irqaction数据结构。当共享中断发生时Linux将调用对应此中断源的所有中断处理过程。没有中断需要服务时,任何共享此中断(所有的PCI设备驱动)的设备驱动都要准备好其中断处理过程的调用。
7.3 中断处理 图7.2 Linux中断处理数据结构Linux中断处理子系统的一个基本任务是将中断正确路由到中断处理代码中的正确位置。这些代码必须了解系统的中断拓扑结构。例如在中断控制器上引脚6上发生的软盘控制器中断必须被辨认出的确来自软盘并路由到系统的软盘设备驱动的中断处理代码中。Linux使用一组指针来指向包含处理系统中断的例程的调用地址。这些例程属于对应于此设备的设备驱动,同时由它负责在设备初始化时为每个设备驱动申请其请求的中断。图7.2给出了一个指向一组irqaction的irq_action指针。每个irqaction数据结构中包含了对应于此中断处理的相关信息,包括中断处理例程的地址。而中断个数以及它们被如何处理则会根据体系结构及系统的变化而变化。Linux中的中断处理代码就是和体系结构相关的。这也意味着irq_action数组的大小随于中断源的个数而变化。