我正在学习linux内核代码,关于pci的部分,我阅读了文件/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))
static 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;
}
内核版本是 2.6.18,所以宏 PCI_CONF1_ADDRESS 让我很困惑。众所周知,使用IO口CF8/CFC时只能访问pci配置空间的前256字节,如果要访问256~4095字节之间的空间,必须使用ECAM(Enhanced Configuration Access机制),但上面的注释说:
具有类型 1 访问的扩展(每个 PCI 功能 4096 字节)配置空间。
这是否意味着在使用 IO 口 CF8/CFC 时可以访问 pci 配置空间的全部 4096 字节?但是为什么 PCI LOCAL BUS SPECIFICATION 从来没有提到这一点呢?
同时,我也对这个表达感到疑惑:
((reg & 0xF00) << 16)
它使用这种方式生成 pci 配置地址,我从未在任何书籍或 SPECIFICATION 中看到此表达式。