如何编写Linux PCIe设备驱动器 之二

news2024/9/17 8:33:36

如何编写Linux PCIe设备驱动器 之二

  • 功能(capability)集
    • 功能(capability)APIs
    • 通过pci_bus_read_config完成功能存取
      • 功能APIs参数pos常量值
      • PCI功能结构
  • PCI功能ID
    • MSI功能
    • 电源功率管理功能

功能(capability)集

功能(capability)APIs

int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val);
int pcie_capability_read_dword(struct pci_dev *dev, int pos, u32 *val);

int pcie_capability_write_word(struct pci_dev *dev, int pos, u16 val);
int pcie_capability_write_dword(struct pci_dev *dev, int pos, u32 val);

int pcie_capability_clear_and_set_word(struct pci_dev *dev, int pos, u16 clear, u16 set);
int pcie_capability_clear_and_set_dword(struct pci_dev *dev, int pos, u32 clear, u32 set);

读PCIe读请求大小代码

/**
 * pcie_get_readrq - get PCI Express read request size
 * @dev: PCI device to query
 *
 * Returns maximum memory read request in bytes or appropriate error value.
 */
int pcie_get_readrq(struct pci_dev *dev)
{
        u16 ctl;

        pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &ctl);

        return 128 << ((ctl & PCI_EXP_DEVCTL_READRQ) >> 12);
}

通过pci_bus_read_config完成功能存取


int pci_read_config_word(const struct pci_dev *dev, int where, u16 *val)
{
        if (pci_dev_is_disconnected(dev)) {
                PCI_SET_ERROR_RESPONSE(val);
                return PCIBIOS_DEVICE_NOT_FOUND;
        }
        return pci_bus_read_config_word(dev->bus, dev->devfn, where, val);
}

static inline int pci_pcie_cap(struct pci_dev *dev)
{
        return dev->pcie_cap;
}
int pcie_capability_read_word(struct pci_dev *dev, int pos, u16 *val)
{
        int ret;

        *val = 0;
        if (pos & 1)
                return PCIBIOS_BAD_REGISTER_NUMBER;

        if (pcie_capability_reg_implemented(dev, pos)) {
                ret = pci_read_config_word(dev, pci_pcie_cap(dev) + pos, val);
                if (ret)
                        *val = 0;
                return ret;
        }
        if (pci_is_pcie(dev) && pcie_downstream_port(dev) &&
            pos == PCI_EXP_SLTSTA)
                *val = PCI_EXP_SLTSTA_PDS;

        return 0;
}

功能APIs参数pos常量值

#define PCI_EXP_FLAGS           0x02    /* Capabilities register */
#define PCI_EXP_DEVCAP          0x04    /* Device capabilities */
#define PCI_EXP_DEVCTL          0x08    /* Device Control */
#define PCI_EXP_DEVSTA          0x0a    /* Device Status */
#define PCI_EXP_LNKCAP          0x0c    /* Link Capabilities */
#define PCI_EXP_LNKCTL          0x10    /* Link Control */
#define PCI_EXP_LNKSTA          0x12    /* Link Status */
#define PCI_EXP_SLTCAP          0x14    /* Slot Capabilities */
#define PCI_EXP_SLTCTL          0x18    /* Slot Control */
#define PCI_EXP_SLTSTA          0x1a    /* Slot Status */
#define PCI_EXP_RTCTL           0x1c    /* Root Control */
#define PCI_EXP_RTCAP           0x1e    /* Root Capabilities */
#define PCI_EXP_RTSTA           0x20    /* Root Status */

下列的代码段读取PCIe的功能数据, 并存储在存储器中。

static int pci_save_pcie_state(struct pci_dev *dev)
{
        int i = 0;
        struct pci_cap_saved_state *save_state;
        u16 *cap;

        if (!pci_is_pcie(dev))
                return 0;

        save_state = pci_find_saved_cap(dev, PCI_CAP_ID_EXP);
        if (!save_state) {
                pci_err(dev, "buffer not found in %s\n", __func__);
                return -ENOMEM;
        }

        cap = (u16 *)&save_state->cap.data[0];
        pcie_capability_read_word(dev, PCI_EXP_DEVCTL, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_LNKCTL, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_SLTCTL, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_RTCTL,  &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_DEVCTL2, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_LNKCTL2, &cap[i++]);
        pcie_capability_read_word(dev, PCI_EXP_SLTCTL2, &cap[i++]);

        return 0;
}

PCI功能结构

在这里插入图片描述

PCI功能ID

在PCI功能结构的PCIe功能ID具有下列的值

/* Capability lists */

#define PCI_CAP_LIST_ID         0       /* Capability ID */
#define  PCI_CAP_ID_PM          0x01    /* Power Management */
#define  PCI_CAP_ID_AGP         0x02    /* Accelerated Graphics Port */
#define  PCI_CAP_ID_VPD         0x03    /* Vital Product Data */
#define  PCI_CAP_ID_SLOTID      0x04    /* Slot Identification */
#define  PCI_CAP_ID_MSI         0x05    /* Message Signalled Interrupts */
#define  PCI_CAP_ID_CHSWP       0x06    /* CompactPCI HotSwap */
#define  PCI_CAP_ID_PCIX        0x07    /* PCI-X */
#define  PCI_CAP_ID_HT          0x08    /* HyperTransport */
#define  PCI_CAP_ID_VNDR        0x09    /* Vendor-Specific */
#define  PCI_CAP_ID_DBG         0x0A    /* Debug port */
#define  PCI_CAP_ID_CCRC        0x0B    /* CompactPCI Central Resource Control */
#define  PCI_CAP_ID_SHPC        0x0C    /* PCI Standard Hot-Plug Controller */
#define  PCI_CAP_ID_SSVID       0x0D    /* Bridge subsystem vendor/device ID */
#define  PCI_CAP_ID_AGP3        0x0E    /* AGP Target PCI-PCI bridge */
#define  PCI_CAP_ID_SECDEV      0x0F    /* Secure Device */
#define  PCI_CAP_ID_EXP         0x10    /* PCI Express */
#define  PCI_CAP_ID_MSIX        0x11    /* MSI-X */
#define  PCI_CAP_ID_SATA        0x12    /* SATA Data/Index Conf. */
#define  PCI_CAP_ID_AF          0x13    /* PCI Advanced Features */
#define  PCI_CAP_ID_EA          0x14    /* PCI Enhanced Allocation */

MSI功能

功能ID为PCI_CAP_ID_MS (0x05)。

PCIe设备需要 MSI中断支持。所有能够生成中断的 PCIe设备功能必须支持 MSI。 MSI 机制通过执行内存写入事务来传递中断。 MSI和MSI-X是边沿触发中断机制。

某些 PCI 设备及其驱动程序依赖于 INTx 类型电平触发中断行为。为了利用 MSI功能,以及边沿触发中断语义,这些设备及其驱动程序可能需要重新设计。

实现 MSI 的传统端点需要支持 MSI 功能结构的 32 位或 64 位消息地址版本。实现 MSI 的 PCIe端点需要支持 MSI 功能结构的 64 位消息地址版本。

MSI事务的请求者必须将事务描述符的 No Snoop 和 Relaxed Ordering 属性设置为 0b。如果启用了 IDO 属性的使用,则允许 MSI事务的请求者设置基于 ID 的排序(IDO)属性。

电源功率管理功能

功能ID为 PCI_CAP_ID_PM (0x01)。

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

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

相关文章

C++(一)----C++基础

1.C的发展史 C语言诞生后&#xff0c;很快普及使用&#xff0c;但是随着编程规模增大且越来越复杂&#xff0c;并且需要高度的抽象和建模时&#xff0c;C语言的诸多短板便表现了出来&#xff0c;为了解决软件危机&#xff0c;上世纪八十年代&#xff0c;计算机界提出了oop&…

