📄 00000007.htm
字号:
所有其它PCII/O和内存地址都将被它忽略。这个过滤使得这些地址信息不会在整个 <BR>系统中扩散。为了实现这点,PCI-PCI桥接器必须编程为有某个PCII/O及PCI内存基 <BR>址和上限,只有在这个地址范围内的PCI地址访问才能从主干总线传递到二级总线。 <BR>一旦系统中的PCI-PCI桥接器被设置成这样,则只要当Linux设备驱动程序通过这个 <BR>窗口访问PCII/O和PCI内存空间时,此PCI-PCI桥接器就将变得透明。这样也给Linux <BR>PCI设备驱动编写者提供了方便。我们在稍后的讨论中将看到Linux对PCI-PCI桥接器 <BR>非常巧妙的配置。 <BR> <BR>6.5.2 PCI-PCI桥接器:PCI配置循环及PCI总线编号方式 <BR> <BR> <BR>为了让CPU上运行的PCI初始化代码能访问位于分支PCI总线上的设备,必须为桥接 <BR>器提供某种机制以便它可以决定是否将配置循环从主干接口传递到其二级接口。循 <BR>环是出现在PCI总线上的一个地址。PCI标准定义了两种PCI配置寻址格式;类型0和 <BR>类型1;它们分别如图6.3及6.4所示。类型0 PCI配置循环不包含总线序号,同时在此 <BR>PCI总线上对应于这个PCI配置地址的所有PCI设备都会来对它们进行解释。类型0 <BR>配置循环的11位到31位用来进行PCI设备选择。有种设计方式是让每位代表系统中 <BR>一个不同的设备。这时11位对应PCI槽0中的PCI设备而12位标识槽1中的设备等等, <BR>如此类推。另外一种方式是直接将设备的槽号写入到位31到11中。系统使用哪种机 <BR>制依赖于系统PCI内存控制器。 <BR> <BR>类型1 <BR>PCI配置循环包含一个PCI总线序号,同时这种配置循环将被除桥接器外的所有PCI设 <BR>备所忽略。所有发现类型1配置循环的PCI-PCI桥接器把它们看到的地址传递到各自 <BR>的下级PCI总线。至于PCI-PCI桥接器是否忽略类型1配置循环或将其传递到PCI总线 <BR>则依赖于PCI-PCI桥接器的配置方式。每个PCI-PCI桥接器都拥有一个主干总线接口 <BR>序号以及一个二级总线接口序号。主干总线是那个离CPU最近的PCI总线而二级总线 <BR>是离它稍远的PCI总线。任何PCI-PCI桥接器还包含一个从属总线序号,这是所有二 <BR>级总线接口所桥接的PCI总线中序号最大的那个。或者说这个从属总线序号是PCI-PCI <BR>桥接器向下连接中PCI总线的最大序号。当PCI-PCI桥接器看到类型1 PCI配置循环时 <BR>它将进行如下操作: <BR> <BR> 如果此总线序号不在桥接器的二级总线序号和从属总线序号之间则忽略掉它。 <BR> <BR> 如果此总线序号与桥接器的二级总线序号相同则将其转换成类型0 <BR> 配置命令。 <BR> <BR> 如果此总线序号位于桥接器的二级总线序号与从属总线序号之间则将它不作 <BR> 改变的传递到二级总线接口中。 <BR> <BR>所以如果想寻址PCI-PCI配置例4中总线3上的设备1,我们继续从CPU中产生一个类型1 <BR>配置命令。桥接器1将其传递给总线1。桥接器2虽然忽略它但会将其转换成一个类型0 <BR>配置命令并送到总线3上,在那里设备1将作出相应反应。 <BR> <BR>PCI配置中总线序号由操作系统来分配。但是序号分配策略必须遵循对系统中所有 <BR>PCI-PCI桥接器都正确的描叙: <BR> <BR>“位于PCI-PCI桥接器后所有的PCI总线必须位于二级总线序号和从属总线序号之间”。 <BR> <BR>如果这个规则被打破,则PCI-PCI桥接器将不能正确的传递与转换类型1 PCI配置循环 <BR>,同时系统将找不到或者不能正确地初始化系统中的PCI设备。为了满足这个序号分配 <BR>策略,Linux以特殊的顺序配置这些特殊的设备。PCI-PCI总线序号分配一节详细描叙 <BR>了Linux的PCI桥接器与总线序号分配策略。 <BR> <BR>6.6 Linux PCI 初始化过程 <BR> <BR>Linux中的PCI初始化代码逻辑上可分成三个部分: <BR> <BR>PCI 设备驱动 <BR> 这个伪设备驱动程序将从总线0开始搜索PCI系统并定位系统中所有的PCI设备与 <BR> 桥接器。它将建立起一个描叙系统拓扑结构的数据结构链表。另外它还为所有的 <BR> 桥接器进行编号。 <BR> <BR>PCI BIOS <BR> 这个软件层提供了在bib-pci-bios定义中描叙的服务。即使Alpha AXP没有BIOS <BR> 服务,Linux核心也将为它提供具有相同功能的代码。 <BR> <BR>PCI Fixup <BR> 系统相关补丁代码将整理PCI初始化最后阶段的一些系统相关事物。 <BR> <BR>6.6.1 Linux 核心PCI数据结构 <BR> <BR> <BR>Linux核心初始化PCI系统时同时也建立了反应系统中真实PCI拓扑的数据结构。 <BR>每个PCI设备(包括PCI-PCI桥接器)用一个pci_dev数据结构来描叙。每个PCI总线用 <BR>一个pci_bus数据结构来描叙。这样系统中形成了一个PCI总线树,每棵树上由一些子 <BR>PCI设备组成。由于PCI总线仅能通过PCI-PCI桥接器(除了主干PCI总线0)存取,所以 <BR>pci_bus结构中包含一个指向PCI-PCI桥接器的指针。这个PCI设备是PCI总线的父PCI总 <BR>线的子设备。 <BR> <BR>在图6.5中没有显示出来的是一个指向系统中所有PCI设备的指针,pci_devices。系统 <BR>中所有的PCI设备将其各自的pci_dev数据结构加入此队列中。这个队列被Linux核心用 <BR>来迅速查找系统中所有的PCI设备。 <BR> <BR>6.6.2 PCI设备驱动 <BR> <BR>PCI设备驱动根本不是真正的设备驱动,它仅是在系统初始化时由操作系统调用的一些 <BR>函数。PCI初始化代码将扫描系统中所有的PCI总线以找到系统中所有的PCI设备(包括 <BR>PCI-PCI桥接器)。 <BR> <BR>它通过PCI BIOS代码来检查当前PCI总线的每个插槽是否已被占用。如果被占用则它建 <BR>立一个pci_dev数据结构来描叙此设备并将其连接到已知PCI设备链表中(由pci_devices <BR>指向)。 <BR> <BR>首先PCI初始化代码扫描PCI总线0。它将试图读取对每个PCI槽中可能的PCI设备厂商标 <BR>志与设备标志域。当发现槽被占用后将建立一个pci_dev结构来描叙此设备。所有这些 <BR>PCI初始化代码建立的pci_dev结构(包括PCI-PCI桥接器)将被连接到一个单向链表 <BR>pci_devices中。 <BR> <BR>如果这个PCI设备是一个PCI-PCI桥接器则建立一个pci_bus结构并将其连接到由pci_root <BR>指向的pci_dev结构和pci_bus树中。PCI初始化代码通过类别代码0x060400来判断此PCI <BR>设备是否是一个PCI-PCI桥接器。然后Linux核心代码将配置此PCI-PCI桥接器下方的PCI <BR>设备。如果有更多的桥接器被找到则进行同样的配置。显然这个过程使用了深度优先搜 <BR>索算法;系统中PCI拓扑将在进行广度映射前先进行深度优先映射。图6.1中Linux将在配 <BR>置PCI总线0上的视频设备前先配置PCI设备1上的以太与SCSI设备。 <BR> <BR>由于Linux优先搜索从属的PCI总线,它必须处理PCI-PCI桥接器二级总线与从属总线序号。 <BR>在下面的pci-pci总线序号分配中将进行详细讨论。 <BR> <BR>配置PCI-PCI桥接器 - 指定PCI总线序号 <BR> <BR> <BR>为了让PCI-PCI桥接器可以传递PCI <BR>I/O、PCI内存或PCI配置地址空间,它们需要如下内容: <BR> <BR>Primary Bus Number:主干总线序号 <BR> 位于PCI-PCI桥接器上方的总线序号 <BR>Secondary Bus Number:二级总线序号 <BR> 位于PCI-PCI桥接器下方的总线序号 <BR>Subordinate Bus Number:从属总线序号 <BR> 在桥接器下方可达的最大总线序号 <BR>PCI I/O and PCI Memory Windows:PCI I/O与PCI内存窗口 <BR> 对于PCI-PCI桥接器下方所有PCI <BR> I/O地址空间与PCI内存地址空间的窗口基址和大小。 <BR> <BR>配置任一PCI-PCI桥接器时我们对此桥接器的从属总线序号一无所知。不知道是否还 <BR>有下一级桥接器存在,同时也不知道指派给它们的序号是什么。但可以使用深度优先 <BR>遍历算法来对扫描出指定PCI-PCI桥接器连接的每条总线,同时将它们编号。当找到 <BR>一个PCI-PCI桥接器时,其二级总线被编号并且将临时从属序号0xff指派给它以便对 <BR>其所有下属PCI-PCI桥接器进行扫描与指定序号。以上过程看起来十分复杂,下面将 <BR>提供一个实例以帮助理解。 <BR> <BR>PCI-PCI 桥接器序号分配:步骤1 <BR> 第一个被扫描到的桥接器将是桥1。所以桥1下方的总线将被编号成总线1,同时 <BR> 桥1被设置为二级总线1且拥有临时总线序号0xff 这意味着所有PCI总线序号为 <BR> 1或以上的类型1 PCI配置地址将被通过桥1传递到PCI总线1上。如果其总线序 <BR> 号为1则此配置循环将被转换成类型0配置循环,对于其它序号不作转换。这正 <BR> 是Linux PCI初始化代码所需要的按序访问及扫描 PCI总线1。 <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -