目前PCIe总线规范,依然在迅猛发展,但并不是所有PCIe设备都支持这些在PCIe总线的最新规范中提及的概念。一般说来,PCIe总线规范提出的新的概念,最先在x86处理器系统的Chipset和Intel设计的PCIe设备中出现。
Linuxx86首先使用“makemenuconfig”命令对内核进行必要的配置,然后产生.config文件。我们假定在.config文件中,CONFIG_PCI、CONFIG_PCI_MSI、CONFIG_PCI_GOANY、CONFIG_PCI_BIOS、CONFIG_PCI_DIRECT、CONFIG_PCI_MMCONFIG等一些必要的参数为“y”,即使能PCI总线驱动、使能MSI中断请求机制等,而且对x86处理器非常重要的CONFIG_ACPI参数也为“y”。
在LinuxPCI中,有两个常用的数据结构,分别为pci_dev和pci_bus结构。这两个数据结构的定义在./include/linux/pci.h文件中。其中pci_dev结构描述PCI设备,包括这个PCI设备的配置寄存器信息,使用的中断资源,还有一些和SR-IOV相关的参数。而pci_bus结构描述PCI桥,包括这个PCI桥的配置寄存器信息和一些状态信息。该结构中self参数值得注意,pci_busàself指向一个pci_dev结构,该结构用于PCI桥的上游总线访问PCI桥,此时PCI桥被当作一个设备。
--------------------------------------------------------------------------------
[1]x86处理器使用的BIOS也是Firmware的一种。
第14章LinuxPCI的初始化过程
LinuxPCI初始化的主要工作是遍历当前处理器系统中的所有PCI总线树,并初始化PCI总线树上的全部设备,包括PCI桥与PCIAgent设备。在Linux系统中,多次使用了DFS算法对PCI总线树进行遍历查找,并分配相关的PCI总线号与PCI总线地址资源。
单纯从一种处理器系统的角度上看,LinuxPCI的实现机制远非完美。其中有许多冗余的代码和多余的步骤,比如LinuxPCI中对PCI总线树的遍历次数过多,从而影响LinuxPCI的初始化代码的执行效率。产生这些不完美的主要原因是,LinuxPCI首先以x86处理器为蓝本书写,而后作为通用代码逐渐支持其他处理器,如ARM、PowerPC和MIPS等。不同的处理器对PCI总线树的遍历机制并不完全相同,而LinuxPCI作为通用代码必须兼顾这些不同,从而在某种程度上造成了这段代码的混乱。这种混乱是通用代码的无奈之举。
本章以x86处理器系统为例,介绍LinuxPCI的执行流程。目前ACPI机制在x86处理器系统已经得到大规模的普及,而且在x86处理器中,只能使用ACPI机制支持处理器最新的特性。因此掌握ACPI机制,对于深入理解x86处理器的软件架构,已经不可或缺。为此本章将重点介绍LinuxPCI在ACPI机制下的初始化过程,而不再介绍LinuxPCI的传统初始化方式。
第15章LinuxPCI的中断处理
LinuxPCI的中断处理包含两部分内容,一部分是PCI设备使用INTx信号,包括PCIe