拓扑排序-广度优先遍历思路

本质&#xff1a; 【广度优先遍历 】【贪心算法】应用于【有向图】的专有名词 应用场景&#xff1a;任务调度&#xff0c;课程安排 作用&#xff1a; 得到一个不唯一的【拓扑序】检测【有向图】是否有环&#xff0c;使用数据【并查集】 使用&#xff1a;先找度为0的前驱节点…

Linux运维排查常见故障_在tmp目录下有大量包含picture_ 的临时文件,每天晚上2 30需要对一天前的文件进行

echo“”>>/etc/security/limits.conf echo“*softnproc65535″>>/etc/security/limits.conf echo“*hardnproc65535″>>/etc/security/limits.conf echo“*softnofile65535″>>/etc/security/limits.conf echo“*hardnofile65535″>>/etc/secur…

【自动驾驶】控制算法(八)横向控制Ⅲ | 代码与模型

写在前面&#xff1a; &#x1f31f; 欢迎光临 清流君 的博客小天地&#xff0c;这里是我分享技术与心得的温馨角落。&#x1f4dd; 个人主页&#xff1a;清流君_CSDN博客&#xff0c;期待与您一同探索 移动机器人 领域的无限可能。 &#x1f50d; 本文系 清流君 原创之作&…

以太网--TCP/IP协议(一)

概述 以太网是局域网的一种&#xff0c;其他的比如还有令牌环、FDDI。和局域网对应的就是广域网&#xff0c;如Internet&#xff0c;城域网等。 从网络层次看&#xff0c;局域网协议主要偏重于低层&#xff08;业内一般把物理层、数据链路层归为低层&#xff09;。以太网协议…

单片机毕业设计基于单片机的智能门禁系统的设计与实现

文章目录 前言资料获取设计介绍功能介绍程序代码部分参考 设计清单具体实现截图参考文献设计获取 前言 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师&#xff0c;一名热衷于单片机技术探索与分享的博主、专注于 精通51/STM32/MSP…

vue动态统计图的绘画

效果图&#xff1a; 实现&#xff1a; 一、导入依赖 import echarts from echarts 二、vue的代码实现 1.在main.js导入文件 // 引入 echarts 插件 import echarts from echarts // 配置成全局组件 Vue.prototype.$echarts echarts2.代码实现 <template><!--为echa…

韩国火烧车影响出现,浙江出现限制电车进入地下车库,车主难受了

韩国电动汽车起火&#xff0c;烧毁140辆汽车&#xff0c;还导致大楼损坏以及居民受伤的后果&#xff0c;如今在中国市场也产生了影响&#xff0c;《华商报》旗下的《大风新闻》报道指&#xff0c;浙江多地的饭店、大厦禁止电动汽车进入地下车库&#xff0c;这下子电动汽车车主又…

滑动窗口在算法中的应用

滑动窗口是一种经典的算法技巧&#xff0c;就像在处理一系列动态数据时&#xff0c;用一扇可以滑动的“窗口”来捕捉一段连续的子数组或子字符串。通过不断地移动窗口的起点或终点&#xff0c;我们能够以较低的时间复杂度来解决一系列问题。在这篇文章中&#xff0c;我们将通过…

图形视频处理软件Adobe After Effects(AE)2024WIN/MAC下载及系统要求

目录 一、Adobe AE软件简介 1.1 什么是Adobe AE软件 1.2 AE软件的发展历程 1.3 AE软件的应用领域 二、Adobe AE软件下载 2.1 下载 2.2 下载注意事项 三、Adobe AE软件系统要求 3.1 最低配置要求 3.2 推荐配置要求 3.3 显示器和分辨率 四、Adobe AE软件安装与使用 …

【MacOS】mac定位服务中删除已经卸载的软件

