基于DDK的PCI设备驱动程序设计
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
基于DDK的PCI设备驱动程序设计
作者:赵彬,田泽,陈佳
来源:《电脑知识与技术》2011年第07期
摘要:该文以基于PCI9056的某项目设备板卡为例,介绍WDM驱动程序和PCI总线协议,分析利用DDK开发WDM驱动程序的主要例程,实现了识别板卡及测试板卡功能。
关键词:WDM;PCI;DDK;设备驱动程序
中图分类号:TP333文献标识码:A 文章编号:1009-3044(2011)07-1534-03
Designed of PCI Device Driver Based on DDK
ZHAO bin1, TIAN Ze1, CHEN Jia2
(1.Xi'an Shiyou University, Xi'an 710065, China; 2. Xidian University, Xi'an 710072, China)
Abstract: This paper takes a PCI device as an example, describes WDM drivers and PCI bus protocols. And introducing a method of WDM driver design base on DDK(Driver Development Kit), realizing identification and testing function.
Key words: WDM; PCI; DDK; device driver
因为某项目的需求,需要在PC机上调试一PCI设备,在Windows系统下实现主机通过PLX9056桥芯片对PCI设备的访问,但前提条件是当操作系统装载驱动程序正确的情况下。
如果驱动程序装载不正常,主机首先就不能够识别PCI设备;如果驱动程序运行不正常,用户就不能正确的访问PCI设备。
因此,PCI驱动程序是实现主机识别板卡以及正确访问设备的关键。
目前常用的驱动开发工具有:微软提供的DDK(Device Driver Kits),以及第三方厂商提供的DriverStudio和WinDriver,现在大多数驱动开发人员都是使用DriverStudio和WinDriver,其中DriverStudio将DDK函数按照逻辑功能组织,把很多常用功能封装成类,建立了一个基于C++语言的面向对象的编程环境,大大降低了开发难度和开发周期;WinDriver将一些基本的操作如存储读写、I/O端口读写、中断服务、DMA操作等进行了封装,开发者只需编写一个外壳来调用这个驱动程序,就可以完成对硬件设备的访问。
前两种开发工具使用简单,开发速度快,但开发的驱动程序执行效率受到限制。
DDK虽然编程难度较大,对编程人员的要求也较高,但是功能强大,编程灵活,使用范围广,可应用于各类硬件驱动程序的编写,而且有助开发人员深刻理解驱动程序和WDM(Windows Driver Mode),所以DDK是更理想的开发工具。
1 WDM式设备驱动的概述
1.1 WDM概念
设备驱动程序需与操作系统最底层进行交互,不同的操作系统底层结构对应于不同的设备驱动程序模型,也影响设备驱动程序的兼容性。
在Windows 2000以后,微软公司加入了新的驱动程序模型,这就是WDM。
1.2 WDM式驱动的基本结构
WDM模型中,两个驱动设备对象分别是物理设备对象(Physical Device Object,简称PDO)和功能设备对象(Function Device Object,简称FDO)。
其关系是“附加”与“被附加”的关系。
当某个设备插入PC机时,PDO会自动创建。
确切的说,PDO是由总线驱动创建的。
PDO 需要配合FDO一起使用,系统会提示检测到新设备,要求安装驱动程序。
需要安装的驱动程序就是WDM程序,此驱动程序就是创建FDO并附加到PDO之上。
当一个FDO附加在PDO 上的时候,PDO设备对象的子域AttachedDevice会记录FDO的位置。
PDO靠近物理设备,被称作底层驱动,而FDO接近发出I/O请求,被称作高层驱动。
并且从WDM驱动的设计思路可以看出,WDM驱动是支持即插即用的。
在FDO和PDO之间还会存在过滤驱动,在FDO上面的过滤驱动被称作上层过滤驱动,在FDO下层的驱动,被称作下层过滤驱动。
在WDM模型中,过滤驱动不是必须存在的,PDO和FDO是必须的。
2 PCI总线协议
PCI总线协议是PC上最基本的总线,一般显卡、网卡都设计成PCI总线设备。
其他总线都是挂在PCI总线上的。
例如,ISA总线是通过PCI-ISA桥设备挂在PCI总线上,而USB总线是通过USB HOST设备挂在PCI总线上的。
2.1 PCI总线简介
PCI(Pheripheral Component Interconnect)总线是当前最流行的总线之一,是由Intel公司首先推出的一种局部总线。
它定义了32位数据地址总线,并且可以扩展为64位,其支持突发读写操作,也同时可以支持多组外围设备。
在当前的PC体系结构内,几乎所有外部设备采用的各种各样的接口总线,均是通过桥接电路挂接在PCI系统内的。
在这种PCI系统中,Host/PCI桥称为北桥,连接主处理器总线到基础PCI局部总线。
PCI-ISA桥称为南桥,连接基础PCI总线到ISA总线。
其中南桥通常还含有中断控制器、IDE控制器、USB控制器和DMA控制器等设备。
2.2 PCI配置空间简介
PCI有三个相互独立的物理地址空间:设备存储器地址空间、I/O地址空间和配置空间。
配置空间是PCI所特有的一个物理空间。
由于PCI支持设备即插即用,所以PCI设备不占用固定的内存地址空间或I/O地址空间,而是可以由操作系统决定其映射的基址。
系统加电时,BIOS检测PCI总线,确定所有连接在PCI总线上的设备以及它们的配置要求,并进行系统配置,实现真正的即插即用。
3 开发实例
Windows从总体上分为内核模式(Kernel Mode)和用户模式(User Mode)。
驱动程序运行在内核模式下,拥有操作系统的最高权限。
编写驱动程序主要是为了操作硬件设备,这些硬件设备的操作主要包括访问物理映射内存、设备端口等。
而应用程序是运行在用户模式下,应用程序无法直接与硬件设备通信,必须借助于驱动程序。
所开发的PCI设备应用软件和驱动软件驻留在PC机中,其中应用软件与特定的子系统有关,应用软件通过调用PCI驱动软件实现子系统功能要求。
应用软件和驱动软件在Windows 下的关系如图2所示。
3.1 PCI设备驱动程序
PCI模块驱动软件是实现PCI板卡与宿主机(PC机)应用软件间的接口控制与数据传递的专用软件,它可提供PCI板卡与PC机各类消息数据的读、写支持,以及对PCI板卡内部程序的调度。
PCI驱动程序开发软件是DDK,用户模式下所有对驱动程序的I/O请求,全部由操作系统转化为IRP(I/O Request Package,即输入输出请求包)数据结构,不同IRP数据会被“派遣”到不同的派遣函数(Dispatch Function)。
驱动软件的入口程序是DriverEntry,在DriverEntry中包含了AddDevice函数的设置。
PCI 设备是属于被动加载的设备,操作系统必须加载PDO后调用AddDevice例程,而AddDevice 例程就是负责创建FDO并附加到PDO之上。
其次,DriverEntry必须加入IRP_MJ_PNP的派遣回调函数。
IRP_MJ_PNP就是即插即用IRP,是由即插即用管理器发送给PCI驱动程序的。
当启动PCI设备的时候,设备管理器将IRP_MN_START_DEVICE发送给PCI驱动。
在处理完此IRP后,驱动程序会将处理结果存储在IRP的设备堆栈中。
程序可从当前堆栈就可以获取PDO从PCI配置空间中的有用信息,如中断号、设备物理内存及IO端口信息等。
因为实际
应用中,不能提前知道这些描述符在数组中出现的位置,因此在实现中必须用循环先把资源值提取到一组局部变量中,然后在处理这些资源信息。
对于枚举PCI设备资源,主要分为四类,分别是设备端口、设备物理内存、DMA、中断等。
在实现中,程序里枚举了I/O端口资源,物理内存资源和中断资源。
其中,I/O端口资源包括I/O端口地址、I/O端口地址长度,物理内存资源包括基地址0和基地址2,中断资源包括中断请求级、中断向量、CPU亲缘关系、中断模式以及共享中断等。
在设备即将停止的时候,即插即用管理器将发送IRP_MN_REMOVE_DEVICE给PCI驱动,这个IRP标志着设备即将关闭,PCI驱动在此时会做一些资源回收工作。
因此开发PCI设备驱动最重要的一步就是将IRP_MN_START_DEVICE中获取的设备资源记录下来,以便以后使用。
3.2 PCI设备应用程序与驱动程序的通讯
PCI设备应用程序的开发软件是VC6.0,在应用程序中寻找设备是通过设备接口和设备号决定的,其实现过程主要是通过SetupDiXX系列函数得到设备接口。
在实际应用中,PLX9056的本地配置寄存器映射在PLX9056配置寄存器中基地址寄存器0,待测试设备的内存空间由硬件设计人员映射在PLX9056的基地址寄存器2。
因此,在应用程序中需定义供用户使用的通过基地址0和基地址2的读写接口函数。
例如:
基本的读函数有:
ULONG ReadFromBase0(HANDLE handle,ULONG Offset,
UCHAR *buff,ULONG length);
ULONG ReadFromBase2(HANDLE handle,ULONG Offset,
UCHAR *buff,ULONG length);
基本的写函数有:
ULONG WriteToBase0(HANDLE handle,ULONG Offset,
UCHAR *buff,ULONG length);
ULONG WriteToBase2(HANDLE handle,ULONG Offset,
UCHAR *buff,ULONG length);
应用程序可以通过Win32 API DeviceIoControl操作设备与驱动程序互相通信。
DeviceIoControl内部会使操作系统创建一个IRP_MJ_DEVICE_CONTROL类型的IRP,然后操作系统会将这个IRP转发到派遣函数中。
而以上的读写接口函数的本质就是调用DeviceIoControl来实现的。
例如从基地址0读函数ReadFromBase0函数原型,如图3。
其中,DDK定义的DeviceIoControl的函数原型为:
BOOL DeviceIoControl{
HANDLE hDevice,//设备句柄
DWORD dwIoControlCode, //控制码
LPVOID lpInBuffer,//输入数据缓冲区指针
DWORD nInBufferSize, //输入数据缓冲区长度
LPVOID lpOutBuffer, //输出数据缓冲区指针
DWORD nOutBufferSize,//输出数据缓冲区长度
LPDWORD lpByteReturned,//输出数据实际长度单元长度
LPOVERLAPPED lpOverlapped //重叠操作结构指针
};
DeviceIoControl的第二个参数是I/O控制码,控制码也称IOCTL值,是一个32位的无符号整型。
DDK提供一个宏CTL_CODE,定义为:
CTL_CODE(DeviceType,Function,Method,Access)
其中,DeviceType为设备对象的类型;Function为驱动程序定义的IOCTL值,0x000到
0x7ff为微软保留,0x800到0xfff由程序员自己定义;Method是操作模式,其中包括METHOD_BUFFERED为使用缓冲区方式操作,METHOD_IN_DIRECT为使用直接写方式操作,METHOD_OUT_DIRECT为使用直接读方式操作,METHOD_NEITHER为使用其他方式操作;Access为访问权限。
如上述例子ReadFromBase0函数,在驱动程序中用CLT_CODE宏定义定义的IOCTL码:
#define IOCTL_READ_BASE_BAR0 CTL_CODE(
FILE_DEVICE_UNKONWN,
0x800,
METHOD_BUFFERED,
FILE_ANY_ACCESS)
驱动程序中IOCTL派遣函数的实现是首先得到当前I/O堆栈,从I/O堆栈中再一次得到输入缓冲区大小,输出缓冲区大小,以及IOCTL。
在实现过程中,运用C语言中的switch语句分别处理不同的IOCTL。
在每个IOCTL情况下,就必须使用DDK提供的内核函数
WRITE_REGISTER_XX系列函数和READ_REGISTER_XX系列函数操作物理设备内存。
具体流程如图4所示。
当应用程序需要操作读写接口函数时,设备管理器就会发送相对应的IRP给设备驱动,驱动程序就会调用DispatchControl函数找到相应的IOCTL码,应用程序再调用DeviceIoControl 操作设备。
4 结束语
本文以实际应用的一个PCI设备驱动开发为例着重介绍了驱动程序和应用程序的相互关系,并且还简单介绍了WDM式设备驱动和PCI总线协议。
设备驱动程序是Windows操作系统重要的内核组建,在系统中起至关重要。
如果驱动程序出错,很容易使Windows操作系统崩溃。
开发利用DDK开发驱动程序能够使开发者加深对Windows内核和WDM规范的理解。
参考文献:
[1] 张帆,史彩成.Windows驱动开发技术详解[M].北京:电子工业出版社,2009.
[2] Walter Oney.Programming The Microsoft Windows Driver Model[M].1999.
[3] PCI Tech Company.PCI 9056BA Data Book[M].USA,2003.
[4] Microsoft Corporation,Windows 2000 DDK[M].USA,2000.
[5] 蹇红梅,居锦武,王兰英.Windows设备驱动程序开发[J].四川理工学院学报:自然科学
版,2007,20(4).。