关于PCI IRQ routing的讨论

关于PCI IRQ routing的讨论

         一直以来,本人就认为,一切事物的兴起和发生均会合时代有关系。任何时期出现的事物都会有一点的历史特征,历史局限性。当然,也要承认他的客观性和合理性。毕竟存在即合理。PC界尤其明显。比如从PATA到SATA总线的进化、ISA总线到PCI总线,再到PCIe总线等。

         这里说的PCI IRQrouting 显而易见,必须牵扯到IRQ的分配。IRQ是什么?为何要研究其分配?而PCI IRQ又有何特征?

         传统的PIC 模式下两个8259A级联,可以提供最多16个IRQ出来,用来给外围设备向cpu申请中断。以前由于外围设备很少,处理就简单化,每个设备固定对应一个IRQ,比如KB使用irq1、mouse使用irq12,这些一直沿袭下来。

         随着PC行业的发展,可用的外围设备已然越来越多,16个IRQ已经不够用了,就算新的APIC模式下也只是24个IRQ。那么自然想到了PCI是否能共享?所以后来相继出现的PCI总线和PCIe总线均是采用IRQ 共享方式。传统的IRQ分配方式已经不能使用新型总线的设计需求了。

         PCI总线上设备是并联的,设备都可以使用总线INT#,中断低电平有效。但是,如果所有的设备都共享到一个IRQ上呢?这种情况当然允许,但是必然会影响到系统性能,可以考虑使用IRQ balance的概念,将这些PCI设备平均分配到不同的IRQ上去,以提高系统处理pci中断的性能。这就自然引出了PCI IRQ routing。在Linux在处理多核系统中断时候,就有个工具,实现多核的irq balance。思想是差不多的。

         我们知道PCI总线上有四个中断Pin,pci设备一般使用INTA#,但是在多功能设备上,则可以使用INTA#、INTB#等线,那么PCI IRQ routing就是需要将所有pci设备这些INTA# 、INTB#、INTC#、INTD#以一定算法公平的分配到不同的IRQ上去。如下图所示,可以将PCI IRQ routing看成一个路由器,对于网络路由器是一对多的,但是PCI IRQ route则是多对多的。

 

如何实现PCI irq routing呢?

这部分的功能实现是需要bios工程师来完成,每添加一个pci slot到总线上,则需要将对应的route方式添加到PCI IRQ Router中来。在bios启动时候,PCI BIOS则会通过某种算法找到PCI IRQ Router(函数GetIRQRoutingTable),再依据Router中的方式对PCI 总线上设备分配IRQ。

这里涉及到两个问题:

1、  BIOS中如何针对HW线路---pci slot来配置Routing table

2、  Routing table的工作机制是如何?

 

问题一

HW线路设计出来,HW工程师会告知至少两个信息:Pcislot的IDSEL线是选的哪个AD线,而slot上的INTA#、INTB#、INTC#、INTD#分别对应南桥的PIRQx,x可以使1-4-8。HW线路上这种绕法不是随便绕的,需要遵循一定规范:

IRQ= (D + I )mod 4

其中,IRQ表示设备使用主板上的irq序号(1/2/3/4);南桥有PIRQa-PIRQd和PIRQe-PIRQh

D表示PCI槽上IDSEL连接到的主板的AD NO;一般情况为AD[31-11]

I表示PCI槽上INTx#的序号(1/2/3/4).

具体的连线搭配如下图

 

问题二

什么是Routing Table呢?这个在Microsoft的官网上可以找到一份权威的文档,说明Routing table的具体概念。这个router表生成之后会保留在memory中,可以搜索F0000h-FFFFFh段的字串“$PIRQ”.找到该字串之后,可以按照格式列出PCI IRQ Routing Table。如下图,是在dos下搜索到的router 表。

 

按照规范,这里简单的说明一下router表单的内容。

Byte Offset

Size in Bytes

Name

0

4

Signature

4

2

Version

6

2

Table Size

8

1

PCI Interrupt Router's Bus

9

1

PCI Interrupt Router's DevFunc

10

2

PCI Exclusive IRQs

12

4

Compatible PCI Interrupt Router

16

4

Miniport Data

20

11

Reserved (Zero)

31

1

Checksum

32

16

First Slot Entry

48

16

Second Slot Entry

(N+1)*16

16

Nth Slot Entry

看上面的表头,byte0开始4个字节表示的Signature即我们要搜索的字串:“$PIRQ”。而byte6开始的两个字节为table size,表示整个Router table的总大小,如果有5个pci slot,那么tableSize为32 + (5 * 16) = 112.

第32个byte开始就是一系列的slot表,每个slot表大小16bytes。其实这16个byte才是PCI IRQ routing的核心。

 

Slot entry的说明:

Byte Offset

Size in Bytes

Name

0

Byte

PCI Bus Number

1

Byte

PCI Device Number (in upper five bits)

2

Byte

Link Value for INTA#

3

Word

IRQ Bitmap for INTA#

5

Byte

Link Value for INTB#

6

Word

IRQ Bitmap for INTB#

8

Byte

Link Value for INTC#

9

Word

IRQ Bitmap for INTC#

11

Byte

Link Value for INTD#

12

Word

IRQ Bitmap for INTD#

14

Byte

Slot Number

15

Byte

Reserved

 

具体解释

PCI Bus Number:这个是HW给出的slot的pci bus号。

PCI Device Number:对应的slot的PCI DeviceNO,该字节的高5bit表示。Hw给出链接的AD线之后,可以算出slot的DeviceNO。NO.=AD-16。

Link Value for INTx# 为对应的slot上,INTx#对应链接到南桥的哪个PIRQ。

IRQ Bitmap :为PCI 设备可以共享使用的IRQ bitmap。这些irq必须对ISA device来说是reserved。

 

其中南桥的PIRQ有两组4个:PIRQ[A-D]和PIRQ[E-H]。分别对应南桥的PIRQx#,这些寄存器是需要将PCI可用的irq填入。

 

如何通过Router表确定PCI分配的IRQ呢?

如下图,举例来说明。

南桥上的两个UHCI,B0/D16/F0和B0/D16/F01. 都是在Bus0 上,Dveice 16上面。

1、  在上图中找到对应的Slotentry行---倒数第二行(行号为E0的那一行)。在RouterTable中Device字节为D0h,取其高5bit,即为16.

2、  在Slot entry行中,解释为:INTA#对应60h(PIRQA#);INTB#对应69h(PIRQF#);INTC#对应62h(PIRQC#);INTD#无分配。

3、  读取两个UHCI的配置寄存器3Dh—interruptPIN。UHCI#1为01h(INTA#);UHCI#2为02h(INTB#).

4、  针对UCHI#1,因为其使用的中断pin为INTA#,那么在其Slotentry行中对应的南桥的PIRQA#寄存器,查找该寄存器中的值为05h,那么相应的UHCI#使用的IRQ为05。

5、  针对UHCI#2,因为其使用的中断PIN为INTB#,哪儿在slotentry行中对应到南桥PIRQF#寄存器,查找寄存器值为07h,那么UHCI#2使用IRQ为7。

6、  其他slot以此类推

 

PCI IRQ的分配是在PCI总线initial的时候完成的,当然,这个过程需要完成的事情很多,包括memory 、io资源的分配,这中间也有很多学问存在。

你可能感兴趣的:(BIOS点滴)