极限首页 业界焦点 软件工程师之路 系统工程师之路 网络工程师之路 软件下载 技术社区
 bash编程学习笔记(一)
 RPM 打包技术与典型 SPEC
 Linux Kernel核心中文手册
 Linux Kernel核心中文手册
 精通递归程序设计
 Linux/Unix环境下的make命
 Linux Kernel核心中文手册
 bash编程学习笔记(二)
 Linux Kernel核心中文手册
 Linux操作系统内核编译详解
 bash编程学习笔记(一)
 RPM 打包技术与典型 SPEC
 Linux Kernel核心中文手册
 Linux Kernel核心中文手册
 精通递归程序设计
 Linux/Unix环境下的make命
 Linux Kernel核心中文手册
 bash编程学习笔记(二)
 Linux Kernel核心中文手册
 Linux操作系统内核编译详解

Shell 中文手册

Python 2.3 中文手册

Python 2.4 中文手册

Mysql 4.x 中文手册

PHP 4.x 中文手册

Apache 2.x 中文手册
更多手册

站内搜索:
当前位置:首页>>软件工程师之路>>编程进阶>>正文
Linux Kernel核心中文手册(5、6、7)(3)
时间:2005-11-08 作者:未知 来源:未知

   

图6.5中没有显示的还有一个指向系统中所有的PCI设备的指针:pci_devices。系统中所有的PCI设备的pci_dev的数据结构都排在这个队列中。Linux核心使用这个队列快速查找系统中所有的PCI设备。

 

6.6.2 The PCI Device Driver(PCI 设备驱动程序)

 

PCI设备驱动程序完全不是一个真正的设备驱动程序,只是系统初始化的时候操作系统调用的一个函数。PCI初始化代码必须扫描系统中所有的PCI总 线,查找系统中所有的PCI设备(包括PCI-PCI桥接设备)。它使用PCI BIOS代码来查看它当前扫描的PCI总线上的每一个可能的槽位是否被占用。如果这个PCI槽位占用,它就建立一个描述这个设备的pci_dev数据结 构,并把它链接到已知PCI设备的列表中(由pci_deivices指向)。

参见drivers/pci/pci.c Scan_bus()

 

PCI初始化代码从PCI总线0开始扫描。它试图读出每一个可能的PCI槽位中每一个可能的PCI设备的Vendor Identification和Device Identification域。当它找到了占用的槽位它就建立一个pci_dev数据结构来描述它。PCI初始化代码所建立的所有的pci_dev数据 结构(包括所有的PCI-PCI桥)都链接到一个链接表:pci_devices。

 

如果找到的设备是一个PCI-PCI桥,则建立一个pci_bus的数据结构,并链接到pci_root指向的由pci_bus和pci_dev数 据结构组成的树上。PCI的初始代码可以判断PCI设备是否PCI-PCI桥,因为它的分类编码(class code)是0x060400。然后Linux核心配置它刚刚找到的PCI-PCI桥的另一端的PCI总线(下游)。如果找到更多的PCI-PCI桥,它 们都一样被配置。这个过程成为深度(depthwize)算法:系统在宽度搜索之前先在深度展开。看图6.1,Linux会首先配置PCI总线1和它的以 太网和SCSI设备,然后配置PCI总线0上的显示设备。

 

在Linux向下游查找PCI总线的时候它必须配置介入的PCI-PCI桥的次总线和附属总线编号。这些在下面的6.6.2节详细描述:

 

Configuring PCI-PCI Bridges – Assigning PCI Bus Numbers(配置PCI-PCI桥-分配PCI总线编号)

 

对于传送通过它们进行的PCI I/O、PCI内存或者PCI配置地址空间的读写,PCI-PCI桥必须直到以下:

 

Primary Bus Number 刚好在PCI-PCI桥上游的总线编号

Secondary Bus Number 刚好在PCI-PCI桥下游的总线编号

Subordinate Bus Number 从这个桥向下可以达到的所有总线中最高的总线编号。

PCI I/O and PCI Memory Windows 从这个PCI-PCI桥向下的所有的地址的PCI I/O地址空间和PCI 内存空间的窗口的base和size。

 

问题是当你希望配置任何指定的PCI-PCI桥的时候你并不知道这个桥的附属总线数目。你不知道是否下游还有其他PCI-PCI桥。就算知道,你也 不知道它们将会被分配什么编号。答案是使用一个深度递归算法(depthwise recursive algorithm)。在每一个总线上找到任何PCI-PCI桥的时候都就给它们分配编号。对于找到的每一个PCI-PCI桥,就给它的次总线分配编号, 并给它分配临时的附属总线编号0xFF,并扫描它的下游所有的PCI-PCI桥并分配编号。这看起来相当复杂,但是下面的实际例子能使这个过程更清楚。

 

PCI-PCI Bridge Numbering: Step 1 参考图6.6中的拓扑,扫描找到的第一个桥是桥1(Bridge1)。桥1下游的PCI总线编号为1,桥1分配一个次总线号1和一个临时的附属总线编号 0xFF。这意味着指定PCI总线1或更高的所用的类型1的PCI配置地址会穿过桥1到达PCI总线1。如果它们的总线编号是1,就转换成为类型0的配置 cycle,否则对于其他的总线编号就不变。这也正是Linux PCI初始化代码需要做的,这样才能访问并扫描PCI总线1。

PCI-PCI Bridge Numbering: Step 2 Linux使用深度算法,所以初始化代码开始扫描PCI总线1。这是它找到了PCI-PCI桥2,桥2之外没有其他的PCI-PCI桥,所以它的附属总线 编号成为2,和它的次接口一样。图6.7显示了总线和PCI-PCI桥这时是如何编码的。

 

PCI-PCI Bridge Numbering:Step 3 PCI初始化代码回来扫描PCI总线1,找到了另一个PCI-PCI桥3。它的主总线接口赋值1而它的次总线接口是3,它的附属总线编号是0xFF。图 6.8显示了系统这时是如何配置的。带有总线编号1、2或3的类型1的PCI配置cycle现在可以正确地传送到适当的PCI总线。

 

6.6.3 PCI BIOS Functions(PCI BIOS函数)

 

PCI BIOS函数是通用的跨平台的一系列标准例程。例如,它们对于Intel和Alpha AXP系统都是一样的。它们允许CPU控制对于所有PCI地址空间的访问。只有Linux核心和设备驱动程序需要使用它们。

参见arch/*/kernel/bios32.c

 

 

6.6.4 PCI Fixup

 

Alpha AXP系统上的PCI整理代码比Intel(基本不做任何事情)要做更多的工作。对于Intel系统,启动时候运行的系统BIOS,已经完全配置了PCI系统。Linux不需要做更多的事情,只是映射PCI的配置。对于非Intel系统,需要做更多的配置:

参见arch/kernel/bios32.c

 

对于每一个设备分配PCI I/O和PCI内存空间

对于系统重的每一个PCI-PCI桥必须配置PCI I/O和PCI内存地址窗口

对于设备产生Interrupt Line值,这些控制设备的中断处理

 

下面描述这些代码如何工作。

 

Finding Out How Much PCI I/O and PCI Memory Space a Device Needs

(找出一个设备需要多少PCI I/O和PCI内存空间)

 

查询找到的每一个PCI设备,找出它需要多少PCI I/O和内存地址空间。为此,把每一个Base Address Register都写成1然后读出来。设备会在不关心的地址位返回1,有效地指定了需要的地址空间。

 

用两个基本的基础地址寄存器(Base Address Register),第一种指示设备的寄存器以及PCI I/O1内存空间必须在哪一个地址空间。这通过寄存器的0位表示。图6.10显示了PCI 内存和PCI I/O的基础地址寄存器的两种形式。

 

为了找出每一个给定的基础地址寄存器需要多少地址空间,需要向所有的寄存器写并读出来。设备会把不关心的地址位设为0,这样就有效地指明了需要的地址空间。这种设计暗示了使用的所有的地址空间都是2的指数,本质上是对齐的。

 

例如,在你初始化DECChip 21142 PCI快速以太网设备的时候,它告诉你在PCI I/O或PCI内存空间它需要0x100字节的地址。初始化代码为它分配空间。在它分配空间之后,21142的控制和状态寄存器就可以在这些地址见到。

 

Allocating PCI I/O and PCI Memory to PCI-PCI Bridges and Devices

(为PCI-PCI桥和设备分配PCI I/O和PCI内存)

 

象所有的内存一样,PCI I/O和PCI内存空间是有限的,其中有一些相当紧缺。对于非Intel系统的PCI整理代码(和Intel系统的BIOS代码)必须有效地为每一个设备 分配它需要的内存量。分配给一个设备的PCI I/O和PCI内存的分配必须自然对齐。例如,如果一个设备请求PCI I/O地址0xB0,那么分配的地址就必须是0xB0的倍数。另外,分配给任何桥的PCI I/O和PCI内存地址的基础必须分别对齐4K和1M的边界。下游的设备给定的地址空间必须位于它所有的上游的PCI-PCI桥的内存范围中间。所以有效 地分配地址空间是有比较困难的问题。

 

Linux使用的算法依赖于用PCI设备驱动程序建立的总线/设备树所描述的每一个设备,它按照PCI I/O内存递增的顺序分配地址空间。又是使用递归算法,遍历PCI初始化代码所建立的pci_bus和pci_dev数据结构。BIOS整理代码从PCI 总线的根(pci_root所指)开始:

 

分别把当前的全局PCI I/O和内存的基础分别对齐在4K和1M的边界

 

对于当前总线上的每一个设备(按照需要的PCI I/O内存顺序排列)

-分配它的PCI I/O和/或PCI内存

-将全局的PCI I/O和内存的基础按照合适的量移动

-允许设备使用给定的PCI I/O和PCI内存

 

分别为当前总线下游的所有总线分配空间,注意这会改变全局的PCI I/O和内存基础。

 

分别把当前的全局PCI I/O和内存的基础对齐在4K和1M的边界,同时指出当前的PCI-PCI桥所需要的PCI I/O和PCI内存的窗口的基础和大小

 

对于连接在当前总线上的PCI-PCI桥,设置它的PCI-PCI I/O和PCI内存地址和限制。

 

打开PCI-PCI桥上桥接PCI I/O和PCI内存访问的功能。这意味着如果任何在桥的主PCI总线上看到的PCI I/O和PCI内存地址如果位于它的PCI I/O和PCI内存地址窗口的话就会被桥接到它的次总线。

 

以图6.1的PCI系统作为PCI整理代码的例子:

 

  共4页: 上一页 [1] [2] 3 [4] 下一页   
推荐】【 】【关闭


关于极限 | 站内地图 | 意见反馈 | 广告服务 | 数据服务 | 联系我们
本站所刊登的文章,技术资料,软件均整理于网络资源或本站原创,转载请务必联系原作者或本站。
Copyright ? 2001-2004 UPLinux.com All Rights Reserved.
本站唯一联系信箱:
京ICP备05010519