linux-kernel - 关于访问 pci 配置空间,宏 PCI_CONF1_ADDRESS 让我感到困惑

标签 linux-kernel pci pci-bus

我正在学习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机制),但上面的注释说:

extended (4096 bytes per PCI function) configuration space with type 1 accesses.



这是否意味着在使用 IO 口 CF8/CFC 时可以访问 pci 配置空间的全部 4096 字节?但是为什么 PCI LOCAL BUS SPECIFICATION 从来没有提到这一点呢?

同时,我也对这个表达感到疑惑:

((reg & 0xF00) << 16)



它使用这种方式生成 pci 配置地址,我从未在任何书籍或 SPECIFICATION 中看到此表达式。

最佳答案

这是 AMD CPU 和芯片组的非标准功能。 AFAIK 它不适用于英特尔平台。至少从 Linux 内核代码中我可以理解,可以使用 CF8/CFC IO 地址访问扩展配置空间。

patch from AMD

关于 ((reg & 0xF00) << 16) - 看起来像是 AMD 用于存储部分地址的 CF8 配置地址端口的保留位 30:24。

关于linux-kernel - 关于访问 pci 配置空间,宏 PCI_CONF1_ADDRESS 让我感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12136215/

相关文章:

windows - 使用 Win32 API 访问 PCI 配置空间

c++ - 有没有人知道上下文切换 - 通过 FSYNC 与 syslog-ng 从应用程序记录到磁盘

c# - 如何获取 PCI 设备的设备 ID?

winapi - 通过 Windows 的 API(用户模式)检索 PCI 坐标

python - Python 中的 PCI 总线接口(interface)

c++ - 如何读取 PCIe 总线上使用的带宽?

linux-kernel - 为什么要读取__turn_mmu_on中的id寄存器?

linux - 如何检查 Linux 内核编译器优化级别

linux-kernel - 当我有 .ko 文件可用时,为什么 modprobe 或 insmod 无法工作?

linux - 关于如何在 Linux 上启动时尽早运行脚本的任何提示?