PCI 基础概括
本章节介绍了PCI 在UEFI应用中主要会涉及的内容。
PCI总线优点:1. PCI总线空间和处理器空间的隔离;2.可扩展性;3.动态配置机制;4.总线带宽;5.共享总线机制;6.中断机制(使用存储器械总线事务传递中断请求)。
PCI总线的组成结构包括 1. HOST主桥;2.PCI总线;3. PCI设备;4. HOST处理器;5. PCI总线的负载;五部分组成。
-
HOST主桥:用来隔离PCI总线域与CPU存储域,管理PCI总线域和存储域地址映射,并且完成处理器与PCI设备间的数据交换。
-
PCI总线:由HOST主桥或者PCI桥管理,用来连接各类设备,如声卡,网卡,显卡。
-
PCI设备:PCI从设备只能被动地接受来自HOST主桥或者其他PCI设备的读写请求;
PCI主设备可以通过总线仲裁获得PCI总线的使用权,主动地向其他PCI设备或者主存储器读写请求。
桥设备作用管理下游的PCI总线,并转发上下游总线之间的总线事务。
-
HOST处理器:通过HOST主桥,发起PCI总线的配置请求总线事务,并对PCI总线上的设备和桥片进行配置。
-
PCI总线负载:PCI总线挂接的负载与总线频率相关,其中总线频率越高,能挂接的负载越少。
PCI总线频率越高,能挂接的负载越少,但是整条总线能提供的带宽越大。
存储器域地址空间到PCI总线域地址空间的转换
其中Outbound寄存器组将存储器域的地址转换为PCI总线域的地址,而Inbound寄存器组将PCI总线域的地址转换为存储器域的地址。
PCI桥:
在一棵PCI总线树上,最多可以挂接256个PCI设备,包括PCI桥。
PCI桥的配置空间在系统软件遍历PCI总线树时进行配置,系统软件不需要专门的驱动程序设置PCI桥的使用方法,这也是PCI桥被称为透明桥的主要原因。
非透明桥:主要作用是连接两个不同的PCI总线域,进而连接两个处理器系统。
PCI桥出现故障,并不会影响PCI桥下设备的之间的通信,但是桥下设备无法与桥上方取得通信,这也是引入PCI桥的一个重要原因。
PCI 设备配置空间
PCI设备通常将PCI配置信息存放在EEPROM中。PCI设备进行上电初始化时,将E2PROM中的信息读取到PCI设备的配置空间中作为初始值。这个过程由硬件逻辑完成。
-
Device ID(设备号) 与 Vendor ID(生产厂商)
-
Revision ID 和 Class Code寄存器。
Revision ID寄存器记载PCI设备的版本号。 Class Code记载PCI设备的分类,用于供系统软件识别当前PCI设备的分类。硬件逻辑设计也需要使用该寄存器识别不同的设备。 当Base Class Code 寄存器为0x06, Sub Class Code寄存器为0x04是,如果Interface寄存器为0x00,表示当前PCI设备为一个标准的PCI桥;如果Interface寄存器为0x01,表示当前PCI设备为一个使用"负向译码"的PCI桥。
-
Heartder Type寄存器
第7位位1表示当前PCI设备时多功能设备,为0表示为单功能设备。
第6~0位表示当前配置空间的类型,为0表示该设备使用PCI 设备的配置空间;为1表示使用PCI桥的配置空间;为2表示使用Cardbus桥片的配置空间。
-
Cache Line Size
该寄存器记录HOST处理器使用的Cache行长度。在PCI总线中和Cache相关的总线事务。
-
Subsystem ID 和 Subsystem Vendor ID寄存器
也是记录PCI设备的生产厂商和设备名称。
-
Expansion ROM base address
有些PCI设备在处理器还没有运行操作系统之前,就需要完成基本的初始化设置。为了"预先执行"功能,PCI设备需要提供一段ROM,而处理器在初始化过程中将运行这段ROM程序,初始化这些PCI设备。这里记载了ROM程序运行的基地址。
-
Capabilities Pointer寄存器
在PCI 设备中,改寄存器是可选的,但是在PCI-X 和 PCIE设备汇总必须支持这个寄存器,这里存放了Capabilities寄存器组的基地址,存放一些与PCI设备相关的扩展配置信息。
-
Interrupt Line
是系统软件对PCI设备进行配置时写入的,该寄存器记录当前PCI设备使用的中断向量号,设备驱动程序可以通过这个寄存器,判断当前PCI设备使用处理器系统中的那个中断向量号。
-
Interrupt Pin寄存器
PCI总线提供了四个中断引脚:INTA#,INTB#,INTC#和INTD。 为1时表示使用INTA#引脚,依次类推。
-
Base Address Register 0~5寄存器
保存PCI设备使用的地址空间的基地址。
系统对Bar空间的配置,需要获取PCI设备使用的Bar空间的长度,其方法是想Bar寄存器写入0xFFFF FFFF,之后读取该寄存器值,然后清除图中特殊编码的值(IO中bit0,bit1,memory 中bit0-3)并取反 加1,结果为Bar空间的大小。
-
Commitand
初始化为0时,此时PCI设备除了能够接受配置请求总线事务之外,不能接收任何存储器或者IO请求。
UEFI通过存储器访问PCI设备时,Memory Space位需要置1,否则不能访问。
-
Status
绝大多数都是只读位,保存PCI设备的状态。
-
Latency Timer
在PCI设备中,多个设备共享一条总线带宽。该寄存器用来控制PCI设备占用PCI总线的时间。
PCI 桥配置空间
PCI桥配置空间和PCI 设备配置空间相比,只有两个Bar空间。PCI桥除了作为PCI设备之外,还需要管理其下连接的PCI总线子树使用的各类资源,即Secondary Bus(下游总线)所连接PCI总线子树使用的资源。这些资源包括存储器,I/O地址空间和总线号。
在PCI桥中,寄存器分为两大类。一类寄存器管理类Secondary Bus之下PCI子树的总线号,如Secondary 和 Subordinate Bus Number寄存器;另一类寄存器管理下游PCI总线的I/O和存储器地址空间。如I/O和Memory BASE寄存器。在PCI桥中还使用Primary Bus寄存器保存上游的PCI总线号。
其中存储器地址空间还分为可预读空间和不可预读空间,Prefetchable Memory Limit 和 Prefetchable Memory BASE寄存器管理可预读空间。而Memory Limit,Memory BASE管理不可预读空间。ROM地址空间是可预读的,其他大多都是不可预读的。
-
Subordinate Bus Number, Secondary Bus Number, Primary Bus Number
Subordinate Bus Number寄存器存放当前PCI子树中,编号最大的PCI总线号。
Secondary Bus Number寄存器存放当前PCI总线号。
Primary Bus Number寄存器存放该PCI桥上游PCI总线号。
-
Secondary Status
与PCI 设备Status寄存器含义相近。
-
Secondary Latency Timer
与PCI寄存器含义相近。
-
IO Limit 和 IO Base
PCI桥管理的PCI子树中包含许多PCI设备,而这些PCI设备可能会使用IO地址空间。存放IO地址空间集合的基地址和大小。
-
Memory Limit 和 Memory Base
存放该PCI桥下所有PCI设备使用的存储器地址空间集合的基地址和大小。 PCI规定这个空间大小至少为1MB。
-
Prefetchable Memory Limit 和Prefetchable Memroy Base 寄存器
存放可预读存储器空间的基地址和大小。
-
Bridge Control Register
该寄存器用来管理PCI桥的Secondary Bus。
IO方式访问配置空间
CF8h: CONFIG_ADDRESS。PCI配置空间地址端口
CFCh: CONFIG_DATA。PCI配置空间数据端口。
CONFIG_ADDRESS寄存器格式:
31 位:Enabled位
23:16 位:总线编号
15:11 位:设备编号
10: 8 位:功能编号
7: 2 位:配置空间寄存器编号
1: 0 位:恒为“00”。这是因为CF8h、CFCh端口是32位端口
在CONFIG_ADDRESS端口填入BDF,即可以在CONFIG_DATA上写入或者读出PCI配置空间的内容
PCIE规范在PCI规范基础上,将配置空间扩展到4KB。原来的CF8/CFC方法仍然可以访问所有PCIE设备配置空间的头256Byte,但是不能访问剩下的(4K-255)配置空间。要对剩下的配置空间访问可以通过存储器映射方式,对PCIE配置空间像内存一样进行读写访问。
按照PCIE规范,最多支持256个bus,每个bus最多支持32Device,每个Device最多支持8个Function。也就是说一个PCI总线域占用内存最大值为256 * 32 * 8 * 4K = 256M.
PCIE设备的扩展配置空间
PCI基本配置空间共由64个字节组成,其地址范围为0x00 ~ 0x3F,这64字节是所有PCI设备必须支持的。此外PCI/PCI-X和PCIE设备还扩展0x40 ~ 0xFF这段配置空间,在这段空间主要存放一些与MSI或者MSI-X中断机制和电源管理相关的Capability结构。其中所有能够提交中断请求的PCIE设备,必须支持MSI或者MSI-X Capabilities结构。
PCIE设备还支持0x100 ~ 0xFFF这段扩展配置空间。PCIE设备使用的扩展配置空间最大为4KB,在PCIE总线的扩展配置空间中,存放PCIE设备独有的一些Capabilities结构,而PCI设备不能使用这段空间。
PCI-X和PCIE总线规范要求其设备必须支持Capabilities结构。在PCI总线的基本配置空间中,包含一个Capabilities Pointer寄存器,该寄存器存放Capabilities结构链表的头指针。在一个PCIE设备中,可能含有多个Capabilities结构,这些寄存器组成一个链表。
每一个Capabilities结构都有唯一的ID号,每一个Capabilities寄存器都有一个指针,指向下一个Capabilities结构,从而组成一个单项链表结构。
一个PCIE设备可以包含多个Capabilities结构,包括与电源管理相关,与PCIE总线相关,中断相关,PCIE 以及 PCEI 扩展的 Capabilities结构。
PCI总线的配置
PCI总线定义了两类配置请求,一类是Type 00h配置请求,另一类是Type 01h配置请求。
这两种配置请求总线事务的不同反映在PCI总线的AD[31:0]信号上。
通过总线事务访问与HOST主桥或者PCI桥相连的PCI Agent设备或者PCI桥时,其中HOST主桥或者PCI桥使用Type00h配置请求。
HOST主桥或者PCI桥使用Type01配置请求,需要至少穿越一个PCI桥,访问没有与其直接相连的PCI Agent设备或者PCI桥。
- PCI总线树Bus号的初始化:
将与HOST主桥直接相连的PCI总线命名为PCI总线0,然后用DFS(深度优先遍历)方式依次对其他PCI总线进行编号。
介绍上图所示,分配BUS号的步骤:
-
首先忽略掉HOST主桥下面所有的PCI设备;
-
HOST主桥发现PCI1桥,并将PCI1桥的Secondary Bus命名为1,系统初始化配置空间,将PCI1桥Primary,Secondary分别赋值为0和1。
-
扫描PCI1桥下设备发现PCI2桥,同理初始化配置空间,将Primary,Secondary分别赋值为1和2。
-
扫描PCI2桥,同理初始化配置空间,将Primary,Secondary分别赋值为2和3。
-
扫描PCI3桥,没有发现任何桥设备,将Subordinate赋值为3,回溯到上一个桥也就是PCI2桥,发现除了PCI3之外没有其他桥设备,将Subordinate赋值为3,继续回溯到PCI1桥,除了PCI2桥之外没有其他PCI桥设备,将Subordinate赋值为3,继续回溯。
-
在HOST桥下面发现PCI4桥,将Primary和Secondary赋值为0和4。继续扫描PCI4桥发现没有其他PCI桥,将Subordinate赋值为4。回溯到HOST总线,发现除了PCI1桥和PCI4桥之外没有其他设备,即结束 PCI总线对DFS总线遍历。
-
PCI总线Device号的分配
PCI设备都有一条独立的IDSEL信号线,而PCI设备的IDSEL信号线与PCI总线AD[31:11]信号的连接关系决定了该设备在这条PCI总线的设备号。
PCI设备CONFIG_ADDRESS,通过Type00访问 总线事务与AD[31:0]对应起来。其中CONFIG_ADDRESS中的Device num与AD[31:11]对应起来。来代表设备号。其中PCI设备0与Device Number字段
-
PCI设备Bar空间的初始化
系统软件使用DFS算法对PCI总线进行遍历时,完成分配这些在PCI总线域的地址空间。
-
处理器到PCI设备的数据传送
当处理器访问PCI设备的地址空间时,需要首先访问该设备在存储器中的地址空间,并通过HOST主桥将这个存储器域的地址空间转化为PCI总线域的地址空间之后,再使用PCI总线事务将数据发送给指定的PCI设备中。
-
PCI设备的DMA操作
PCI设备访问存储器域地址空间,即进行DMA操作时,也是首先访问该存储器地址空间所对应的PCI总线地址空间,之后通过HOST主桥将这个PCI总线地址空间转化为存储器地址空间,再由DDR控制器对存储器进行读写访问。
-
PCI设备的正向译码和负向译码
正向译码:指的是访问PCI设备,访问的PCI总线地址在PCI域地址内, 将接收PCI总线请求。
负向译码:指的是访问PCI设备,访问的PCI总线地址不在PCI域地址内。处理器系统也不会对该设备进行枚举过程。PCI -to - ISA以及PCI桥都可以作为负向译码设备。
PCI驱动
UEFI BIOS提供了两个主要的模块来支持PCI总线,一个是PCI HOST Bridge控制器驱动,另一个是PCI总线驱动。
PCI HOST Bridge控制器驱动是跟特定的平台硬件绑定的。 根据系统实际IO空间和Memory Map,为PCI设备指定IO空间和Memory空间的范围,并且产生PCI HOST Bridge Resource Allocation协议供PCI总线驱动使用。
该驱动还对HostBridge控制器下所有RootBridge设备产生句柄(Handle),该句柄安装了PCIRootBridgeProtocol。PCI总线驱动则利用PCIROOTBridgeIO Protocol枚举系统中所有PCI设备,发现并获取PCI设备的Option ROM,并且调用PCI HOST Bridge Resource Allocation协议分配PCI设备资源。PCI HOST Bridge Resource Allocation 协议的实现是跟特定的芯和平台相结合的,毕竟只有平台所有者才知道从哪里来和有多少。 每一个PCI HOSTBridge Controller下面可以接一个或者多个PCI root Bridge,PCI Root Bridge会产生 PCI local Bus。
其他情况可见上文。PCI设备驱动不会使用PCI Root Bridge I/O协议访问PCI设备,而是会使用PCI总线驱动为PCI设备产生的PCI IO Protocol来访问PCI设备的IO/MEMORY空间和配置空间。PCI Root Bridge I/O协议(Protocol)是安装在RootBridge设备的句柄上(handle),同时在该handle上也会有表明RootBridge设备的DevicePath协议(Protocol),如下图所示
PCI总线驱动在BDS阶段会枚举整个PCI设备树并分配资源(BUS,MMIO和IO等),它还会在不同的枚举点调用Notify event通知平台,平台的Hook可以挂接在这些点上做些特殊的动作。具体各种点的定义请参阅UEFI spec。
PCI Lib
在MdePackage下有很多PCI lib。有Cf8/CFC形式访问配置空间的,有PCIe方式访问的。都有些许不同。注意Cf8/CFC只能访问255以内的,而PCIe方式访问的要配置正确PCIe base address PCD。