Linux源码阅读笔记20-PCI设备驱动详解

news2024/11/16 7:40:08

PCI基础

  1. PCI总线为高性能局部总线,主要解决外部设备之间以及外部设备与主机之间高速数据传输。在数字图形、图像等处理,以及告诉实时数据采集与处理等队数据传输速率要求高的应用中,采用PCI总线进行数据传输。
  2. PCI规范能够实现32位并行数据传输,工作频率为33MHz或66MHz,最大吞吐率为266MB/s。PCI-E是目前PCI系列最具代表性的一种,与并行PCI总线区别在于它采用串行传输数据模式,最大支持32个串行连接。每个传输方向上吞吐率为250MB/s,方向上总传输速率达8GB/s。
  3. 串行通讯比并行通讯速度快,成本低。比如PCIe64位总线,133MHz,吞吐率1GB/s,内存于台式机和服务器,比PCI宽,但是能插入PCI卡。
  4. PCI总线特点
    • 具有隐含的中央仲裁系统。
    • 具有与处理器和存储器自诩痛完全并行操作的能力。
    • 提供地址和数据的奇偶校验,完全的多总线主控能力。

PCI数据结构

  1. 连接CPU和PCI系统对应的数据结构类型pci_host_bridge

  1. 描述PCI总线对应的数据结构类型pci_bus

  1. 用于指向PCI读写操作函数集的结构体类型pci_ops

  1. 专门用于描述总线的物理插槽的结构体类型pci_slot

  1. PCI设备结构体类型pci_dev

  1. PCI驱动程序结构体类型pci_driver

  1. PCI卡标识结构类型pci_driver_i

PCI驱动实例

/* PCI设备驱动编程,必须包括两个核心重要的头文件 */
#include <linux/module.h>
#include <linux/pci.h>

/* 用户自定义结构体类型,作用于中断服务函数里面 */
struct pci_Card 
{
   resource_size_t io;
   long range, flags;
   void __iomem *ioaddr;
   int irq;
};


static struct pci_device_id ids[] = 
{
    { 
        PCI_DEVICE(PCI_VENDOR_ID_INTEL,
        0x100f)
    },

    { 
        PCI_DEVICE(PCI_VENDOR_ID_INTEL, 
        PCI_DEVICE_ID_INTEL_80332_0) 
    },

    {0,}
};


MODULE_DEVICE_TABLE(pci, ids);


void skel_get_configs(struct pci_dev *dev) 
{

    uint8_t revisionId;
    uint16_t vendorId, deviceId;
    uint32_t classId;

    pci_read_config_word(dev, PCI_VENDOR_ID, &vendorId);
    printk("vendorID = %x", vendorId);

    pci_read_config_word(dev, PCI_DEVICE_ID, &deviceId);
    printk("deviceID = %x", deviceId);

    pci_read_config_byte(dev, PCI_REVISION_ID, &revisionId);
    printk("revisionID = %x",revisionId);

    pci_read_config_dword(dev, PCI_CLASS_REVISION, &classId);
    printk("classID = %x",classId);
}


static irqreturn_t pci_Mcard_interrupt(int irq, void *dev_id) 
{
   struct pci_Card *pci_Mcard = (struct pci_Card *)dev_id;

   printk("irq = %d, pci_Mcard_irq = %d\n", irq, pci_Mcard->irq);
   return IRQ_HANDLED;
}


static int probe(struct pci_dev *dev, const struct pci_device_id *id) 
{
    int retval = 0;
    struct pci_Card *pci_Mcard;
    printk("probe func\n"); 
    
    /* 设备使能 */
    if(pci_enable_device(dev)) {
        printk (KERN_ERR "IO Error.\n");
        return -EIO;
    }

    pci_Mcard = kmalloc(sizeof(struct pci_Card),GFP_KERNEL);
    if(!pci_Mcard) {
        printk("In %s,kmalloc err!",__func__);
        return -ENOMEM;
    }

    /* 设备中断号 */
    pci_Mcard->irq = dev->irq;
    if(pci_Mcard->irq < 0) {
        printk("IRQ is %d, it's invalid!\n",pci_Mcard->irq);
        goto out_pci_Mcard;
    }

    /*获取io内存相关信息*/
    pci_Mcard->io = pci_resource_start(dev, 0);
    pci_Mcard->range = pci_resource_end(dev, 0) - pci_Mcard->io + 1;
    pci_Mcard->flags = pci_resource_flags(dev,0);
    printk("start %llx %lx %lx\n",pci_Mcard->io, pci_Mcard->range, pci_Mcard->flags);
    printk("PCI base addr 0 is io%s.\n",(pci_Mcard->flags & IORESOURCE_MEM)? "mem":"port");

    /*防止地址访问冲突,所以这里先申请*/
    retval = pci_request_regions(dev,"pci_module");
    if(retval) {
        printk("PCI request regions err!\n");
        goto out_pci_Mcard;
    }

    /*再进行映射*/
    pci_Mcard->ioaddr = pci_ioremap_bar(dev, 0);
    if(!pci_Mcard->ioaddr) {
      printk("ioremap err!\n");
      retval = -ENOMEM;
      goto out_regions;
    }

    /*申请中断IRQ并设定中断服务子函数*/
    retval = request_irq(pci_Mcard->irq, pci_Mcard_interrupt, IRQF_SHARED, "pci_module", pci_Mcard);
    if(retval) {
      printk (KERN_ERR "Can't get assigned IRQ %d.\n",pci_Mcard->irq);
      goto out_iounmap;
    }

    pci_set_drvdata(dev, pci_Mcard);
    skel_get_configs(dev);
    return 0;

out_iounmap:
    iounmap(pci_Mcard->ioaddr);
out_regions:
    pci_release_regions(dev);
out_pci_Mcard:
    kfree(pci_Mcard);
    return retval;
}

/* 移除PCI设备 */
static void remove(struct pci_dev *dev) 
{
   struct pci_Card *pci_Mcard = pci_get_drvdata(dev);
   free_irq (pci_Mcard->irq, pci_Mcard);
   iounmap(pci_Mcard->ioaddr);
   pci_release_regions(dev);
   kfree(pci_Mcard);
   pci_disable_device(dev);
   printk("remove pci device ok\n");
}

/* 结构体成员变量填充 */
static struct pci_driver pci_driver = 
{
    .name = "pci_module",
    .id_table = ids,
    .probe = probe,
    .remove = remove,
};

/* 模块入口函数 */
static int __init pci_module_init(void) 
{
    printk("PCI module entry function\n");

    return pci_register_driver(&pci_driver);
}

/* 模块退出函数 */
static void __exit pci_module_exit(void) 
{
    printk("PCI module exit function.\n");

    // PCI驱动被卸载时,需要调用pci_unregister_driver
    pci_unregister_driver(&pci_driver);
}

MODULE_LICENSE("GPL");

module_init(pci_module_init);
module_exit(pci_module_exit);



本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1993657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

我在高职教STM32——I2C通信入门(3)

大家好,我是老耿,高职青椒一枚,一直从事单片机、嵌入式、物联网等课程的教学。对于高职的学生层次,同行应该都懂的,老师在课堂上教学几乎是没什么成就感的。正是如此,才有了借助CSDN平台寻求认同感和成就感的想法。在这里,我准备陆续把自己花了很多心思设计的教学课件分…

STM32G070KBT6的RTC HAL库使用

*配置问题 首先使能时钟源&#xff0c;这里在时钟配置中选择LSI&#xff0c;为什么后面会说&#xff0c;然后使能Calender结构体&#xff0c;保证可以对RTC的年月日时分秒等进行写入和读取&#xff1b;alarmA和alarmB是闹钟&#xff0c;这里不用就Disable&#xff1b; Tam…

突破•指针六

听说这是目录哦 数组和指针笔试题解析&#x1fae7;一维数组1&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355;&#x1f355; 字符数组1&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;&#x1f354;2&#…

高并发下的分布式缓存 | Read-Through缓存模式

缓存系列文章链接如下&#xff1a; 高并发下的分布式缓存 | 缓存系统稳定性设计 高并发下的分布式缓存 | 设计和实现LRU缓存 高并发下的分布式缓存 | 设计和实现LFU缓存 高并发下的分布式缓存 | Cache-Aside缓存模式 Read-Through 模式的缓存操作 Read-Through模式的一个关键…

Scanner类、String类和StringBuffer类的相关使用

一、Scanner: 主要用于键盘录入的 构造方法&#xff1a; Scanner(InputStream source) 构造一个新的 Scanner &#xff0c;产生从指定输入流扫描的值。 1、next()和nextLine()区别&#xff1a; String line sc.next(); // 不会接收特殊字符&#xff0c;比如空格回…

高效的编程学习方法和技巧

编程小白如何成为大神&#xff1f;大学新生的最佳入门攻略 编程已成为当代大学生的必备技能&#xff0c;但面对众多编程语言和学习资源&#xff0c;新生们常常感到迷茫。如何选择适合自己的编程语言&#xff1f;如何制定有效的学习计划&#xff1f;如何避免常见的学习陷阱&…

基于单片机的智能空气净化系统

【摘 要】 设计了一种基于单片机的智能空气净化系统。通过传感器实时采集空气中 PM2.5 、甲醛等有害健康物质的浓度&#xff0c;将各项数据显示到液晶显示屏&#xff0c;当浓度超过设置的警戒值时&#xff0c;控制蜂鸣器发出警报。根据浓度大小控制空气净化器电机转速&#xf…

04.C++类和对象(中)

1.类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不重…

Selenium + Python 自动化测试04(操作方法1)

上一篇我们讲述了webdriver 元素定位方法。我们对如何定位元素有了一个基本的认识。接着我们详细讲述对元素常见的一些基本操作方法&#xff0c;以便我们可以做很多功能操作的测试。这一篇侧重最基本的操作方面。 1、send_keys 方法 此方法类似于模拟键盘输入。还是以下面网站…

