第二十七篇:Windows驱动中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace

本文主要是介绍第二十七篇:Windows驱动中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

最近有些人问我PCI设备驱动的问题, 和他们交流过后, 我建议他们先看一看<<The Windows NT Device Driver Book>>这本书, 个人感觉, 这本书写得非常连贯流畅.


PCI设备驱动基本包括了PCI的资源获取, 配置空间的读写, 中断的处理, 中断后半部在DPC中的处理.

同时, 也必须了解DMA, ScatterGater, MapRegister, Common Buffer等基础.


1.1 PCI设备资源获取

PCI设备的资源是系统根据设备的属性(配置空间中寄存器的值)来动态分配的.

驱动中只需在PNP START中获取这些系统分配的资源:

例如: 笔者开发的PCI电视卡驱动中, 就使用到了其中了两类资源, CmResourceTypePort与CmResourceTypeInterrupt.

Port地址作为设备寄存器首地址, 之后, 可以使用WRITE_PORT_ULONG与READ_PORT_ULONG加上相应的OFFSET来对设备寄存器进行访问.

Interrupt资源中解释出来的内容, 则主要作为IoConnectInterrupt系统函数的参数, 将设备的硬件中断与ISR相关联, KINTERRUPT的实例则是设备中断的软件形式的载体.


1.2 DMA

DMA设备, 在系统中分为MASTER与SLAVE, 另外一个很重要的能力就是是否支持Scatter/Gather.

这些能力最终表现在DEVICE_DESCRIPTION所定义的数据结构的成员中, 例如:DmaWidth, ScatterGather, Master, Dma32BitAddresses, Dma64BitAddresses.

系统最终将各种不同类型的设备DMA抽象为DMA_ADAPTER的实例, 它是设备DMA软件形式的载体.

驱动代码通过IoGetDmaAdapter系统调用, 将物理设备对象PDO与DMA描述结构作为参数, 最终得到这个DMA_ADAPTER对象, 作为后续一系列DMA相关操作的实体对象.


1.3 Map Register

用户空间, 内核空间的虚拟内存与物理内存的关联是通过页表来映射的, 驱动程序员常常会使用MDL, 它也是某一特定区域虚拟内存与物理内存的映射关系.

而DMA设备则需要从总线地址(MSDN中又叫逻辑地址)与内存物理的映射关系角度去看待系统内存.

这个映射的关系就是由Map Register承担的.

不过, 这批Map Register则根据系统而定, 有些是硬件实现, 有些是软件中划分出来的特定的一块内存.

IoGetDmaAdapter的调用, 也是向系统申请Map Register的过程.


1.4 Common Buffer

这也是大家问得最多的问题

简单地讲, Common buffer是以DMA_ADAPTER为代表所申请的, 申请成功后, 既能通过虚拟地址访问, 也可以通过DMA控制器所属逻辑地址空间的地址来访问的连续物理内存.

它的好处就是物理上连续, 存在的问题是系统中连续物理内存是随着系统的运行时间的流逝, 越来越稀缺.

AllocateCommonBuffer系统调用是作为DMA_ADAPTER的DmaOperations形式存在的, 所以, 具体的一块Common Buffer可以说, 是与具体的一个DMA控制器所关联的.

AllocateCommonBuffer成功调用后, 会返回虚拟地址与DMA控制器所属逻辑空间的逻辑地址.

笔者开发的PCI电视卡, 就是通过AllocateCommonBuffer分配一块较小的连续物理内存, 用来存放Scatter/Gather列表 (某块内存的逻辑地址SCATTER_GATHER_LIST.Elements[i].Address.LowPart 与该内存的长度SCATTER_GATHER_LIST.Elements[i].Length, 相应操作通过common buffer的虚拟地址 ).

这个Scatter/Gather List列表最终由具有S/G能力的DMA控制器来读取(相应操作通过common buffer的逻辑地址), 根据其中的表项, 进行DMA读/写操作.


1.5 S/G

S/G的能力是DMA控制器的特性, 如果具有S/G的能力, 则可以批量地DMA操作, 否则, 必须一次一次地使用MapTransfer来完成DMA操作.

系统空间的中虚拟内存与物理内存之间的联系通过IoAllocateMdl与MmBuildMdlForNonPagedPool建立特定的MDL来表示.

其后,通过DMA_ADAPTER的DmaOperations中的GetScatterGatherList获取MDL所描述的虚拟地址内存的S/G列表, 最后, 在GetScatterGatherList的

ExecutionRoutine 函数中, 将该列表填入Common buffer的TABLE(起始逻辑地址 与 长度)中, 以供DMA Controller所用.

1.6 ISR与DPC 刚才已经提到, ISR是通过IoConnectInterrupt注册的. ISR在设备中断到来时实调用, 但具体的事项则交由(KeInsertQueueDpc)DPC来处理. 而DPC则是通过KeInitializeDpc系统调用, 将DPC对象KDPC与具体的KDEFERRED_ROUTINE DPC处理函数相关联的.
1.7 PCI设备配置空间的访问
事实上, 一般情况下, Windows PCI设备并不需要访问PCI设备配置空间. 但作为一个完整的PCI设备驱动, 这里提及一下.
由于PCI设备的配置空间与IO/MEM空间是分开的, 前面已经提及IO/MEM的访问方式, 配置空间的访问如下: 定义变量:BUS_INTERFACE_STANDARD m_BusInterfaceStandard; 建立: IRP, 主与次分别为IRP_MJ_PNP, IRP_MN_QUERY_INTERFACE, 得到BUS_INTERFACE_STANDARD数据结构. 之后, 通过BUS_INTERFACE_STANDARD中的 SetBusData与 GetBusData来进行PCI配置空间的寄存器读写.

 

