Linux下PCI设备驱动开发详解(一)

Linux下PCI设备驱动开发详解(一)

PCI总线是目前应用最广泛的计算机总线标准,而且是一种兼容性最强,功能最全的计算机总线。
而linux作为一种开源的操作系统,同时也为PCI总线与各种新型设备互联成为可能。尤其被现在的异构计算GPU/FPGA、软硬结合新的方向广泛运用。

一、PCI设备和驱动概述

应用程序位于用户空间,驱动程序位于内核空间。linux系统规定,用户空间不可以直接调用内核函数,所以必须经过系统调用,应用程序才可以调用驱动程序的函数。另外应用程序通过系统调用去调用驱动程序的函数,还有一个前提就是驱动程序必须留有接口,这里的接口就是ops函数的操作集合。

          在这里插入图片描述

  驱动最终通过与文件系统相关的系统调用或C库函数(本质也是基于系统调用)被访问,而设备驱动的结构也是为了迎合应用程序,提供给应用程序的SDK API。

sys:linux设备驱动模型中的总线、驱动和设备都可以在sysfs文件系统中找到相应的节点。当内核检测到系统中出现新的设备后,内核会在sysfs文件系统中为设备生成一项新的记录。

sysfs是一个虚拟的文件系统,它可以产生一个包括所有系统硬件的层级视图,与提供进程和状态的proc文件系统十分类似。可以让用户空间存取,向用户空间导出内核数据结构以及它的属性

在linux内核中,设备和驱动是分开注册的,注册1个设备的时候,并不需要驱动已经存在,而1个驱动被注册的时候,也不需要对应的设备被注册。设备和驱动各自涌入内核,而每个设备和驱动涌入内核的时候,都会寻找另外一半_。而正是bus_type的match()成员函数将两者绑定在一起。

简单来说,设备和驱动就是红尘的男女,而bus_type的match()则是牵引红线的月老,它可以识别什么设备与什么驱动,是配对的。一旦成功,xxx_driver的probe就被执行。

二、PCI总线描述

          
在这里插入图片描述

PCI是CPU和外围设备通信的高速传输总线。普通PCI总线带宽一般为132MB/s或者264MB/s。

PCI总线体系结构是一种层次式的体系结构,PCI桥设备占据重要的地位,它将父总线与子总线连接在一起,从而使整个系统看起来像一颗倒置的树形结构。

三、PCI配置空间

PCI有3种地址空间:PCI配置空间、PCI/IO空间、PCI内存地址空间。

1. PCI配置空间

          在这里插入图片描述

deviceID和vendorID寄存器:由pcisig分配,只读,vendorID代表pci设备的厂商,deviceID代表厂商的具体设备;
status:设备状态字;
command:设备状态字;
base address register:决定pci/pcie设备空间映射到系统具体位置的寄存器,IO和memory映射两种;

2. PCI/IO空间(PIO)

pio端口的编址是独立于系统的地址空间,其实是一段地址区域,所有外设的地址都映射到这段区域中。不同外设的IO端口不同,访问IO端口需要特殊的IO指令,OUT/IN,out用于write操作,in用于read操作;
IO地址空间有限;

3. PCI内存地址空间(MMIO)

io内存就是把寄存器的地址空间直接映射到系统的地址空间,系统地址空间保留一段内存用于MMIO的映射。

上述的方案只适用于外设和内存进行小数据量的传输时,假如进行大数据量的传输,PIO以字节为单位的传输不用说了,MMIO虽然进行了内存映射,但是范围相对于大量的数据,不值得一提,所以即使采用了MMIO仍然满足不了需要,会让吧CPU大部分时间处理繁琐的映射,极大浪费CPU资源。在这种情况下,引入了DMA,由DMA控制器控制,完成后中断通知CPU,极大解放了CPU。后面的文章会接收DMA。

四、PCI设备驱动组成

PCI本质上就是一种总线,具体的PCI设备可以是字符设备、网络设备、USB等,所以PCI设备驱动应该包括两个部分:

  1. PCI通用驱动
  2. 根据实际需要的设备驱动
    根据需求的设备驱动是最终目的,PCI驱动只是手段帮助设备驱动达到最终目的而已。换句话,PCI设备驱动不仅实现PCI驱动还要包括具体需求的设备驱动。
              
    在这里插入图片描述
    PCI驱动注册与注销:
int pci_register_driver(struct pci_driver *driver);
int pci_unregister_driver(struct pci_driver *driver);

PCI_driver结构体:

struct pci_driver {
    struct list_head node;
    char *name; /* 驱动程序的名称 */
    struct module *owner;
    /* 指向设备驱动程序感兴趣的设备ID的一个列表,包括:
     * 厂商ID、设备ID、子厂商ID、子设备ID、类别、类别掩码、私有数据
     */
    const struct pci_device_id *id_table;
    /* 指向一个函数对于每一个id_table中的项匹配的且未被其他驱动程序处理的设备,
     * 在执行pci_register_driver时候调用此函数或者如果是以后插入的一个新设备的话,只要满足上述条件也会调* 用此函数
     */
    int (*probe) (struct pci_dev *dev, const struct pci_device_id *id);
    /* 指向一个函数当驱动函数程序卸载或者被该驱动程序管理的设备被卸下的时候,调用此函数
     */
    int (*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);
};

五、未完待续

Linux下PCI设备驱动开发详解(二),将介绍具体的函数实现。

  • 32
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
Linux 设备驱动开发详解 4.0》是由马上飞鱼科技有限公司的紫金福老师所著的一本经典的书籍,该书是目前国内关于 Linux 设备驱动开发方面的最好的教材之一。该书主要介绍了 Linux 设备驱动的基本知识和开发方法,对于想学习 Linux 设备驱动开发或者对于嵌入式系统开发有兴趣的工程师是非常有价值的一本入门书籍。 该书从 Linux 内核的基本架构入手,介绍了 Linux 设备驱动的编写和调试方法。该书结合了实战案例,分步骤地开展了驱动开发的实践,详细分析了 Linux 的 I/O 模型、中断和 DMA、并发性问题等。同时,还详细介绍了外部总线的驱动,如 SPI、I2C、PCI、USB 等,并给出了完整的 demo 程序和相应的测试方法。 另外,该书还介绍了常见的设备驱动,如字符设备驱动、块设备驱动和网络设备驱动的编写方法,并且还介绍了常见设备驱动的硬件架构和硬件接口,使得读者能够更加深入地理解设备驱动的本质。 除此之外,《Linux 设备驱动开发详解 4.0》还介绍了如何通过编写 Linux 独立模块来实现设备驱动,如何使用内核 API 接口和系统调用等技术,并且还引导读者了解一些不常见的驱动开发技术,如用户空间驱动程序和内核模块参数。 总之,《Linux 设备驱动开发详解 4.0》是一本非常实用的 Linux 设备驱动开发指南,它涵盖了 Linux 设备驱动开发的方方面面,包括理论知识和实际操作,对于想深入了解 Linux 设备驱动开发的工程师来说是不可多得的一本书。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北京不北

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值