全部博文(44)
分类:
2010-03-08 11:53:28
忘了上面这个复杂的信号转换吧,它会让我们偏离我们的目标——我们仅仅需要知道的是:需要把PCI中断映射到ISA中断,需要把电平触发转换为边缘触发,剩下的事情,是电子工程师的领域,作为一个附录应该不错:)
为了描述PCI到ISA中断的映射,微软公司在最开始就提出了PCI Interrupt Routing Table的数据结构,它的作用就是用来描述在使用8259中断控制器的系统下,PCI中断(INTA-INTD)如何路由到ISA的IRQ。
不说废话了,给出PIRQ Table的数据结构:
表3-1 PIRQ Table数据结构
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 |
每个slot entry的结构如下:
表3-2 Slot字段
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 Interrupt Router's Bus:
PCI Interrupt Router's DevFunc:
PCI Interrupt Router是一个硬件设备,而且是一个PCI设备!这两个字段描述该设备的BDF地址。
PCI Exclusive IRQs:
并不是所有ISA的IRQ都能用来作为PCI的映射IRQ,因此这个字段描述了那些只能被PCI使用的IRQ。换句话说,这些IRQ不能被ISA设备使用。
IRQ Bitmap for INTA#:
每个INTx可能会有多个IRQ可供选择,因此需要一个bitmap
容易看出,PIRQ Table描述了每个PCI设备(BDF地址指定)的每个INTx对应的可能的IRQ值。下面是我在虚拟机上得到的结果:
Entry Location Bus Device Pin Link IRQs
0 slot 1 0 3 A 0x60 0 1 4 6 8 9 10 11 12 15
0 slot 1 0 3 B 0x61 1 2 4 6 8 9 10 11 12 15
0 slot 1 0 3 C 0x62 0 3 4 6 8 9 10 11 12 15
0 slot 1 0 3 D 0x63 2 3 4 6 8 9 10 11 12 15
1 slot 2 0 4 A 0x61 0 1 5 6 8 9 10 11 12 15
1 slot 2 0 4 B 0x62 1 2 5 6 8 9 10 11 12 15
1 slot 2 0 4 C 0x63 0 3 5 6 8 9 10 11 12 15
1 slot 2 0 4 D 0x60 2 3 5 6 8 9 10 11 12 15
2 slot 3 0 4 A 0x62 0 1 4 5 6 8 9 10 11 12 15
2 slot 3 0 4 B 0x63 1 2 4 5 6 8 9 10 11 12 15
2 slot 3 0 4 C 0x60 0 3 4 5 6 8 9 10 11 12 15
2 slot 3 0 4 D 0x61 2 3 4 5 6 8 9 10 11 12 15
3 slot 4 0 4 A 0x63 0 1 7 8 9 10 11 12 15
3 slot 4 0 4 B 0x60 1 2 7 8 9 10 11 12 15
3 slot 4 0 4 C 0x61 0 3 7 8 9 10 11 12 15
3 slot 4 0 4 D 0x62 2 3 7 8 9 10 11 12 15
4 slot 5 0 4 A 0x60 0 1 4 7 8 9 10 11 12 15
4 slot 5 0 4 B 0x61 1 2 4 7 8 9 10 11 12 15
4 slot 5 0 4 C 0x62 0 3 4 7 8 9 10 11 12 15
4 slot 5 0 4 D 0x63 2 3 4 7 8 9 10 11 12 15
5 slot 6 0 5 A 0x61 0 1 5 7 8 9 10 11 12 15
5 slot 6 0 5 B 0x62 1 2 5 7 8 9 10 11 12 15
5 slot 6 0 5 C 0x63 0 3 5 7 8 9 10 11 12 15
5 slot 6 0 5 D 0x60 2 3 5 7 8 9 10 11 12 15
6 embedded 0 0 A 0x60 0 1 4 5 7 8 9 10 11 12 15
6 embedded 0 0 B 0x61 1 2 4 5 7 8 9 10 11 12 15
6 embedded 0 0 C 0x62 0 3 4 5 7 8 9 10 11 12 15
6 embedded 0 0 D 0x63 2 3 4 5 7 8 9 10 11 12 15
7 embedded 0 1 A 0x60 0 1 6 7 8 9 10 11 12 15
7 embedded 0 1 B 0x61 1 2 6 7 8 9 10 11 12 15
7 embedded 0 1 C 0x62 0 3 6 7 8 9 10 11 12 15
7 embedded 0 1 D 0x63 2 3 6 7 8 9 10 11 12 15
8 embedded 0 0 A 0x60 0 1 4 6 7 8 9 10 11 12 15
8 embedded 0 0 B 0x61 1 2 4 6 7 8 9 10 11 12 15
看到这里,提出两个问题:
1、 PCI Interrupt Router的作用是映射PCI中断到ISA中断,而它自己也是一个PCI设备,会不会出现“先有鸡还是先有蛋”的问题呢?
不会,PCI Interrupt Router其实是作为南桥的一个功能单元而存在,访问这个设备是通过配置寄存器实现的,因此只需要BDF即可。下面是Intel主板的一个实现:
不同芯片组支持的设备可能不同,因此这些可能的IRQ也可能会有差别。通过这个4个寄存器,我们甚至可以动态地将PCI的某个中断映射到不同的IRQ值(虽然并不多见)。 2、 BIOS怎么知道那些IRQ可用? 这个表是BIOS提供给OS使用的,但是BIOS也不能凭空捏造吧。其实说BIOS“凭空捏造”也未尝不可,因为BIOS都是这些主板厂商自己写的,他们太了解这些东西了,看看下面BIOS的一段代码就恍然大悟了: const struct irq_routing_table intel_irq_routing_table = { PIRQ_SIGNATURE, /* u32 signature */ PIRQ_VERSION, /* u16 version */ 32+16*4, /* there can be total 5 devices on the bus */ 0x00, /* Bus 0 */ 0x08, /* Device 1, Function 0 */ 0x0000, /* reserve IRQ 11, 9, 5, for PCI */ 0x1039, /* Silicon Integrated System */ 0x0008, /* SiS 85C503/5513 ISA Bridge */ 0x00, /* u8 miniport_data - "crap" */ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */ CHECKSUM, /* u8 checksum - mod 256 checksum must give zero */ { /* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */ {0x00, 0x08, {{0x41, 0xdcb8}, {0x42, 0xdcb8}, {0x43, 0xdcb8}, {0x44, 0xdcb8}}, 0x00, 0x00}, {0x00, 0x10, {{0x41, 0xdcb8}, {0x42, 0xdcb8}, {0x43, 0xdcb8}, {0x44, 0xdcb8}}, 0x00, 0x00}, {0x00, 0x48, {{0x41, 0xdcb8}, {0x42, 0xdcb8}, {0x43, 0xdcb8}, {0x44, 0xdcb8}}, 0x01, 0x00}, {0x00, 0x58, {{0x43, 0xdcb8}, {0x44, 0xdcb8}, {0x41, 0xdcb8}, {0x42, 0xdcb8}}, 0x02, 0x00}, } }; printk(KERN_INFO "Copying IRQ routing tables..."); memcpy((char *) RTABLE_DEST, &intel_irq_routing_table, intel_irq_routing_table.size); printk(KERN_INFO "done.\n"); 原来,在BIOS的代码中是将这个PIRQ Table写死的,然后BIOS将这个表拷贝到一个合适的地方,供OS使用。 笔者:感谢bluesky_jxc同学为我们带来PIRQ Table的知识。PIRQ Table由微软提出,描述了从OS的观点,如何看待中断路由的问题,它并没有规定硬件厂商如何实现。PRIQ spec和MP spec一起构成了早期MP平台中断几乎所有的内容,但往事如尘埃,俱往矣。ACPI替代了它们。从长远的眼光看,我们在学习相关内容时,应该尽可能的多着眼于ACPI,对于历史,了解即可。 关于PIRQ table的详细内容可参考: