首页 理论教育Linux与PCI总线的重要指南

Linux与PCI总线的重要指南

【摘要】:值得注意的是,在不同处理器体系结构中,Linux系统初始化PCI总线的过程并不相同。Linux x86将继承BIOS对PCI总线的初始化成果,并在此基础上进行Linux PCI子系统的初始化,并执行PCI设备的Linux驱动程序的初始化模块。在Linux x86中,PCI总线的初始化由一系列模块协调完成。在Linux PCI中,有两个常用的数据结构,分别为pci_dev和pci_bus结构。

本篇主要讲述Linux系统与PCI/PCIe总线相关的一些内容,其重点在于Linux系统PCI/PCIe总线驱动程序的实现。并以此为基础说明PCI总线控制器及其相关设备在系统软件的初始化过程。本篇并不会拘泥于Linux系统的实现细节,但是仍将介绍一些与Linux系统相关的基本知识。本篇内容基于Linux 2.6.31.6内核。

值得注意的是,在不同处理器体系结构中,Linux系统初始化PCI总线的过程并不相同。如在Linux x86系统中,BIOS为PCI总线的初始化做出了许多辅助工作,而在Linux PowerPC或者Linux ARM中使用的Firmware,如U-Boot,并没有做类似的工作。

从系统软件的角度来看,PCI总线与PCIe总线的初始化过程和资源分配较为类似,为节约篇幅,本篇将PCI和PCIe总线统称为PCI总线,并将Linux系统的PCI和PCIe子系统简称为Linux PCI。

在第12.3节中讲述了一个最基本的、基于PCI总线的Linux设备驱动程序。这个PCI设备驱动程序使用了一些Linux系统提供的标准API和数据结构,例如使用pci_re source_start和pci_resource_len函数获得该设备BAR空间的基地址长度,并在request_irq函数中使用pci_dev→irq参数注册该设备使用的中断服务例程。

该PCI设备(Capric卡)在驱动程序中使用的这些存储器资源,由系统软件对PCI总线进行初始化时确定,而中断资源在使能相应的PCI设备时由系统软件分配。这个系统软件包括操作系统和Firmware[1]

与其他处理器系统相比,x86处理器作为一个通用处理器平台,始终强调向前兼容的重要性。而实现向前兼容需要做出许多牺牲,这也造成了Linux x86对PCI总线的初始化过程最为复杂也最为繁琐,x86处理器在引入了ACPI(Advanced Configuration and Power Interface Specification)机制之后,方便了处理器系统对“不规范外部设备”的管理,但是使得PCI总线的初始化过程更为复杂。(www.chuimin.cn)

下文将以Linux x86为主线说明PCI总线的初始化过程。Linux x86在对PCI总线进行初始化之前,BIOS对PCI总线做出了部分初始化工作,如创建ACPI表、预先分配PCI设备使用的存储器资源,并执行PCI设备ROM中的初始化代码等一系列步骤。

Linux x86将继承BIOS对PCI总线的初始化成果,并在此基础上进行Linux PCI子系统的初始化,并执行PCI设备的Linux驱动程序的初始化模块。在Linux x86中,PCI总线的初始化由一系列模块协调完成。

Linux x86首先使用“make menuconfig”命令对内核进行必要的配置,然后产生.config文件。假定在.config文件中,CONFIG_PCI、CONFIG_PCI_MSI、CONFIG_PCI_GOANY、CONFIG_PCI_BIOS、CONFIG_PCI_DIRECT、CONFIG_PCI_MMCONFIG等一些必要的参数为“y”,即使能PCI总线驱动、使能MSI中断请求机制等,而且对x86处理器非常重要的CON-FIG_ACPI参数也为“y”。

在Linux PCI中,有两个常用的数据结构,分别为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桥被当作一个设备。