- 论坛徽章:
- 0
|
hi,大家好:
最近学习linux内核代码,当看到文件/arch/x86/pci/Direct.c时,对里面的部分代码感到困惑:
- /*
- * Functions for accessing PCI base (first 256 bytes) and extended
- * (4096 bytes per PCI function) configuration space with type 1
- * accesses.
- */
- #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
- (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
- | (devfn << 8) | (reg & 0xFC))
- int pci_conf1_read(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 *value)
- {
- unsigned long flags;
- if ((bus > 255) || (devfn > 255) || (reg > 4095)) {
- *value = -1;
- return -EINVAL;
- }
- spin_lock_irqsave(&pci_config_lock, flags);
- outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
- switch (len) {
- case 1:
- *value = inb(0xCFC + (reg & 3));
- break;
- case 2:
- *value = inw(0xCFC + (reg & 2));
- break;
- case 4:
- *value = inl(0xCFC);
- break;
- }
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
- int pci_conf1_write(unsigned int seg, unsigned int bus,
- unsigned int devfn, int reg, int len, u32 value)
- {
- unsigned long flags;
- if ((bus > 255) || (devfn > 255) || (reg > 4095))
- return -EINVAL;
- spin_lock_irqsave(&pci_config_lock, flags);
- outl(PCI_CONF1_ADDRESS(bus, devfn, reg), 0xCF8);
- switch (len) {
- case 1:
- outb((u8)value, 0xCFC + (reg & 3));
- break;
- case 2:
- outw((u16)value, 0xCFC + (reg & 2));
- break;
- case 4:
- outl((u32)value, 0xCFC);
- break;
- }
- spin_unlock_irqrestore(&pci_config_lock, flags);
- return 0;
- }
复制代码 内核版本为2.6.18。大家知道,如果使用IO端口CF8/CFC访问PCI配置空间的时候,只能访问配置空间的前256字节,如果要访问大于256字节的空间,必须使用ECAM(Enhanced Configuration Access Mechanism)机制,关于这点,在PCI规范里有提到,在PCI[1].Express.Base.Specification.v1.0中第313页中有如下文字:
The extended PCI Express region can only be accessed by using the enhanced PCI Express configuration access mechanism
上面说的extended PCI Express region指的就是256字节以上的空间。
但是上面的代码中的注释说可以访问前256字节和所有的4096字节,我感到不解。上面代码中的宏PCI_CONF1_ADDRESS:- #define PCI_CONF1_ADDRESS(bus, devfn, reg) \
- (0x80000000 | ((reg & 0xF00) << 16) | (bus << 16) \
- | (devfn << 8) | (reg & 0xFC))
复制代码 如果此时访问前256字节,那么((reg & 0xF00) << 16)就为0,此时就生产了一个地址用来访问配置空间,这种方式很好理解,PCI规范里说的很清楚。但是如果访问的字节偏移大于256字节,那么((reg & 0xF00) << 16)就不为0,这种(生成地址的)方式不管是在PCI规范里还是在书里都没见到过。哪位大侠指教指教,谢谢! |
|