Linux 核心--7.PCI设备( 四 )



在图6.5中没有显示出来的是一个指向系统中所有PCI设备的指针 , pci_devices 。系统中所有的PCI设备将其各自的pci_dev数据结构加入此队列中 。这个队列被Linux核心用来迅速查找系统中所有的PCI设备 。


6.6.2PCI设备驱动
PCI设备驱动根本不是真正的设备驱动 , 它仅是在系统初始化时由操作系统调用的一些函数 。PCI初始化代码将扫描系统中所有的PCI总线以找到系统中所有的PCI设备(包括PCI-PCI桥接器) 。

它通过PCI BIOS代码来检查当前PCI总线的每个插槽是否已被占用 。如果被占用则它建立一个pci_dev数据结构来描叙此设备并将其连接到已知PCI设备链表中(由pci_devices指向) 。

首先PCI初始化代码扫描PCI总线0 。它将试图读取对每个PCI槽中可能的PCI设备厂商标志与设备标志域 。当发现槽被占用后将建立一个pci_dev结构来描叙此设备 。所有这些PCI初始化代码建立的pci_dev结构(包括PCI-PCI桥接器)将被连接到一个单向链表pci_devices中 。

如果这个PCI设备是一个PCI-PCI桥接器则建立一个pci_bus结构并将其连接到由pci_root指向的pci_dev结构和pci_bus树中 。PCI初始化代码通过类别代码0x060400来判断此PCI设备是否是一个PCI-PCI桥接器 。然后Linux 核心代码将配置此PCI-PCI桥接器下方的PCI设备 。如果有更多的桥接器被找到则进行同样的配置 。显然这个过程使用了深度优先搜索算法;系统中PCI拓扑将在进行广度映射前先进行深度优先映射 。图6.1中Linux将在配置PCI总线0上的视频设备前先配置PCI设备1上的以太与SCSI设备 。

由于Linux优先搜索从属的PCI总线,它必须处理PCI-PCI桥接器二级总线与从属总线序号 。在下面的pci-pci总线序号分配中将进行详细讨论 。


配置PCI-PCI桥接器 - 指定PCI总线序号





图6.6 配置PCI系统:第一部分

为了让PCI-PCI桥接器可以传递PCI I/O、PCI内存或PCI配置地址空间 , 它们需要如下内容:


Primary Bus Number:主干总线序号
位于PCI-PCI桥接器上方的总线序号
Secondary Bus Number:二级总线序号
位于PCI-PCI桥接器下方的总线序号
Subordinate Bus Number:从属总线序号
在桥接器下方可达的最大总线序号
PCI I/O and PCI Memory Windows:PCI I/O与PCI内存窗口
对于PCI-PCI桥接器下方所有PCI I/O地址空间与PCI内存地址空间的窗口基址和大小 。
配置任一PCI-PCI桥接器时我们对此桥接器的从属总线序号一无所知 。不知道是否还有下一级桥接器存在,同时也不知道指派给它们的序号是什么 。但可以使用深度优先遍历算法来对扫描出指定PCI-PCI桥接器连接的每条总线 , 同时将它们编号 。当找到一个PCI-PCI桥接器时 , 其二级总线被编号并且将临时从属序号0xff指派给它以便对其所有下属PCI-PCI桥接器进行扫描与指定序号 。以上过程看起来十分复杂 , 下面将提供一个实例以帮助理解 。


PCI-PCI 桥接器序号分配:步骤1
考虑图6.6所显示的拓扑结构 , 第一个被扫描到的桥接器将是桥1 。所以桥1下方的总线将被编号成总线1,同时桥1被设置为二级总线1且拥有临时总线序号0xff 。这意味着所有PCI总线序号为1或以上的类型1 PCI配置地址将被通过桥1传递到PCI总线1上 。如果其总线序号为1则此配置循环将被转换成类型0 配置循环 , 对于其它序号不作转换 。这正是Linux PCI初始化代码所需要的按序访问及扫描 PCI总线1 。



图6.7 配置PCI系统:第二部分



PCI-PCI 桥接器序号分配:第二步
由于Linux使用深度优先算法,初始化代码将继续扫描PCI总线1 。在此处它将发现一个PCI-PCI桥接器2 。除此桥接器2外再没有其它桥接器存在 , 因此它被分配给从属总线序号2 , 这正好和其二级接口序号相同 。图6.7画出了此处的PCI-PCI桥接器与总线的编号情况 。

推荐阅读