你读了报价
无法使用传统 PCI 方法访问此扩展配置空间(通过端口 0xCF8 和 0xCFC)
你离题了。
这是上下文中的引用(强调我的):
PCI Express 总线将配置空间从 256 字节扩展到 4096 字节。使用传统 PCI 方法(通过端口 0xCF8 和 0xCFC)无法访问此扩展配置空间。
作者说的是从 0x100 开始的 PCIe 配置空间 部分。
一开始,每个 PCI 设备功能都有一个 256 字节的配置空间。
这个空间是使用 PCI 传统机制(我们可以忽略有两种机制的事实)在端口 0xcf8 和 0xcfc 访问的。
PCIe 将此空间从 256 字节扩展到 4KiB,并引入了一种新机制来访问配置空间(全部)。
所以,回顾一下:
- 有一个 4KiB 的 PCI 配置空间。它分为PCI 3.0 兼容区域(从 0x000 到 0x0ff)和 PCIe 扩展配置区域(从 0x100 到 0xfff)。
- 有两种机制可以访问 PCI 配置空间。一种是 0xcf8/0xcfc 的遗留机制,另一种是内存映射区域。
- Legacy 机制只能访问兼容区域(前 256 个字节)。
- ECAM 可以访问所有空间。
引用 PCIe 规范:
PCI Express 将每个功能的配置空间扩展到 4096 字节,而 PCI 本地总线规范允许 256 字节。
PCI Express 配置空间分为一个 PCI 3.0 兼容区域,它由功能配置空间的前 256 个字节组成,以及一个 PCI Express 扩展配置空间,它由剩余的配置空间组成(见图 7-3)。
可以使用 PCI 本地总线规范[NdR:传统配置机制]中定义的机制或本节后面描述的 PCI Express 增强配置访问机制 (ECAM) 来访问与 PCI 3.0 兼容的配置空间。
使用任一访问机制进行的访问是等效的。PCI Express 扩展配置空间只能使用 ECAM 访问。
英特尔的CPU很有可能在未来很多年都支持传统的 PCI 配置机制。
在内部,生成 PCI 配置事务(即系统代理/UBox)的非核心部分已经仅使用 PCIe 配置事务(即由 ECAM 生成的相同 MMCFG 类型),但未删除旧软件接口。
由于 PCIe 根复合体位于 CPU 内,因此 CPU 是遗留 PCI软件兼容性的唯一关注点(遗留 PCI 需要 PCIe 到 PCI 桥接器,这可能会暴露配置机制)。
简而言之,您可以安全地使用传统 PCI 机制来访问 PCIe 配置空间的前 256 个字节(每个功能)。
实际上,除非英特尔找到配置非核心设备的新方法,否则旧机制永远不会消失,因为它需要配置 ECAM 本身。
遗留机制可以直接使用,您已经发布了一些使用它的代码。我不确定还需要什么。
你可以像这样使用它:
%define CFG(bus, dev, fun, reg) (0x80000000 | (bus << 16) | (dev << 11) | (fun << 8) | reg)
%macro cfg_arm 4
mov dx, 0cf8h
mov eax, CFG(%1, %2, %3, %4)
out dx, eax
%endmacro
%macro cfg_read 4
cfg_arm %1, %2, %3, %4
mov dx, 0cfch
in eax, dx
%endmacro
%macro cfg_write 5
cfg_arm %1, %2, %3, %4
mov dx, 0cfch
mov eax, %5
out dx, eax
%endmacro
cfg_read 0, 0, 0, 0 ;eax <- VID:DID of dev 0, fun 0 on bus 0
此代码未经测试
如果您指的是配置空间的内容(即设置什么),那就太宽泛了。
您可以阅读感兴趣设备的数据表,它们通常会记录 PCI 规范中定义的标准寄存器。
或者,您可以阅读 PCI 规范本身。
如果您问如何使用 ECAM,请阅读 Brendan 的回答。
我唯一可以补充的是,对于您的 CPU,您可以通过从 CPU 的 iMC(总线 0,dev 0)的(传统)PCI 配置空间读取寄存器 PCIEXBAR(偏移 60h)来找到 ECAM 的基础, 有趣 0)。
像这样的东西:
cfg_read 0, 0, 0, 60h ;Low 32-bit
mov ebx, eax
cfg_read 0, 0, 0, 64h ;high 32-bit
shl rax, 32
or rax, rbx ;RAX = ptr to ECAM area
固件已经配置了一切以正确使用该区域。