PCI 设备配置空间的访问机制
PCI 总线规定访问配置空间的总线事务,即配置读写总线事务,使用 ID 号进行寻址。PCI 设备的 ID 号由 总线号(Bus Number)、设备号(Device Number)和功能号(Function Number)组成。
,通常与 HOST 主桥直接相连的 PCI 总线编号为 0,系统软件使用 DFS(Depth-First Search)算法扫描 PCI 总线树上的所有 PCI 总线,并依次进行编号。一个 PCI 设备中最多有 8 个功能设备,而且每一个功能设备都有各自的 PCI 配置空 间,而在绝大多数 PCI 设备中只有一个功能设备。
(1)PCIE的PCI AGENT 配置空间
(1) Device ID 和 Vendor ID 寄存器
这两个寄存器的值由 PCISIG 分配,只读。其中 Vendor ID 代表 PCI 设备的生产厂商,而 Device ID 代表这个厂商所生产的具体设备。如 Intel 公司的基于 82571EB 芯片的系列网卡,其 Vendor ID 为 0x8086[1], 而 Device ID 为 0x105E[2]。
(2) Revision ID 和 Class Code 寄存器
这两个寄存器只读。其中 Revision ID 寄存器记载 PCI 设备的版本号。该寄存器可以被认为是 Device ID 寄存器的扩展。
(3) Header Type 寄存器,该寄存器只读,由 8 位组成。
第 7 位为 1 表示当前 PCI 设备是多功能设备,为 0 表示为单功能设备。第 6~0 位表示当前配置空间的类型,为 0 表示该设备使用 PCI Agent 设备的配置空间,普通 PCI 设备都
使用这种配置头;为 1 表示使用 PCI 桥的配置空间,PCI 桥使用这种配置头;为 2 表示使用 Cardbus 桥片 的配置空间,Card Bus 桥片使用这种配置头,
(4) Cache Line Size 寄存器
对于 PCIe 设备,该寄存器的值无意义,因为 PCIe 设备在进行数据传送时,在其报文中含有一次数 据传送的大小,PCIe 总线控制器可以使用这个“大小”,判断数据区域与 Cache 行的对应关系。
(5) Subsystem ID 和 Subsystem Vendor ID 寄存器
Xilinx 公司在 FGPA 中集成了一个 PCIe 总线接口的 IP 核,即 LogiCORE。用户可以使用 LogiCORE 设计 各种各样基于 PCIe 总线的设备,但是这些设备的 Device ID 都是 0x10EE,而 Vendor ID 为 0x0007[3]。
(6) Expansion ROM base address 寄存器
有些 PCI 设备在处理器还没有运行操作系统之前,就需要完成基本的初始化设置,比如显卡、键盘和硬盘等设备。为了实现这个“预先执行”功能,PCI 设备需要提供一段 ROM 程序,而处理器在初始化过程中将运 行这段 ROM 程序,初始化这些 PCI 设备。Expansion ROM base address 记载这段 ROM 程序的基地址。
(7) Capabilities Pointer 寄存器
在 PCI 设备中,该寄存器是可选的,但是在 PCI-X 和 PCIe 设备中必须支持这个寄存器,Capabilities Poi nter 寄存器存放 Capabilities 寄存器组的基地址,PCI 设备使用 Capabilities 寄存器组存放一些与 PCI 设备 相关的扩展配置信息。
8) Interrupt Line 寄存器
这个寄存器是系统软件对 PCI 设备进行配置时写入的,该寄存器记录当前 PCI 设备使用的中断向量号,设 备驱动程序可以通过这个寄存器,判断当前 PCI 设备使用处理器系统中的哪个中断向量号,并将驱动程序 的中断服务例程注册到操作系统中。
(9) Interrupt Pin 寄存器
这个寄存器保存 PCI 设备使用的中断引脚,PCI 总线提供了四个中断引脚 INTA#、INTB#、INTC#和 INT D#。Interrupt Pin 寄存器为 1 时表示使用 INTA#引脚向中断控制器提交中断请求,为 2 表示使用 INTB#,为 3 表示使用 INTC#,为 4 表示使用 INTD#。
(10) Base Address Register 0~5 寄存器
该组寄存器简称为 BAR 寄存器,BAR 寄存器保存 PCI 设备使用的地址空间的基地址,该基地址保存的是 该设备在 PCI 总线域中的地址。其中每一个设备最多可以有 6 个基址空间,但多数设备不会使用这么多组 地址空间。处理器访问 PCI 设备的 BAR 空间时,需要使用 BAR 寄存器提供的基地址。值得注意的是,处理器使用存储器域的地址,而 BAR 寄存器存放 PCI 总线域的地址。因此处理器系统并不能直接使用“BAR 寄存器+偏移”的方式访问 PCI 设备的寄存器空间,而需要将 PCI 总线域的地址转换为存储器域的地址。如果 x86 处理器系统使能了 IOMMU 后,这两个地址也并不一定相等,
(11) Command 寄存器
该寄存器为 PCI 设备的命令寄存器,该寄存器在初始化时,其值为 0,此时这个 PCI 设备除了能够接收配置请求总线事务之外,不能接收任何存储器或者 I/O 请求。系统软件需要合理设置该寄存器之后,才能访问该设备的存储器或者 I/O 空间。在 Linux 系统中,设备驱动程序调用 pci_enable_device 函数,使能该寄存器的 I/O 和 Memory Space 位之后,才能访问该设备的存储器或者 I/O 地址空间。
(12) Status 寄存器该寄存器的绝大多数位都是只读位,保存 PCI 设备的状态。
(13) Latency Timer 寄存器
在 PCI 总线中,多个设备共享同一条总线带宽。该寄存器用来控制 PCI 设备占用 PCI 总线的时间,当 PCI 设备获得总线使用权,并使能 Frame#信号后,Latency Timer 寄存器将递减,当该寄存器归零后,该设备 将使用超时机制停止[6]对当前总线的使用。PCIe 设备不需要使用该寄存器,该寄存器的值必须为0;这个基本配置空间共由 64 个字节组成,其地址范围为 0x00~0x3F,这 64 个字节是所有 PCI 设备必须支持的。此外 PCI/PCI-X 和 PCIe 设备还扩展了 0x40~0xFF 这段配置空间,在这段空间主要存放一些与 MSI 或者 MSI-X 中断机制和电源管理相关的 Capability 结构。PCIe 设备还支持 0x100~0xFFF 这段扩展配置空间。PCIe 设备使用的扩展配置空间最大为4KB,在 PCIe 总线的扩展配置空间中,存放 PCIe 设备所独有的一些 Capability 结构,而 P CI 设备不能使用这段空间。PCI-X 和 PCIe 总线规范要求其设备必须支持 Capabilities 结构。在 PCI 总线的基本配置空间中,包含一个Capabilities Pointer寄存器,该寄存器存放Capabilities结构链表的头指针。在一个 PCIe 设备中,可能含有多个 Capability 结构,这些寄存器组成一个链表,其结构如
其中每一个 Capability 结构都有唯一的 ID 号,每一个 Capability 寄存器都有一个指针,这个指针指向下一个 Capability 结构,从而组成一个单向链表结构,这个链表的最后一个 Capability 结构的指针为 0。一个 PCIe 设备可以包含多个 Capability 结构,包括与电源管理相关、与 PCIe 总线相关的结构、与中断请求相关的 Capability 结构、PCIe Capability 结构和 PCIe 扩展的 Capability 结构。