React项目中引用视频播出插件 easyPlayer.js 部署趟坑日志

目录 前文记录背景问题摸排&#xff1a;第一天前端打包失败&#xff1f;远程打包逻辑与本地打包逻辑不一致&#xff1f;远程入口页被篡改&#xff1f;再次排查本地webpack打包逻辑 问题摸排&#xff1a;第二天确认本地与远程打包一致排查远程nginx代理定位问题 index.html 的所…

AI10-PaddleDetection2.7安装测试

1、下载PaddleDetect-release-2.7开源项目 https://github.com/PaddlePaddle/PaddleDetection https://github.com/PaddlePaddle/PaddleDetection/releases PaddleDetection: PaddleDetection的目的是为工业界和学术界提供丰富、易用的目标检测模型 2、安装 环境要求 * Paddl…

[Qt][QWidget]详细讲解

目录 1.概述2.QWidget核心属性1.简介2.核心属性概览 3.QWidget常用属性1.enabled2.geometry1.是什么&#xff1f;2.Window Frame的影响3.相关API4.注意 3.windowTitile4.windowIcon5.windowOpacity6.cursor8.font9.toolTip10.focusPolicy11.styleSheet 1.概述 Widget是Qt中的核…

2024新版ChatGPT系统源码SparkAi系统,支持GPT4.0全模型,AI绘画,AI换脸+自定义智能体GPTs应用+AI视频+文档分析

一、文章序言 人工智能技术正迅猛发展&#xff0c;AI语言模型、AI绘画和AI视频已经在许多领域得到广泛应用。这些技术不仅在科技创新方面表现出色&#xff0c;还在艺术创作、内容生成和商业应用中展现出巨大的潜力。 SparkAi创作系统是一款基于ChatGPT和Midjourney开发的智能…

【Linux】系列入门摘抄笔记-4-查看文件内容命令cat/more/less/tail

cat 查看文件内容 cat [选项] [参数] cat 命令可以用来显示文本文件的内容&#xff08;类似于 DOS 下的 type 命令&#xff09;&#xff0c;也可以把几个文件内容附加到另一个文件中&#xff0c;即连接合并文件。 tac 反向显示文件内容 tac [选项] [参数] 将文件全部内容从…

玩转Docker:Lsky pro图床+私有化部署大模型(Ollama+Openwebui)

最近搞了一个测试服务器&#xff0c;捣鼓了下一键搭建dnmp集成环境&#xff0c;然后还搭建了一个Lysk pro图床服务&#xff0c;后面又看到了开源大模型&#xff0c;也试着搭建了一下&#xff0c;中间出了一点小插曲。不过也算搭建成功了。做一个小结汇总。 1.前情回顾 DNMP:基…

探索list与iterator的区别及yield的用法

1 问题 探索list与iterator的区别探索yield的用法 2 方法 通过网上学习后了解到 List返回的类型是list&#xff0c;list只会查询一级缓存。list()中返回的List中每个对象都是原本的对象。查询的时候没遍历一个对象会产生一条sql&#xff1b;而iterator这个迭代器返回的类型是it…

Apache HTTPD 换行漏洞(CVE-2017-15715)

Vulhub - Docker-Compose file for vulnerability environment Apache HTTPD是一款HTTP服务器&#xff0c;它可以通过mod_php来运行PHP网页。其2.4.0~2.4.29版本中存在一个解析漏洞&#xff0c;在解析PHP时&#xff0c;1.php\x0A将被按照PHP后缀进行解析&#xff0c;导致绕过一…

sns.distplot()用法

seaborn.distplot(aNone, binsNone, histTrue,kdeTrue, rugFalse, fitNone, hist_kwsNone,kde_kwsNone, rug_kwsNone, fit_kwsNone,colorNone, verticalFalse, norm_histFalse,axlabelNone, labelNone, axNone, xNone)参数解释 a: 序列series、一维数组或者list&#xff0c;上…

经典街机游戏:拳皇97 for Mac(KOF97) 支持M1 中文移植版

游戏玩家一定会上手的游戏就是拳皇系列了吧&#xff0c;其中最经典的就是拳皇97&#xff0c;小编为大家提供的就是拳皇97mac版&#xff0c;熟悉的场景&#xff0c;熟悉的操作&#xff0c;原来Mac上打街机也可以这么爽&#xff0c;亲测拳皇97 for Mac 支持M1 Mac&#xff0c;喜欢…

ASP.NET Core Web API 使用Autofac框架

总目录 前言 主要介绍如何在ASP.NET Core Web API 使用Autofac框架 一、创建ASP.NET Core Web API 我们先创建一个ASP.NET Core Web API项目&#xff0c;然后准备相关的代码 1 假如我们需要实现登录的功能&#xff0c;现在我们创建相关的服务接口 public interface ILoginSe…