为了访问PCI配置空间,根据各种文章,使用I / O端口地址0xCF8、0xCFC。
mov eax, dword 0x80000000 mov dx, word 0x0CF8 out dx, eax mov dx, word 0x0CFC in eax, dx
上面代码中eax的值是0x12378086
,表示vendor ID = 0x8086
和device ID = 0x1237
。
这是问题。
Q1。我已经看到此方法仅适用于PCI配置空间。那么,访问PCIe配置空间的另一种方法是什么?
“ 无法使用传统的PCI方法(通过端口0xCF8和0xCFC)访问此扩展的配置空间”
https://wiki.osdev.org/PCI_Express
但是另一些文章说,这种传统方法也与PCIe配置空间兼容。
这很混乱。
Q2。如果传统的0xCF8、0xCFC也可以与PCIe配置空间配合使用,那么将不胜枚举NASM汇编源代码(不涉及linux),因为我看过很多ECAM(增强型配置访问机制)文章,但所有这些都是关于概念性内容。
硬件规格:
Motherboard : P775TM1 Processor : Intel i7 8700K
Brendan.. 5
Q1。我已经看到此方法仅适用于PCI配置空间。那么,访问PCIe配置空间的另一种方法是什么?
对于80x86 PC,实际上有3种机制可以访问PCI配置空间。您提到的传统机制(使用IO端口0x0CF8和0x0xCFC)是“机制#1”。还有另一种称为“机制2”的传统机制,该机制也使用了0x0CF8和0x0xCFC。但是许多芯片组并没有使用它,并且(对于现代计算机)可以认为它已经过时了。
最初,每个PCI“功能”的PCI配置空间的大小为256字节;对于这两种传统机制,您只能访问256个字节。当他们发明PCI-E时,他们添加了第三种机制(内存映射的ECAM),并且还将每个PCI-E“功能”的PCI配置空间增加到4096字节。传统的“机制#1”仍然有效,但是仍然只能访问前256个字节(PCI-E“功能”可以拥有的4096个字节中的一个)。幸运的是,硬件制造商足够聪明,可以确保较旧的操作系统需要访问的内容在前256个字节之内,因此不支持PCI-E的较旧的操作系统仍然可以正常工作(使用“机制#1”),其余4096字节(可以
注意:可能有一个“ PCI-E到PCI常规”桥,在该桥后面有PCI常规设备。在这种情况下,PCI常规设备/功能将仅提供256字节的PCI配置空间,即使它仍在使用ECAM。
使用ECAM;您将需要使用ACPI的“表索引”(RSDT或XSDT)来查找称为“ MCFG”的表。遗憾的是(除非自从我上次查找以来已更改),该表在所属的ACPI规范中没有进行描述;而是在PCI规范中进行了描述,该规范被锁定在“恶意昂贵”的PCI SIG付费墙后面。希望您可以在某处找到可靠的第三方描述。
一般来说; MCFG表由描述用于一系列总线号的地址范围的条目组成;总线号的多个不同范围可能有多个不同的地址范围。这个想法是使用设备的总线号来找到正确区域的地址。然后组合“ address_of_area + ((bus - first_bus_for_area) <<20) | (device <<15) | (function <<12)
”以找到功能的PCI配置空间的起始地址。找到后,您可以在该物理页面中读/写偏移量,以访问函数的PCI配置空间中的相应偏移量。
Q1。我已经看到此方法仅适用于PCI配置空间。那么,访问PCIe配置空间的另一种方法是什么?
对于80x86 PC,实际上有3种机制可以访问PCI配置空间。您提到的传统机制(使用IO端口0x0CF8和0x0xCFC)是“机制#1”。还有另一种称为“机制2”的传统机制,该机制也使用了0x0CF8和0x0xCFC。但是许多芯片组并没有使用它,并且(对于现代计算机)可以认为它已经过时了。
最初,每个PCI“功能”的PCI配置空间的大小为256字节;对于这两种传统机制,您只能访问256个字节。当他们发明PCI-E时,他们添加了第三种机制(内存映射的ECAM),并且还将每个PCI-E“功能”的PCI配置空间增加到4096字节。传统的“机制#1”仍然有效,但是仍然只能访问前256个字节(PCI-E“功能”可以拥有的4096个字节中的一个)。幸运的是,硬件制造商足够聪明,可以确保较旧的操作系统需要访问的内容在前256个字节之内,因此不支持PCI-E的较旧的操作系统仍然可以正常工作(使用“机制#1”),其余4096字节(可以
注意:可能有一个“ PCI-E到PCI常规”桥,在该桥后面有PCI常规设备。在这种情况下,PCI常规设备/功能将仅提供256字节的PCI配置空间,即使它仍在使用ECAM。
使用ECAM;您将需要使用ACPI的“表索引”(RSDT或XSDT)来查找称为“ MCFG”的表。遗憾的是(除非自从我上次查找以来已更改),该表在所属的ACPI规范中没有进行描述;而是在PCI规范中进行了描述,该规范被锁定在“恶意昂贵”的PCI SIG付费墙后面。希望您可以在某处找到可靠的第三方描述。
一般来说; MCFG表由描述用于一系列总线号的地址范围的条目组成;总线号的多个不同范围可能有多个不同的地址范围。这个想法是使用设备的总线号来找到正确区域的地址。然后组合“ address_of_area + ((bus - first_bus_for_area) <<20) | (device <<15) | (function <<12)
”以找到功能的PCI配置空间的起始地址。找到后,您可以在该物理页面中读/写偏移量,以访问函数的PCI配置空间中的相应偏移量。
您阅读了报价
无法使用旧式PCI方法(通过端口0xCF8和0xCFC)访问此扩展的配置空间。
你离题了。
这是上下文中的引号(重点是我的):
PCI Express总线将配置空间从256字节扩展到4096字节。无法使用旧式PCI方法(通过端口0xCF8和0xCFC)访问此扩展的配置空间。
作者谈论的是PCIe配置空间中从0x100开始的部分。
最初,每个PCI设备功能都有一个256字节的配置空间。
在端口0xcf8和0xcfc处使用PCI传统机制(我们可以忽略存在两种机制的事实)来访问此空间。
PCIe将该空间从256字节扩展到4KiB,并引入了一种新的机制来访问配置空间(全部)。
因此,回顾一下:
有一个4KiB的PCI配置空间。它分为PCI 3.0兼容区域(从0x000到0x0ff)和PCIe扩展配置区域(从0x100到0xfff)。
有两种访问PCI配置空间的机制。一种是位于0xcf8 / 0xcfc的旧机制,另一种是内存映射区域。
传统机制只能访问兼容区域(前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兼容的配置空间。
使用任何一种访问机制进行的访问都是等效的。只能使用ECAM来访问PCI Express扩展配置空间。
它很(非常)可能是英特尔的处理器将支持许多年里传统PCI配置机制。
在内部,生成PCI配置事务的非核心部分(即,系统代理/ UBox)已经仅使用PCIe配置事务(即,由ECAM生成的相同MMCFG类型),但是未删除旧版软件接口。
由于PCIe根联合体位于CPU内,因此在涉及传统PCI 软件兼容性时,CPU是唯一需要考虑的问题(传统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的(传统)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
固件已经配置了所有内容以正确使用此区域。