空闲看看PCIE 5.0 spec, 照本宣科简单记录一下。
先上框架图,部件互连是点对点链接(point-to-point link),由Root Complex(RC), Endpoints(I/O devices), Switch, PCI Express to PCI/PCI-X Bridge组成。PCI Express Link由两个差分信号对组成,发送对和接受对(a Transmit pair and a Receive pair).


PCI Express配置模型支持两种Configuration Space访问机制:
1. PCI-compatible Configuration Access Mechanism(CAM)
2. PCI Express Enhanced Configuration Access Mechanism(ECAM)
为了保持与PCI软件配置机制的兼容性,所有PCIE设备都具有PCI兼容的Configuration Space. 与PCI允许的256字节相比,PCIE将每个Function的Configuration Space扩展到了4096字节。如图所示,PCIE Configuration Space分为PCI-compatible region和PCI Express Extended Configuration Space. PCI-compatible region 由Configuration Space的前256(0 ~ FFh)个字节组成,PCI Express Extended Configuration Space由剩余空间(100 ~ FFFh)组成。前者可以通过CAM和ECAM两种方式访问,而后者只能通过ECAM访问。

ECAM机制使用 a flat memory-mapped address space来访问设备配置空间的寄存器。memory address space与PCI Express Configuration Space address的映射规则如下图所示。

edk2 codebase里边定义了将Bus、Device、Function、Register转换成映射的memory address的宏。
/**
Macro that converts PCI Bus, PCI Device, PCI Function and PCI Register to an
ECAM (Enhanced Configuration Access Mechanism) address. The unused upper bits
of Bus, Device, Function and Register are stripped prior to the generation of
the address.
@param Bus PCI Bus number. Range 0..255.
@param Device PCI Device number. Range 0..31.
@param Function PCI Function number. Range 0..7.
@param Register PCI Register number. Range 0..4095.
@return The encode ECAM address.
**/
#define PCI_ECAM_ADDRESS(Bus,Device,Function,Offset) \
(((Offset) & 0xfff) | (((Function) & 0x07) << 12) | (((Device) & 0x1f) << 15) | (((Bus) & 0xff) << 20))
映射到Configuration Space的memory address范围的大小和基址由host bridge和firmware确定。
下面部分讲PCI-Compatible Configuration Registers,首先是Type 0/1 Common Configuration Space,如图

Vendor ID Register (Offset 00h)
Vendor ID是HwInit的,用于识别设备制造商,ID一般由PCI_SIG统一分配,确保唯一性。当值为FFFFh时表示设备不存在,在edk2里边扫描PCI总线时就是以此为根据来判断Device是否存在,部分代码如下(ScanForRootBridges)
//
// Scan all the PCI devices on the primary bus of the PCI root bridge
//
for (Device = 0, NumberOfDevices = 0; Device <= PCI_MAX_DEVICE; Device++) {
for (Function = 0; Function <= PCI_MAX_FUNC; Function++) {
//
// Compute the PCI configuration address of the PCI device to probe
//
Address = PCI_LIB_ADDRESS (PrimaryBus, Device, Function, 0);
//
// Read the Vendor ID from the PCI Configuration Header
//
if (PciRead16 (Addre


4027

被折叠的 条评论
为什么被折叠?



