全部博文(44)
分类: LINUX
2008-04-27 21:38:23
史前的PIC
8259A是即我们通常说的PIC,如图1-1所示:
图1-1 8259A
其中最重要的管脚是IR0~IR7(Interrupt Request0~7,用于连接设备)、INT(连接CPU,当有中断请求时,拉高该管脚以通知CPU中断的到来)、INTA(连接CPU,CPU通过该管脚应答中断请求,并通知PIC提交中断的vector到数据线)。此外,由于一片8259A只能连接8个设备,对于现代PC架构来说显得过少,通常会通过CS(片选)将两个8259A连在一起构成一个可以连接15个设备(有一个管脚用于串联另一片8259A)的PIC。
既然是可编程的芯片,8259A当然少不了寄存器。除了ICW(Initialization Command Word,初始化命令寄存器,用于初始化8259A)和OCW(Operation Command Word,操作命令字,用于控制8259A)外,最重要的有3个寄存器:
u IRR:Interrupt Request Register,中断请求寄存器,共8bit,对应IR0~IR7八个中断管脚。当某个管脚的中断请求到来后,若该管脚没有被屏蔽,IRR中对应的bit被置一。表示PIC已经收到设备的中断请求,但还未提交给CPU。
u ISR:In Service Register,服务中寄存器,共8bit,每bit意义同上。当IRR中的某个中断请求被发送给CPU后,ISR中对应的bit被置一。表示中断已发送给CPU,但CPU还未处理完。
u IMR:Interrupt Mask Register,中断屏蔽寄存器,共8bit,每bit意义同上。用于屏蔽中断。当某bit置一时,对应的中断管脚被屏蔽。
与APIC不同,PIC的每个管脚具有优先级,以0号管脚最高。也就说,连接号码较小的设备具有较高的中断优先级。通过对PIC的ICW寄存器编程,可以设定起始vector号,以计算当前中断的vector。例如,起始vector号设为16,IR3管脚产生了中断请求,则IR3对应的vector = 16+3 =19。通过PIC发起中断的典型流程如下:
1、 一个或多个IR管脚上产生电平信号,若对应的中断没有被屏蔽,IRR中相应的bit被置一。
2、 PIC拉高INT管脚通知CPU中断发生。
3、 CPU通过INTA管脚应答PIC,表示中断请求收到。
4、 PIC收到INTA应答后,将IRR中具有最高优先级的bit清零,并设置ISR中对应的bit。
5、 CPU通过INTA管脚第二次发出脉冲,PIC收到后计算最高优先级中断的vector,并将它提交到数据线上。
6、 等待CPU写EOI。收到EOI后,ISR中最高优先级的bit被清零。如果PIC处于AEOI模式,当第二个INTA脉冲收到后,ISR中最高优先级的bit自动清零。
上述流程中,EOI(End Of Interrupt)是CPU通知PIC中断处理结束的方式,由中断处理程序发起。对于PIC来说,EOI由OCW寄存器中的一个bit表示,可以通过写该寄存器发起EOI。AEOI(Auto EOI)是PIC的一种工作模式,由OCW寄存器配置。PIC有多种工作模式,我们最常使用的是PIC默认的模式,被称为Full Nested Mode。有兴趣的朋友可以参考8259A的spec了解详细信息。
前面提到,PIC的各个管脚是具有优先级的,当一个中断正被CPU处理时,优先级等于或低于该中断的中断被自动屏蔽。一个比当前中断优先级更高的中断会被马上发送给CPU,而不管CPU是否为当前中断写EOI。
PIC产生于那个动态配置还很少见的时代,大多中断管脚都被一些legacy设备(leagcy可以理解为老式设备)占用了,一个典型的PIC中断分配见图1-2:
图1-2 典型的PIC中断分配(摘自《Linux内核完全注释》)
当然,现代PC通常没有图中那么多并口、串口,也没有协处理器,一般来说5、7、9、 10、11管脚是可以被其它设备使用的。但万恶的是,出于兼容的目的,即使某个管脚没有接legacy设备,BIOS通常也会把它预留下来,例如IRQ3、4、13就经常是这种情况。由此可见,PIC能接的设备实在太少了,更致命的是,它无法适用于MP(Multiple Processor,多处理器)平台。随着SMP越来越普及,PIC注定要退出历史舞台,让位给来者。
笔者:上面对于PIC工作模式的论述,特别是优先级的论述,是基于PIC默认的Full Nested模式说的。这是PIC最常用的模式。实际上PIC还有优先级轮转(rotating)、特殊优先级轮转模式。优先级轮转是指PIC在服务完一个管脚后将其优先级降低,并升高未服务管脚的优先级,以实现一种类似轮询的模式。这和后面讲到的LAPIC Arb机制类似。