zoukankan      html  css  js  c++  java
  • linux PCI 寻址

    每个 PCI 外设有一个总线号, 一个设备号, 一个功能号标识. PCI 规范允许单个系统占 用多达 256 个总线, 但是因为 256 个总线对许多大系统是不够的, Linux 现在支持 PCI 域. 每个 PCI 域可以占用多达 256 个总线. 每个总线占用 32 个设备, 每个设备可以是 一个多功能卡(例如一个声音设备, 带有一个附加的 CD-ROM 驱动)有最多 8 个功能. 因 此, 每个功能可在硬件层次被一个 16-位地址或者 key , 标识. Linux 的设备驱动编写 者, 然而, 不需要处理这些二进制地址, 因为它们使用一个特定的数据结构, 称为 pci_dev, 来在设备上操作.

    大部分近期的工作站至少有 2 个 PCI 总线. 在单个系统插入多于 1 个总线要通过桥实 现, 桥是特殊用途的 PCI 外设, 它的工作是连接 2 个总线. 一个 PCI 系统的全部分布 是一个树, 这里每个总线都连接到一个上层总线, 直到在树根的总线 0 . CardBus PC- card 系统也通过桥连接到 PCI 系统. 图一个典型 PCI 系统的布局表示了一个典型的 PCI 系统, 其中各种桥被突出表示了.

     和 PCI 外设相关的 16-位硬件地址, 尽管大部分隐藏在 struct pci_dev 结构中, 仍然 是可偶尔见到, 特别是当使用设备列表. 一个这样的情形是 lspci 的输出( pciutils 的 一部分, 在大部分发布中都有)和在 /proc/pci 和 /porc/bus/pci 中的信息排布. PCI 设备的 sysfs 表示也显示了这种寻址方案, 还有 PCI 域信息. [40]当显示硬件地址时, 它 可被显示为 2 个值( 一个 8-位总线号和一个 8-位 设备和功能号), 作为 3 个值( bus, device, 和 function), 或者作为 4 个值(domain, bus, device, 和 function); 所有 的值常常用 16 进制显示.

    例如, /proc/bus/pci/devices 使用一个单个 16-位 字段(来便于分析和排序), 而

    /proc/bus/busnumber 划分地址为 3 个字段. 下面内容显示了这些地址如何显示, 只显 示了输出行的开始:

    $ lspci | cut -d: -f1-3 0000:00:00.0 Host bridge

    0000:00:00.1 RAM memory

    0000:00:00.2 RAM memory

    0000:00:02.0 USB Controller

    0000:00:04.0 Multimedia audio controller 0000:00:06.0 Bridge

    0000:00:07.0 ISA bridge

    0000:00:09.0 USB Controller

    0000:00:09.1 USB Controller

    0000:00:09.2 USB Controller 0000:00:0c.0 CardBus bridge 0000:00:0f.0 IDE interface 0000:00:10.0 Ethernet controller

    0000:00:12.0 Network controller

    0000:00:13.0 FireWire (IEEE 1394)

    0000:00:14.0 VGA compatible controller

    $ cat /proc/bus/pci/devices | cut -f1 0000

    0001

    0002

    0010

    0020

    0030

    0038

    0048

    0049

    004a

    0060

    0078

    0080

    0090

    0098

    00a0

    $ tree /sys/bus/pci/devices/

    /sys/bus/pci/devices/

    |-- 0000:00:00.0 -> ../../../devices/pci0000:00/0000:00:00.0

    |-- 0000:00:00.1 -> ../../../devices/pci0000:00/0000:00:00.1

    |-- 0000:00:00.2 -> ../../../devices/pci0000:00/0000:00:00.2

    |-- 0000:00:02.0 -> ../../../devices/pci0000:00/0000:00:02.0

    |-- 0000:00:04.0 -> ../../../devices/pci0000:00/0000:00:04.0

    |-- 0000:00:06.0 -> ../../../devices/pci0000:00/0000:00:06.0

    |-- 0000:00:07.0 -> ../../../devices/pci0000:00/0000:00:07.0

    |-- 0000:00:09.0 -> ../../../devices/pci0000:00/0000:00:09.0

    |-- 0000:00:09.1 -> ../../../devices/pci0000:00/0000:00:09.1

    |-- 0000:00:09.2 -> ../../../devices/pci0000:00/0000:00:09.2

    |-- 0000:00:0c.0 -> ../../../devices/pci0000:00/0000:00:0c.0

    |-- 0000:00:0f.0 -> ../../../devices/pci0000:00/0000:00:0f.0

    |-- 0000:00:10.0 -> ../../../devices/pci0000:00/0000:00:10.0

    |-- 0000:00:12.0 -> ../../../devices/pci0000:00/0000:00:12.0

    |-- 0000:00:13.0 -> ../../../devices/pci0000:00/0000:00:13.0

    `-- 0000:00:14.0 -> ../../../devices/pci0000:00/0000:00:14.0

    所有的 3 个设备列表都以相同顺序排列, 因为 lspci 使用 /proc 文件作为它的信息源. 拿 VGA 视频控制器作一个例子, 0x00a 意思是 0000:00:14.0 当划分为域(16 位), 总线 (8 位), 设备(5 位)和功能(3 位).

    每个外设板的硬件电路回应查询, 固定在 3 个地址空间: 内存位置, I/O 端口, 和配置 寄存器. 前 2 个地址空间由所有在同一个 PCI 总线上的设备共享(即, 当你存取一个内 存位置, 在那个 PCI 总线上的所有的设备在同一时间都看到总线周期). 配置空间, 另外 的, 采用地理式寻址. 配置只一次一个插槽地查询地址, 因此它们从不冲突.

    至于驱动, 内存和 I/O 区用通常的方法, 通过 inb, readb, 等等来存取. 另一方面, 配 置传输通过调用特殊的内核函数来存取配置寄存器. 考虑到中断, 每个 PCI 插槽有 4 个 中断脚, 并且每个设备功能可以使用它们中的一个, 不必关心这些引脚如何连入 CPU. 这

    样的连接是计算机平台的责任并且是在 PCI 总线之外实现的. 因为 PCI 规范要求中断线 是可共享的, 即便一个处理器有有限的 IRQ 线数, 例如 x86, 可以驻有许多 PCI 接口板 ( 每个有 4 个中断脚).

    PCI 总线的 I/O 空间使用一个 32-位地址总线( 产生了 4 GB 的 I/O 端口), 而内存空 间可使用 32-位或者 64-位地址存取. 64-位地址在大部分近期的平台上可用. 假设地址 对每个设备是唯一的, 但是软件可能错误地配置 2 个设备到同样的地址, 使得不可能存 取任何一个. 但是这个问题不会产生, 除非一个驱动想玩弄不应当触动的寄存器. 好消息 是每个由接口板提供的内存和 I/O 地址区可被重新映射, 通过配置交易. 那是, 在系统 启动时固件初始化 PCI 硬件, 映射每个区到不同地址来避免冲突.[41]这些区当前被映射到 的地址可从配置空间读出, 因此 Linux 驱动可存取它的设备而不用探测. 在读取了配置 寄存器后, 驱动可安全地存取它的硬件.

    PCI 配置空间为每个设备包含 256 字节(除了 PCI Express 设备, , 它每个功能有 4 KB 地配置空间), 并且配置寄存器的排布是标准化的. 配置空间的 4 个字节含有一个唯一的 功能 ID, 因此驱动可标识它的设备, 通过查找那个设备的特定的 ID.[42] 总之, 每个设备 板被地理式寻址来获取它的配置寄存器; 这些寄存器中的信息可接着被用来进行正常的 I/O 存取, 不必进一步的地理式寻址.

    从这个描述应当清楚, PCI 接口标准对比 ISA 主要的创新是配置地址空间. 因此, 除了 通常的驱动代码, 一个 PCI 驱动需要存取配置空间的能力, 为了从冒险的探测任务中解 放自己.

    本章的剩余部分, 我们使用词语设备来指一个设备功能, 因为在多功能板的每个功能如同 一个独立的实体. 当我们引用一个设备, 我们的意思是"域号, 总线号, 设备号, 和功能 号"的组合.

  • 相关阅读:
    java.lang.NoSuchMethodError: org.springframework.core.io.ResourceEditor错误
    http://blog.sina.com.cn/s/blog_6145ed810102vr8k.html
    异或巧用:Single Number
    Highcharts:X轴分组堆叠图
    Vs2012在Linux开发中的应用(5):项目属性的定义
    BZOJ 1005 明明的烦恼 Prufer序列+组合数学+高精度
    Python 点滴 I
    easyUI 验证控件应用、自己定义、扩展验证 手机号码或电话话码格式
    InnoDB: Error: io_setup() failed with EAGAIN after 5 attempts
    Java设计模式-设计模式的六种原则
  • 原文地址:https://www.cnblogs.com/fanweisheng/p/11146911.html
Copyright © 2011-2022 走看看