LINUX核心之 (第六章)
第 6 章 PCI
Peripheral Component Interconnect(PCI),外设部件连接,是一个标准,描述的是如何将一个系统中
的外设以一种结构化的,可控制化的方式连接在一起。PCI标准刻划了系统外设部件连接的电气方案,
和在该标准下外设部件的行为归约。本章探讨Linux核心如何初始化系统的PCI总线和PCI设备。
图6.1 基于PCI总线的系统
图6.1是一个基于PCI总线系统的例子的逻辑框图。PCI总线和PCI桥负责将系统中的部件连接在一起。
CPU连在PCI总线0;在主PCI总线(PCI 0)上挂着视频设备。PCI-PCI桥,一个特殊的PCI设备将主PCI
总线于次PCI总线(PCI 1)相连。用PCI归约的术语来讲,PCI总线1被称作PCI-PCI桥的downstream,
PCI总线0叫做桥的upstream。在第二个PCI总线上,是系统的SCSI和Ethernet设备。这个PCI-PCI桥,
第二个PCI总线和其上的两块设备在物理上都可以在一个PCI卡上。系统中的PCI-ISA桥支持ISA设备。
上图所示ISA总线下挂着一个多功能I/O控制器,控制系统的键盘,鼠标器和软驱。
6.1 PCI地址空间
CPU与PCI设备需要存取在它们之间共享的内存。设备驱动程序使用这片内存来控制PCI设备并用来传
送信息。一般而言,这些共享内存中包含设备的控制和状态寄存器。这些寄存器用来控制设备和读
取设备的状态。例如,PCI SCSI设备驱动程序读取SCSI设备的状态寄存器以探测该设备是否已就绪
可以将一个数据块写入SCSI磁盘。又例如,设备驱动程序可以在控制寄存器中写入控制数据从而使
设备开始运转在设备电源被开启之后。
上述的共享内存可以是CPU的系统内存。但如果这样的话,每次PCI设备存取内存时,CPU将被阻塞,
等待PCI设备存取的结束。一般而言,在某个特定时刻,只能一个系统部件存取一个特定的内存。
所以,上述方法会使系统性能降低。另外,允许系统的外设不在一个良好的控制下存取主内存不
是一个好的方法。这将会是非常危险的事情。一个“淘气”的设备可以使得系统非常不稳定。
因此,外设一般拥有它们自己的内存空间。CPU可以存取这个空间。但是反之外设存取系统内存必须
在DMA(Direct Memory Access)的控制之下。ISA设备可以存取两种地址空间,ISA I/O(Input/Output
)和ISA memory。PCI可以有三种:PCI I/O,PCI memory和PCI Configuration空间。所有的这些地址
空间都可以被CPU所存取。其中设备驱动程序要使用PCI I/O和PCI memory空间。Linux核心中的PCI初
始化代码要用到PCI Configuration空间。
6.2 PCI 配置头(Configuration Header)
图6.2 PCI Configuration Header (配置头)
系统中的每个PCI设备,包括PCI-PCI桥,都有一个配置数据结构在PCI Configuration地址空间中。
这个PCI Configuraton Header(配置头)被系统用来定位和控制一个设备。至于这个数据结构具体
位于PCI Configuration空间的何处,依赖于设备位于PCI拓朴结构中的位置。例如,一个PCI视频
(Video)卡插在PCI 母板(motherboard)上的一个PCI槽中,它的数据配置头结构将会在一个地方;
如果被插在另一个地方,其数据配置头将会位于PCI Configuration空间中的另外一个地方。当然,
这没有关系。不论PCI设备和PCI桥在哪里,系统都将检测到,并使用它们的配置头中的状态和配置
寄存器来对它们进行配置。
一般来讲,每个PCI插槽的PCI配置头都位于在PCI Configuration空间的一个偏移量(Offset)处,
这个偏移量是与每个PCI插槽的位置顺序相关的。例如,PCI板上的第一个PCI插槽的PCI配置在偏
移量0;第二个PCI插槽的配置在偏移256处(所有的配置头的大小是256个字节)。系统中提供一
与硬件有关的机制,使得PCI配置代码可以试图检测在一个给定的PCI总线上所有可能的PCI配置
头,从而知道哪个PCI插槽上目前有设备,哪个插槽上暂无设备。这是通过读取配置头上的某个
域而完成的(一般是“Vendor Identification\" 域)。如果一个插槽上为空,上述操作会返回一些
错误返回值,如0xFFFFFFFF。
图6.2所示的是一个完整的256字节的PCI配置头数据结构。它包含下列数据域:
Vendor Identification(厂商标识)
一个唯一的数字标识描述一个PCI设备的出处。Digital的PCI厂商标识是
0x1011; Intel的是0x8086。
Device Identification(设备标识)
一个唯一的数字标识用来描述一个设备。例如Digital的21141快速Ethernet
网卡有一个设备标识0x0009。
Status(状态)
这个域给出一个设备的状态。这个域的每个位的含义是由一个标准来定义的。
Command(命令)
系统通过在这个域中写入数据来控制设备。例如,让设备存取PCI I/O空间。
Class Code(设备类代码)
这个域用来标定一个设备的类型。每一种设备都对应一个标准的类。
如video(视频),SCSI等等。SCSI设备的类码是0x0100。
Base Address Registers(基地址寄存器)
这些寄存器用来决定和分配一个设备可用的存储空间类型
(如,PCI I/O和PCI memory)大小和位置。
Interrupt Pin(中断管脚)
在每个PCI卡上,有4个物理管脚可以传送中断信号到PCI总线上。其标准的
标号是A,B,C和D。这个”Interrupt Pin\"域描述的是这个PCI设备正在用
那个物理中断管脚。通常来讲,对一个特定的设备,其使用的中断管脚是
被固定好的。也就是说,每次系统重新启动时,该设备使用同样的中断管
脚。这个信息使得中断处理子系统知道如何管理这个设备的中断。
(译者注:请参阅中断处理章节。注意PCI设备于ISA设备在中断方面的区别)
Interrupt Line(中断线)
设备的PCI配置头数据结构的\"Interrupt Line\"域用来在PCI初始化代码,
设备驱动程序和Linux中断处理子系统之间传递一个中断处理。这个域中的
值对于设备驱动程序而言是无意义的,但其可以使得中断例程正确地将一个
中断从一个PCI设备传递(route)到Linux中相应的设备驱动程序的中断处理
代码中。请参阅第七章关于Linux如何处理中断。
6.3 PCI I/O 和PCI Memory 地址
设备使用这两种地址空间来与其在Linux核心中运行的设备驱动程序进行通信。例如,
DECchip 21141 快速Ethernet设备映射其内部寄存器到PCI I/O地址空间中。从而其设备驱动程
序可以读和写这些寄存器来控制该设备。Video驱动器经常使用大量的PCImemory空间来存放视
频信息。
在PCI系统初始化完成,使用上述的”command“命令允许设备存取地址空间之前,系统不能存取
这块地址。值得注意的是只有PCI配置代码才读和写PCI Configuration地址。Linux设备驱动程
序只能读和写PCI I/O和PCI memory地址空间。
6.4 PCI-ISA桥
PCI-ISA桥通过将对PCI I/O和PCI memory地址空间的存取转换到对ISA I/O和ISA memory地址空间
的存取来支持对ISA设备的支持。许多系统中含有一些ISA总线槽和几个PCI总线槽。随着时间的推
移,这种为了向后兼容的机器配置将会消失。系统将会只支持PCI系统。在ISA地址空间中(ISA
I/O和ISA memory),系统中的ISA设备的寄存器地址被固定在某个地方(自从早期的Intel 8080 PC开
始)。例如,一个$5000的基于Alpha AXP的计算机的软盘控制器与早期的IBM PC的在ISA地址空间中
占据的是同一片地址。PCI归约(Specification)通过在PCI I/O 和PCI memory地址空间的低端为
ISA外设的使用保留一片区域并通过PCI-ISA桥来将对这片保留的PCI地址空间的存取映射到对系统中
ISA地址的存取上。(译者注:细心的读者不难发现,这种通过加”Layer\",或“映射”的方法在计算
机软硬件系统中几乎无处不见。系统就是这样一层一层的抽象出更高的概念提供给更高的层使用,
直到用户层,从而使得一切细节的复杂性变的越来越透明。)
6.5 PCI-PCI桥
PCI-PCI桥是一种特殊的PCI设备。它将系统中的PCI总线粘合作一起。简单的系统只有通常一个PCI总
线。一个PCI总线上可支持的PCI设备的数目是有限的。使用PCI-PCI桥可以解决上述问题,允许将更
多的PCI总线加入系统从而支持更多的PCI设备。这对于高性能的服务器来说是非常重要的。Linux全
面地支持PCI-PCI桥机制。
6.5.1 PCI-PCI桥:PCI I/O 和PCI memory 窗口
PCI-PCI桥只负责传递一部份对PCI I/O和PCI memory读和写的请求到downstream(请参见第一节)。例
如,图6.1中,仅当读和写请求中的PCI I/O或PCI memory地址属于PCI-PCI桥SCSI或Ethernet设备时
PCI-PCI桥才将这些总线上的请求从PCI总线0传递到PCI总线1。其他的将被忽略。这种过滤机制可以
避免地址在系统中没必要的繁衍。为了做到这点,每个PCI-PCI桥必须正确地被设置好它所负责的PCI
I/O和PCI memory地址的起始和大小。当一个读或写请求落在其负责的范围之内,这个请求将被映射到
次一级的PCI总线上。系统中的PCI-PCI桥一旦设置完毕,如果Linux中的设备驱动程序存取的PCI I/O
和PCI memory地址只在这些窗口之内,这些PCI-PCI桥是不可见的(译者注:窗口在这里的含义是指每
个PCI-PCI桥都仅负责一定范围的空间映射;上述原文是:\"Once the PCI-PCIBridges in a system
have been configured then so long as the Linux device drivers only access PCI I/O and PCI
Memeory space via these windows, the PCI-PCI Bridges are invisible.\")。这是个很重要的特性
使得Linux PCI设备驱动程序开发者的工作容易些。然而,这也使得Linux配置PCI-PCI桥变的有点迷惑。
我们将在下面的章节中看到这一点。
6.5.2 PCI-PCI桥:PCI配置周期(Configuration Cycles)和PCI总线计数方法(Bus Numbering)
图6.3 PCI配置周期类型0
图6.4 PCI配置周期类型1
既然CPU的PCI初始化代码可以存取那些不在主PCI总线上的设备,那么必须存在一个机制使得这些桥能
够判断是否将一个PCI配置周期从它们的(译者住:它们指的是PCI-PCI桥设备)主接口传递它们的次接口。
所谓一个“周期”指的是一个出现在PCI总线上的一个地址。PCI归约(Specification)定义了两种PCI配
置寻址格式;类型0和类型1。图6.3和图6.4所示分别是这两种寻址类型。PCI配置周期类型0中不含有总
线号码,被所有的设备当作针对当前这个PCI总线上的PCI配置周期。类型0地址中的31-11位被用来作为
设备选择域。一种设计方案是每一位对应一个设备。在这种情况下,位11表示插槽0上的PCI设备。位12
表示插槽2上的PCI设备并以此类推。另一种方法是直接地将设备的插槽号码写入位31-11中。具体采用
哪种机制依赖于系统的PCI存储控制器(memory controller)。
类型1的PCI配置周期地址中含有一个PCI总线号码。当这种类型的配置周期(或命令)出现在一个PCI总线
上时,除了PCI-PCI桥之外,所有其他的PCI设备会将其忽略。所有”看见“配置命令类型1的PCI-PCI桥
可能选择将类型1的配置周期传递到其downstream PCI总线上或忽略之。选择的决定依赖于PCI-PCI桥的
配置。没一个PCI-PCI桥有一个主PCI总线接口号和一个第二PCI总线接口号。主总线接口是那个离CPU更
近的;第二总线接口是那个离CPU较远的。每个PCI-PCI桥还拥有一个次级总线号码。这个数目代表着在
这个PCI-PCI桥第二总线接口之下的所有PCI总线中的最大数。换种方式讲,这个次级总线数目是这个
PCI-PCI桥的PCI总线downstream的最大数目。当一个PCI-PCI桥看见一个类型1 PCI配置周期时,桥的行
为如下:
* 忽略这个命令,如果指定的总线号码不在第二和次级总线号码之间。(包含边界值)
* 将其转换成类型0配置命令,如果指定的总线号码是桥的第二级总线接口。
* 将其(原封不动地)传递到第二级总线接口,如果指定的总线号码大于该桥的第二总线号
但小于或等于次级总线号。
因此,如果我们想访问在图6.9中总线3上的设备1,我们必须从CPU产生一个类型1的PCI配置命令。桥1
将原封不动地将此命令传递到总线1;桥2将忽略此命令,但桥3将接受这个命令并将其转换成一个类型0
的配置命令,然后发送到设备1所在的PCI总线3上。
关于在PCI配置期间如何分配总线号码依赖于具体的操作系统。然而不论什么样的分配方案,对系统中所
有的PCI-PCI桥来说,必须满足下列要求:
”在PCI-PCI桥后面的所有PCI总线的编号必须在该桥的第二总线接口号码和次级总线号码之间“
如果违反这个规则,PCI-PCI桥将不会正确地传递和翻译类型1的PCI配置命令。系统将不能正确地发现和
初始化系统中的PCI设备。为了完成这个赋值方案,Linux依照一个特殊的顺序来配置这些PCI设备。
从图6.6开始我们描述了Linux PCI桥和总线的号码赋值方案。并举出了一个例子。
6.6 Linux PCI初始化
Linux PCI 初始化代码逻辑上分为三个部份:
PCI设备驱动程序
这个伪设备驱动程序从总线0开始查询PCI系统并且定位系统中所有的PCI设备和桥。它建立一个
可以用来描述这个PCI系统拓朴层次的数据结构链表。并且对所有的发现的桥编码。
PCI BIOS
这个软件层提供在bib-pci-bios归约中描述的服务。虽然Alpha AXP不提供BIOS服务,在其Linux
版本中包含了相应的功能。
PCI Fixup
与特定系统相关的PCI初始化修补代码
6.6.1 Linux核心的PCI数据结构
图6.5 Linux 核心PCI数据结构
当Linux核心初始化PCI系统时,它建立一些可以描述系统PCI拓朴的数据结构。图6.5所示是反映图6.1系统
的数据结构之间的关系。
每一个PCI设备(包括PCI-PCI桥)用一个pci_dev数据结构来描述。每个PCI总线用一个pci_bus结构来描述。
这样的结果是产生了一个PCI总线树状关系结构。每个PCI总线结构pci_bus下挂着在该总线上的PCI设备。
因为除了主PCI总线,总线0,PCI总线只能通过PCI-PCI桥来存取,每个pci_bus中含有一个指向其上的PCI
设备(PCI桥)的指针(这些设备pci_bus结构用链表连在一起,如图6.5)。一个PCI设备是其”父“PCI总线的
”孩子“。(请注意图6.5中指针children)
图6.5中没有显示出来的一个指针是pci_devices。它用来指向系统中所有的PCI设备。系统中所有的PCI设
备将其pci_dev数据结构加入到这个队列中。这个队列被Linux核心用来快速查找系统中的PCI设备。
6.6.2 PCI设备驱动程序
PCI设备驱动程序并不是真正的,严格意义上的驱动程序。它是在系统初始化时被调用的一个操作系统函数。
PCI初始化代码必须扫描系统中所有的PCI总线,寻找系统中所有的PCI设备(包括PCI-PCI桥设备)。
它使用PCI BIOS代码来发现它正在扫描的PCI总线上的每个插槽上是否已有设备安装。如果在一个插槽上发现
了一个设备,一个用来描述该设备的pci_dev数据结构将被创建并且加入到被pci_devices所指向的队列中。
PCI初始化代码从PCI总线0开始扫描。它通过读取”Vendor Identification\"和\"Device Identification\"
来试图发现每一个插槽上的设备(请参阅6.2)。
如果发现了一个PCI-PCI桥,则创建一个pci_bus数据结构并且连入到由pci_root指向的pci_bus和pci_dev
数据结构组成的树中。PCI初始化代码通过设备类代码0x060400来判断一个PCI设备是否是PCI-PCI桥。然后,
Linux核心开始构造这个桥设备另一端的PCI总线和其上的设备。如果还发现了桥设备,就以同样的步骤来
进行构建。这个处理过程称之为深度优先算法。系统的PCI拓朴在广度查询之前,先进行深度优先查找。
请参阅图6.1,由上述算法可知,在构造PCI总线0上的Video设备之前,Linux将首先构造PCI总线1和其上的
Ethernet和SCSI设备(译者注:这里的前提是:图6.1中PCI-PCI桥所在的插槽号码小于video卡所在的PCI插
槽的号码)
当Linux查询downstream PCI总线时,它必须构造PCI-PCI桥的第二级和次级总线编号的号码。下面我们将对
此进行相信描述。
构造PCI-PCI桥---对PCI总线号码进行赋值
图6.6构造一个PCI系统:第一步
PCI-PCI桥要想正确传递对PCI I/O,PCI Memory或PCI Configuration地址空间的读和写请求,必须知道下
列信息:
Primary Bus Number(主总线号)
该PCI-PCI桥的紧接的upstream总线的编号。
Secondary Bus Number(第二级总线号)
该PCI-PCI桥的紧接的downstream总线的编号。
Subordinate Bus Number(次级总线号)
该桥的downstream总线中最大的总线编号。
PCI I/O 和 PCI Memory 窗口
对于该桥的所有downstream地址中的PCI I/O和PCI Memory地址空间的窗口的基址和大小。
存在的问题是当你想要配置一个PCI-PCI桥的时候,你不知道这个桥的次级总线接口号码。你不知道该桥下
是否还有其他的PCI-PCI桥。即使你知道,也不清楚如何对它们进行赋值。解决方案是利用上述讲过的深度
递归算法来扫描每个总线。每当发现PCI-PCI桥就对它们进行赋值。当发现一个PCI-PCI桥时,它的第二级
PCI总线接口号可以被确定。然后我们暂时先将其次级总线接口号赋值为0xFF。紧接着,开始扫描该
PCI-PCI桥的downstream桥。这个过程看起来有点复杂。但下面的例子将给出清晰的解释。
PCI-PCI桥的赋值--第一步
以图6.6的拓扑结构为例,扫描时首先发现的桥是Bridge1(桥1)。桥1的downstream PCI总线号码被赋值1。
自然该桥的第二级总线号码也是1。其次级总线号码被暂时赋值为0xFF。上述赋值的含义是所有类型1的
含有PCI总线1或更高(<255)的号码的PCI配置地址将被桥1传递到PCI总线1上。如果PCI总线号是1,桥1
还负责将配置地址的类型转换成类型0。否则,就不做转换。上述动作就是开始扫描总线1时Linux初始化
代码所完成的对总线0的配置工作。
图6.7 构造一个PCI系统:第二步
PCI-PCI桥的赋值--第二步
Linux使用深度优先算法进行扫描。所以初始化代码开始扫描总线1。从而PCI-PCI桥2被发现。因为在桥2
下面不再发现有PCI-PCI桥,所以桥2的次级总线号是2,等于它的第二总线接口号。图6.7显示了在这个时刻
总线和PCI-PCI桥的赋值情况。
图6.8 构造一个PCI系统:第三步
PCI-PCI桥的赋值--第三步
PCI初始化代码从总线2的扫描中回来接着进行扫描总线1。这时,另外一个PCI-PCI桥,桥3,被发现。它的
主总线号被赋值为1;第二级总线号为3。因为总线3上还发现了桥,所以桥3的次级总线号被暂时赋值0xFF。
图6.8显示了这个时刻系统配置的状态。到目前为止,含有总线号1,2和3的类型1PCI配置周期都可以被正确
地传送到相应的总线上。
图6.9 构造一个PCI系统:第四步
PCI-PCI桥的赋值--第四步
现在Linux开始扫描PCI总线3,桥3的downstream.PCI总线3上有另外一个PCI-PCI桥,桥4。因此桥4的主总线
号的值为3。第二总线号为4。由于桥4下面没有别的桥设备,所以桥4的次级总线号为4。然后初始化代码回到
PCI-PCI桥3。这时就将桥3的次级总线号从0xFF改为4,表示总线4是从桥3往下走的最远的PCI-PCI桥。最后,
PCI初始化代码将4以同样的道理赋值给桥1的次级总线号。图6.9反映了系统最后的状态。
6.6.3 PCI BIOS函数
PCI BIOS函数是一些在所有平台上都通用的一些标准例程。例如,对于Intel和Alpha AXP系统,它们都一样。
BIOS函数的存在使得CPU可以存取所有的PCI地址空间。
只有Linux核心代码和设备驱动程序可以使用这些函数。
6.6.4 PCI Fixup(补充或修补)
相对于Intel系统,Alpha AXP系统的PCI fixup代码要作更多的事情。对于Intel系统,基本上PCI fixup
什么也不做。
对于Intel系统,系统的BIOS在启动时,已经基本上将PCI系统构造好了。这使得Linux只需将配置映射过来
就好了。对于非Intel系统,Linux还需做如下构建:
*为每个PCI设备分配PCI I/O和PCI Memory空间。
*为系统中的每个PCI-PCI桥,配置相应的PCI I/O和PCI Memory地址窗口。
*为每个设备的配置头产生“Interrupt Line\"值;这些值控制设备的中断处理。
下面我们讲述上述行为的实现。
查询设备所需的PCI I/O和PCI Memory空间大小
系统对每个找到的PCI设备查询设备所需的PCI I/O和PCI Memory空间大小。为了做到这一点,每个基址
寄存器先全写入1然后再读。设备将在没有用的位上返回0值。从而我们可以得知地址空间的大小。
图6.10 PCI配置头:基地址寄存器
基地址寄存器分两种类型,以表示一个寄存器是位于PCI I/O空间或PCI Memory空间。这是通过寄存器的位
0来设置的。图6.10所示是对应于PCI I/O和PCI Memory的两种形式的基址寄存器。
为了探测一个给定的基地址寄存器要申请的地址空间的大小,可以通过上述先向寄存器写入全1然后再读取
的方法。返回值即是该基地址寄存器所申请的空间大小。这种设计还保证了所有的地址空间都是2的幂数从
而且是自然对齐的。
例如当初始化DECChip 21142 PCI快速Ethernet设备时,我们会知道它需要0x100字节的PCI I/O或PCI Memory
空间。Linux PCI初始化代码将负责分配这片内存。然后,21142的控制和状态寄存器就可以在这些地址上被
访问。
为PCI-PCI桥和PCI设备分配PCI I/O和PCI Memory空间
象所有的存储空间一样,PCI I/O和PCI Memory空间也是非常有限的,或稀少的。PCI Fixup代码必须非常
有效地为每个设备分配其申请的空间。PCI I/O和PCI Memory必须以自然对齐的方式来被分配。例如,如果一
个设备申请0xB0字节的PCI I/O空间,它必须对齐在一个是0xB0倍数的地址上。另外,对任何一个桥,其所需
要的PCI I/O和PCI Memory必须分别对齐4K和1M的边界。由于一个桥的所有的downstream设备的地址空间都必
须位于PCI-PCI桥的地址空间内,所以有必要提供一个有效的算法来进行控制。
Linux使用的算法依赖于由PCI设备驱动程序建立的总线/设备树状数据结构中的每个设备分配的空间。空间
是朝上增长的。系统使用一个递归算法来扫描pci_bus和pci_dev数据结构。扫描从PCI总线的根开始
(其指针是pci_root)。具体的行为如下:
*分别依照4K和1M字节的边界,调整当前的PCI I/O和PCI Memory的基址。
*对当前总线上的每个设备:
。分配PCI I/O和Memory空间
。相应调整全局的PCI I/O和PCI Memory基址
。使能(enable)设备使用被分配的空间
*递归地对该总线下面的所有总线进行空间分配。注意这会改变PCI I/O和PCI Memory基址。
*分别依照4K和1M字节的边界,调整当前的PCI I/O和PCI Memory的基址。并且计算出当前
PCI-PCI桥的PCI I/O和PCI Memory空间窗口的基址和大小。
*将上一步骤计算出来的值对当前的PCI桥进行赋值。
*打开桥的对PCI I/O和PCI Memory地址过滤功能。这意味着如果一个在桥的主总线上的对
PCI I/O和PCI Memory 地址的寻址落在这个桥的PCI I/O和PCI Memory窗口内,该寻址指令
将被传递到桥的第二级总线上。
以图6.1 PCI系统为例,我们给出PCI Fixup代码的工作如下:
校准PCI基址
PCI I/O在0x4000; PCI Memory在0x100000。这使得PCI-ISA桥将接受所有低于这些值的寻址,作为ISA寻
址周期。
Video 设备
这个设备需要0x200000字节的PCI Memory。因为为了和要求的空间大小对齐,我们从0x20000地址开始
分配0x200000空间。PCI Memory的基址移到0x400000。PCI I/O的基址还是0x4000。
PCI-PCI桥
现在碰到了PCI-PCI桥并对其分配PCI内存。 注意在这里我们不需要调整基地址。
Ethernet 设备
该设备为其PCI I/O和PCI Memory空间各要求0xB0字节。在PCI Memory的基址0x400000和PCI I/O的基址
0x4000的基础上进行分配。结果是PCI I/O基址的值为0x40B0。PCI Memory基址为0x4000B0。
SCSI 设备
该设备要求0x1000 PCI Memory空间。系统依照对齐的要求,在0x401000的基础上开始分配。从而PCI
Memory的基址被调整至0x402000。PCI I/O的基址不变。
PCI-PCI桥的PCI I/O和PCI Memory 窗口
现在来设置桥的PCI I/O和PCI Memory的窗口大小。PCI I/O的窗口在0x4000与0x40B0之间。
PCI Memory的窗口在0x400000与0x402000之间。这将使得桥总线上忽略对Video的寻址,而将传递对
SCSI和Ethernet的寻址。
发布人:netbull 来自:linuxeden