PCIe 枚举示例 (Single Root)

摘要:本文主要是对 Single-Root System 的枚举过程进行分析。


在这里插入图片描述


启动阶段,处理器上的系统软件执行的枚举步骤如下:

  1. 系统软件将 Host/PCI 桥的 Secondary Bus Number 设置为 0,将 Subordinate Bus Number 设置为 255。直到所有的总线都被枚举完成后,再改变这两个值。

Secondary Bus Number: 桥设备(Bridge)下游端口连接的 PCIe 总线号。
Subordinate Bus Number:挂载到桥设备(Bridge)下的最大的 PCIe 总线号。

  1. 从 Device 0 开始,依次尝试读取 Bus 0 上可能存在的 32 个 Device 的 Function 0 的 Vendor ID。如果 Device 0 返回一个合法的 Vendor ID,则证明 Device 0 存在并且包含至少一个 Function。如果返回的 Vendor ID 不合法,则开始尝试 Bus 0 Device 1 Function 0。

一个 Bus 上最多包含 32 个 Device,所以每个 Bus 都需要遍历 Device 0 ~ Device 31。

  1. 在图片事例中,Bus 0 Device 0 Function 0 的 Header Type 寄存器的 Bit[6;0] 位是 0x01,表明该设备是 PCI-to-PCI 桥。Header Type 寄存器的 Bit[7] 是 0,表明该 Device 只包含 1 个 Function。

