如何写linux pci设备驱动程序-看
Linux下PCI驱动程序的开发
用 3 2位 数 据 总 线 , 但
PI C 规范 中已 经 给 出 了 6 4位 的扩 展 实现 , 而 从
使 PI C 总线能 够更好 地
气 特性 和行 为 规约 ,并 且 详 细定 义 了计 算 机 系统 中的 各 个不 同部件 之 间应该 如何 正确 地进 行交 互 。
无论 是 在基 于 It 芯 片 的 P ne l C机 中 ,或 是 在 基 于
Apa芯 片 的工 作 站 上 ,C 毫 无 疑 问 都是 目前 使 用最 lh PI 广 泛 的 一种 总 线 接 口标 准 。 同 旧式 的 IA 总 线 不 同 , S
信. 电技 术
2 1 年( 3 卷) 1 00 第 9 第 期
来 完 成 同总线 子系统 的交 互 , 图 1 示 。 见 所
以像普通文件一样来看待 :它们可以使用和操作文件
相 同 的 、 准 的 系统 调 用 接 口来 完 成 打 开 、 闭 、 写 标 关 读 和I / O控制 操作 , 驱动程 序 的 主要任 务也 就是 要 实现 而
1 9
由于 使 用 了更 高 的时 钟频 率 ,因此 P I C 总线 能够
关键 词 : iu ; C 驱 动 ; 动架 构 Ln x P I 驱
Ln x 作 系 统 因 为其 高效 、 全 、 动 态 加 载 及 iu 操 安 可
源代码 开放 等 特点 ,深受 设 备驱 动 程序 开 发人 员 的喜
获得 比 IA总线更 好 的 S 整 体性 能 。P I C 总线 的 时 钟 频 率 一 般 在
Linux下PCI设备驱动开发方法及应用实例
种 平台 和 体 系结 构 中 采用 不 同 的方 法 设 计出 各 种 PCI 接 口 卡 , ule 函数从内核中将该驱动程序卸载, 否则返回出错信息。
编 写出 各 种 平台 下 的 接口 卡 驱 动程 序 实 现控 制 系 统高 速 、高 精
1.3 设备驱动程序接口
度、低功耗下通过 PCI 总线对外围 I/O 设备的操作。
1.4 设备驱动程序结构 Linux 的设备驱动程序大致可以分为如下几个 部 分:驱动 程 序 的注 册 与 注销 、设 备 的打 开 与 释放 、设 备 的读 写 操 作、设 备 的
的 内容 , 如 果 缓冲 区 中 的数 据 能 满足 用 户 的要 求 就 返回 相 应 的 控制 操 作 、设备 的 中 断和 轮 询 处理 。驱 动 程序 的 注 册是 通 过 内
struct file_operations dispatch_table; /* 系 统 参 数 dis- patch_table 是 设 备 驱动 程 序 对 应 用 程 序 提 供 诸 如 打 开 , 读 写 , I/ 0 控制等等操作的入口 */
}dev_object ; 3.1 初始化 PCI 设备 在初 始 化 PCI 设 备 时 , 首 先 要 检 查 PCI 总 线 是 否 被 Linux 内 核 支持,主 要 是通 过 内 核函 数 pci_ present()来 实 现 , 该 函 数 用 来 确 定 PCI 总 线 是 否 己 经 被 Linux 内 核 支 持 。 然 后 调 用 pci_ find_device()函数 用 来 查找 系 统 中存 在 的 第一 个 PCI 设 备, 函 数 如下所示: pci_ find_device( PCI_ANY_ID, PCI_ANY_ID,NULL); 该函数检查设备是否插在总线插槽上, 如果在的话则保存
一、如何编写LinuxPCI驱动程序
⼀、如何编写LinuxPCI驱动程序PCI的世界是⼴阔的,充满了(⼤部分令⼈不快的)惊喜。
由于每个CPU体系结构实现不同的芯⽚集,并且PCI设备有不同的需求(“特性”),因此Linux内核中的PCI⽀持并不像⼈们希望的那么简单。
这篇简短的⽂章介绍⽤于PCI设备驱动程序的Linux APIs。
1.1 PCI驱动程序结构PCI驱动程序通过pci_register_driver()在系统中"发现"PCI设备。
事实上,恰恰相反。
当PCI通⽤代码发现⼀个新设备时,具有匹配“描述”的驱动程序将被通知。
详情如下。
pci_register_driver()将设备的⼤部分探测留给PCI层,并⽀持在线插⼊/删除设备[因此在单个驱动程序中⽀持热插拔PCI、CardBus和Express-Card]。
pci_register_driver()调⽤需要传⼊⼀个函数指针表,从⽽指⽰驱动程序的更⾼⼀级结构体。
⼀旦驱动程序知道了⼀个PCI设备并获得了所有权,驱动程序通常需要执⾏以下初始化:启⽤设备请求MMIO / IOP资源设置DMA掩码⼤⼩(⽤于⼀致性DMA和流式DMA)分配和初始化共享控制数据(pci_allocate_coherent())访问设备配置空间(如果需要)注册IRQ处理程序(request_irq())初始化non-PCI(即LAN/SCSI/等芯⽚部分)启⽤DMA /处理引擎当使⽤设备完成时,可能需要卸载模块,驱动程序需要采取以下步骤:禁⽌设备产⽣irq释放IRQ (free_irq())停⽌所有DMA活动释放DMA缓冲区(包括流式DMA和⼀致性DMA)从其他⼦系统注销(例如scsi或netdev)释放MMIO / IOP资源禁⽤该设备下⾯⼏节将介绍这些主题中的⼤部分。
其余部分请查看LDD3或<linux/pci.h>。
如果PCI⼦系统没有配置(没有设置CONFIG_PCI),下⾯描述的⼤多数PCI函数都被定义为内联函数,要么完全空,要么只是返回⼀个适当的错误代码,以避免在驱动程序中出现⼤量ifdefs。
Linux系统下PCI设备驱动程序的研究
配置头。 目前 P I2 C2 规范定义 了 3 . 种配置头格式 , 分别是 0 1 2 , 和 型配 置头 。其 中类型 0 为标准的 P I C 应用设备 , 指除类型 l 和类 型 2 的所 外
有PI C 设备 。类型 ‘ 为 P IP I I C— C 桥设 备 , 于对 P I 用 C 总线扩展 , 将两条
置寄存器组 成 , P I 在 C 配置空间中对 P I 备信息进行描 述 , C设 包括设备
图 1 PI C 总线的体 系结构
P I 外围设备互联 (epeaC m oetn r net的简称 。 C是 P rhr o pnn Ie onc i l tc ) 作 为一种通用 的总线接 口标准 。 它在 目前的计算机系统中得到了2 P I a u 桥 , 为 C— r s 主要用于笔记本 的插 卡式 CB 总线 。这里只对类 型 0的配置头加以说 明, 配置空间见图 2 。 组成 P I C 配置空 问的寄存器 当中包括 厂商代码 、 设备号 、 版本号 、 类 别 号 、 系统 厂商号和子 系统号 , 些寄存 器标 明 P I 子 这 C 设备类 , 启动 时。 系统将根据这些寄存器辨 别出 P I C 设备 , 并为它加载 相应 的驱动程
20 年 第 1 卷 第 2 期 06 6 3
收稿 日 : 0 — 7 1 期 2 6 0—5 0
Lnx系统 下 P I i u C 设备驱动程序 的研究
贺金平 , 刘永祥 , 杨 吕
( 昆明理工大学信息工程与 自动化学院 , 云南昆明 ,5 0 1 6 05 )
摘 要 :C 总线提 供 了许 多优于其他 总线标准( ES PI 如 IA) 新特性 , 目前 已经成 为计
由于一个计算机系统 中可 能有多个主设备 , 墨 l 由l 可知 . 】 这些设备 都直接或间接地连接在 P I C 总线上 , 它们有可能在同一时间都需要 占用 P1 C 总线。这将发生 P I C 总线的竞 争问题 。为 了解决竞争使 用总线 的问 题, P1 在 C 总线上配备 了总线 仲裁器。 在一个 P 1 C 应用 系统 中。 了总 取得 线控制权的设备称为“ 主设备”而被主设备选中以进 行通信 的设备称为 , “ 从设备” “ 标 设备 ” 或 目 。外部设备如果要使用 P I C 总线 , 首先发 出总线
Linux下PCI设备驱动开发详解
一、设备驱动程序概述自Linux在中国发展以来,得到了许多公司的青睐。
在国内的玩家也越来越多了,但目前还是停留在玩的水平上,很少有玩家对Linux的系统进行研究。
因为它的开放,我们可以随时拿来“把玩”。
这也是Linux一个无可比拟的优势,这样我们可以修改后再加入到里面。
但很少有专门的书籍讲到Linux驱动程序的开发,像上海这样的大城市也很少有讲Linux驱动开发的资料,唉,谁让这个是人家的东西呢,我们还是得跟着人家跑。
我现在讲的这些驱动开发的细节,并不特定哪个版本的内核,这只是大体的思路与步骤。
因为大家都知道Linux 2.6.x 与Linux 2.4.x是有不少改动的。
所以,具体的大家可以去参考Linux Device Driver 2.4 和Linux Device Driver 2.6这几本书。
这是我们学习开发驱动必不可少的东西。
好了,下面就开始学习吧。
根据设备的行为,我们可以把设备分为字符设备和块设备,还有网络设备。
字符设备是以字节为单位进行顺序读写,数据缓冲系统对它们的访问不提供缓存。
而块设备则是允许随机访问与读写,每次读写的数据量都是数据块长度的整数倍,并且访问还会经过缓冲区缓存系统才能实现。
与Unix版本不同的是:Linux的内核允许不是数据块长度整数倍的数据量被读取,用官方的语言就是:但这种不同只是纯粹学术方面的东西。
大多数设备驱动程序都要通过文件系统来进行访问的,但网络设备是不同的。
/dev子目录里都是关于设备的特殊文件,但看起来它们与普通的目录没有什么两样。
如下:$ ls -l /dev...brw-rw--- 1 root disk 22, 1 May 5 1998 hdc1crw-rw--- 1 root daemon 6 0 May 5 1998 lp0与普通文件有所不同是开头的“C” 和“B”,即char 和block的意思,即字符设备和块设备。
再后面的“22,1” 和“6,0”即设备的主设备号和次设备号,主设备号表明它是哪一种设备,这与你在Windows里添加硬件时看到的那些是一个意思。
Linux命令行中的硬件信息查看和驱动管理
Linux命令行中的硬件信息查看和驱动管理在Linux命令行中,我们可以通过一些命令来查看硬件信息和管理驱动,这对于系统维护和故障排除非常重要。
本文将介绍几个常用的命令及其用法,帮助您快速获取硬件信息和管理驱动。
1. 查看硬件信息1.1 lshw命令lshw(或者lswhw)是一个用于查看硬件信息的命令,可以列出系统中所有硬件的详细信息,包括处理器、内存、硬盘、网卡等。
使用示例:```$ sudo lshw```运行以上命令后,您将看到完整的硬件信息列表,可以通过滚动查看或者使用管道和grep命令过滤感兴趣的部分。
1.2 lspci命令lspci命令用于列出系统中所有PCI设备的信息,包括显卡、网卡、声卡等。
使用示例:```$ lspci```该命令会输出PCI设备的详细信息,可以通过管道和grep进行过滤。
1.3 lsusb命令lsusb命令用于列出系统中所有USB设备的信息。
使用示例:```$ lsusb```该命令会输出USB设备的详细信息,可以通过管道和grep进行过滤。
2. 管理驱动2.1 modprobe命令modprobe命令用于加载和卸载Linux内核模块,包括驱动程序。
使用示例:```$ sudo modprobe <module_name> // 加载模块$ sudo modprobe -r <module_name> // 卸载模块```其中,`<module_name>`为要加载或卸载的模块名称。
2.2 lsmod命令lsmod命令用于列出当前已加载的内核模块。
使用示例:```$ lsmod```该命令会输出已加载模块的列表,包括模块名称、使用次数等信息。
2.3 rmmod命令rmmod命令用于卸载已加载的内核模块。
使用示例:```$ sudo rmmod <module_name>```其中,`<module_name>`为要卸载的模块名称。
linux设备驱动之pci设备的IO和内存
linux设备驱动之pci设备的I/O和内存------------------------------------------Pci设备的I/O和内存是一个比较复杂的问题.如下的总线结构:在上图的总线结构中,ethernet设备和pci-pci bridge的同类型资源空间必须要是pci bus0的一个子集例如,pci bus 0的I/O端口资源是0x00CC~0x01CC. Ethernet设备的I/O范围的是0x00CC~0x0xE0.那么pci-pci bridge的I/O端口范围就必须要在0x0xE0~0x01CC之间. 同样,SCSI和VIDEO同类型资源必须要是pci_bus1的子集.pci bus1上有一个pci桥,对应的资源也就是它所连桥上的资源.即pci_bus->self.也就是说,下层总线的资源是它上层总线资源的子集。
上层总线资源是下层总线资源的父集。
其实,每个PCI设备的资源地始地址都是由操作系统设置的.在x86上,都由bios设置好了.假若没有bios的时候,我们应该怎么去设置设备的资源起始范围呢?可能在pci枚举完成之后:1:从根总线开始,设置根总线的资源范围是从0开始,到0xFFFF或者0xFFFFFFFF的最大范围. 2:对其它的设备,可往其资源寄存器全部写入1,就可以求得该资源项的类型和长度.3:设备从根总线的资源那里分得对应长度的资源.4:如果设备是pci-pci bridge,则递归配置它.可能有人会有这样迷惑,对应于上图,如果pci-pci bridge的资源大小是N.而SCSI和video资源范围超过了N怎么办呢?我们必须要注意一点,总线的区间是可以自已设定的,而设备资源的区间是在设计的时候就已经确定好了.也就是说,我们可以更改pci device区间的起始地址,但我们不能改变它的大小.因此,出现了上面所说的这种情况.可能是由bios在处理PCI的时候出现了BUG.我们需要调整总线的资源区间.其实对于pci_bus的资源范围就是它的过滤窗口.对于过滤窗口的作用,我们在枚举的时候分析的很清楚了.CPU访问PC过程是这样的(只有一个根总线和pci-pci bridge过滤窗口功能打开的情况): 1:cpu向pci发出一个I/O请求.首先经过根总线.它会判断是否在它的资源范围内.如果在它的范围,它就会丢向总线所在的每一个设备.包括pci bridge. 如果没有在根总线的资源范围,则不会处理这个请求.2:如果pci设备判断该地址属于它的资源范围,则处理后发出应答4:pci bridge接收到这个请求,它会判断I/O地址是否在它的资源范围内.如果在它的范围,它会把它丢到它的下层子线.5:下层总线经过经过相同的处理后,就会找到这个PCI设备了一个PCI设备访问其它PCI设备或者其它外设的过程:1:首先这个PCI发出一个请求,这个请求会在总线上广播2:如果要请求的设备是在同级总线,就会产生应答3:请求的设备不是在同层总线,就会进行pci bridge.pci桥判断该请求不在它的范围内(目的地不是它下层的设备),就会将它丢向上层.4:这样辗转之后,就能找到对应的设备了经过这样的分析过来,相信对pci bridge的过滤窗口有更深的理解了.Linux中使用struct resource的结构来表示I/O端口或者是设备内存。
Linux操作系统下的PCI驱动开发
PI C 驱动 通常可 以看 做字符 设备 的驱动 来设计 。
Ln x iu 的操 作 过程 分 为 两个 步骤 :首 先用 P 1 C 驱 动将 内核 与设备 挂接 起来 :紧接着 通过 应用 程
合 P I 地 总 线 规 范 22 ,并 配 有 可 选 的 串行 C本 .版
E PO E R M接 口 。芯 片 的本 地 总 线 时钟 可 与P 1 C 时 钟 异 步 ,其 内部有 6 可编 程 FF 种 IO,可 以实 现零 等 待 突发传输 及 本地 总线 与P 1 C 总线 的异 步操 作 , 同时支持 主模 式 、从 模式 、D 传 输模 式 ,可广 MA
消费 电子等领 域 的主流操 作 系统 。 本 文 主要 对Ln x iu 环境 下 开 发P I0 4 片 驱 C9 5 芯
2 Ln x 的P I 动 程 序 iu 下 C驱
Ln x iu 将所 有 外 部设 备 看成 是 一类 特 殊文 件 ,
动 的具体方 法 进行描 述 ,并 给 出了如何 将 驱动 程
泛用 于嵌人式 系统 中。
P I0 4 C 9 5 的地 址 资 源是 由其 基 址 寄 存 器来 设
置 的 ,P I0 4 C 9 5 的配 置 空 间 有 六 个 基 址 寄存 器 : B R~A 5 A 0 B R .其 中B R 映射 到 配置 空 间 的基 地 A 0 址 .B R1 映 射 到 Y A 为 O空 间 的基 地 址 ,B R ~ A 2
收 稿 日期 :0 9 1 — 6 2 0 — 2 1
序来 根据 设备 文件 所属 类型 并通 过驱 动 提供 的接
口 函数 来 操 作 设备 。这 使得 P I 动 至少 应 该 包 C驱 含 两部 分 内容 :一 是 P 1 备驱 动 ,二 是具 体 设 C设 备本 身 的驱 动 。
Linux网络设备驱动_PCI网卡
⏹ Linux 网络设备驱动结构Linux的加载和卸载设备的注册初始化和注销设备的打开和释放据包的发送和接收络连接状况数设置和统计数据此驱动所支持的网卡系列初始化网络设备注销网络设备设备挂起函数设备恢复函数打开网络设备关闭网络设备读取包的网卡收发包的状态,统计数据用户的ioctl 命令系统调用硬件处理数据包发送ISR 数据包发送和接收⏹ struct pci_driver如果网络设备(包括wireless )是PCI 规范的,则先是向内核注册该PCI 设备(pci_register_driver),然后由pci_driver 数据结构中的probe 函数指针所指向的侦测函数来初始化该PCI 设备,并且同时注册和初始化该网络设备。
如果网络设备(包括wireless )是PCMCIA 规范的,则先是向内核注册该PCMCIA 设备(register_pccard_driver),然后driver_info_t 数据结构中的attach 函数指针所指向的侦测函数来初始化该PCMCIA 设备,并且同时注册和初始化该网络设备。
1. 申明为PCI 设备:static struct pci_driver tg3_driver = {.name = DRV_MODULE_NAME,//此驱动所支持的网卡系列,vendor_id, device_id.id_table = tg3_pci_tbl,//初始化网络设备的回调函数.probe = tg3_init_one,//注销网络设备的回调函数.remove = __devexit_p(tg3_remove_one),//设备挂起函数.suspend = tg3_suspend,//设备恢复函数.resume = tg3_resume};2. 驱动模块的加载和卸载static int __init tg3_init(void){//先注册成PCI设备,并初始化,如果是其他的ESIA,PCMCIA,用其他函数return pci_module_init(&tg3_driver);}static void __exit tg3_cleanup(void){pci_unregister_driver(&tg3_driver);//注销PCI设备}module_init(tg3_init); //驱动模块的加载module_exit(tg3_cleanup); //驱动模块的卸载3. PCI设备探测函数probe,初始化网络设备主要工作:申请并设置pci资源(内存),申请并设置net_device网络设备结构,IO映射,注册网络设备static int __devinit tg3_init_one(struct pci_dev *pdev, const struct pci_device_id *ent){//初始化设备,使I/O,memory可用,唤醒设备pci_enable_device(pdev);//申请内存空间,配置网卡的I/O,memory资源pci_request_regions(pdev, DRV_MODULE_NAME);pci_set_master(pdev);//设置DMA属性pci_set_dma_mask(pdev, (u64) 0xffffffffffffffff);//网卡 I/O,memory资源的启始地址tg3reg_base = pci_resource_start(pdev, 0);//网卡I/O,memory资源的大小tg3reg_len = pci_resource_len(pdev, 0);//分配并设置网络设备dev = alloc_etherdev(sizeof(*tp));//申明为内核设备模块SET_MODULE_OWNER(dev);//初始化私有结构中的各成员值tp = dev->priv;tp->pdev = pdev;tp->dev = dev;……//锁的初始化spin_lock_init(&tp->lock);//映射I/O,memory地址到私有域中的寄存器结构tp->regs = (unsigned long) ioremap(tg3reg_base, tg3reg_len);dev->irq = pdev->irq;//网络设备回调函数赋值dev->open = tg3_open;dev->stop = tg3_close;dev->get_stats = tg3_get_stats;dev->set_multicast_list = tg3_set_rx_mode;dev->set_mac_aDDRess = tg3_set_mac_addr;dev->do_ioctl = tg3_ioctl;dev->tx_timeout = tg3_tx_timeout;dev->hard_start_xmit= tg3_start_xmit;//网卡的MAC地址赋值dev->addrtg3_get_device_address(tp);//注册网络设备register_netdev(dev);//把网络设备指针地址放入PCI设备中的设备指针中pci_set_drvdata(pdev, dev);}4. 注销网络设备主要工作:注销并释放网络设备,取消地址映射,释放PCI资源static void __devexit tg3_remove_one(struct pci_dev *pdev){struct net_device *dev = pci_get_drvdata(pdev);//注销网络设备unregister_netdev(dev);//取消地址映射iounmap((void *) ((struct tg3 *)(dev->priv))->regs);//释放网络设备kfree(dev);//释放PCI资源pci_release_regions(pdev);//停用PCI设备pci_disable_device(pdev);//PCI设备中的设备指针赋空pci_set_drvdata(pdev, NULL);}5. 网络设备挂起主要工作:停用网卡的中断寄存器,停止网卡收发包,停用网卡某些硬件,设置电源状态static int tg3_suspend(struct pci_dev *pdev, u32 state){//停用网卡的中断寄存器tg3_disable_ints(tp);//停止网卡收发包netif_device_detach(dev);//停止网卡某些硬件,fireware的一些功能tg3_halt(tp);//设置网卡的电源状态tg3_set_power_state(tp, state);}6. 网络设备恢复主要工作:恢复网卡电源,允许收发包,初始化收发包的缓冲区,初始化网卡硬件,打开网卡中断寄存器static int tg3_resume(struct pci_dev *pdev){//恢复网卡电源tg3_set_power_state(tp, 0);//允许网卡收发包netif_device_attach(dev);//初始化收发包的缓冲区tg3_init_rings(tp);//初始化网卡硬件tg3_init_hw(tp);//打开网卡中断寄存器tg3_enable_ints(tp);}struct net_device1. 打开网络设备主要工作:分配中断及注册中断处理函数,初始化硬件及收发缓冲区,初始化定时器及注册超时函数,允许网卡开始传送包static int tg3_open(struct net_device *dev){//分配一个中断request_irq(dev->irq, tg3_interrupt, SA_SHIRQ, dev->name, dev);/* int request_irq(unsigned int irq,void (*handler)(int irq, void *dev_id, struct pt_regs *regs),unsigned long irqflags,const char * devname,void *dev_id);irq是要申请的硬件中断号。
linux中pcie设备初始化流程
linux中pcie设备初始化流程PCIe(Peripheral Component Interconnect Express)是一种高速串行总线接口,用于连接计算机主板和外部设备。
在Linux系统中,PCIe设备的初始化是一个重要的过程,它确保设备能够正常工作并与系统进行通信。
本文将介绍Linux中PCIe设备初始化的流程。
1. 设备检测与识别在Linux系统启动时,内核会进行设备检测与识别的过程。
对于PCIe设备,内核会扫描PCIe总线,识别连接在总线上的设备。
这个过程是通过读取PCIe设备的配置空间来完成的。
配置空间是一块特殊的内存区域,包含了设备的各种信息,如设备ID、厂商ID、设备类别等。
2. 分配资源一旦设备被识别,内核会为其分配必要的资源,如内存空间、中断线等。
这些资源的分配是通过解析设备的配置空间来完成的。
内核会根据设备的需求和系统的可用资源进行分配,以确保设备能够正常工作。
3. 驱动加载设备的驱动程序是用来控制和管理设备的软件模块。
在Linux系统中,驱动程序是以内核模块的形式存在的。
一旦设备被识别并分配了资源,内核会加载与之对应的驱动程序。
驱动程序会与设备进行通信,配置设备的寄存器、中断等,并提供相应的接口供用户空间程序使用。
4. 设备初始化设备初始化是指对设备进行一系列的配置和初始化操作,以使其能够正常工作。
设备初始化的具体过程是由设备的驱动程序来完成的。
驱动程序会根据设备的特性和需求,对设备进行相应的配置和初始化。
这包括设置设备的工作模式、参数、中断处理等。
5. 设备注册设备注册是将设备与系统进行关联的过程。
在Linux系统中,设备注册是通过设备模型来完成的。
设备模型是一种用于描述和管理设备的框架,它提供了一套标准的接口和方法,用于设备的注册、管理和访问。
设备注册的过程包括将设备添加到设备模型中,并分配设备号等。
6. 设备启动设备启动是指设备开始正常工作的过程。
在Linux系统中,设备启动是由设备的驱动程序来完成的。
基于Linux系统的PCI设备DMA驱动开发
基于Linux系统的PCI设备DMA驱动开发范哲超,吴永亮(内蒙古机电职业技术学院,内蒙古呼和浩特010070)摘要:目前PCI总线已经成为计算机系统中应用最为广泛最为通用的总线标准,Linux的内核能较好地支持PCI总线。
文章探讨了在Linux系统下开发PCI主设备DMA驱动程序的基本过程。
关键词:Linux;DMA;驱动开发中图分类号:TP311文献标识码:A文章编号:1673-1131(2014)04-0117-02Linux驱动程序实现DMA操作,涉及内存I/O端口操作、中断操作、内存映射以及DMA映射过程等内容。
DMA传输过程步骤如下:(1)申请I/O资源、中断资源、内存资源,初始化。
(2)分配DMA缓冲区,设置DMA寄存器。
(3)硬件将数据写入到DMA缓冲区,写入完毕产生PCI 中断。
(4)应答中断、并且唤醒进程读取数据。
I/O端口是驱动程序与设备之间的通信方式,驱动程序需要通过I/O端口对DMA寄存器设置,因此内核允许驱动程序声明自己需要操作的I/O端口。
在申请I/O端口之前调用pci_ resource_start获得I/O空间基地址,调用request_region(unsigned long firstaddress,unsigned long length,const char*name)在Linux系统模块中使用中断前要先申请中断通道(或者中断请求IRQ),使用完毕后释放中断,DevEx.irq是设备中断号,my_interrupt是中断服务例程,SA_SHIRQ中断管理选项表示可以在设备间共享中断,DRV_NAM获得中断设备名,PCI 设备结构体。
request_irq(DevEx.irq,my_interrupt,SA_SHIRQ,DRV_ NAME,&DevEx)free_irq(DevEx.irq,&DevEx)如果request_irq登记成功,在/proc/interrupts文件中可以看到所请求的中断。
PCI驱动开发手册
Linux2.6内核PCI驱动程序开发一,PCI相关数据结构说明1.1struct pci_driver这个数据结构在文件/linux/pci.h里,这是Linux内核版本2.4之后为新型的PCI设备驱动程序所添加的,其中最主要的是用于识别设备的id_table结构,以及用于检测设备的函数probe( )和卸载设备的函数remove( )。
struct pci_driver {struct list_head node;char *name;const struct pci_device_id *id_table;int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);void (*remove) (struct pci_dev *dev);int (*save_state) (struct pci_dev *dev, u32 state);int (*suspend)(struct pci_dev *dev, u32 state);int (*resume) (struct pci_dev *dev);int (*enable_wake) (struct pci_dev *dev, u32 state, int enable);};为创建一个正确的struct pci_driver 结构, 只有4个字段需要被初始化:name,id_table,probe和remove。
其中id_table初始化可以用到宏PCI_DEVICE(VENDOR_ID,DEVICE_ID),VENDOR_ID 和DEVICE_ID分别为设备和厂商编号,由板卡生产厂家指定。
Static const struct pci_device_id mypci[] ={{PCI_DEVICE(VENDOR_ID,DEVICE_ID)},{}};1.2pci_dev这个数据结构也在文件include/linux/pci.h里,它详细描述了一个PCI设备几乎所有的硬件信息,包括厂商ID、设备ID、各种资源等。
linuxpci枚举流程
linuxpci枚举流程1.PCI配置空间每个PCI设备都有一个256字节的配置空间,其中包含设备的标识符、寄存器等信息。
Linux内核通过读取这些PCI配置空间来识别和配置设备。
2.驱动加载当Linux内核启动时,它会自动加载与PCI设备相关的驱动程序模块。
驱动程序模块是内核扩展的一部分,用于控制和管理特定类型的PCI设备。
3.PCI总线扫描当驱动程序模块加载成功后,Linux内核将开始扫描主机上的PCI总线。
PCI总线是一个硬件接口,用于将CPU与PCI设备连接起来。
4.根总线控制器PCI总线上至少有一个根总线控制器,用于控制所有PCI设备的访问和数据传输。
Linux内核通过根总线控制器扫描整个PCI总线。
5.PCI总线配置空间扫描内核通过读取PCI总线上每个设备的配置空间来识别和配置设备。
它使用PCI配置空间中的设备ID、物理地址、中断号等信息来确定设备的类型和特性。
6.分配资源一旦设备被识别,内核将为其分配资源,例如物理内存、中断请求等。
分配资源是确保每个设备可以正确运行的重要步骤。
7.驱动绑定一旦设备被识别和配置,内核将为其加载正确的驱动程序。
驱动程序将与设备绑定,以便允许操作系统与设备进行交互。
8.驱动初始化加载驱动程序后,该驱动程序将进行初始化。
初始化过程可能包括设备注册、中断处理程序的安装和设备功能的启用等。
9.设备操作一旦设备被成功初始化,操作系统将能够通过驱动程序与设备进行交互。
这包括读取和写入设备寄存器、发送和接收数据等。
10.设备卸载当不再需要一些PCI设备时,可以卸载其驱动程序。
这将释放设备占用的资源,并将设备设置为未配置状态。
总的来说,Linux PCI枚举流程包括PCI配置空间、驱动加载、PCI总线扫描、根总线控制器、配置空间扫描、资源分配、驱动绑定、驱动初始化、设备操作和设备卸载等步骤。
这个流程确保了PCI设备被正确识别、配置和管理,并能够与操作系统进行正常的数据交互。
linux下pci的数据读写流程
linux下pci的数据读写流程Linux下PCI的数据读写流程一、引言PCI(Peripheral Component Interconnect,外设互联)是一种计算机总线标准,用于连接计算机的主板与外部硬件设备。
在Linux系统下,PCI设备的数据读写是通过访问设备的寄存器来实现的。
本文将介绍Linux下PCI的数据读写流程。
二、PCI设备的识别和配置在Linux系统启动时,会进行PCI总线的枚举和设备的识别与配置。
Linux内核会扫描PCI总线上的设备,并为每个设备分配唯一的设备标识符,称为PCI设备号。
系统将会为每个PCI设备分配资源,并将设备驱动程序与设备进行匹配。
三、设备驱动程序的加载与初始化在设备识别和配置完成后,系统会加载与该设备匹配的驱动程序。
设备驱动程序是对设备进行管理和控制的软件模块。
当驱动程序被加载时,会进行初始化操作,包括分配内存空间、注册中断处理程序等。
四、设备寄存器的映射设备驱动程序在初始化过程中需要访问设备的寄存器来进行数据的读写。
为了实现对设备寄存器的访问,驱动程序需要将设备寄存器映射到内核空间。
在Linux中,可以通过ioremap函数将设备寄存器的物理地址映射到内核虚拟地址空间。
五、数据读写操作一旦设备寄存器映射完成,驱动程序就可以通过读写内核虚拟地址来实现对设备寄存器的读写操作。
通常,设备寄存器是以字节为单位进行读写的。
驱动程序可以使用readb、readw、readl函数来读取设备寄存器的值,使用writeb、writew、writel函数来向设备寄存器写入数据。
六、同步与互斥在进行数据读写操作时,为了保证数据的正确性和一致性,需要进行同步与互斥操作。
同步操作可以通过在读写操作前后使用memory barrier指令来实现,确保读写操作的顺序性。
互斥操作可以通过自旋锁或信号量机制来实现,防止多个进程同时对设备进行读写操作。
七、数据传输与中断处理在进行数据读写操作的同时,设备可能会触发中断。
Linux下PCI设备驱动开发方法及应用实例
Linux下PCI设备驱动开发方法及应用实例
高翊宇;马林华
【期刊名称】《微计算机信息》
【年(卷),期】2007(023)010
【摘要】Linux是一种日趋成熟完善的操作系统.越来越多的软硬件厂商开始使用Linux平台来开发自己的产品,因而对基于该平台的设备驱动程序的需求也愈来愈多.同时PCI总线作为一个具有兼容性强、平台无关性等特点从的计算机总线标准.日前得到了广泛的应用.本文通过实例讨论了如何在Linux下实现PCI设备驱动程序的开发.
【总页数】3页(P310-312)
【作者】高翊宇;马林华
【作者单位】710038,陕西西安,空军工程大学工程学院;710038,陕西西安,空军工程大学工程学院
【正文语种】中文
【中图分类】TP316
【相关文献】
1.Linux下无配置信息PCI设备的驱动开发 [J], 陈宁;虢莉敏;王新梅
2.基于Linux系统的PCI设备DMA驱动开发 [J], 范哲超;吴永亮
3.Linux下PCI设备流式DMA驱动开发 [J], 朱红星;苗克坚
4.Linux设备驱动开发方法及应用实例 [J], 王小龙;何克忠;房小翠;丁冬花
5.Linux字符设备驱动开发方法与应用实例 [J], 简杰鸿;刘朝辉
因版权原因,仅展示原文概要,查看原文内容请购买。
Linux下基于PCI接口的DSP驱动程序设计
引言 三 、L nx驱动 程序 开 发 iu 数 字信 号处 理器 (S ) DP 在通 讯 、 音 图像处 理 、 据加 密等 各 语 数 L nx下对 TS 2C 46加密 卡进行 驱动 程序 开发 ,要完 成 iu M 306 1 方 面得 到越 来越 广泛 的 应用 。T 60 系列 DP芯 片 内嵌 P I I 00 C S C 接 的工作 主 要包 括 :对 P I C 设备 的查 找 、初始 化 、卸载 ,对字 符 设 口,支 持主/ 从模 式 的读 写, 以 3 Mz 的工作 频率 和 3 地址 / 备 的数 据读 写和控 制 , 中断处 理等 。 3t t 2位 ( )P I - C 设备 初始 化 数据 总 线进 行数 据传 输 , 论上 最 高可 以支持 12B t/ 的数 据 理 3 My e s 传输 , 速度 上远 远超 过 DP常用 的 H I M BP总线 , 全 可 以 在 S P 、 cS 完 在 Ln x . iu2 6内核 中,使 用 p id ie c—r vr结 构体来 定义 P I C 驱 动 。 设 备 查 找 时 通 过 i _ a l 结 构 体 中 的 的 V N E _ D、 dt be ED R I 满足 传 输实 时性 的要 求 。
规 方法 比 ,显著 地提 高 了传 输速度 ,具有较 高的应 用价 值 。
二 、T S 2 C 4 6的 P பைடு நூலகம் 口 M 30 6 1 CI
I 来 区别 不 同的设 备 , D 对于 T S 2 C 4 6 片 , E D R I M 30 6 1 芯 V NE _D 和 DV C. D分别 为 O l4 、0 a0 。 E IE I x 0 c x l6 pc d ie i rv r结构 体 中的 p o e rb 0函数 向内核提 供 了对硬 件进 行 探测 并 初始 化 的接 口 。p oe r b 0函数 完成 的功 能有 : 1 读取 D P 加 密 卡 B s O 2 空 间 基 地 址 和 中 断 号 ,通 过 . S ae 一
[转载]应用程序中pci配置空间读写
[转载]应⽤程序中pci配置空间读写PCI原⽂地址:应⽤程序中pci配置空间读写作者:云⽉应⽤程序中pci配置空间读写~~~~~~~~~~~~~~~~~~~~~~~1. 概述主要讲述在linux操作系统中应⽤程序如何读写pci配置空间。
2. 基本原理对于pci设备,由cpu通过⼀个统⼀的⼊⼝地址向pci总桥发出命令,再由相应的pci桥间接地完成具体的读写操作。
对于X86结构,pci总线的设计者在I/O地址空间保留了8个字节⽤于这个操作:0xcf8 - 0xcff。
这8个字节分成两个32位的寄存器,0xcf8是地址寄存器,0xcfc是数据寄存器。
cpu先往地址寄存器中写⼊⽬标地址,然后通过数据寄存器读写数据,写⼊地址寄存器中的⽬标地址是⼀种包括总线号、设备号、功能号以及配置寄存器地址的综合地址。
具体如下:bit31 1bit30-bit24 保留bit23-bit16 总线号bit15-bit11 设备号bit10-bit8 功能号bit7-bit0 寄存器地址,最低两位为0设备的这些信息都可以通过lspci命令获取。
3. ioport读写权限由于要通过操作ioport,所以先要获取ioport的读写权限。
能获取读写权限的函数有两个ioperm()和iopl()。
由于pci的⼝地址⽐较⾼,要⽤iopl(3)获取权限。
4. 读程序#define PCI_CFG_DATA 0xcfc#define PCI_CFG_CTRL 0xcf8void pci_read_config_byte(unsigned char bus, unsigned char dev, unsigned char offset, unsigned char *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset & ~0x3)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA) >> ((offset & 3) * 8);}void pci_read_config_word(unsigned char bus, unsigned char dev, unsigned char offset, unsigned short *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset & ~0x3)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA) >> ((offset & 3) * 8);}void pci_read_config_dword(unsigned char bus, unsigned char dev, unsigned char offset, unsigned int *val){unsigned char fun = 0;outl((0x80000000 | ((bus)<<16) |((dev)<<11) | ((fun)<<8) | (offset)), PCI_CFG_CTRL);*val = inl(PCI_CFG_DATA);}很明显就是先向控制寄存器写⼊综合地址,格式前⾯已经提到,对⽐⼀下是完全⼀样的。
linux中编译驱动的方法
linux中编译驱动的方法
在Linux中编译驱动的方法通常涉及以下步骤:
1. 编写驱动代码:首先,您需要编写适用于Linux内核的驱动代码。
这通常是在内核源代码树之外编写的。
驱动代码通常以C语言编写,并遵循内核编程约定。
2. 获取内核源代码:为了编译驱动,您需要获得Linux内核的源代码。
您可以从Linux官方网站或镜像站点下载内核源代码。
3. 配置内核:在编译驱动之前,您需要配置内核以包含您的驱动。
这可以通过运行`make menuconfig`命令来完成。
在配置菜单中,您可以选择要编译的驱动以及相关的内核选项。
4. 编译驱动:一旦您配置了内核并选择了要编译的驱动,您可以使用`make`命令来编译驱动。
这将在内核源代码目录下生成可执行文件或模块文件。
5. 加载和测试驱动:一旦驱动被编译,您可以将其加载到Linux 内核中以进行测试。
您可以使用`insmod`命令将模块加载到内核,然后使用`dmesg`命令检查内核日志以查看驱动是否正确加载。
这些是基本的步骤,但具体的步骤可能会因您的环境和需求而有所不同。
在编译和加载驱动时,请确保您具有适当的权限和知识,因为这可能需要管理员权限,并且错误的操作可能会导致系统不稳定或损坏。
Linux系统PCI设备驱动程序的实现方法
增 加 内 核 的 大 小 . 动 内 核 的 源 文 件 。如 果 新 添 加 一 个 硬 件 ,就 要 重 改 新 编 译 内 核 。 如 果 去 掉 一 个 硬 件 ,那 么 这 个 硬 件 的 驱 动 程 序 已 经 编 译 到 内核就 会 造 成资 源 的 浪费 。 另 一 种 方 法 是 将 驱 动 程 序 编 译 成 可 安 装 模 块 ( d l) 通 过 使 用 moue , is o nm d命 令 动 态 加 载 到 内 核 中 . 之 成 为 系 统 内核 的 一 部 分 。 不 使 使 当
较为 容 易 。
oeain p rt s( o
s mc du e o e ; t t mo l wn r
s ie sz
—
t(ra )(t tfe , hr ,s e t oft ) ed s l mc i c a i —,l _ ; z f t(w t)(t tfe ,e ntca ,s e t oft ) r e smc l i i os h r i —,1f ; z _
P I提 供 了 ~ 组 完 整 的 总 线 接 口规 范 . 不 依 附 于 具 体 处 理 器 C 且 的 局 部 总 线 。 P I在 C U 和 原 来 的 系 统 总 线 之 间 插 入 的 一 级 总 线 。 C P
由一 个 桥 接 电 路 实 现 对 这一 层 的管 理 , 实 现 上 下 之 间 的 数 据 传 送 。 并
Src l t t Fi u e
_
P I Pr h rlC m o e tIt cn et ( 围 设 备 互 联 ) 的 简 作 。 Icu el u /sh 中 的 Fl_ prtn C 是 ei ea o p nn ne o nc p r 外 nld / nx f. i i o eai s数 据 结 构 定 义 如 下 : e o 称 .C P I总 线 作 为 一 个 具 有 兼 容 性 强 、 台 无 关 性 等 特 点 的 计 算 机 总 平 线 标 准 . 目 前 计 算 机 系 统 中 应 用 最 为 广 泛 的 总 线 标 准 。 Ln x内 核 是 iu 较 好 地 支 持 了 P I总 线 ,使 得 在 Ln x环 境 下 驱 动 程 序 的 编 写 变 得 C iu
linux查看显卡
linux查看显卡
Linux系统下,可以使用一些命令和工具来查看显卡信息。
1. lspci命令:用于列举PCI设备的信息,包括显卡。
```shell
lspci | grep -i vga
```
这个命令会列出计算机上安装的显卡信息,包括制造商、型号和供应商信息。
2. lshw命令:用于显示硬件的信息,包括显卡。
```shell
sudo lshw -C display
```
这个命令会显示所有可用的显示设备的详细信息,包括制造商、型号、驱动程序等。
3. nvidia-smi命令:适用于NVIDIA显卡,用于查看显卡的相
关信息。
```shell
nvidia-smi
```
这个命令会显示NVIDIA显卡的状态、驱动程序版本、显存
使用情况等信息。
4. glxinfo命令:用于查看OpenGL相关的信息。
```shell
glxinfo | grep "OpenGL version"
```
这个命令会显示OpenGL版本信息,可以用来确认显卡是否支持OpenGL。
5. inxi命令:适用于Debian和Ubuntu系统,用于查看系统信息,包括显卡。
```shell
inxi -G
```
这个命令会显示显卡的详细信息,包括制造商、型号和驱动程序等。
以上是一些常用的命令和工具来查看Linux系统下的显卡信息。
不同的Linux发行版可能会有所不同,可以根据实际情况选择
合适的命令来查看显卡信息。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
何写linux pci设备驱动程序original file:/Documentation/pci.txt translated by terracePCI总线应用领域及其广泛并且令人惊奇。
不同的pci设备有不同的需求以及不同的问题。
因此,在linux内核中pci层支持就非常重要啦。
本文档就是想为驱动程序设计开发人员解决pci处理中的各种问题。
Pci设备驱动程序的结构现在有两种风格的的pci驱动程序结构:新风格的驱动(即让pci层来做大量设备探测工作并且支持热插拔功能)和旧风格的驱动(即由驱动程序自己探测设备)。
除非你有很好的理由,否则就不要用旧风格写驱动程序。
当驱动程序找到所驱动的设备后,将执行以下步骤:①.启用设备②.访问设备配置空间③.检测设备资源(如基地址和中断号)④.分配设备资源与设备通讯下文将论述以上大部分步骤,其余部分请参考,它有不错的注释。
如果没有配置pci 子系统(即CONFIG_PCI 没有置位),以下介绍的大部分函数都被定义为内联函数,它们要么是空的,要么返回对应的错误代码以避免在驱动中出现过多的条件宏ifdefs。
1.新风格的驱动程序新风格的驱动程序只是在初始化时调用pci_register_driver,调用时使用一个指向struct pci_driver 的结构指针。
该指针包含以下几个分量:name 驱动程序名称id_table 指向一个与驱动程序相关的设备ID表的指针。
大多数驱动程序应当用MODULE_DEVICE_TABLE(pci,…)将该设备ID表导出。
在调用prob( )时设成NULL 以让系统检测到所有的pci设备。
probe 指向设备检测函数prob( ) 的指针。
该函数将在pci设备ID与设备ID表匹配且还没有被其它驱动程序处理时(一般在对已存在的设备执行pci_register_driver或以后又有新设备插入时)被调用。
调用时传入一个指向struct pci_driver结构的指针和与设备匹配的设备ID表做参数。
若成功(驱动程序检测到pci设备)则返回0,否则返回一个负的错误代码。
这个函数总是在上下文之间调用的,因此可以进入睡眠状态的。
remove 指向一个设备卸载函数remove( )的指针。
该函数在pci设备被卸载时(如在注销设备驱动程序或者手动拔出该设备)被调用。
同probe一样,该函数也是可以睡眠的。
save_state 在设备被暂停前所保存的设备状态。
suspend 将设备转入低功耗状态而暂停。
sesume 将一个暂停的设备(低功耗状态中)唤醒启动。
enable_wake 允许设备产生唤醒事件以从低功耗状态中恢复。
(请参考Documentation/power/pci.txt 文件中关于pci电源管理以及相关函数的说明)ID表是一个struct pci_device_id 类型的数组,该数组以该类型中每一项都为NULL时结束。
structpci_device_id中有以下几个分量:vendor,device 设备对应的厂商ID号和设备ID号(或者是PCI_ANY_ID)subvendor,subdevice 设备对应的子厂商ID号和子设备ID号(或者是PCI_ANY_ID)class,class_mask 设备对应的类,类掩码表示在比较中采用设备类(class)中的那些位。
driver_data 设备的私有数据。
当一个设备驱动程序存在,只需要调用pci_unregister_driver就可由pci层调用remove( )函数自动将所驱动的所有设备卸载掉。
请将初始和清理函数前加上以下适当的宏(该宏定义在中):__init 初始化标记,置于驱动程序中初始化函数前。
__exit 结束标记,在非模块化的驱动程序中将被忽略。
__devinit 设备初始化标记。
若编译内核时选择了CONFIG_HOTPLUG选项,则等同于__init。
__devexit 同__exit一样。
一般技巧:在module_init( )/module_exit( )函数前应标上__init/__exit标记;结构体struct pci_driver不要标上以上任何标记;ID表数组应当标上__devinitdata标记;probe( )和remove( )函数应当标上__devinit/exit标记;如果你确信不是一个支持热插拔的驱动程序,就可只用__init/exit __initdata/exitdata;一个指向标记了__devexit的函数的指针,一定要由__devexit_p(function_name)来产生。
它会产生对应的函数名,若没有标记了__devexit的函数,则产生NULL。
2.旧风格的pci设备驱动程序旧风格的pci设备驱动程序不会用到pci_register_driver()去探测设备,而需要手动(由驱动程序)使用以下结构去探测设备:根据厂商ID和设备ID探测设备:struct pci_dev *dev =NULL;while(dev = pci_find_device(VENDOR_ID,DEVICE_ID,dev))configure_device(dev);根据类ID探测设备:pci_find_class(CLASS_ID,dev);根据厂商ID和设备ID以及子系统厂商ID和设备ID探测设备:pci_find_subsys(VENDOR_ID,DEVICE_ID,SUBSYS_VENDOR_ID, SUBSYS_DEVICE_ID, dev);你可以使用常量PCI_ANY_ID作为通配符取代VENDOR_ID、DEVICE_ID,这样你就可以搜索都所有的设备。
如果你要以更复杂的条件探测设备,那就得自己遍历所有已知的pci设备:struct pci_dev *dev;pci_for_each_dev(dev) {... do anything you want with dev ...}为了向上兼容,也可以用pci_for_each_dev_reverse(dev)去遍历设备表。
3.启用设备在你对找到的设备进行任何操作之前,你需要调用pci_enable_device( )来启用设备的I/O和内存资源,分配不足的资源,如果需要,还要唤醒一个处于暂停状态的设备。
需要注意的是,这个操作可能会失败。
如果你想设定设备工作在总线主设备模式,调用pci_set_master() 会把PCI_COMMAND寄存器中的总线主设备允许位置1,并且还会修改延迟计数器中的值。
若你想使用pci内存写无效事务,调用pci_set_swi() ,它会把PCI_COMMAND寄存器中的Mem_Wr_Inval位置1,还要确认缓存行长度寄存器(CACHE_LINE_REGISTER)的设置是否正确。
要注意检查pci_set_swi()的返回值,并不是所有设备都支持pci内存写无效的。
4.如何访问pci设备配置空间必须使用pci_(read|write)_config_(byte|word|dword) 去访问pci设备(由struct pci_dev *表示)的配置空间。
所有以上的函数在成功时返回0,失败时返回错误代码。
大多数驱动程序期望在访问有效的pci设备时是不会失败的。
若你要访问的是pci配置头标准空间,就可以用符号常量来表示寄存器地址以及位设置,这些符号常量定义在中。
若要访问pci扩展空间能力寄存器,只需要对每个特定的能力调用pci_find_capability()就可以找到相应的寄存器块。
5.寻址和中断内存和端口基地址以及中断号不要从pci配置空间中读出而要使用pci_dev结构体中相应的值,因为它们可能被映射到内核中。
关于如何访问设备内存,请参阅Documentation/IO-mapping.txt 文件。
还需要调用request_region()函数和request_mem_region()分别申请IO地址和设备内存地址范围以确保没有其它驱动使用该设备。
所有的中断处理程序要使用共享中断号,还可以使用参数devid将中断号IRQs映射为设备数据结构。
6.其它有用的函数pci_find_slot() 根据设备所在的总线号和插槽号,探测相应的pci设备pci_set_power_state() 设置pci电源管理状态pci_find_capability() 在设备的能力表中找出指定的能力pci_module_init() 内联函数,确保驱动程序正确的初始化以及错误处理pci_resource_start() 返回pci地址范围的总线起始地址pci_resource_end() 返回pci地址范围的总线终止地址pci_resource_len() 返回pci地址范围的长度,以字节为单位pci_set_drvdata() 为pci_dev设置私有数据指针pci_get_drvdata() 从pci_dev结构中得到其私有数据指针pci_set_mwi() 启用设备内存写无效事务pci_clear_mwi() 禁用设备内存写无效事务7.其它提示当向用户显示pci插槽时(如驱动程序想告诉用户它所找到的设备卡),可用pci_dev->slot_name。
总是使用一个指向struct pci_dev的指针来引用某个pci设备。
所有的pci层接口函数都使用该指针。
不要使用总线/插槽号/功能号,它们有特别的用途――有多个主总线的系统说起来是很复杂的。
8.已弃用的函数以下的接口函数只是为了向上兼容而暂时保留,请不要在你的新式驱动程序中使用它们:pcibios_present() 以前在使用,现在你不必测试pci子系统是否存在。
若不存在pci子系统,pci 设备表是空的,并且所有的探测设备函数都将返回NULL。
pcibios_(read|write)_* 现已被相应的pci_(read|write)_*取代pcibios_find_* 现已被相应的pci_find_*取代。