一些 PCI 配置寄存器是要求的, 一些是可选的. 每个 PCI 设备必须包含有意 义的值在被要求的寄存器中, 而可选寄存器的内容依赖外设的实际功能. 可选的字段不被 使用, 除非被要求的字段的内容指出它们是有效的. 因此, 被要求的字段声称板的功能, 包括其他的字段是否可用.

注意 PCI 寄存器一直是小端模式. 尽管标准被设计为独立于体系, PCI 设计者有时露出 一些倾向 PC 环境. 驱动编写者应当小心处理字节序, 当存取多字节配置寄存器时; 在 PC 上使用的代码可能在其他平台上不工作. Linux 开发者已经处理了这个字节序问题(见 下一节, "存取配置空间"), 但是这个问题必须记住. 如果你曾需要转换数据从主机序到 PCI 序, 或者反之, 你可求助在 <asm/byteorder.h> 中定义的函数, 在第 11 章介绍, 知道 PCI 字节序是小端.

描述所有的配置项超出了本书的范围. 常常地, 随每个设备发布的技术文档描述被支持的 寄存器. 我们感兴趣的是一个驱动如何能知道它的设备以及它如何能存取设备的配置空间.

3 个或者 4 个 PCI 寄存器标识一个设备: verdorID, deviceID, 和 class 是 3 个常常 用到的. 每个 PCI 制造商分配正确的值给这些只读寄存器, 并且驱动可使用它们来查找 设备. 另外, 字段 subsystem verdorID 和 subsystem deviceID 有时被供应商设置来进 一步区分类似的设备.

我们看这些寄存器的细节: vendorID

这个 16-位 寄存器标识一个硬件制造商. 例如, 每个 Intel 设备都标有相同的供 应商号, 0x8086. 这样的号有一个全球的注册, 由 PCI 特别利益体所维护, 并且 供应商必须申请有一个唯一的分配给它们的号.

deviceID

这是另一个 16-位 寄存器, 由供应商选择; 对于这个设备 ID 没有要求官方的注 册. 这个 ID 常常和 供应商 ID 成对出现来组成一个唯一的 32-位 标识符给一个 硬件设备. 我们使用词语"签名"来指代供应商和设备 ID 对. 一个设备驱动常常依 靠签名来标识它的设备; 你可在硬件手册中找到对于目标设备要寻找的值.

class

每个外设都属于一个类. 类寄存器是一个 16-位 值, 它的高 8 位标识"基类"(或 者群). 例如, "ethernet"和"token ring"是 2 个类都属于"network"群, 而 "serial"和"parallel"属于"communication"群. 一些驱动可支持几个类似的设备, 每个都有一个不同的签名但是都属于同样的类; 这些驱动可依赖类寄存器标识它们 的外设, 就象后面所示.

subsystem vendorID subsystem deviceID

这些字段可用来进一步标识一个设备. 如果芯片对于本地总线是一个通用接口芯片, 它常常被用在几个完全不同的地方, 并且驱动必须标识出它在与之通话的实际设备. 子系统标志用作此目的.

使用这些不同的标识符, 一个 PCI 驱动可告知内核它支持什么类型的设备. struct pci_device_id 结构被用来定义一个驱动支持的不同类型 PCI 设备的列表. 这个结构包 含不同的成员:

u32 vendor;

u32 device;

这些指定一个设备的 PCI 供应商和设备 ID. 如果驱动可处理任何供应商或者设备 ID, 值 PCI_ANY_ID 应当用作这些成员上.

u32 subvendor;

u32 subdevice;

这些指定一个设备的 PCI 子系统供应商和子系统设备 ID. 如果驱动可处理任何类 型的子系统 ID, 值 PCI_ANY_ID 应当用作这些成员上.

u32 class;

u32 class_mask;

这 2 个值允许驱动来指定它支持一类 PCI 类设备. 不同的 PCI 设备类( 一个 VAG 控制器是一个例子 )在 PCI 规范里被描述. 如果一个驱动可处理任何子系统 ID, 值 PCI_ANY_ID 应当用作这些字段.

kernel_ulong_t driver_data;

这个值不用来匹配一个设备, 但是用来持有信息, PCI 驱动可用来区分不同的设备, 如果它想这样.

有 2 个帮助宏定义应当被用来初始化一个 struct pci_device_id 结构: PCI_DEVICE(vendor, device)

这个创建一个 struct pci_device_id , 它只匹配特定的供应商和设备 ID. 这个 宏设置这个结构的子供应商和子设备成员为 PCI_ANY_ID.

PCI_DEVICE_CLASS(device_class, device_class_mask)

这个创建一个 struct pci_device_id, 它匹配一个特定的 PCI 类. 一个使用这些宏来定义一个驱动支持的设备类型的例子, 在下面的内核文件中可找到:

drivers/usb/host/ehci-hcd.c:

static const struct pci_device_id pci_ids[] = { {

/* handle any USB 2.0 EHCI controller */

PCI_DEVICE_CLASS(((PCI_CLASS_SERIAL_USB << 8) | 0x20), ~0),

.driver_data = (unsigned long) &ehci_driver,

},

{ /* end: all zeroes */ }

};

