第二十七篇: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设备须要考虑驱动设计中的方方面面, 希望这篇文章对大家有所借鉴作用.

时间: 2024-11-08 02:12:31

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

第二十三篇:Windows中的ACPI

一直不太清楚ACPI驱动在WINDOWS中的作用. 甚至不了解ACPI协议的作用. 于是, 随便翻了下"格蠹汇编"中的第24章, 如何跟踪ACPI代码, 算是对ACPI有了一个初步性的了解. ACPI向OS报告硬件信息, 而OS通过ACPI控制硬件. ACPI就是OS与硬件/固件之间的一个标准接口协议. ACPI通过ASL(ACPI SOURCE LANGUAGE)来描述系统硬件的属性与方法, ASL最终会被编译为AML(ACPI MACHINE LANGUAGE)的字节码(BYTEC

Egret入门学习日记 --- 第二十三篇(书中 9.9~9.11 节 内容)

第二十三篇(书中 9.9~9.11 节 内容) 今天,来9.9节. 重点: 1.VSlider的声明和使用. 操作: 1.VSlider的声明和使用. 其实和HSlider的使用方式差不多. 至此,9.9节 内容结束. 开始 9.10节. 重点: 1.配合TextureMerger,生成艺术字图集资源. 2.导入艺术字资源,并使用. 3.调整艺术字间距. 操作: 1.配合TextureMerger,生成艺术字图集资源. 打开TextureMerger,选择Bitmap Font . 点击添加字符

linux设备驱动第五篇:驱动中的并发与竟态

综述 在上一篇介绍了linux驱动的调试方法,这一篇介绍一下在驱动编程中会遇到的并发和竟态以及如何处理并发和竞争. 首先什么是并发与竟态呢?并发(concurrency)指的是多个执行单元同时.并行被执行.而并发的执行单元对共享资源(硬件资源和软件上的全局.静态变量)的访问则容易导致竞态(race conditions).可能导致并发和竟态的情况有: SMP(Symmetric Multi-Processing),对称多处理结构.SMP是一种紧耦合.共享存储的系统模型,它的特点是多个CPU使用共

第二十七篇 类和对象相关知识

类和对象 1. 什么叫类:类是一种数据结构,就好比一个模型,该模型用来表述一类食物(食物即数据和动作的结合体),用它来生产真是的物体(实例) 2. 什么叫对象:睁开眼,你看到的一切事物都是一个个的对象,你可以把对象理解为一个具体的事物(事物即数据和动作的结合体) (铅笔是对象,人是对象,房子是对象,狗是对象,你看到的都是类) 3.类与对象的关系:对象都是由类产生的,女娲造人,首先由一个造人的模板,这个模板就是人类,然后女娲根据类的定义来生产一个个的人 4. 什么叫实例化:由类生产对象的过程叫实例

python全栈开发基础【第二十七篇】IO模型

相关名词解析 同步(synchronous):一个进程在执行某个任务时,另外一个进程必须等待其执行完毕,才能继续执行 #所谓同步,就是在发出一个功能调用时,在没有得到结果之前,该调用就不会返回.按照这个定义, 其实绝大多数函数都是同步调用.但是一般而言,我们在说同步.异步的时候, 特指那些需要其他部件协作或者需要一定时间完成的任务. #举例: #1. multiprocessing.Pool下的apply #发起同步调用后,就在原地等着任务结束, 根本不考虑任务是在计算还是在io阻塞,总之就是一

我的第二十七篇博客---beautifulsoup与csv操作方法

Beautiful Soup和lxml一样,也是一个HTML/XML的解析器,主要的功能也是如何解析和提取HTML/XML数据lxml只会局部遍历,而Beautiful Soup是基于HTML DOM的,会载入整个文档,解析整个DOM树,因此时间和内存开销都会大很多,所以性能要低于lxml/Beautiful Soup 用来解析HTML比较简单,API非常人性化,支持CSS选择器,Python标准库中的HTML解析器,也支持lxml的解析器 bs4的基本使用实:首先必须要导入bs4库from b

第二十七篇 人间正道

在浩瀚的宇宙中,人类世界的整体发展已经走过了非常漫长的旅程.在这漫长的发展过程中,人类世界经历了风风雨雨.自从有了人类到开始创建不同层次级别的世界,人类前辈祖宗们经历了多少坎坷我们无法想象!创建世界无比艰难,而要把创建的世界管理好就更不容易. 如今,人类世界已处在不断快速向上发展的阶段.比起刚开始创建人类世界的前辈祖宗们,我们这些后辈现在的条件要好得多,这得益于前辈祖宗们打下的良好基础.这些要归功于所有为人类世界努力付出的前辈祖宗们.作为后辈,我们要心存感恩,并且要继承人类前辈祖宗们不畏艰难.勇

第二十七篇:QQ好友列表,UITableViewHeaderFooterView用法

1.设置tableView的headerView注要以下几个: #pragma mark - tableView代理方法 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{ // 取得一个自定义的 headerView QJHeaderView * headerView = [QJHeaderView headerViewWithTableView:tableView]

第二十七篇:SOUI中控件属性查询方法

SOUI项目的SVN根目录下有一个doc目录,下面有一份控件属性表.包含了大部分控件的大部分属性,不过也不一定完全准确.最保险的办法还是查源代码. SOUI对象包含控件及ISkinObj等从SObject派生的对象都可以使用XML配置属性.要知道如何查SOUI对象属性,首先要看一下SOUI解释属性的流程. BOOL SObject::InitFromXml( pugi::xml_node xmlNode ) { if(!xmlNode) return FALSE; #ifdef _DEBUG {