⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 (ldd) ch15-外围总线概览(转载).txt

📁 献给ARM初学者
💻 TXT
📖 第 1 页 / 共 4 页
字号:
(LDD) Ch15-外围总线概览(转载)
       
       
      第十五章  外围总线概览
       
       
       
      在第八章“硬件管理”中,我们介绍了最低级的硬件控制,本章提供一个较高级的总线
      体系结构的概览。总线由电气接口和编程接口组成。在这一章,我打算介绍编程接口。
       
      本章覆盖了几种总线体系结构。不过,基本重点是访问PCI外围的核心功能,因为近来,
      PCI总线是最常用的外围总线,也是核心支持最好的总线。
       
       
       
      PCI接口

      PCI接口
       
       
       
      尽管很多计算机用户认为PCI(外围部件互连,Peripheral Component Interconnect)
      是布局电气线路的一种方法,但实际上,它是一组完全的规范,定义了计算机的不同部
      分是如何交互的。
       
      PCI规范覆盖了与计算机接口相关的绝大多数方面。我不打算在这里全部介绍,在本节中
      ,我主要关心一个PCI驱动程序是如何找到它的硬件,并获得对它的访问的。在第二章“
      构造和运行模块”的“自动和手工配置”一节,及在第九章“中断处理”的“自动检测
      中断号”一节中讨论过的探测技术同样可以应用于PCI设备,但规范还提供了探测的另外
      办法。
       
      PCI结构被设计来替代ISA标准,由三个主要目标:在计算机和其外围之间传送数据时有
      更高的性能,尽可能地做到平台无关性,使在系统中增减外围设备得到简化。
       
      PCI通过使用比ISA高的时钟频率来获得更高的性能;它的时钟运行在25或33MHZ(实际时
      钟是系统时钟的几分之一的整数倍),而且马上就会游66MHZ的扩展。另外,它被装配在
      32位的数据总线上,64位的扩展正在规范中。平台无关性一直是计算机总线的一个设计
      目标,这是PCI的尤其重要的一个特征,因为PC世界一直以来总是被处理器特定的标准所
      主宰。
       

       
      不过对驱动程序作者来说,最要紧的是对接口板自动检测的支持。PCI设备是无跳线的(
      与大多数ISA外围不同),并且在引导时被自动配置。因此,设备驱动程序必须能访问设
      备上的配置信息来完成初始化。这些情形都不需要任何探测。
       
       
       
      PCI寻址
       
      每个外围由一个总线号、一个设备号、和一个功能号确定。虽然PCI规范允许一个系统最
      多拥有256条总线,但PC只有一条。每条总线最多带32个设备,但每个设备可以是最多个
      功能的多功能板(如一个音频设备带一个CD-ROM驱动器)。每个功能可以由一个16位的
      键或两个8位的键确定。Linux核心采用后一种方法。
       
      每个外围板子的硬件电路回答与三个地址空间相关的询问:内存位置,I/O端口,和配置
      寄存器。前两个地址空间由PCI总线上的所有设备共享(也就是说,当你访问一个内存位
      置,所有的设备都将同时看到这个总线周期)。而配置空间则利用“地理寻址”,每个
      槽有一个配置事务的私用使能线,PCI控制器一次访问一个板子,不会有地址冲突。考虑
      到驱动程序,内存和I/O是以通常的inb,memcpy等来访问。而配置事务则通过调用特定的
      核心函数访问配置寄存器来完成。至于中断,每个PCI设备有4个中断管脚,它们到处理
      器中断线的路由是主板的任务;PCI中断可以设计为共享的,这样即使是一个有限中断线
      的处理器也能带很多PCI接口板。
       

       
      PCI总线的I/O空间使用32位的地址总线(这样就是4GB的I/O端口),而内存空间则可以
      用32位或64位地址访问。地址对每个设备来说应该是唯一的,但也有可能有两个设备错
      误地映射到同一个地址,使得哪个都不能被访问。一个好消息是接口卡提供的每个内存
      和I/O地址区段都可以通过配置事务重映射。这就是设备可以在引导时被初始化从而避免
      地址冲突的机制这些区段当前映射到的地址可以从配置空间读出,因此Linux驱动程序可
      以不通过探测就访问其设备。一旦配置寄存器被读出,驱动程序就可以安全的访问它的
      硬件。
       
      PCI配置空间由每个设备函数256个字节构成,配置寄存器的布局是标准化的。配置空间
      有四个字节含有一个唯一的函数ID,因此驱动程序可以通过在外围查找特定的ID来B确定
      它的设备*。总之,每个设备板子被地理寻址以取得它的配置寄存器;这个信息可以用来
      确定这个板子或采取进一步动作。
       
      从前面的描述,应该清楚PCI接口标准比ISA的主要创新是配置地址空间。因此,除了通
      常的驱动程序代码外,PCI驱动程序还需要访问配置空间的能力。
       
      在本章的其余部分,我将使用单词“设备”来指一个设备功能,因为多功能板上的每个
      功能均是一个独立的实体。当我提到一个设备,我是指元组“总线号,设备号,功能号
      ”。如前所述,每个元组在Linux中由两个8位数字表示。
       
       
       

       
      引导时
       
      让我们看一下PCI是如何工作的,从系统引导开始,因为那时设备被配置。
       
      当PCI设备被加电时,硬件关闭。或者说,设备只对配置事务响应。加电时,设备没有映
      射到计算机地址空间的内存和I/O端口;所有其它的设备特定的特征,象中断线,也都被
      关闭。
       
      幸运的是,每个PCI母板都装有懂得PCI 的固件,根据平台的不同被称做BIOS、NVRAM、
      或PROM。固件提供对设备配置地址空间的访问,即使处理器的指令集不提供这样的能力
       
      在系统引导时,固件对每个PCI外围执行配置事务,从而为它提供的任何地址区段分配一
      个安全的地方。到设备驱动程序访问设备时,它的内存和I/O区段已经被映射到处理器的
      地址空间。驱动程序可以改变这个缺省的分配,但它通常并不这样做,除非有一些设备
      相关的原因要求这样。
       
      在Linux中,用户可以通过读/proc/pci来查看PCI 设备,这是个文本文件,系统中每个P
      CI板子有一项。下面是/proc/pci中一项的例子:
       
      (代码344)
       

       
      /proc/pci中每一项是一个设备的设备无关特征的概述,如它的配置寄存器所描述的。例
      如,上面这一项告诉我们这个设备有板上内存,已被映射到地址0xf1000000。一些古怪
      的细节的含义以后在我介绍过配置寄存器后将会清楚。
       
       
       
      检测设备
       
      如前面提到的,配置空间的布局是设备无关的。在这一节,我们将看看用来确定外围的
      配置寄存器。
       
      PCI设备有一个256字节的地址空间。前64个字节是标准化的,而其余的则是设备相关的
      。图15-1显示了设备无关配置空间的布局。
       
      如图所示,有些PCI的配置寄存器是要求的,而有些则是可选的。每个PCI设备必须在必
      要寄存器中包含有意义的值,而可选寄存器的内容则以来与实际外围的能力。可选域并
      不使用,除非必要域的内容表明它们是有效的。这样,必要域断言了板子的能力,包括
      其它域可用与否。
       
      有意思的是注意到PCI寄存器总是小印地安字节顺序的。尽管标准要设计为体系结构无关
      的,PCI的设计者有时还是显示出对PC环境的偏见。驱动程序的作者应该留神字节顺序,
      特别是访问多字节的配置寄存器时;在PC上工作的代码可能在别的平台上就不行。Linux

      特别是访问多字节的配置寄存器时;在PC上工作的代码可能在别的平台上就不行。Linux
      的开发者已经注意了字节排序问题(见下一节“访问配置空间”),但这个问题还是要
      牢记在心。不幸的是,标准函数ntohs和ntohl都不能用,因为网络字节顺序与PCI顺序相
      反;在Linux2.0中没有标准函数将PCI字节顺序转换为主机字节顺序,每个用单个字节构
      成多字节值的驱动程序都应该特别小心地正确处理印地安字节序。核心版本2.1.10引入
      了几个函数来处理这些字节顺序问题,它们在第十七章“最近的发展”中“转换函数”
      一节介绍。
       
      (图15-1:标准化的PCI配置寄存器)
       
      描述所有的配置项超出了本书的范围。通常,与设备一起发布的技术文档会描述它支持
      的寄存器。我们感兴趣的是驱动程序如何找到它的设备,以及它如何访问设备的配置空
      间。
       
      三个PCI寄存器确定一个设备:销售商,设备ID,和类。每个PCI外围把它自己的值放入
      这些只读寄存器,驱动程序可以用它们来查找设备。让我们更仔细地看看这些寄存器:
       
      销售商
       
      这个16位的寄存器确定硬件的生产商。例如,每个Intel的设备都会标上同样的销售商号
      ,8086 hex(是个随即值?)。这样的号码有一个全球的注册,生产商必须申请一个唯
      一的号。
       

       
      设备ID
       
      这是另一个16位寄存器,由生产商选择;不需要有官方的注册。这个ID通常与销售商ID
      成对出现,形成一个硬件设备的唯一的32位标志符。我将用单词“签名”来指销售商/设
      备ID对。一个设备驱动程序经常以来于签名来确定它的设备;驱动程序的作者从硬件文
      档中知道要寻找什么值。
       
       
      每个外围设备都属于一个类。类寄存器是个16位的值,它的高八位确定 “基类”(或组
      )。例如,“以太网”和“令牌环”是属于“网络”组的两类,而“串行”和“并行”
      类属于“通信”组。有些驱动程序可以支持几种类似的设备,它们虽然有不同的签名,
      却属于同一类;这些驱动程序可以依赖于类寄存器来确定它们的外围,如以后所示。
       
       
       
      下面的头文件,宏,以及函数都将被PCI驱动程序用来寻找它的硬件设备:
       
      #include <linux/config.h>
       
      驱动程序需要知道是否PCI函数在核心是可用的。通过包含这个头文件,驱动程序获得了
      对CONFIG_宏的访问,包括CONFIG_PCI(将在下面介绍)。从1.3.73以来,这个头文件包含

      对CONFIG_宏的访问,包括CONFIG_PCI(将在下面介绍)。从1.3.73以来,这个头文件包含
      在<linux/fs.h>中;如果想向后兼容,你必须把它显式地包含。
       
      CONFIG_PCI
       
      如果核心包括对PCI BIOS调用的支持,那么这个宏被定义。并不是每个计算机都有PCI总
      线,所以核心的开发者应该把 PCI的支持做成编译时选项,从而在无PCI的计算机上运行
      Linux时节省内存。如果CONFIG_PCI没有定义,那么这个列表中其它的函数都不可用,驱
      动程序应使用预编译的条件语句将PCI支持全都排除在外,以避免加载时的“未定义符号
      ”错。
       
      #include <linux/bios32.h>
       
      这个头文件声明了本节介绍的所有的原型,因此一定要被包含。这个头文件还定义了函

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -