PCI总线树的枚举由pci_scan_child_bus函数完成,该函数的主要作用是分配PCI总线树的PCI总线号,而并不初始化PCI设备使用的BAR空间。subordinate总线号记载当前PCI总线树中最后一个PCI总线号,因此只有完成了对PCI总线树的枚举后,才能获得该参数。值得注意的是,在Linux系统中,许多PCIe设备并没有提供该结构。PCI总线规范规定了获取BAR空间的标准实现方法。......
2023-10-20
在一个处理器系统中,每一个HOST主桥都推出一棵PCI总线树。在一棵PCI总线树中有多少个PCI桥(包括HOST主桥),就含有多少条PCI总线。系统软件在遍历当前PCI总线树时,需要首先对这些PCI总线进行编号,即初始化PCI桥的Primary、Secondary和Sub-ordinate 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总线号的分配过程。
图2-13 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。(www.chuimin.cn)
(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 Num-ber寄存器赋值为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号。
有关PCI Express体系结构导读的文章
PCI总线树的枚举由pci_scan_child_bus函数完成,该函数的主要作用是分配PCI总线树的PCI总线号,而并不初始化PCI设备使用的BAR空间。subordinate总线号记载当前PCI总线树中最后一个PCI总线号,因此只有完成了对PCI总线树的枚举后,才能获得该参数。值得注意的是,在Linux系统中,许多PCIe设备并没有提供该结构。PCI总线规范规定了获取BAR空间的标准实现方法。......
2023-10-20
Linux系统在初始化时,将在do_initcalls函数中执行__initcall_xyz_initx函数,从而执行xyz_init函数。Linux系统使用这种方法规范初始化模块的执行,并保证这些模块可以按照指定的顺序依次执行。在Linux内核的System.map[4]文件中,可以找到在__early_initcall_end和__initcall_end之间所有的函数指针,其中与PCI总线初始化相关的函数如源代码14-4所示,这些函数将按照在以下源代码中出现的顺序依次执行。......
2023-10-20
对于Linux x86而言,BIOS已经将PCI设备使用的存储器和I/O资源设置完毕,而其他Linux系统,如Linux PowerPC,需要使用该函数设置PCI设备使用的存储器和I/O资源。pci_init函数的主要作用是对已经完成枚举的PCI设备进行修复工作,用于修补一些BI-OS中对PCI设备有影响的Bugs。CompactPCI总线在通信系统中较为常见。而pci_sysfs_init函数与sysfs文件系统相关,主要功能是将每一个PCI设备加入到sysfs文件系统的相应目录中,本节对此不做进一步介绍。Linux x86对PCI总线进行初始化时,使用了许多不完美的源代码。......
2023-10-20
本节重点讲述PCI桥如何将Type 01h配置请求转换为Type 00h配置请求。下面将举例说明PCI总线配置请求的转换原则,并以图2-8为例说明处理器如何访问PCI设备01和PCI设备31的配置空间。PCI总线规定Type01h配置请求只能由PCI桥负责处理。而1<Bus Number≤3,所以PCI桥1将接收来自PCI总线0的Type 01h配置请求,并将这个配置请求直接下推到PCI总线1。......
2023-10-20
PCIe总线的序基于PCI总线的序,并进行了许多扩展。在TLP的Attr字段中有一个Relaxed Ordering位,表示该TLP是否支持PCIe总线的Re-laxed Ordering方式,但是TLP是否可以使用Relaxed Ordering还与这个TLP经过的设备有关。目前大多数PCIe设备不支持Relaxed ordering方式进行TLP的传递。在PCIe总线中,所有数据传送类型,如存储器、I/O、配置和Message总线事务都需要遵循规定的传送顺序。......
2023-10-20
Linux PowerPC初始化PCI总线树的步骤与Linux x86类似,也调用了一些Linux系统中与PCI总线相关的通用函数。但是PowerPC处理器使用的HOST主桥与x86处理器并不相同,因此Linux PowerPC初始化PCI总线树的过程与Linux x86有些差别。本节以MPC8572处理器为例,说明Linux PowerPC初始化PCI总线树的过程。Linux PowerPC在引入了Open Firmware机制[22]后,使用dts文件管理PCI总线控制器。Linux PowerPC执行完毕setup_arch函数后,还会执行一些和PCI总线......
2023-10-20
图2-14 PCI总线设备号的分配PCI总线推荐了一种Device Number字段与AD[31∶16]之间的映射关系。其中PCI设备0与Device Number字段的0b00000对应;PCI设备1与Device Number字段的0b00001对应,并以此类推,PCI设备15与De vice Number字段的0b01111对应。在一个处理器系统的设计中,如果在一条PCI总线上使用的PCI插槽少于4个时,笔者建议优先使用AD[17∶20]信号与PCI设备的IDSEL信号连接。......
2023-10-20
PCI-X总线改变了PCI总线使用的传送协议。PCI-X 1.0总线可以使用的最高总线频率为133MHz,而PCI-X 2.0总线可以使用的最高总线频率为533MHz,远比PCI总线使用的总线频率高。除了信号传送协议外,PCI-X总线在进行DMA读写时,可以不进行Cache共享一致性操作,而PCI总线进行DMA读写时必须进行Cache一致性操作。第3.3节将详细讨论与Cache一致性相关的PCI总线事务。此外PCI-X总线还支持乱序总线事务,即Relaxed Ordering,该总线事务被PCIe总线继承。......
2023-10-20
相关推荐