Peripheral Component
Interconnect(PCI),似乎它的名字暗示的一样,是描述如何通过一个结构化和可控制的方式把系统中的外设组件连接起来的一个标准。标准的PCI Local
Bus规范描述了系统组件电气连接的方法和它们行为的方法。本章探讨Linux核心如何初始化系统的PCI总线和设备。
图6.1是一个PCI基础的系统的逻辑图。PCI总线和PCI-PCI桥(bridge)是系统组件联系在一起的粘合剂。CUP和video设备连在主要的PCI总线,PCI总线0。一个非凡的PCI设备,PCI-PCI桥把主总线连接到次PCI总线,PCI总线1。按照PCI规范的术语,PCI总线1描述成为PCI-PCI桥的下游而PCI总线0是桥的上游。连接在次PCI总线上的是系统的SCSI和以太网设备。物理上桥、次要PCI总线和这两种设备可以在同一块PCI卡上。系统中的PCI-ISA桥支持老的、遗留的ISA设备,本图显示了一个超级I/O控制芯片,控制键盘、鼠标和软驱。
6.1 PCI Address Space(PCI地址空间)
CPU和PCI设备需要访问它们所共享的内存。这些内存让设备驱动程序控制这些PCI设备并在它们之间传递信息。一般地共享的内存包括设备的控制和状态寄存器。这些寄存器用于控制设备和读取它的状态。例如:PCI SCSI设备驱动程序可以读取SCSI设备的状态寄存器,判定它是否可以向SCSI磁盘写一块信息。或者它可以写入控制寄存器让它关闭的设备开始运行。
CPU的使用的系统内存可以用作这种共享内存,但是假如这样的话,每一次PCI设备访问内存,CPU都不得不停顿,等待PCI设备完成。对于内存的访问通常有限制,同一时间只能有一个系统组件答应访问。这会使得系统速度降低。答应系统的外部设备在一个不受控的方式下访问主内存也不是一个好主意。这会非常危险:一个恶意的设备会让系统非常不稳定。
外部设备由它们自己的内存空间。CPU可以访问这些空间,但是设备对于系统内存的访问受到严格的控制,必须通过DMA(Direct Memory Access直接内存存取)通道。ISA设备可以访问两种地址空间:ISA I/O(输入/输出)和ISA内存。PCI由三中:PCI I/O、PCI内存和PCI配置空间(configuration space)。CPU可以访问所有的地址空间其中PCI I/O和PCI内存地址空间由设备驱动程序使用而PCI配置空间由Linux和心中的PCI初始化代码使用。
Alpha AXP处理器没有对于除了系统地址空间之外的地址空间的天生的访问模式。它需要使用支持芯片来访问象PCI配置空间这样的其他地址空间。它使用了一个地址空间的映射方案,从巨大的虚拟地址空间中偷出一部分映射到PCI地址空间。
6.2 PCI Configuration Headers(PCI配置头)
系统中的每一个PCI设备,包括PCI-PCI桥都由一个配置数据结构,位于PCI配置地址空间中。PCI配置头答应系统识别和控制设备。这个头位于PCI配置地址空间的确切位置依靠于设备使用的PCI拓扑。例如,插在PC主板一个PCI槽位的一个PCI显示卡配置头会在一个位置,而假如它被插到另一个PCI槽位则它的头会出现在PCI配置内存中的另一个位置。但是不管这些PCI设备和桥在什么位置,系统都可以发现并使用它们配置头中的状态和配置寄存器来配置它们。
通常,系统的设计使得每一个PCI槽位的PCI配置头都有一个和它在板上的槽位相关的偏移量。所以,举例来说,板上的第一个槽位的PCI配置可能位于偏移0而第二个槽位的在偏移256(所有的头都一样长度,256字节),依此类推。定义了系统相关的硬件机制使得PCI配置代码可以尝试检查一个给定的PCI总线上的所有可能的PCI配置头,试图读取头中的一个域(通常是Vendor Identification 域)得到一些错误,从而知道那些设备存在而那些设备不存在。PCI Local Bus规范描述了一种可能的错误信息:试图读取一个空的PCI槽位的Verdor Identification和Device Indentification域时候返回0xFFFFFFFF。
图6.2显示了256字节的PCI配置头的布局。它包括以下域:
参见include/linux/pci.h
Vendor Identification 唯一的数字,描述这个PCI设备的发明者。Digital的PCI Vendor Identification 是0x1011而Intel是0x8086。
Device Identification 描述设备自身的唯一数字。例如Digital的21141快速以太网设备的设备标识符是0x0009。
Status 此域给除了设备的状态,它的位的含义由PCI Local Bus规范规定。
Command 系统通过写这个域控制这个设备。例如:答应设备访问PCI I/O内存。
Class Code 标识了设备的类型。对于每一种设备都有标准分类:显示、SCSI等等。对于SCSI的类型编码是0x0100。
Base Address Registers 这些寄存器用于确定和分配设备可以使用的PCI I/O和PCI内存的类型、大小和位置。
Interrupt Pin PCI卡的物理管脚中的4个用于向PCI总线传递中断。标准中把它们标记为A、B、C和D。Interrupt Pin域描述了这个PCI设备使用那个管脚。通常对于一个设备来说这时硬件决定的。就是说每一次系统启动的时候,这个设备都使用同一个中断管脚。这些信息答应中断处理子系统治理这些设备的中断。
Interrupt Line PCI配置头中的Interrupt Line域用于在PCI初始化代码、设备驱动程序和Linux的中断处理子系统之间传递中断控制。写在这里的数字对于设备驱动程序来讲是没有意义的,但是它可以让中断处理程序正确地把一个中断从PCI设备发送到Linux操作系统中正确的设备驱动程序的中断处理代码处。Linux如何处理中断参看第7章。
6.3 PCI I/O and PCI Memory Address(PCI I/O和PCI内存地址)
这两种地址空间用于设备和CPU上运行的Linux核心的它们的设备驱动程序通讯。例如:DECchip 21141快速以太网设备把它的内部寄存器映射到了PCI I/O空间。然后它的Linux设备驱动程序通过读写这些寄存器来控制设备。显示驱动程序通常使用大量的PCI内存空间来放置显示信息。
直到PCI系统建立起来并使用PCI配置头中的Command域打开了设备对于这些地址空间的访问为止,设备都无法访问这些空间。应该注重的是只有PCI配置代码读写PCI配置地址,Linux的设备驱动程序只是读写PCI I/O和PCI内存地址。
6.4 PCI-ISA Bridges(PCI-ISA桥)
这种桥把对于PCI I/O和PCI内存地址空间的访问转换成为ISA I/O和ISA内存访问,用来支持ISA设备。现在销售的多数系统都包括几个ISA总线插槽和几个PCI总线插槽。这种向后的兼容的需要会不断减少,将来会有只有PCI的系统。在早期的Intel 8080基础的PC时代,系统中的ISA设备的ISA 地址空间(I/O和内存)就被固定下来。甚至一个S5000 Alpha AXP基础的计算机系统的ISA软驱驱动器的ISA I/O地址也会和第一台IBM PC一样。PCI规范保留了PCI I/O和PCI内存的地址空间中的较低的区域保留给系统中的ISA外设并使用一个PCI-ISA桥把所有对于这些区域的PCI内存访问转换为ISA访问。
6.5 PCI-PCI Bridges(PCI-PCI桥)
PCI-PCI桥是非凡的PCI设备,把系统中的PCI总线粘和在一起。简单系统中只有一个PCI总线,当时单个PCI总线可以支持的PCI设备的数量有电气限制。使用PCI-PCI桥增加更多的PCI总线答应系统支持更多的PCI设备。这对于高性能的服务器尤其重要。当然,Linux完全支持使用PCI-PCI桥的使用。
6.5.1 PCI-PCI Bridges: PCI I/O and PCI Memory Windows
PCI-PCI桥只向下游传递对于PCI I/O和PCI内存读和写的一个子集。例如在图6.1中,只有读和写的地址属于SCSI或者以太网设备的时候PCI-PCI桥才会把读写的地址从PCI总线0传递到总线1,其余的都被忽略。这种过滤阻止了不必要的地址信息遍历系统。为了达到这个目的,PCI-PCI桥必须编程设置它们必须从主总线向次总线通过的PCI I/O和PCI内存地址空间访问的基础(base)和限制。一旦系统中的PCI-PCI桥设置好,只要Linux设备驱动程序只是通过这些窗口存取PCI I/O和PCI内存空间,PCI-PCI桥是不可见的。这是个重要的特性,使得Linux的PCI设备驱动程序的作者的日子好过了。但是它也让Linux下的PCI-PCI桥在一定程度上需要技巧才能配置,我们不久就会看到。
6.5.2 PCI-PCI Bridges: PCI Configuration Cycles and PCI Bus Numbering(PCI-PCI桥:PCI配置cycle和PCI总线编号)
既然CPU的PCI初始化代码可以定位不在主PCI总线上的设备,必须有一种机制使得桥可以决定是否把配置cycle从它的主接口传递到次接口上。一个cycle就是它显示在PCI总线上的地址。PCI规范定义了两种PCI地址配置格式:类型0和类型1,分别在图6.3和图6.4中显示。类型0的PCI配置cycle不包含总线号,被这个PCI总线上的所有的PCI设备解释用于PCI地址配置。配置cycle的位32:11看作是设备选择域。设计系统的一个方法是让每一个位选择一个不同的设备。这种情况下为11可能选择槽位0的PCI设备,位12选择槽位1的PCI设备,依此类推。另一种方法是把设备的槽位号直接写到位31:11中。一个系统使用哪一种机制依靠于系统的PCI内存控制器。
类型1的