drivers/i2c/busses/i2c-i810.c:

static struct pci_device_id i810_ids[] = {

{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) },

{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) },

{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) },

{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) },

{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) },

{ 0, },

};

这些例子创建一个 struct pci_device_id 结构的列表, 列表中最后一个是被设置为全零 的的空结构. 这个 ID 的数组用在 struct pci_driver (下面讲述), 并且它还用来告诉 用户空间这个特定的驱动支持哪个设备.

Linux 内核 标准 PCI 配置寄存器的更多相关文章

  1. linux内核编译环境配置

    linux内核编译环境配置 如果不是编译内核,只需要安装与内核相匹配的kernel-devel开发包即可.即是/lib/modules/`uname -r`/build -> /usr/src/ ...

  2. linux内核编译,配置本机驱动

    1.前言  编译linux内核失败的原因很多时候就是驱动选错,适合自己本机的驱动没编译进去.面对特殊平台(或者有些洁癖者,我就是^_^),要编译精简内核,只要本机驱动,其他都不需要.面对内核里面这么多 ...

  3. linux内核源代码、配置与编译

    内核源代码下载:www.kernel.org Linux内核源代码采用树形结构进行组织,非常合理地把功能相关的文件都放在同一个子目录下,使得程序更具可读性. linux内核代码最好不要在windows ...

  4. Linux 内核USB 接口配置

    USB 接口是自己被捆绑到配置的. 一个 USB 设备可有多个配置并且可能在它们之间转换 以便改变设备的状态. 例如, 一些允许固件被下载到它们的设备包含多个配置来实现这个. 一个配置只能在一个时间点 ...

  5. 云服务器-Ubuntu更新系统版本-更新Linux内核-服务器安全配置优化-防反弹shell

    购入了一台阿里云的ESC服务器,以前都用CentOS感觉Yum不怎么方便,这次选的Ubuntu16.04.7 搭好服务之后做安全检查,发现Ubuntu16.04版本漏洞众多:虽然也没有涉及到16.04 ...

  6. Linux内核配置、编译及Makefile简述

    Hi,大家好!我是CrazyCatJack.最近在学习Linux内核的配置.编译及Makefile文件.今天总结一下学习成果,分享给大家^_^ 1.解压缩打补丁 首先是解压缩你获取到的Linux内核. ...

  7. Linux内核同步

    Linux内核剖析 之 内核同步 主要内容 1.内核请求何时以交错(interleave)的方式执行以及交错程度如何. 2.内核所实现的基本同步机制. 3.通常情况下如何使用内核提供的同步机制. 内核 ...

  8. Linux 内核中的数据结构:基数树(radix tree)

    转自:https://www.cnblogs.com/wuchanming/p/3824990.html   基数(radix)树 Linux基数树(radix tree)是将指针与long整数键值相 ...

  9. [内核同步]浅析Linux内核同步机制

    转自:http://blog.csdn.net/fzubbsc/article/details/37736683?utm_source=tuicool&utm_medium=referral ...

随机推荐

  1. 用Sketch和PaintCode快速得到绘制代码

    http://www.cocoachina.com/ios/20150901/13155.html 作者:codeGlider 授权本站转载. 在我的上一篇文章中 swift10分钟实现炫酷的导航控制 ...

  2. vue cli3 子目录问题

    在使用 vue-cli3 build的时候,使用非子目录需要在 vue.config.js 中添加如下代码: module.exports = { baseUrl: process.env.NODE_ ...

  3. el-table中加载图片问题

    <el-table-column label="头像" width="100"> <template scope="scope&qu ...

  4. python-selenium自动化测试(火狐、谷歌、360浏览器启动)

    一.打开谷歌浏览器 import selenium from selenium import webdriver browser = webdriver.Chrome(executable_path ...

  5. 用select提取List元素自身序号

    var cs = currentCitys.Select((c, i) => new { id = c.CITY_ID, 序号 = (i + 1).ToString(), 城市类型 = c.IS ...

  6. python基础---集合类型(Sets)

    集合类型(Sets) 集合对象是不同的(不可重复)hashable对象的无序集合.常见用法包括:成员关系测试.移除序列中的重复.以及科学计算,例如交集.并集.差分和对称差分.通俗点来说,集合是一个无序 ...

  7. POJ1664 放苹果

    #include <iostream> #include <cstdio> #include <cstring> using namespace std; int ...

  8. php开发微信支付获取用户地址

    http://mp.weixin.qq.com/s/uNpWE_Z5RZ48PDIWkmGBYQ 使用微信获取地址信息是和微信支付一道申请的,微信支付申请通过,就可以使用该功能. 微信商城中,使用微信 ...

  9. day5_python之subprocess模块

    subprocess作用:用来执行系统命令它会开启一个子进程,通过子进程去执行一些命令 读取正确的命令执行结果,如果没有指定把结果输出到哪里,默认打印到屏幕上 #subprocess.Popen(r' ...

  10. BLOB类型对应Long binary,CLOB对应Long characters

    BLOB类型对应Long binary,CLOB对应Long characters