1. 概述
前两节介绍了PCI 访问桥设备和非桥设备的方法,本节就讲述PCIE 的配置过程
2. TLP事务层格式
2.1 Posted和Non-Posted
PCI 总线规定了两类数据传送方式,分别是Posted 和Non-Posted 数据传送方式。其中使用Posted 数据传送方式的总线事务也被称为Posted 总线事务;而使用Non-Posted 数据传送方式的总线事务也被称为Non-Posted 总线事务。
其中Posted 总线事务指PCI 主设备向PCI 目标设备进行数据传递时,当数据到达PCI 桥后,即由PCI 桥接管来自上游总线的总线事务,并将其转发到下游总线。采用这种数据传送方式,在数据还没有到达最终的目的地之前,PCI 总线就可以结束当前总线事务,从而在一定程度上解决了PCI 总线的拥塞。
而Non-Posted 总线事务是指PCI 主设备向PCI 目标设备进行数据传递时,数据必须到达最终目的地之后,才能结束当前总线事务的一种数据传递方式。
由以上可以发现,Posted 数据请求在通过PCI 总线之后,将逐级释放总线资源,因此PCI 总线的利用率较高。而使用Non-Posted 方式进行数据传送的处理过程与此不同,Non-Posted 数据请求在通过PCI 总线时,并不会及时释放总线资源,从而在某种程度上影响PCI 总线的使用效率和传送带宽。
2.2 TLP通用格式
- 下图为
TLP 格式组成: TLP Header 组成及其包内的Fmt 和Type 解释如下:
- 类型(
Type ):读写内存、读写IO 、读写配置 ,存放于Header 里; - 地址:对于内存读写、
IO 读写,地址保存在Header 里 Bus/Dev/Function/Regiser :对于配置读写,这些信息保存在Header 里- 数据:对于内存读、
IO 读、配置读,先发出请求,再得到数据
- 分为
2 个阶段:读请求报文、完成报文 - 读请求报文:不含数据
- 完成报文:含数据
3. PCIe配置过程
3.1 PCIe设备的访问的访问方法
- 通常如下图,在
CPU 通过addr_cpu 地址访问到PCIE 控制器,PCIE 控制器再通过addr_pcie 地址去访问PCIE 桥设备,PCIE 桥设备再通过各自端口分配的地址去访问外挂的PCIE 设备,但是,这是在PCIE 配置初始化后的访问方式,在没有初始化的时候,是如何访问的呢?接下来会展开讲解。
3.2 配置与RC直连的设备
RC (Root Complex )本身就是一个桥,要去访问跟桥直接相连的设备,用CfgRd0 类型的TLP Fmt 和Type 取值为0b00 , 0b00100 ,表示:Configuration Read Type 0 TLP 中设置有"Bus/Device/Funciton/Register "- 提问:上图红圈中是设备,怎么知道它自己的
Bus 号是0 ,Device 分别是0、1、2 ?
- 红圈中的设备都是在
RC 内部,它们的Device 号是硬件里写死的(hard-coded ) - 当这些设备监测到
Bus0 上的TLP 是CfgRd0 后,忽略TLP 中的Bus ,比对TLP 中的Device - 如果
Device 吻合,就回应TLP
4. PCIe配置示例
4.1 PCIe设备的配置寄存器
PCI/PCIe 设备、桥,它们的配置寄存器前面若干字节格式是一样的,可以从里面的"Header Type "分辨:
- 它是普通设备,还是桥
- 它是单功能设备,还是多功能设备:所谓功能,就是
Function ,一个物理设备可以有多个功能,也就有多个逻辑设备
这些总线号示例如下:
-
在Type Header 里面有个Type 参数,他就是设置PCI 的访问方式,前几章节也提到过,这里针对PCIE 再展开分析。 -
Type 0 Configuration Request 如果要配置的设备,就在当前总线上,即目标设备的Bus号等于当前桥的Secondary Bus Number ,那么在当前总线(即Secondary Bus Number )上传输的就是"Type 0 Configuration Request ": TLP 格式如下图所示, Type0 不会穿过桥,直接访问设备。
Type 1 Configuration Request 如果要配置的设备,不在当前总线上,但是在它下面的总线上,即: ①目标设备的Bus 号大于当前桥的Secondary Bus Number ,②目标设备的Bus号小于或等于当前桥的Subordinate Bus Number ,那么在当前总线(即Secondary Bus Number )上传输的就是"Type 1 Configuration Request ":TLP 格式如下图所示,Type1 设备会穿过桥,到达设备时,跟设备直接连接的桥会把它转换为"Type 0 Configuration Request "
4.1 配置过程示例
4.1.1 硬件拓扑结构
以下图中的设备的配置过程为例,给大家做示范。
4.1.2 配置过程演示
下文中BDF 表示Bus ,Device ,Function ,用这三个数值来表示设备。
- 软件设置
Host/PCI Bridge的Secondary Bus Number 为0 ,Subordinate Bus Number 为255 (先设置为最大,后面再改)。 从Bus 0 开始扫描:先尝试读到BDF (0,0,0 )设备的Vendor ID ,如果不成功表示没有这个设备,就尝试下一个设备BDF (0,1,0 )。一个桥下最多可以直接连接32个设备,所以会尝试32 次:Device 号从0 到31 。注意:在Host/PCI Bridge 中,这些设备的Device 号是硬件写死的。- 步骤
2 读取BDF (0,0,0 )设备(即使图中的A )时,发现它的Header Type 是01h ,表示它是一个桥、单功能设备 - 发现了设备A是一个桥,配置它:
Primary Bus Number Register = 0 :它的上游总线是Bus0 Secondary Bus Number Register = 1 :从它发出的总线是Bus1 Subordinate Bus Number Register = 255 :先设置为最大,后面再改 - 因为发现了桥
A ,执行"深度优先"的配置过程:先去枚举A 下面的设备,再回来枚举跟A 同级的B - 软件读取
BDF(1,0,0) 设备(就是设备C )的Vendor ID ,成功得到Vendor ID ,表示这个设备存在。 - 它的
Header Type 是01h ,表示这是一个桥、单功能设备。 - 配置桥
C :
Primary Bus Number Register = 1 :它的上游总线是Bus 1 Secondary Bus Number Register = 2 :从它发出的总线是Bus 2 Subordinate Bus Number Register = 255 :先设置为最大,后面再改 - 继续从桥
C 执行"深度优先"的配置过程,枚举Bus 2 下的设备,从BDF(2,0,0) 开始 - 读取
BDF(2,0,0) 设备(就是设备D )的Vendor ID ,成功得到Vendor ID ,表示这个设备存在。 - 它的
Header Type 是01h ,表示这是一个桥、单功能设备。 - 配置桥D:
Primary Bus Number Register = 2 :它的上游总线是Bus 2 Secondary Bus Number Register = 3 :从它发出的总线是Bus 3 Subordinate Bus Number Register = 255 :先设置为最大,后面再改 - 继续从桥
D 执行"深度优先"的配置过程,枚举Bus 2 下的设备,从BDF(3,0,0) 开始 - 读取
BDF(3,0,0) 设备的Vendor ID ,成功得到Vendor ID ,表示这个设备存在。 - 它的
Header Type 是80h ,表示这是一个Endpoing 、多功能设备。 - 软件枚举这个设备的所有
8 个功能,发现它有Function0 、1 - 软件继续枚举
Bus 3 上其他设备(Device 号1~31 ),没发现更多设备 - 现在已经扫描完桥
D 即Bus 3 下的所有设备,它下面没有桥,所以桥D 的Subordinate Bus Number 等于3 。扫描完Bus 3 后,回退到上一级Bus 2 ,继续扫描其他设备,从BDF(2,1,0) 开始,就是开始扫描设备E 。 - 读取
BDF(2,1,0) 设备(就是设备E )的Vendor ID ,成功得到Vendor ID ,表示这个设备存在。 - 它的
Header Type 是01h ,表示这是一个桥、单功能设备。 - 配置桥
E :
Primary Bus Number Register = 2 :它的上游总线是Bus 2 Secondary Bus Number Register = 4 :从它发出的总线是Bus 4 Subordinate Bus Number Register = 255 :先设置为最大,后面再改 - 继续从桥
D 执行"深度优先"的配置过程,枚举Bus 4 下的设备,从BDF(4,0,0) 开始 - 读取
BDF(4,0,0) 设备的Vendor ID ,成功得到Vendor ID ,表示这个设备存在。 - 它的
Header Type 是00h ,表示这是一个Endpoing 、单功能设备。 - 软件继续枚举
Bus 4 上其他设备(Device 号1~31 ),没发现更多设备 - 已经枚举完设备
E 即Bus 4 下的所有设备了,更新设备E 的Subordinate Bus Number 为4 。然后继续扫描设备E的同级设备:Bus=2 ,Device 从2 到31 ,发现Bus 2 上没有这些设备。 - 软件更新设备
C 即Bus 2 的桥,把它的Subordinate Bus Number 设置为4 。然后继续扫描设备C 的同级设备:Bus=1 ,Device 从1 到31 ,发现Bus 1 上没有这些设备。 - 软件更新设备
A 即Bus 1 的桥,把它的Subordinate Bus Number 设置为4 。然后继续扫描设备A 的同级设备:Bus=0 ,Device 从1 到31 ,发现Bus 0 上的设备B 。 - 配置桥
B :
Primary Bus Number Register = 0 :它的上游总线是Bus 0 Secondary Bus Number Register = 5 :从它发出的总线是Bus 5 Subordinate Bus Number Register = 255 :先设置为最大,后面再改 - 再从桥
B 开始,执行"深度优先"的配置过程。
返回总目录
|