在这里插入图片描述

  1. 系统软件识别到 Bus 0 Device 0 Function 0 是 PCI-to-PCI 桥后,对它的配置空间寄存器做如下修改:

    • Primary Bus Number Register = 0
    • Secondary Bus Number Register = 1
    • Subordinate Bus Number Register = 255

    配置完成后,这个 PCI-to-PCI 桥就知道它的上游端口直接相连的是 Bus 0,下游端口直接相连的是 Bus 1,并且它的下游端口可以访问的最大的总线号是 255。


  1. PCIe 总线枚举采用的是深度优先(depth-first)算法,因此,完成第 4 步的配置之后,需要先去搜索 Bus 1 上的设备,而不是去搜索 Bus 0 Device 1 Function 0。

  1. 系统软件尝试去读取 Bus 1 Device 0 Function 0 的 Vendor ID。在本例中,Bus 1 Device 0 Function 0 是 C 桥(Bridge C),所以能返回合法的 Vendor ID,表明 Bus 1 Device 0 Function 0 设备存在。

  1. 系统软件读取 Bus 1 Device 0 Function 0 的 Header Type 寄存器,发现 Bit[6:0] = 0x1,表明这是个 PCI-to-PCI 桥;Bit[7] = 0,表明该 Device 只包含 1 个 Function。

  1. 系统软件对 C 桥(Bridge C)的配置空间寄存器进行如下配置:

    • Primary Bus Number Register = 1
    • Secondary Bus Number Register = 2
    • Subordinate Bus Number Register = 255

    配置完成后,这个 PCI-to-PCI 桥就知道它的上游端口直接相连的是 Bus 1,下游端口直接相连的是 Bus 2,并且它的下游端口可以访问的最大的总线号是 255。


  1. 根据深度优先(depth-first)算法,继续读取 Bus 2 Device 0 Function 0 的 Vendor ID。在本例中,Bus 2 Device 0 Function 0 对应的是 D 桥(Bridge D)。

  1. 系统软件会从 Bus 2 Device 0 Function 0 得到合法的 Vendor ID,表明 Bus 2 Device 0 Function 0 存在。

  1. 读取 Bus 2 Device 0 Function 0 的 Header Type 寄存器,发现 Bit[6:0] = 0x1,表明这是个 PCI-to-PCI 桥;Bit[7] = 0,表明该 Device 只包含 1 个 Function。

  1. 系统软件对 D 桥(Bridge D)的配置空间寄存器进行如下配置:
    • Primary Bus Number Register = 2
    • Secondary Bus Number Register = 3
    • Subordinate Bus Number Register = 255

  1. 根据深度优先(depth-first)算法,继续读取 Bus 3 Device 0 Function 0 的 Vendor ID。

  1. 从 Bus 3 Device 0 Function 0 中获取合法的 Vendor ID,表明 Bus 3 Device 0 Function 0 存在。

  1. 读取 Bus 3 Device 0 Function 0 的 Header Type,发现 Bit[6:0] = 0x0,表明 Bus 3 Device 0 Function 0 是个 Endpoint;Bit[7] = 1,表明 Bus 3 Device 0 上包含多个 Function。

  1. 每个 Device 最多允许包含 8 个 Function,所以系统软件会依次尝试读取 Bus 3 Device 0 Function 1 ~ Bus 3 Device 0 Function 7。在本例中,只有 Bus 3 Device 0 Function 1 会返回合法的 Vendor ID,表明 Bus 3 Device 0 Function 1 存在。与此同时,Bus 3 Device 0 Function 1 的 Header Type Bit[6:0] = 0x1,表明这是个 Endpoint。

  1. 系统软件继续尝试读取 Bus 3 Device 1 Function 0 ~ Bus 3 Device 31 Function 的 Vendor ID。在本例中,由于这些设备都不存在,所以得到的 Vendor ID 都是非法的。

  1. 此时,系统软件已经枚举了 D 桥(Bridge D)下的所有设备,能够确认 D 桥(Bridge D)的下游端口(downstream)连接的最大的总线号就是 3。因此,系统软件需要将 D 桥(Bridge D)的 Subordinate Bus Number Register 设置为 3。既然 Bus 3 已经遍历完了,那就需要回退的 Bus 2,开始接着遍历 Bus 2 上的其他 Device 。在本例中,Bus 2 Device 1 Function 0 对应的是 E 桥(Bridge E)。

  1. 从 Bus 2 Device 1 Function 0 中获取合法的 Vendor ID,表明 Bus 2 Device 1 Function 0 存在。

  1. 读取 Bus 2 Device 1 Function 0 的 Header Type,发现 Bit[6:0] = 0x1,表明 Bus 2 Device 1 Function 0 是个 PCI-to-PCI 桥;Bit[7] = 0,表明 Bus 2 Device 1 上只包含 1 个 Function。

  1. 系统软件对 E 桥(Bridge E)的配置空间寄存器进行如下配置:
    • Primary Bus Number Register = 2
    • Secondary Bus Number Register = 4 (E 桥引入了一条新的 Bus)
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,尝试读取 Bus 4 Device 0 Function 0 的 Vendor ID。

  1. 从 Bus 4 Device 0 Function 0 中获取合法的 Vendor ID,表明 Bus 4 Device 0 Function 0 存在。

  1. 读取 Bus 4 Device 0 Function 0 的 Header Type,发现 Bit[6:0] = 0x0,表明 Bus 4 Device 0 Function 0 是个 Endpoint;Bit[7] = 0,表明 Bus 4 Device 0 上只包含 1 个 Function。

  1. 继续尝试枚举 Bus 4 上的其他 Device 1 ~ 31,发现都不存在。

  1. 此时,E 桥(Bridge E)下游端口(downstream)Bus 4 上的所有 Device & Function 都枚举完成了,能够确认 E 桥下游端口连接的最大总线号就是 4。因此,系统软件将 E 桥的 Subordinate Bus Number Register 设置为 4。Bus 4 枚举完成之后,再返回 Bus 2 进行枚举,读取 Bus 2 Device 2 Function 的 Vendor ID。在本例中,Bus 2 Device 2~31 Function 0 都不存在,所以返回的都是非法 Vendor ID。

  1. Bus 2 的枚举到此结束,能够确认 C 桥(Bridge C)下游端口(downstream)连接的最大的总线号是 4。因此,系统软件需要将 C 桥(Bridge C)的 Subordinate Bus Number Register 设置为 4。然后,返回 Bus 1,继续枚举下一个 Device(Bus 1 Device 1 Function 0)。在本例中,Bus 1 Device 1~31 Function 0 都不存在,所以返回的都是非法 Vendor ID。

  1. Bus 1 的枚举到此结束,能够确认 A 桥(Bridge A)下游端口(downstream)连接的最大的总线号是 4。因此,系统软件需要将 A 桥(Bridge A)的 Subordinate Bus Number Register 设置为 4。Bus 1 枚举结束后,返回 Bus 0 继续枚举下一个 Device (Device 1)。在本例中,Bus 0 Device 1 Function 0 是一个 PCI-to-PCI 桥。

  1. 像之前的步骤一样,系统软件检测到 Bus 0 Device 1 Function 0 是一个 PCI-to-PCI 桥,于是修改它的配置空间寄存器:
    • Primary Bus Number Register = 0
    • Secondary Bus Number Register = 5
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,开始枚举 Bus 5,于是发现了 F 桥。系统软件修改 F 桥的配置空间寄存器:
    • Primary Bus Number Register = 5
    • Secondary Bus Number Register = 6
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,开始枚举 Bus 6,于是发现了 G 桥。修改 G 桥的配置空间寄存器:
    • Primary Bus Number Register = 6
    • Secondary Bus Number Register = 7
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,开始枚举 Bus 7, 于是发现了 Bus 7 Device 0 Function 0 是一个 Endpoint,并且该 Device 只包含 1 个 Function。到此,Bus 7 枚举结束,需要将 G 桥的 Subordinate Bus Number Register 修改为 7。

  1. Bus 7 枚举完成,返回 Bus 6 继续枚举下一个 Device(Bus 6 Device 1 Function 0),于是发现了 H 桥。修改 H 桥的配置如下:
    • Primary Bus Number Register = 6
    • Secondary Bus Number Register = 8
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,开始枚举 Bus 8,于是发现了 J 桥。修改其配置空间寄存器:
    • Primary Bus Number Register = 8
    • Secondary Bus Number Register = 9
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,枚举 Bus 9 上的所有 Device & Function,发现没有 Bridge,全是 Endpoint。此时能够确定 J 桥下游端口(downstream)连接的最大总线号是 9。修改 J 桥的 Subordinate Bus Number Register 为 9。返回 Bus 8 继续枚举,发现没有其它 Device & Function 了,所以修改 H 桥的 Subordinate Bus Number Register 为 9 。

  1. Bus 8 枚举完成后,返回 Bus 6 继续枚举下一个 Device(Bus 6 Device 2 Function 0),于是发现了 I 桥。修改 I 桥的配置空间寄存器:
    • Primary Bus Number Register = 6
    • Secondary Bus Number Register = 10
    • Subordinate Bus Number Register = 255

  1. 根据深度优先算法,开始枚举 Bus 10,发现只有一个 Endpoint(Bus 10 Device 0 Function 0)。

  1. Bus 10 枚举完成,修改 I 桥的 Subordinate Bus Number Register 为 10。

  1. 返回 Bus 6,发现没有其它的 Device & Function 了,于是修改 F 桥的 Subordinate Bus Number Register 为 10。

  1. 返回 Bus 5,发现没有其它的 Device & Function 了,于是修改 B 桥的 Subordinate Bus Number Register 为 10。

  1. 返回 Bus 0,发现没有其它的 Device & Function 了,于是修改 Host/PCI 桥的 Subordinate Bus Number Register 为 10。


到此为止,整个枚举的过程就完成了!!!

声明:本文中的图片来自MindShare, Inc 经典书籍《PCI Express Technology》。

更多 PCIe 知识,点击该链接。

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值