mac定位服务中删除已经卸载的软件 网上的帖子真不靠谱 直接右键 WeTypeSettings &#xff0c;查找位置&#xff0c;丢废纸篓即可&#xff01;会提示你卸载的&#xff01;

Pyramid: Real-Time LoRa Collision Decoding with Peak Tracking技术思考与解读

一点点个人的论文解读、技术理解&#xff0c;难免会有错误&#xff0c;欢迎大家一起交流和学习~~ &#x1f600;作者关于lora的系列文章从问题陈述到方法论的提出&#xff0c;再到实验评估&#xff0c;文章结构条理清晰&#xff0c;逻辑性强&#xff0c;并深入分析了LoRa信号处…

力扣刷题(5)

整数转罗马数字 整数转罗马数字-力扣 思路&#xff1a; 把各十百千位可能出现的情况都列出来&#xff0c;写成一个二维数组找出该数的各十百千位&#xff0c;与数组中的罗马元素对应 const char* ch[4][10]{{"", "I", "II", "III"…

webpack - 五大核心概念和基本配置(打包一个简单HTML页面)

// 五大核心概念 1. entry&#xff08;入口&#xff09; 指示Webpack从哪个文件开始打包2. output&#xff08;输出&#xff09; 指示Webpack打包完的文件输出到哪里去&#xff0c;如何命名等3. loader&#xff08;加载器&#xff09; webpack本身只能处理js&#xff0c;json等…

Bev pool 加速(2):自定义c++扩展

文章目录 1. c++扩展2. 案例2.1 案例12. 1.1 代码实现(1) c++ 文件(2) setup.py编写(3) python 代码编写2.1 案例1在bevfusion论文中,将bev_pooling定义为view transform中的效率瓶颈,bevfusion 主要就是对bev_pooling进行了加速,使得视图转换的速度提高了40倍,延迟从500ms…

charles配置安卓抓包(避坑版)

下载Charleshttps://www.charlesproxy.com/安装&#xff0c;疯狂点击下一步即可注册&#xff1a;打开Charles&#xff0c;选择“Help”菜单中的“Register Charles”&#xff0c;进网站生成密钥&#xff1a;https://www.zzzmode.com/mytools/charles/,将生成的密钥填入注册重启…

JavaScript练手小技巧:利用鼠标滚轮控制图片轮播

近日&#xff0c;在浏览网站的时候&#xff0c;发现了一个有意思的效果&#xff1a;一个图片轮播&#xff0c;通过上下滚动鼠标滚轮控制图片的上下切换。 于是就有了自己做一个的想法&#xff0c;顺带复习下鼠标滚轮事件。 鼠标滚轮事件&#xff0c;参考这篇文章&#xff1a;…

Vue 3 + Element Plus 封装单列控制编辑的可编辑表格组件

在Web应用开发中&#xff0c;经常需要提供表格数据的编辑功能。本文将介绍如何使用Vue 3结合Element Plus库来实现一个支持单列控制编辑功能的表格&#xff0c;并通过封装组件的形式提高代码的复用性。通过本教程&#xff0c;你将学会如何构建一个具备单列控制编辑功能的表格组…

Cloudways搭建WordPress外贸独立站完整教程(1)

验证邮件发送完成后&#xff0c;就等待Cloudways的回复邮件&#xff0c;一般24小时之内就会收到激活的邮件。 Cloudways账号升级 激活成功后还需要账户升级&#xff0c;Cloudways提供了为期3天的免费试用体验。如果在试用期结束之前未绑定信用卡以升级账户&#xff0c;试用期…

UE5学习笔记21-武器的射击功能

一、创建C类 创建武器子弹的类&#xff0c;创建生产武器子弹的类&#xff0c;创建弹壳的类&#xff0c;生产武器子弹的类的父类是武器的类 创建后如图&#xff0c;ProjectileMyWeapon类(产生子弹的类)继承自weapon类&#xff0c;Projectile(子弹的类)&#xff0c;Casing(弹壳声…