为了被正确注册到内核, 所有的 PCI 驱动必须创建的主结构是 struct pci_driver 结构. 这个结构包含许多函数回调和变量, 来描述 PCI 驱动给 PCI 核心. 这里是这个结构的一 个 PCI 驱动需要知道的成员:

const char *name;

驱动的名子. 它必须是唯一的, 在内核中所有 PCI 驱动里面. 通常被设置为和驱 动模块名子相同的名子. 它显示在 sysfs 中在 /sys/bus/pci/drivers/ 下, 当驱 动在内核时.

const struct pci_device_id *id_table;

指向 struct pci_device_id 表的指针, 在本章后面描述它.

int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);

指向 PCI 驱动中 probe 函数的指针. 这个函数被 PCI 核心调用, 当它有一个它 认为这个驱动想控制的 struct pci_dev 时. 一个指向 struct pci_device_id 的 指针, PCI 核心用来做这个决定的, 也被传递给这个函数. 如果这个 PCI 驱动需 要这个传递给它的 struct pci_dev, 它应当正确初始化这个设备并且返回 0. 如 果这个驱动不想拥有这个设备, 或者产生一个错误, 它应当返回一个负的错误值. 关于这个函数的更多的细节在本章后面.

void (*remove) (struct pci_dev *dev);

指向 PCI 核心在 struct pci_dev 被从系统中去除时调用的函数的指针, 或者当 PCI 驱动被从内核中卸载时. 关于这个函数的更多的细节在本章后面.

int (*suspend) (struct pci_dev *dev, u32 state);

当 struct pci_dev 被挂起时 PCI 核心调用的函数的指针. 挂起状态在 state 变 量里传递. 这个函数是可选的; 一个驱动不必提供它.

int (*resume) (struct pci_dev *dev);

当 pci_dev 被恢复时 PCI 核心调用的函数的指针. 它一直被调用在调用挂起之后. 这个函数时可选的; 一个驱动不必提供它.

总之, 为创建一个正确的 struct pci_driver 结构, 只有 4 个字段需要被初始化: static struct pci_driver pci_driver = {

.name = "pci_skel",

.id_table = ids,

.probe = probe,

.remove = remove,

};

为注册 struct pci_driver 到 PCI 核心, 用一个带有指向 struct pci_driver 的指针 调用 pci_register_driver. 传统上这在 PCI 驱动的模块初始化代码中完成:

static int   init pci_skel_init(void)

{

return pci_register_driver(&pci_driver);

}

注意, pci_register_driver 函数要么返回一个负的错误码, 要么是 0 当所有都成功注 册. 它不返回绑定到驱动上的设备号,或者一个错误码如果没有设备被绑定到驱动上. 这 是自 2.6 发布之前的内核的一个改变, 并且是因为下列的情况而来的:

  • 在支持 PCI 热插拔的系统上, 或者 CardBus 系统, 一个 PCI 设备可在任何时间 点出现或消失. 如果驱动可在设备出现前被加载是有帮助的, 可以减少用来初始化 一个设备的时间.
  • 2.6 内核允许新 PCI ID 被动态地分配给一个驱动, 在它被加载之后. 这是通过被 创建在 sysfs 中的所有 PCI 驱动目录的文件 new_id 来完成的. 如果一个新设备 在被使用而内核对它还不知道时, 这是非常有用的. 一个用户可写 PCI ID 值到 new_id 文件, 并且接着驱动绑定到新设备. 如果一个驱动不被允许加载直到一个 设备在系统中出现, 这个接口将不能工作.

当 PCI 驱动被卸载, struct pci_drive 需要从内核中注销. 这通过调用 pci_unregister_driver 完成. 当发生这个调用, 任何当前绑定到这个驱动的 PCI 设备 都被去除, 并且这个 PCI 驱动的 remove 函数在 pci_unregister_driver 函数返回之前 被调用.

static void   exit pci_skel_exit(void)

{

pci_unregister_driver(&pci_driver);

}

linux 注册一个 PCI 驱动的更多相关文章

  1. Linux 内核注册一个 USB 驱动

    所有 USB 驱动必须创建的主要结构是 struct usb_driver. 这个结构必须被 USB 驱动填 充并且包含多个函数回调和变量, 来向 USB 核心代码描述 USB 驱动: struct ...

  2. Linux 内核 标准 PCI 配置寄存器

    一些 PCI 配置寄存器是要求的, 一些是可选的. 每个 PCI 设备必须包含有意 义的值在被要求的寄存器中, 而可选寄存器的内容依赖外设的实际功能. 可选的字段不被 使用, 除非被要求的字段的内容指 ...

  3. Linux的PCI驱动分析

    1. 关键数据结构 PCI设备上有三种地址空间:PCI的I/O空间.PCI的存储空间和PCI的配置空间.CPU可以访问PCI设备上的所有地址空间,其中I/O空间和存储空间提供给设备驱动程序使用,而配置 ...

  4. 【原创】Linux PCI驱动框架分析(二)

    背 景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本 ...

  5. 【原创】Linux PCI驱动框架分析(三)

    背 景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本 ...

  6. Linux pci驱动源码

    #include <linux/kernel.h>#include <linux/errno.h>#include <linux/module.h>#include ...

  7. 【原创】Linux PCI驱动框架分析(一)

    背景 Read the fucking source code! --By 鲁迅 A picture is worth a thousand words. --By 高尔基 说明: Kernel版本: ...

  8. linux一个例子驱动

    我们介绍的驱动称为 short (Simple Hardware Operations and Raw Tests). 所有它做 的是读和写几个 8-位 端口, 从你在加载时选择的开始. 缺省地, 它 ...

  9. 芯灵思SinlinxA33开发板 Linux平台总线设备驱动

    1.什么是platform(平台)总线? 相对于USB.PCI.I2C.SPI等物理总线来说,platform总线是一种虚拟.抽象出来的总线,实际中并不存在这样的总线. 那为什么需要platform总 ...

随机推荐

  1. SDUT-2498_AOE网上的关键路径

    数据结构实验之图论十一:AOE网上的关键路径 Time Limit: 2000 ms Memory Limit: 65536 KiB Problem Description 一个无环的有向图称为无环图 ...

  2. docker 与host互传文件

    docker 的cp命令可以从容器往外复制,也可以从本机复制的容器. docker cp 文件路径 容器id:/容器目录 docker help cp Usage:    docker cp [OPT ...

  3. 【C++】关于map的遍历 删除

    int main(int argc, char* argv[]) { map<string, string> mapData; mapData["a"] = " ...

  4. 微信开发之web开发者工具

    web开发者工具. 有任何疑问或建议请私信我,或者在评论区大家一起探讨. 概述 为帮助开发者更方便.更安全地开发和调试基于微信的网页,我们推出了 web 开发者工具.它是一个桌面应用,通过模拟微信客户 ...

  5. 2019-8-31-dotnet-控制台-Hangfire-后台定时任务

    title author date CreateTime categories dotnet 控制台 Hangfire 后台定时任务 lindexi 2019-08-31 16:55:58 +0800 ...

  6. python 数据的读取

  7. @bzoj - 2395@ [Balkan 2011]Timeismoney

    目录 @description@ @solution@ @accepted code@ @details@ @description@ 有n个城市(编号从0..n-1),m条公路(双向的),从中选择n ...

  8. mysql 忘记root密码的处理办法

    参考地址: https://blog.csdn.net/vv19910825/article/details/82979563 1.修改配置文件mysql\bin\my.ini 在文本  [mysql ...

  9. Python深入:02浅拷贝深拷贝

    对象赋值实际上是简单的对象引用.也就是说当你创建一个对象,然后把它赋给另一个变量的时候,Python并没有拷贝这个对象,而只是拷贝了这个对象的引用. 假设想创建一对小夫妻的通用档案,名为person. ...

  10. 动画删除cell出问题

    删除UITableView行的代理时出了问题 解决办法 先remove数据,再执行 [_mTableView deleteRowsAtIndexPaths:[NSArray arrayWithObje ...