PCI设备驱动完全可以用在PCIe设备上, 毕竟上层来讲, 他们没有太多的区别.

与USB驱动不同, PCI设备需要考虑驱动设计中的方方面面, 希望这篇文章对大家有所借鉴作用.







这篇关于第二十七篇:Windows驱动中的PCI, DMA, ISR, DPC, ScatterGater, MapRegsiter, CommonBuffer, ConfigSpace的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1118454

相关文章

Linux_kernel驱动开发11

一、改回nfs方式挂载根文件系统         在产品将要上线之前,需要制作不同类型格式的根文件系统         在产品研发阶段,我们还是需要使用nfs的方式挂载根文件系统         优点:可以直接在上位机中修改文件系统内容,延长EMMC的寿命         【1】重启上位机nfs服务         sudo service nfs-kernel-server resta

在 Windows 上部署 gitblit

在 Windows 上部署 gitblit 在 Windows 上部署 gitblit 缘起gitblit 是什么安装JDK部署 gitblit 下载 gitblit 并解压配置登录注册为 windows 服务 修改 installService.cmd 文件运行 installService.cmd运行 gitblitw.exe查看 services.msc 缘起

Windows如何添加右键新建菜单

Windows如何添加右键新建菜单 文章目录 Windows如何添加右键新建菜单实验环境缘起以新建`.md`文件为例第一步第二步第三步 总结 实验环境 Windows7 缘起 因为我习惯用 Markdown 格式写文本,每次新建一个.txt后都要手动修改为.md,真的麻烦。如何在右键新建菜单中添加.md选项呢? 网上有很多方法,这些方法我都尝试了,要么太麻烦,要么不凑效

Windows下Nginx的安装及开机启动

1、将nginx-1.16.1.zip解压拷贝至D:\web\nginx目录下。 2、启动Nginx,两种方法: (1)直接双击nginx.exe,双击后一个黑色的弹窗一闪而过。 (2)打开cmd命令窗口,切换到nginx目录下,输入命令 nginx.exe 或者 start nginx ,回车即可。 3、检查nginx是否启动成功。 直接在浏览器地址栏输入网址 http://lo

STM32 ADC+DMA导致写FLASH失败

最近用STM32G070系列的ADC+DMA采样时,遇到了一些小坑记录一下; 一、ADC+DMA采样时进入死循环; 解决方法:ADC-dma死循环问题_stm32 adc dma死机-CSDN博客 将ADC的DMA中断调整为最高,且增大ADCHAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_Buffer_Size); 的ADC_Bu

Windows环境利用VS2022编译 libvpx 源码教程

libvpx libvpx 是一个开源的视频编码库,由 WebM 项目开发和维护,专门用于 VP8 和 VP9 视频编码格式的编解码处理。它支持高质量的视频压缩,广泛应用于视频会议、在线教育、视频直播服务等多种场景中。libvpx 的特点包括跨平台兼容性、硬件加速支持以及灵活的接口设计,使其可以轻松集成到各种应用程序中。 libvpx 的安装和配置过程相对简单,用户可以从官方网站下载源代码

C++实现俄罗斯方块(Windows控制台版)

C++实现俄罗斯方块(Windows控制台版) 在油管上看到一个使用C++控制台编写的俄罗斯方块小游戏,源代码200多行,B站上也有相关的讲解视频,非常不错,值得学习。 B站讲解视频地址为:【百万好评】国外技术大神C++游戏编程实战教程,油管580W收藏,新手10小时入门,并快速达到游戏开发能力(中英字幕) B站 CSDN博主千帐灯无此声还为此写了一篇博客:C++实现俄罗斯方块(源码+详解),讲

Windows下php扩展开发c++动态库

PHP扩展开发,从零了解到初步完成一个小项目,经过三天的仔细研究,现整理如下 一、需求介绍 PHP扩展开发,调用自己之前的c++动态库,完成功能 二、项目之前 系统:windows xp  开发工具:vs 2008 web环境:apache2.4  PHP5.3.29-VC9-ts-x86 aphach和PHP 环境之前已经搭建完成 PHP源码:去官网http://www.php.n

驱动(RK3588S)第七课时:单节点设备树

目录 需求一、设备树的概念1、设备树的后缀名:2、设备树的语法格式3、设备树的属性(重要)4、设备树格式举例 二、设备树所用函数1、如何在内核层种获取设备树节点:2、从设备树上获取 gpio 口的属性3、获取节点上的属性只针对于字符串属性的4、函数读取 np 结点中的 propname 属性的值,并将读取到的 u32 类型的值保存在 out_value 指向的内存中,函数的返回值表示读取到的

OpenStack镜像制作系列4—Windows Server2019镜像

本系列文章主要对如何制作OpenStack镜像的过程进行描述记录  CSDN:OpenStack镜像制作教程指导(全) OpenStack镜像制作系列1—环境准备 OpenStack镜像制作系列2—Windows7镜像 OpenStack镜像制作系列3—Windows10镜像 OpenStack镜像制作系列4—Windows Server2019镜像 OpenStack镜像制作系