PCIe学习(一)
PCIe学习(二)
PCIe学习(三)
PCIe学习(四)
PCIe学习(五)
PCIe学习(六)
PCIe学习(七)
PCIe学习(八)
先跳过第6章
7 软件初始化和配置
PCIe配置模型支持两种配置空间访问机制:
- PCI兼容的配置访问机制(Configuration Access Mechanism,CAM):完全兼容PCI
- PCIe增强型配置访问机制(Enhanced Configuration Access Mechanism,ECAM):增加可用配置空间的大小并优化配置空间访问
7.1 PCIe配置空间
为了使PCIe设备能够正常使用,主机的系统软件需要对PCIe设备进行合理的配置。PCIe协议规定,每个Function有一个专有的配置地址空间块。
在PCI时代,这个空间是256-Byte大小,即16-DW。其中,前64-Byte是基础的配置空间,也称为配置空间Header;后面192-Byte是能力寄存器(Capability Registers)空间。
对于Switch和EP,配置空间Header结构不同。Type 0是EP需要实现的配置空间类型;Type 1是Switch需要实现的配置空间类型。
所谓能力,就是PCIe组件具有哪些“本领“。这些能力绝大多数是协议规定好的,只有少部分能力是必选项,大多数是可选项。如果PCIe组件实现了这个能力,就通过能力寄存器体现出来。这样主机软件通过读取这些寄存器,就可以明确知道PCIe组件具备的能力,然后根据系统需要决定是否开启这些能力,以及如何配置参数。为了不引起混淆,后文将沿用Capability一词,不再翻译。
到了PCIe时代,256-Byte的配置空间不够用了,所以PCIe将配置空间扩展到了4KB大小。从偏移地址100h往后都是PCIe扩展配置寄存器空间。
一个PCIe拓扑结构最多可以有256个Bus,每个Bus最多有32个Device,每个Device最多有8个Function,每个Function有4KB的配置空间。这样算下来。主机端最多需要256MB的地址空间来映射全部的设备配置空间。
其实,主机端的RC也需要实现Capability寄存器,但是在主机端可以直接访问这些寄存器,不需要通过配置请求。此外,PCIe协议允许RC实现额外4KB的寄存器块,叫做RCRB(Root Complex Register Block)。
7.1.1 Type 0和Type 1公用的配置空间Header部分
不管是Type 0还是Type 1,配置空间有一部分寄存器定义的相同,如下图。
- Vendor ID:厂商ID,是PCI-SIG组织分配的
- Device ID:设备ID,是PCI-SIG组织分配的。系统软件读取到Vendor ID和Device ID就知道该设备是什么,然后为其调用对应的驱动程序
- Command:指示了Function支持哪些特性
- Status:保存一些当前状态
- Revision ID:保存的是设备的小版本号,与Vendor ID和Device ID一起供系统软件使用
- Class Code:保存设备类型编码,PCI-SIG对PCIe设备进行类分类,比如显示类,存储类等等
- Cache Line Size:由系统固件或者OS来配置,记录当前使用的缓存行大小
- Latency Timer:起源于PCI,在PCIe中已不适用,需要硬件上固定为0值
- Header Type:对于Type 0,其值是00h;对于Type 1,其值是01h
- BIST:用来控制和指示BIST状态,如果Function不支持BIST,则其需要硬件上固定为0
- Capabilities Pointer:用于指向此Function实现的Capability列表的指针
- Interrupt Line:保存中断线路由信息,此寄存器值是供设备驱动和OS使用,对设备本身没有意义
- Interrupt Pin:只读寄存器,指示Function使用的传统中断消息,合法值是01h,02h,03h,04h,分别对应INTA,INTB,INTC,INTD。对于SFD,只有INTA可以使用;对于MFD,可以最多使用到INTD
7.1.2 Type 0配置空间Header
下图是Type 0配置空间Header的完整结构。
新增的寄存器有这些:
- Base Address Registers:简称BAR,后面详细讲
- Cardbus CIS Pointer:不适用于PCIe
- Subsystem Vendor ID:子系统厂商ID寄存器
- Subsystem ID:子系统ID寄存器,与Subsystem Vendor ID寄存器用于唯一标识PCIe组件所在的适配器或子系统。其实是为供应商提供了一种机制,即使组件上可能有相同的PCIe组件(Vendor ID和Device ID相同),也可以将其彼此区分开来。
- Expansion ROM Base Address:用来处理扩展ROM的基本地址和大小信息。应用场景是有些外接卡需要用本地ROM作为扩展ROM。
- Min_Gnt:不适用于PCIe
- Max_Lat:不适用于PCIe
重点要讲一下基地址寄存器BAR,对于EP也就是Type 0,BAR寄存器共有六个。也就是说最多可以映射到六块存储空间。其中每个寄存器的最低位,也就是BAR[0]指示该空间是存储器空间还是I/O空间。如果是存储器空间,BAR[2:1]指示是32-bits地址还是64-bits地址,BAR[4]指示该空间是否可预取(Prefetchable)。如果是64-bits地址空间,则需合用两个BAR寄存器。如果是IO空间,就更简单了。
BAR是设备想要展现给主机的地址空间,对应的是设备内部寄存器块或内部RAM等资源。那么BAR寄存器到底需要映射到多大的地址范围,主机如何将这块地址范围映射到系统地址,协议制定的很巧妙。首先,BAR寄存器的低位是固定接成0的(非最低几位指示字段),主机的系统软件通过判断多少位被接成0就知道这段空间在设备里有多大。大致过程是,系统软件先读取BAR寄存器的值,然后向BAR寄存器写全1,再读取BAR寄存器,检查哪些BAR寄存器的低位没有变化。比如读取到低12位没有变化,则说明这个地址空间是4KB(2^12)。随后,主机系统软件根据实际情况,将这4KB映射到系统地址中,然后将分配的系统地址高位写到BAR寄存器的高位。最后,Host中对这段系统地址的访问都会被发送给PCIe设备。
7.1.3 Type 1配置空间Header
下图是Type 1配置空间Header的完整结构。
可以看出,对于Type 1,BAR寄存器只有两个。
新增的寄存器有这些:
- Primary Bus:主总线
- Secondary Bus:次级总线
- Subordinate Bus:从属总线
- Secondary Latency Timer:不适用于PCIe
- I/O Base:
- I/O Limit:与I/O Base寄存器合起来用于定义下游连接的I/O地址范围,暂时可以忽略
- Secondary Status:用于PCIe到PCI/PCI-X的转接桥
- Memory Base:
- Memory Limit:与Memory Limit寄存器合起来用于记录一段存储地址范围,包括下游设备的地址空间。如果Switch接收到的TLP请求的地址在这段地址范围内,则说明TLP是发给其下游设备的,向对应的下游端口转发即可。
- Prefetchable Memory Base:
- Prefetchable Memory Limit:与Prefetchable Memory Base合起来定义了一个可预取的存储地址范围
- Prefetchable Memory Base Upper 32 Bits:高32位地址
- Prefetchable Memory Limit Upper 32 Bits:高32位地址
- I/O Base Upper 16 Bits:高16位地址
- I/O Base Limit 16 Bits:高16位地址
- Bridge Control:用于扩展Command寄存器
以上寄存器,需要着重分析的是Primary Bus,Secondary Bus,Subordinate Bus这三个,其它的从名字基本就能猜出其用意。
为了兼容PCI,RC的根端口呈现为PCI-PCI桥,Switch的所有端口都呈现为PCI-PCI桥,如下面两图。所谓的“枚举”,就是配置软件发现系统拓扑并分配总线号和系统资源的过程。
RC与处理器连接的部分是主桥(Host Bridge),其每个下游端口对应有一个PCI-PCI桥;Switch的上游端口和下游端口都有对应的PCI-PCI桥;EP只有一个上游端口,不存在PCI-PCI桥。P2P桥上方的总线称为Primary Bus,下方的总线称为Secondary Bus,该桥的下游设备的最后一个总线编号是其Subordinate Bus。
参照下图,RC有两个下游端口,每个下游端口连接一个Switch,每个Switch连接两个设备。RC的主桥向上没有PCIe总线,也就不存在Primary Bus,主桥下面的总线是整个PCIe拓扑结构中的0号总线,所以主桥的Secondary Bus是0,主桥的Subordinate Bus是拓扑结构中的最后一个总线编号,即右下角的Bus 9。大家可自行分析两个Switch的三个总线编号。
当然,这里只是分析三个总线编号概念,在实际的应用中,需要在系统上电后,通过PCIe枚举过程来探索拓扑结构,最终才能确定RC和Switch的Subordinate Bus。
因为PCIe拓扑结构探索采用的是深度优先遍历(Depth First Search,DFS)算法,即优先探索每个分支到底部,然后再探索其它分支。所以对于Switch来说,记录这三个总线编号信息,就知道下游的结构。
MindShare的《PCI Express Technology - Comprehensive Guide to Generations 1.x, 2.x, 3.0》第三章中有Single-Root系统和Multi-Root系统枚举的示例。
7.1.4 能力结构
配置空间除去了前面16-DW的Header部分,其余部分是能力(Capability)寄存器。PCIe协议定义了很多种Capability,组件可以根据需要选择实现其中的部分能力。这些Capability寄存器对应的是某种功能特性。不同功能特性需要的Capability寄存器组的大小也不一样,有的寄存器组需要占用几个DW,而有的寄存器组需要占用几十个DW。一个寄存器组就是一个能力结构(Capability Structure)。
PCIe协议对Capability进行了编号,方便主机系统软件识别。并且PCIe协议采用链表式管理配置空间中的Capability寄存器,大家还记得Header中的Capability Pointer寄存器吧,它指向第一个Capability Structure。每个Capability Structure的第一个DW中有一个Next Capability Pointer寄存器指向下一个,最后一个Capability Structure的Pointer指向000h,表示全部Capability链表结束。这样,主机系统软件就很容易将设备的全部Capability寄存器扫描出来。
配置空间的地址40h – FFh区间(48 DW)是PCI的Capability寄存器和PCIe的基础Capability寄存器,地址100h后面的空间(960-DW)都是PCIe扩展的Capability寄存器空间。
下表是我总结的Gen 5中的Capability Structure及其ID。因为这些分析寄存器会占用大量篇幅,且容易使人昏昏欲睡,这里就不展开了,其它章节中用到哪项Capability的时候再具体分析。
7.2 配置机制
PCIe协议中支持两种配置机制:PCI兼容配置机制和PCIe增强的配置访问机制(Enhance Configuration Access Mechanism,ECAM)。配置空间的前256-Bytes是PCI兼容配置空间,可以通过PCI兼容配置机制或者ECAM机制访问;配置空间的后3840-Bytes是PCIe扩展配置空间,只能通过ECAM机制访问。
7.2.1 PCI兼容配置机制
此机制是为了兼容PCI设备和配置软件。
在PCI中,x86处理器是不能直接配置空间的,需要非MMIO机制来访问。
7.2.2 ECAM
ECAM使用存储器映射地址空间访问设备配置寄存器。在这种情况下,存储器地址用来确定访问的配置寄存器,通过存储器写入操作更新配置寄存器中的内容,通过存储器读取操作获得配置寄存器的内容。
存储器地址空间与PCIe配置空间的映射关系如下表:
END
作者:老秦谈芯
文章来源:老秦谈芯
推荐阅读
更多 IC 设计干货请关注IC 设计专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。