在PCI总线桥的配置空间中,有几个重要的寄存器用于描述和管理与该PCI桥连接的PCI总线的编号和层次结构。其中包括:
-
Primary Bus Number 寄存器:
- 作用:Primary Bus Number寄存器指示了该PCI桥所连接的上游PCI总线的编号。
- 配置方式:在PCI桥初始化时,系统软件会为每个PCI桥设置Primary Bus Number寄存器的值,通常是根据DFS算法遍历PCI总线树确定的上游PCI总线编号。
-
Secondary Bus Number 寄存器:
- 作用:Secondary Bus Number寄存器指示了该PCI桥所连接的下游PCI总线的编号。
- 配置方式:系统软件会为每个PCI桥设置Secondary Bus Number寄存器的值,也是根据DFS算法遍历PCI总线树确定的下游PCI总线编号。
这两个寄存器在PCI设备的配置空间中是基础性的配置寄存器,用于建立和维护整个PCI总线系统的层次结构和拓扑关系。它们的设置确保了PCI设备及其所连接的其他PCI设备在总线系统中的正确识别和通信。
配置示例:
例如,对于一个PCI桥连接的情况:
- 如果一个PCI桥连接到编号为0的PCI总线(HOST主桥),那么该PCI桥的Primary Bus Number寄存器将设置为0。
- 如果该PCI桥下连接了编号为1的PCI总线,那么该PCI桥的Secondary Bus Number寄存器将设置为1。
这种配置方式通过寄存器的设置,有效地定义了每个PCI桥的上下游PCI总线关系,确保了数据在PCI总线树中的正确流动和访问。
Subordinate Bus寄存器是PCI总线桥中的一个重要配置寄存器,用于指示该PCI桥下游所有PCI总线中最大的编号,从而定义了该PCI桥所管辖的总线范围。
主要作用和配置方式:
-
作用:
- Subordinate Bus寄存器主要用于描述和管理该PCI桥所连接的下游PCI总线的范围。它指示了从该PCI桥开始到其下连接的最远PCI总线的编号,即该PCI桥的管辖总线范围的上限。
-
配置方式:
- 在初始化PCI桥时,系统软件需要为每个PCI桥设置Subordinate Bus寄存器的值。
- 这个值通常是通过DFS算法遍历PCI总线树确定的,系统会识别从当前PCI桥出发,能够达到的最远的PCI总线编号,并将这个最大编号设置为Subordinate Bus寄存器的值。
示例说明:
假设在一个PCI总线树中,有如下的PCI桥连接关系:
- HOST主桥连接的PCI总线编号为0。
- PCI桥1连接的Primary Bus Number为0,Secondary Bus Number为1。
- PCI桥2连接的Primary Bus Number为1,Secondary Bus Number为2。
- PCI桥3连接的Primary Bus Number为2,Secondary Bus Number为3。
在这种情况下,设置Subordinate Bus寄存器的步骤如下:
- 对于PCI桥1,其连接了编号为1的PCI总线,没有下游PCI桥,因此Subordinate Bus寄存器的值为1。
- 对于PCI桥2,其连接了编号为2的PCI总线,也没有下游PCI桥,因此Subordinate Bus寄存器的值为2。
- 对于PCI桥3,其连接了编号为3的PCI总线,同样没有下游PCI桥,所以Subordinate Bus寄存器的值为3。
这些设置确保了每个PCI桥在系统启动时,能够正确识别其管辖的PCI总线范围,从而在数据传输和管理时能够精确地控制和路由数据。
PCI总线树Bus号的初始化
在一个处理器系统中,每一个HOST主桥都推出一颗PCI总线树。在一颗PCI总线树中有多少个PCI桥(包括HOST主桥),就含有多少条PCI总线。系统软件在遍历当前PCI总线树时,需要首先对这些PCI总线进行编号,即初始化PCI桥的Primary、Secondary和Subordinate Bus Number寄存器。
在一个处理器系统中,一般将与HOST主桥直接相连的PCI总线被命名为PCI总线0。然后系统软件使用DFS(Depth First Search)算法,依次对其他PCI总线进行编号。值得注意的是,与HOST主桥直接相连的PCI总线,其编号都为0,因此当处理器系统中存在多个HOST主桥时,将有多个编号为0的PCI总线,但是这些编号为0的PCI总线分属不同的PCI总线域,其含义并不相同。
在一个处理器系统中,PCI总线树的结构如图2 13所示。当然在一个实际的处理器系统中,很少会出现这样复杂的PCI总线树结构,本节采用这个结构的目的是便于说明PCI总线号的分配过程。
在PCI总线中,系统软件使用深度优先DFS算法对PCI总线树进行遍历,DFS算法和广度优先BFS(Breadth First Search)算法是遍历树型结构的常用算法。与BFS算法相比,DFS算法的空间复杂度较低,因此绝大多数系统系统在遍历PCI总线树时,都使用DFS算法而不是BFS算法。
DFS是搜索算法的一种,其实现机制是沿着一颗树的深度遍历各个节点,并尽可能深地搜索树的分支,DFS的算法为线性时间复杂度,适合对拓扑结构未知的树进行遍历。在一个处理器系统的初始化阶段,PCI总线树的拓扑结构是未知的,适合使用DFS算法进行遍历。下文以图2 13为例,说明系统软件如何使用DFS算法,分配PCI总线号,并初始化PCI桥中的Primary Bus Number、Secondary Bus Number和Subordinate Bus number寄存器。所谓DFS算法是指按照深度优先的原则遍历PCI胖树,其步骤如下。
(1) HOST主桥扫描PCI总线0上的设备。系统软件首先忽略所有这条总线上的PCI Agent设备,因为在这些设备之下不会挂接新的PCI总线。例如PCI设备01下不可能挂接新的PCI总线。
(2) HOST主桥首先发现PCI桥1,并将PCI桥1的Secondary Bus命名为PCI总线1。系统软件将初始化PCI桥1的配置空间,将PCI桥1的Primary Bus Number寄存器赋值为0,而将Secondary Bus Number寄存器赋值为1,即PCI桥1的上游PCI总线号为0,而下游PCI总线号为1。
(3) 扫描PCI总线1,发现PCI桥2,并将PCI桥2的Secondary Bus命名为PCI总线2。系统软件将初始化PCI桥2的配置空间,将PCI桥2的Primary Bus Number寄存器赋值为1,而将Secondary Bus Number寄存器赋值为2。
(4) 扫描PCI总线2,发现PCI桥3,并将PCI桥3的Secondary Bus命名为PCI总线3。系统软件将初始化PCI桥3的配置空间,将PCI桥3的Primary Bus Number寄存器赋值为2,而将Secondary Bus Number寄存器赋值为3。
(5) 扫描PCI总线3,没有发现任何PCI桥,这表示PCI总线3下不可能有新的总线,此时系统软件将PCI桥3的Subordinate Bus number寄存器赋值为3。系统软件在完成PCI总线3的扫描后,将回退到PCI总线3的上一级总线,即PCI总线2,继续进行扫描。
(6) 在重新扫描PCI总线2时,系统软件发现PCI总线2上除了PCI桥3之外没有发现新的PCI桥,而PCI桥3之下的所有设备已经完成了扫描过程,此时系统软件将PCI桥2的Subordinate Bus number寄存器赋值为3。继续回退到PCI总线1。
(7) PCI总线1上除了PCI桥2外,没有其他桥片,于是继续回退到PCI总线0,并将PCI桥1的Subordinate Bus number寄存器赋值为3。
(8) 在PCI总线0上,系统软件扫描到PCI桥4,则首先将PCI桥4的Primary Bus Number寄存器赋值为0,而将Secondary Bus Number寄存器赋值为4,即PCI桥1的上游PCI总线号为0,而下游PCI总线号为4。
(9) 系统软件发现PCI总线4上没有任何PCI桥,将结束对PCI总线4的扫描,并将PCI桥4的Subordinate Bus number寄存器赋值为4,之后回退到PCI总线4的上游总线,即PCI总线0继续进行扫描。
(10) 系统软件发现在PCI总线0上的两个桥片PCI总线0和PCI总线4都已完成扫描后,将结束对PCI总线的DFS遍历全过程。
从以上算法可以看出,PCI桥的Primary Bus和Secondary Bus号的分配在遍历PCI总线树的过程中从上向下分配,而Subordinate Bus号是从下向上分配的,因为只有确定了一个PCI桥之下究竟有多少条PCI总线后,才能初始化该PCI桥的Subordinate Bus号。