PCI与PCIE

Published: 4/9/2025

PCI

PCI(Peripheral Component Interconnect)中文名为外围组件互连,是一种总线标准,用于连接计算机的外围设备. PCI不同的版本支持33MHz,66MHz一级133MHz的时钟频率,并且支持32位和64位的数据总线. 现如今已被PCIe所取代.

总的来说,PCI支持计算机交互多种设备。PCI总线之间可以通过PCI桥与ISA桥来进一步扩展可搭载设备的数量。PCI设备与PCI局部总线相连,PCI局部总线与计算机总线相连来进行通信,PCI桥的作用就是用来联通不同的PCI总线使之能够相互通信。

PCI为所有的连接设备提供了256字节的配置空间。配置空间的访问往往取决于连接PCI局部总线的方式,很多情况下需要通过北桥芯片来访问,对北桥芯片的访问地址寄存器写入需要访问的PCI配置空间地址,就可以通过北桥的访问数据寄存器来读写数据。通过读取配置空间的设备ID和厂商ID来识别设备,0XFFFF表示空设备。

一个PCI设备可以有多个Function,多个Capability,每个Function都有上面提到的256字节配置空间。Function的意义在于,一个设备可能会提供多种功能,很多情况下这些功能独立运行,所以需要独立地对其配置,同时每个Function可以提供多个Capability,这些Capability可以被理解为特性,比如设备的电源管理等。Capbaility的属性存放于配置空间中,属性结构体存放了数据存放的地址(BAR)。PCI在配置空间中提供了5个32位的BAR配置,用来存放设备的内存地址或IO地址。对于之前提到的属性结构体,其BAR成员则提供了capability数据存放的地址,通过其offset成员就找到capability的数据。

图片来源:https://docs.oracle.com/cd/E19455-01/805-7378/hwovr-22/index.html

Function

同一设备可能会拥有多种功能,每一种功能都会拥有一个256字节大小的配置空间。每个设备最多可以拥有8个Function,Function 0是默认提供的。

Configuration Space

PCI标准为每个PCI设备定义了256字节大小的配置空间,其中前64字节是标准配置空间,后192字节由设备厂商自行定义使用。通过配置空间,CPU可以读取PCI设备的配置信息,识别PCI设备是否有效,下面是PCI配置空间的结构图:

CPU会通过Device ID与Vendor ID来识别设备,如果读取返回0xffff,则表示没有设备连接在该地址上。

Command域用于控制设备的行为,最主要的功能是控制CPU对设备内存空间与IO空间的访问权限。

Status域用于显示设备的状态,比如设备是否支持PCI总线的中断,是否有Capability等。

设备寻址

PCI设备配置空间的寻址是通过Bus NumberDevice NumberFunction Number来确定的,Bus Number用于确定PCI总线,Device Number用于确定设备,Function Number用于确定设备上的功能。一台主机最多连接256根PCI总线,每根PCI总线最多连接32个设备,每个设备最多支持8个功能。这里需要注意每个设备可能会有多个功能,如果这样的话,那么每个设备的每个功能就会拥有单独的256字节PCI配置空间。功能的数量通过Header Type域来确定,如果Header Type域的第7位为1,那么表示该设备有多个功能。

具体的寻址方式为:

    31-24     23-16  15-11  10-8   7-2    1-0
  ConfigEn      0     Bus   Device Function Register

Capability

PCI设备可能会提供一些额外的功能,PCI标准使用Capability list来表示PCI设备的特定能力,Capability list是一个链表结构,每个Capability都有一个指向下一个Capability的指针,最后一个Capability的指针为0。Capability list的起始地址在PCI配置空间的0x34字节处,每个Capability结构体前16字节格式如下:

BAR

每个PCI设备,都有6个32位的BAR寄存器,用于指定设备的内存地址空间或者IO地址空间,BAR寄存器的地址在PCI配置空间的0x10字节处,根据BAR寄存器的标志位,两个BAR寄存器可以组成一个64位的BAR寄存器,下面是BAR寄存器的结构:

内存空间与IO空间通过Memory SpaceIO Space位来区分,Prefetchable位用于指示是否支持预取,Type位用于指示BAR寄存器的类型,Base Address用于指定BAR寄存器的基地址。需要注意设备初始化时,BAR寄存器并未初始化,通过向BAR寄存器写入0XFFFFFFFF,设备会返回表示设备地址空间大小的值,通过消除标志位,取反并加1来得到设备地址空间的大小,之后需要写回原来的值。得到空间大小后,通过向Command寄存器写入0x3来使得CPU能够访问设备的内存空间和IO空间,PCI会自动将对应的基地址写入对应的寄存器。

BAR寄存器指向的空间用于实现PCI设备具体的操作,CPU通常使用该空间来与PCI设备进行通信。

设备探寻与初始化

根据PCI-HOST桥设备,遍历PCI配置空间尝试寻找对应设备。如果找到该设备,则首先读取设备的Capability list,然后读取设备的BAR寄存器,开启对应空间访问,获取设备的内存空间与IO空间的基地址和大小。之后通过BAR寄存器指向的空间与设备进行通信。

通信方式

PCIE

PCI-E(Peripheral Connect Interface Express)或者是PCIe,是沿用PCI概念并具有更高速的串行通信系统标准,并且仅应用于内部互联,提供了不同规格标准的带宽,比如PCIe x16 ,PCIe x8。PCI标准使得其通用性很强,可以连接设备与设备,设备与芯片组,甚至是GPU等设备,这样就能简化计算机对IO的处理,提高可移植性和模块性。PCI-E自2003年由PCISIG发布1.0标准。

具体而言,与PCI相比,PCIe有这些不同:

  1. PCIe使用高速串行通信,采用点对点连接,而PCI使用并行通信,共享总线。这表示PCIe每个设备都会有自己的数据传输通道,而非像PCI那样通过共享总线传输数据从而减少带宽性能,反而大大提高了自身性能。

  2. PCIe配置空间从固定的256字节扩大到最大可达4KB大小,具体实现取决于厂商设计,其中前256字节与PCI配置空间相同,后续字节则提供了PCIe自己的特性。

  3. PCIe提供了多类型的插槽与带宽规格,而PCI插槽固定大小。

参考

  1. PCISIG

  2. PCI-E WIKI