【C语言】linux内核pci_enable_device函数和_PCI_NOP宏
pci_enable_device
一、注释
static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
{struct pci_dev *bridge;int err;int i, bars = 0;/** 此时电源状态可能是未知的,可能是由于新启动或者设备移除调用。* 因此获取当前的电源状态,这样像 MSI 消息写入这样的操作会按预期行为* (比如,如果设备在 enable 时确实位于 D0 状态)。*/if (dev->pm_cap) {u16 pmcsr;pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);}// 如果设备已经启用,只增加引用计数,然后直接返回if (atomic_inc_return(&dev->enable_cnt) > 1)return 0; /* 已经启用 */// 查找上游桥设备,如果存在则启用它bridge = pci_upstream_bridge(dev);if (bridge)pci_enable_bridge(bridge);// 只跳过和 SR-IOV 相关的资源for (i = 0; i <= PCI_ROM_RESOURCE; i++)if (dev->resource[i].flags & flags)bars |= (1 << i);for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++)if (dev->resource[i].flags & flags)bars |= (1 << i);// 实际启用 PCI 设备err = do_pci_enable_device(dev, bars);if (err < 0)atomic_dec(&dev->enable_cnt); // 如果启用失败,则减少引用计数return err;
}/*** pci_enable_device - 在驱动程序使用设备前初始化设备。* @dev: 需要初始化的 PCI 设备** 在驱动程序使用设备前初始化设备。要求底层代码去启用 I/O 和内存。* 如果设备已经进入休眠,则将其唤醒。注意,该函数可能会失败。** 注意如果我们反复调用这个函数,我们不会真正多次启用设备(我们只是增加计数)。*/
int pci_enable_device(struct pci_dev *dev)
{return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
EXPORT_SYMBOL(pci_enable_device);
在这段代码中,`pci_enable_device_flags` 是一个静态函数,它接受两个参数:一个指向 PCI 设备的指针和一个标志集合。函数的目的是启用指定的 PCI 设备,但首先会检查设备的电源管理(PM)能力和当前的电源状态,并递增设备的启用计数。如果设备已经启用,函数会立即返回。然后函数检查是否有上游桥设备,若存在则递归地启用桥设备。接下来,它会确定需要启用的资源并最终调用 do_pci_enable_device
函数。
pci_enable_device
函数封装了 pci_enable_device_flags
函数,用于启用 PCI 设备的 I/O 和内存资源。该函数导出了符号 pci_enable_device
,使得其他内核模块可以通过符号名引用该函数。
二、讲解
这段代码是Linux内核中用于启动PCI设备的一部分。下面将对这段代码的关键部分进行讲解。
static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
这是一个静态函数,其目的是用给定的标志(`flags`)来启动一个PCI设备(`dev`)。
struct pci_dev *bridge;int err;int i, bars = 0;
定义了指向PCI设备的桥接器的指针`bridge`,一个整型错误码`err`以及两个整型变量`i`和`bars`,其中`bars`用于跟踪需要启用的设备资源条目(BARs)。
if (dev->pm_cap) {
检查设备(dev
)是否支持电源管理(PM)功能。
u16 pmcsr;pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);}
如果支持,就从设备的配置空间中读取电源管理控制状态寄存器(PMCSR),并更新设备当前的电源状态。
if (atomic_inc_return(&dev->enable_cnt) > 1)return 0; /* already enabled */
使用原子操作增加设备使能计数器`enable_cnt`,如果这不是第一次使能(计数大于1),则表示设备已经使能,函数直接返回0。
bridge = pci_upstream_bridge(dev);if (bridge)pci_enable_bridge(bridge);
找到设备的上游桥接器(bridge
),如果存在,就启用这个桥接器。
for (i = 0; i <= PCI_ROM_RESOURCE; i++)...for (i = PCI_BRIDGE_RESOURCES; i < DEVICE_COUNT_RESOURCE; i++)...
这两个循环检查设备的所有资源条目,确定哪些BAR需要被启用,这基于给定的标志和资源的类型。
err = do_pci_enable_device(dev, bars);if (err < 0)atomic_dec(&dev->enable_cnt);return err;
}
调用`do_pci_enable_device`来实际启用这些资源。如果有错误发生,减少使能计数器并返回错误码。
int pci_enable_device(struct pci_dev *dev)
{return pci_enable_device_flags(dev, IORESOURCE_MEM | IORESOURCE_IO);
}
EXPORT_SYMBOL(pci_enable_device);
这是一个外部可见的函数,用默认的标志(内存和I/O资源)来启用一个PCI设备。
整体而言,这段代码是驱动程序在使用PCI设备之前,对设备进行初始化和启用操作的过程。它确保设备可以响应内存和I/O操作,以及从低功耗状态中唤醒设备。
本函数在drivers\pci\pci.c中定义。
_PCI_NOP宏
一、注释
/** 如果系统没有PCI,很显然这些函数会返回错误。定义这些函数为简单的内联函数,* 以避免在驱动程序中的复杂操作。*/
#define _PCI_NOP(o, s, t) \static inline int pci_##o##_config_##s(struct pci_dev *dev, \int where, t val) \{ return PCIBIOS_FUNC_NOT_SUPPORTED; } // 定义宏_PCI_NOP来构造内联函数,若PCI操作不被支持,则返回错误码#define _PCI_NOP_ALL(o, x) _PCI_NOP(o, byte, u8 x) \ // 利用_PCI_NOP宏定义读写byte、word、dword三种操作_PCI_NOP(o, word, u16 x) \_PCI_NOP(o, dword, u32 x)_PCI_NOP_ALL(read, *) // 定义所有的read操作,如果系统无法执行PCI读取操作,它们将返回错误
_PCI_NOP_ALL(write,) // 定义所有的write操作,如果系统无法执行PCI写入操作,它们将返回错误
二、讲解
这段代码是用于操作PCI配置空间的宏定义和内联函数,适用于没有PCI支持的系统环境。在这种情况下,对PCI配置空间的读写操作将返回一个错误码,通常是因为PCI功能不被支持(`PCIBIOS_FUNC_NOT_SUPPORTED`)。
代码解释:
1. _PCI_NOP 宏定义: 它用于声明一个静态的内联函数,这个函数对应于PCI读或写操作,并返回一个错误码 PCIBIOS_FUNC_NOT_SUPPORTED。这个宏接收三个参数:操作类型 (o)、数据大小 (s) 和数据类型 (t)。具体来说:
- o 表示操作类型,可以是 read 或 write。
- s 表示数据的大小,可以是 byte(8位),`word`(16位)或 dword(32位)。
- t 表示对应的数据类型,分别是 u8(unsigned 8-bit)、`u16` (unsigned 16-bit)、`u32` (unsigned 32-bit).
2. _PCI_NOP_ALL 宏定义: 它是一个帮助宏,用于针对读和写操作声明所有可能的大小的内联函数,即字节、字和双字。
3. _PCI_NOP_ALL(read, *) 和 _PCI_NOP_ALL(write,): 这两个宏分别为读和写操作创建了三个函数,即针对 byte、`word` 和 dword 大小的数据。对 read 操作的函数,传入变量 val 是一个指针(`*指明取地址),这是因为读操作需要一个指针来存放读到的值。对 write` 操作,`val` 是一个普通变量,因为写操作是将该值写入到PCI配置空间。
4. 函数 pci_##o##_config_##s: 这是一个构建函数名的宏,这里使用了宏的字符串化(##)来组合操作类型和数据大小,创建特定的函数名。例如,`pci_read_config_byte` 或 pci_write_config_dword。
总结一下,这段代码就是为不支持PCI操作的系统提供了一组空操作(no-operation, NOP)函数,以便在该系统的PCI驱动中使用,从而避免了在驱动代码中添加复杂的条件编译指令。当驱动尝试进行PCI配置空间的访问时,这些函数会直接返回一个“功能不支持”的错误码。
相关文章:

【C语言】linux内核pci_enable_device函数和_PCI_NOP宏
pci_enable_device 一、注释 static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags) {struct pci_dev *bridge;int err;int i, bars 0;/** 此时电源状态可能是未知的,可能是由于新启动或者设备移除调用。* 因此获取当前的电源状态&…...

网络: 套接字
套接字: 在网络上进行进程间通信 网络字节序与主机字节序的转化 sockaddr sockaddr struct sockaddr {sa_family_t sa_family; // 地址族char sa_data[14]; // 地址数据,具体内容与地址族相关 };sockaddr_in :主要是地址类型, 端口号, IP地址. 基于IPv4编程…...

Day57-Nginx反向代理与负载均衡初步应用
Day57-Nginx反向代理与负载均衡初步应用 1. Nginx代理介绍2. Nginx代理常见模式2.1 正向代理2.2 反向代理2.3 正向与反向代理区别 3. Nginx代理支持协议4. Nginx反向代理场景实践5. lb01安装部署nginx 1. Nginx代理介绍 1)在没有代理的情况下,都是客户端…...
【PHP】通过PHP开启/暂停Apache、MySQL或其他服务
目录 一、前言 二、代码 一、前言 有些时候我们需要开启或暂停一些服务,比如说开启Apach或暂停MySQL服务等,最近工作中也开发了这方面的功能,记录下来怎样使用PHP语言来开启或暂停Apache、MySQL服务的运行状态。 这种方法也适用其他服务。…...
JAVA中spring介绍
Spring框架是一个开源的Java平台,它最初由Rod Johnson于2003年创建,目的是简化企业级应用的开发。Spring框架的核心特性包括控制反转(IoC)、面向切面编程(AOP)、事务管理、数据访问等。它通过提供一套综合的…...

latex下载与安装
用jupyter导出pdf时,需要用到Tex 1.Tex下载安装 官网 直接git下载 git clone https://github.com/latex3/latex2e.git 或者 清华大学开源软件镜像 双击.bat文件 大概需要1-2小时,如果安装失败,重新进行安装 查看是否安装成功ÿ…...

JavaParser 手动安装和配置
目录 前言 一、安装 Maven 工具 1.1 Maven 软件的下载 1.2 Maven 软件的安装 1.3 Maven 环境变量配置 1.4 通过命令检查 Maven 版本 二、配置 Maven 仓库 2.1 修改仓库目录 2.2 添加国内镜像 三、从 Github 下载 JavaParser 3.1 下载并解压 JavaParser 3.2 从路径打…...
再次度过我的创作纪念日
机缘 写博客的机缘巧合已经在上一篇博客中写到了,至于收获和成就也不一一赘述了。想和大家聊的呢就这最近这一年左右的经历吧 日常 自从2022年开始,入职了一家大型的项目外派公司,名字就不说了。开始了我的保险公司系统的开发工作。工作地点…...

云电脑火爆出圈,如何选择和使用?--腾讯云、ToDesk云电脑、青椒云使用评测和攻略
前言: Hello大家好,我是Dream。在当下,科技的飞速发展已经深入影响着我们的日常生活,特别是随着物联网的兴起和5G网络的普及,云计算作为一个重要的技术概念也逐渐走进了我们的视野。云计算早已不再是一个陌生的名词&am…...
webpack原理之-打包流程热更新HMR
webpack打包流程? 1. 初始化: 启动构建,读取与合并配置参数,加载Plugin,实例化Compiler; 2. 编译: 从 entry出发,针对每个 Module 串行调用对应的 loader 去翻译文件的内容,再找到该 Module 依赖…...

SELinux详解
文章目录 SELinux详解什么是SELinux当初设计的目标:避免资源的误用传统的文件权限与账号主要的关系:自主访问控制(DAC)以策略规则制定特定进程读取特定文件:强制访问控制(MAC) SELinux的运行模式安全上下文进程与文件SELinux类型字段的相关性…...
Go语言实现SSE中转demo
Go语言实现SSE中转demo 文章概要:本文主要通过一个demo来介绍如何使用Go语言实现SSE中转。 本文内容来自:谷流仓AI - ai.guliucang.com 前提 已安装Go语言环境(参考这篇文章:Macbook安装Go以及镜像设置) 创建项目 创建项目目录…...

国内IP修改软件下载指南
在互联网时代,IP地址扮演了一个非常重要的角色。国内IP修改成为一些用户迫切需求的问题,因为它可以帮助用户解决一些特定的网络访问问题。那么,要修改国内IP地址,我们该使用哪些软件呢?虎观代理小二将为大家列举几款可…...
模数转换器 SIG1230A 国产平替 ADS1230,替代 ADS1230
信格勒微电子的芯片产品已通过行业头部大厂导入验证,深受百万终端客户好评。 而且因为 fully compatible. 板子拿来,换个芯片, 性能更好 。MCU不用改 c code。 SIG1230A 10/80SPS 20-bit ADC with PGA Compatible Parts ADS1230 fully…...

获取淘宝商品评论的爬虫技术分享(已封装API,可测试)
item_review-获得淘宝商品评论 公共参数 请求地址: taobao/item_review 名称类型必须描述keyString是调用key(必须以GET方式拼接在URL中)secretString是调用密钥api_nameString是API接口名称(包括在请求地址中)[item_search,it…...

由vue2版本升级vue3版本遇到的问题
一、vuedraggable 由vue2版本升级vue3版本后,可能会遇到以下几种bug: 1、vue3vuedraggable报错TypeError: Cannot read properties of undefined (reading ‘updated’):这个一般是因为插件使用语法有问题,vue3版本的插件使用时&…...

数据挖掘终篇!一文学习模型融合!从加权融合到stacking, boosting
模型融合:通过融合多个不同的模型,可能提升机器学习的性能。这一方法在各种机器学习比赛中广泛应用, 也是在比赛的攻坚时刻冲刺Top的关键。而融合模型往往又可以从模型结果,模型自身,样本集等不同的角度进行融合。 数据…...

24考研数学炸了,给25考研人的启示
复习原则和要素 在选择老师、思路的时候,一定要看清楚,认不认可这个老师的复习思路。 有的老师认为大家基础不错,讲的内容可能不会特别细致。有的老师注重基础,讲的很细致,防止0基础的学生吃力。所以,思路…...
嵌入式学习第三十天!(单向链表练习)
1. 单向链表的逆序: int Is_Empty_Link(LINK_LIST *plist) {return plist->phead NULL; }void Reverse_Link(LINK_LIST *plist) {LINK_NODE *ptmp plist->phead;LINK_NODE *pinsert NULL;plist->phead NULL;if(Is_Empty_Link(plist)){return;}else{wh…...

Linux:rpm部署Jenkins(1)
1.获取Jenkins安装包 我这里使用的是centos7系统,ip为:192.168.6.6 2G运存 连接外网 Jenkins需要java环境,java的jdk包你可以去网上下载离线包,或者直接去yum安装,我这里使用的是yum安装 再去获取Jenkins的rpm包…...

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型
摘要 拍照搜题系统采用“三层管道(多模态 OCR → 语义检索 → 答案渲染)、两级检索(倒排 BM25 向量 HNSW)并以大语言模型兜底”的整体框架: 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后,分别用…...
在软件开发中正确使用MySQL日期时间类型的深度解析
在日常软件开发场景中,时间信息的存储是底层且核心的需求。从金融交易的精确记账时间、用户操作的行为日志,到供应链系统的物流节点时间戳,时间数据的准确性直接决定业务逻辑的可靠性。MySQL作为主流关系型数据库,其日期时间类型的…...

【WiFi帧结构】
文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成:MAC头部frame bodyFCS,其中MAC是固定格式的,frame body是可变长度。 MAC头部有frame control,duration,address1,address2,addre…...
Nginx server_name 配置说明
Nginx 是一个高性能的反向代理和负载均衡服务器,其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机(Virtual Host)。 1. 简介 Nginx 使用 server_name 指令来确定…...

【单片机期末】单片机系统设计
主要内容:系统状态机,系统时基,系统需求分析,系统构建,系统状态流图 一、题目要求 二、绘制系统状态流图 题目:根据上述描述绘制系统状态流图,注明状态转移条件及方向。 三、利用定时器产生时…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
Xen Server服务器释放磁盘空间
disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

短视频矩阵系统文案创作功能开发实践,定制化开发
在短视频行业迅猛发展的当下,企业和个人创作者为了扩大影响力、提升传播效果,纷纷采用短视频矩阵运营策略,同时管理多个平台、多个账号的内容发布。然而,频繁的文案创作需求让运营者疲于应对,如何高效产出高质量文案成…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...