开发板WDM驱动程序说明及开发流程
WDM驱动开发之路(1)
WDM驱动开发之路(1)WDM开发之路(1)--驱动开发网WDM教程WDM驱动开发之路写在前面:在专栏的前几期中,我们一起初步学习了vxd的开发技术。
Vxd技术是很深奥的,不是一篇两篇文章能讲清楚,但你已经入了门,剩下的就要看你的修行了。
多看书,多泡论坛(当然是上咱们的驱动开发网论坛了:->),多写程序…我的手不够用了。
功到自然成嘛。
不过话又说回来,vxd只是权宜之计,WDM才符合当今的潮流(程序员都是时髦人士,君不见先是VB、VC然后是asp、JSP、PHP,数也数不过来呀),Win9x寿终正寝时也就是vxd的末日,你不想随它而去吧(开个玩笑),那就随我来。
按笔者的想法,这篇文章写成连载形式,一次讲一个主题,并且必要时带着例子,让大伙step by step地把WDM驱动弄个透底,不想让大家觉得稀里糊涂,也不想让大家觉得白买杂志了。
今天我们一起讨论第一部分,了解篇。
(一)了解篇WDM模型(Windows Driver Model)是微软公司为当前主流操作系统Windows98和Windows 2000的驱动程序设计的一种构架。
它和传统的win3.x和win95使用的vxd的驱动是完全不同的体系结构。
不过对于最终用户来说,WDM驱动程序在Windows98和Windows2000下的表现很相似。
作为驱动开发人员来说,它在两者中有很多的不同。
并且Windows98中的WDM只能算是Windowss2000中的WDM的一个了集。
在Windows98中有一些驱动程序只能使用VXD来实现,如串行通讯驱动等。
要写驱动程序,首先要了解操作系统的结构。
在WDM体系中,windows2000操作系统中是最标准的实现方式,Windows98则是部分兼容WDM结构。
照微软的说法,Windows98和Windows2000 X86(Intel 架构)版本实现二进制码兼容(参见98DDK),Windows2000 x86版本与其它CPU平台版本实现源码级兼容(因为Windows 2000是基本NT相似的结构,最底层是硬件抽象层HAL,所有我们相信它们之间能源码级兼容)。
WDM驱动程序设计
I/O端口资源的处理
// 遍历资源描述符数组 for (ULONG i = 0; i < nres; ++i, ++resource) { switch (resource->Type) { case CmResourceTypePort: portbase = resource->u.Port.Start; pdx->nports = resource->u.Port.Length; pdx->mappedport = (resource->Flags & CM_RESOURCE_PORT_IO) == 0; break; ... } (接下页 接下页) } 接下页
内存映射寄存器的处理
for (ULONG i = 0; i < nres; ++i, ++resource) { switch (resource->Type) { case CmResourceTypeMemory: membase = resource->u.Memory.Start; pdx->nbytes = resource->u.Memory.Length; break; ... } pdx->membase = (PUCHAR) MmMapIoSpace(membase, pdx->nbytes, MmNonCached); WRITE_REGISTER_UCHAR(pdx->membase +1, ‘A’);
I/O端口资源的处理
// 利用局部变量记录 利用局部变量记录PNP管理器分配的 资源 管理器分配的I/O资源 管理器分配的 typedef struct _DEVICE_EXTENSION { ... PUCHAR portbase; ULONG nports; BOOLEAN mappedport; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; PHYSICAL_ADDRESS portbase; // base address of range ... ... ... ... (接下页 接下页) 接下页
WDM驱动程序简介
设;避免在代码中直接引用硬件
可抢先性和可中断性 多处理器安全 基于对象 数据包驱动 异步
Windows XP 系统结构
WDM驱动程序模型
WDM模型主要包含以下内容:
1、描述了设备驱动程序的标准结构和应该完成的主 要功能。
一个应用程序打开了设备因此系统发送给驱动另一个irp处理函数进行了少量的操作之后返回???操作系统与驱动的交互过程?应用程序尝试读取或者写入一些数据因此系统发送一个irp处理例程将irp放入一个队列之后返回
设备驱动程序设计
第二讲
WDM驱动程序简介
Windows XP 驱动程序分类
内核模式驱动程序的属性
迷你驱动:包含在类驱动中,用于管理设备实例的厂商专有
特征例程。类驱动和迷你驱动合在一起才构成一个完整的 功能驱动程序。
IRP包
WDM驱动的层次结构
上层过滤器驱动程序 功能驱动程序
下层过滤器驱动程序 总线驱动程序
驱动程序如何工作
驱动程序是一个收集让操作系统调用的用来执行各 种涉及到硬件操作的子程序的容器。
某些I/O操作引发设备中断,中断服务例程做一些 很少的操作,然后请求一个DPC,之后返回。
DPC例程运行了,它可能要读回数据,或者继续下 一次的写操作等,然后开始下一个排在队列中的 IRP,之后DPC例程返回系统。
随着时间变化,在这期间系统会发送各种IRP给驱 动程序,驱动程序进行相应的处理。
操作系统与驱动的交互过程
系统运行时设备插入或者系统重新启动发现了某个 设备,系统就会装载可执行的驱动程序到内存中, 并且调用其DriverEntry例程。DriveEntry做了一些 初始化操作之后返回。
构造WDM驱动程序开发环境安装成功WindowsDDK后课件
结构化异常处理
终止处理 Windows应用程序在运行时通常要分配资源,使用这些资源,
然后释放它们 由于异常改变了控制的流程,因此很容易导致无法释放在产
生异常的代码块中分配的资源 使用终止处理程序可以保证进行这样的清除工作
25
结构化异常处理
终止处理
– __try –{ – ... –} – __finally –{ – ... –}
26
结构化异常处理
终止处理 有两种情况可能使受保护段不正常地结束
– 在try块中执行了return、goto、break或continue等控制语句 – 在try块中发生异常
27
结构化异常处理
软件异常 当一个函数执行失败时,习惯上要返回一些特殊的值来,函
数的调用者可以检查这些特殊值并采取一种替代的动作 如果这个调用者是被另一个调用者调用的函数,那么它还需
部分通过资源编译器组合为一个完整的EXE文件 将用户界面资源一类的静态数据与程序代码相分离有如下一
些优点:
– 减少内存要求; – 划清了程序员与用户界面设计人员的任务分工 – 用户界面风格的变化可以不必修改程序代码或只需进行少量的
修改
11
Windows应用程序设计模式
Windows应用程序的开发流程
36
Windows驱动程序模型
WDM以Windows NT 4.0的内部结构为基础,同时引入了 Windows 9x的即插即用特性,为存在于Windows 98和 Windows 2000/XP/2003操作系统中的设备驱动程序提供了 一个统一的参考框架
9
Windows应用程序设计模式
硬件输入
事件驱动
Windows 系统消息队列
《设备驱动程序开发技术》大作业
《设备驱动程序开发技术》大作业WDM驱动程序的开发流程和要点班级:计算机科学与技术1004摘要DWDM(Windows Driver Model)是Microsoft公司推出的一种符合Windows2k/XP下的内核模式驱动程序的分层体系结构的驱动程序模式。
它源于 Windows NT的分层32位设备驱动程序模型,它支持更多的特性,如即插即用( PnP ,Plug and Play )、电源管理( PM ,Power Management )、Windows管理诊断( WMI ,Windows Management Instrumentation )和 NT 事件。
它为Windows操作系统的设备驱动程序提供了统一的框架,在Windows平台上,WDM将成为主流的驱动模式。
WDM是Windows98和Windows2000使用的新的驱动程序设计规范。
使用WDM使得硬件驱动程序更加稳定,让操作系统对硬件更加有效地控制硬件。
除了定义一个驱动程序与操作系统连接的标准接口以外,WDM也指明了驱动程序应该采用的更加模块化的设计。
关键词: WDM、驱动程序、操作系统1 概述WDM(Windows Driver Model)是Microsoft公司推出的一种符合Windows2k/XP下的内核模式驱动程序的分层体系结构的驱动程序模式。
相对于以前的KDM、VXD来说,它的性能更高、系统之间移植更加方便。
随着Microsoft的操作系统的不断升级,WDM已逐步取代了KDM、VXD,成为了Microsoft系统下驱动程序开发的主流。
WDM是通过一个128位的全局唯一标识符(GUID)实现驱动程序的识别。
应用程序与WDM 驱动程序通信时,应用程序将每个用户请求形成I/O请求包(IRP)发送到驱动程序。
驱动程序识别出IRP请求后指挥硬件执行相应操作。
2 WDM驱动模型WDM模型为存在于Windows 98和Windows 2000操作系统中的设备驱动程序提供了一个参考框架。
基于Windows开发WDM设备驱动程序的方法
基于Windows2000开发WDM设备驱动程序的方法摘要:本文介绍了Windows 2000 WDM驱动程序结构及其原理,给出一个驱动程序的例子关键词: WDM 驱动程序1.概述引入了全新的WDM (Win32 Driver Model)的驱动程序架构,说是新技术,其实早在1997年Microsoft就提出了该项技术并在Windows 98中得到了充分的应用,换句话说,Windows 98也支持WDM。
这样WDM就成为了一个跨平台的驱动程序模型不仅如此WDM驱动程序还可以在不修改源代码的情况下经过重新编译后在非Intel平台上运行。
2.WDM设备驱动程序的特点和原理2.1通用驱动程序对基本上一样的硬件,因为他们共享一个总线或完成类似的任务,设备驱动程序可以使用这些标准的驱动程序功能,使公共总线的共享容易,且更容易写出新的驱动程序,总线驱动程序,如USB、1394,和类驱动程序。
(1)Win32程序接口:可以使用Win32函数像访问文件那样访问设备CreateFile() 、Closehandle()、ReadFile()、WriteFile()、DeviceIoControl ()用于发出特殊请求,可发送数据给驱动和从驱动得到数据,IOCTL代码可以是预先定义的也可是自己定义的。
(2)创建设备大多数WDM设备对象都是在PnP管理器中调用AddDevice入口时创建,这个PnP 例程在插入新设备和安装Inf文件时被调用,此后一系列的PnP IRP 被发送到驱动程序,指示设备应如何启动和查询它的功能2.2WDM-的工作原理WDM是在NT 4.0驱动程序结构上发展起来的,所以它与NT 4.0驱动程序极为相似,但是它却有了本质上的提高,比如它支持USB、IEEE 1394、ACPI等全新的硬件标准。
虽然Windows 98与Windows 2000都支持WDM,可是并不意味着Windows 98下的VxD可以在 Windows 2000下运行,而NT下的WDM却可以在Windows 98下运行。
开发WDM型USB设备驱动程序
开发WDM型USB设备驱动程序USB设备驱动程序开发⼯具开发USB设备驱动程序需要专门的开发⼯具,⽬前应⽤⼴泛的⼯具主要有两⼤类。
⼀类是Microsoft公司提供的Windows DDK(Device Driver Kit)。
它有Windows 98 DDK 和Windows 2000 DDK两个版本。
Windows 98 DDK能够开发Windows 95/98/Me/NT下的VxD、KMD和WDM驱动程序。
Windows 2000 DDK 能够开发Windows 98/Me/NT/2000下的KMD和WDM驱动程序。
由于DDK基于汇编语⾔的编程⽅式和内核模式的调⽤,对没有深厚的OS原理和编程⽔平的⼈员来说,任务相当艰巨。
另⼀类是NuMega公司提供的DriverStudio,它是⼀个⼤的开发⼯具包,包含VtoolsD、SoftICE和DriverWorks等开发⼯具。
VtoolsD开发包提供了对VxD编程的C/C++类库⽀持,利⽤VtoolsD中的QuickVxD⼯具可以快速⽣成VxD的C/C++代码框架,开发者可以在此基础上根据各⾃的需要添加⾃⼰的代码。
DriverWorks⽤于开发KMD和WDM驱动程序,并且对DDK函数进⾏了类的封装,从⽽为开发Windows NT、Windows 2000和Widnwos98 WDM设备驱动程序提供了⼀个⾃动化的⽅法。
DriverWorks,提供了VC++下的开发向导Driver Wizard,按照它的提⽰可以迅速地⽣成驱动程序的框架。
这个框架结构提供可以正确执⾏WDM动态环境中IRP的请求,⽽且,也包含⽤于简化系统提供的标准类驱动程序(如HID、流)和总线驱动程序(如PCI和USB)接⼝的类等。
总之,利⽤DriverWorks开发WDM驱动程序,可以⼤⼤简化开发⼈员的⼯作量、缩短开发周期以及降低开发驱动程序的难度。
[1]⽤DriverWorks开发WDM型USB设备驱动程序要想使⽤DriverWorks,必须先安装以下软件:DriverStudio2.5,VisualStudio6.0,以及Windows2000DDK。
wdm设备驱动程序入门共39页文档
应用程序对设备对象的操作过程
操作接口:设备驱动程序的Win32 API函数,或重载的设备驱动程序的 Win32 API回调函数。 操作参数:设备句柄、操作类型及其它信息。 例:DeviceIoControl(hDevice, DIOC_MY_IO, NULL, 0,
NULL, 0, NULL,NULL); Win32子系统处理:将I/O操作转换后交I/O管理器处理, I/O管理器创建 一个I/O请求包(IRP)后,送到设备对象栈的最上层设备对象对应的驱动 程序。
已装 入?
执行DriverEntry(),设置各例程 的入口地址,将对象指针装入I/O 管理器中
PnP管理器装入最底层过滤驱动程序,调用其 AddDevice函数,该函数创建一个FiDO,实现FiDO与 同级驱动程序的连接
AddDevice函数把PDO连接到FiDO上 PnP管理器依次装入各级驱动程序,完成整个设备对象栈
PnP管理器根据需要给设备发送各种PnP IRP PnP管理器给设备发送“启动设备”PnP IRP,驱动程序将分 配的资源信息向下传送到设备配置头区域中,并启动设备
驱动程序处于等待状态,等待IRP的到来
WDM驱动程序的结构
WDM驱动程序包含许多例程,操作系统调用这些例程来执
行对IRP的各种操作。
Hale Waihona Puke 基本驱动程序例程取得厂商、设备类型、版本、资源需求等信息
PnP管理器就创建PDO,在注册表中添加某些项
N
所有硬件检测完毕?
Y PnP管理器决定分配哪些资源给各个设备
设备驱动程序的装入过程
PnP管理器查找注册表中与该PDO相吻合的各级驱 动程序
找到? N
Y
读INF文件,按INF文 件指令安装各级驱动
WDM驱动程序设计之编译安装篇
设计开发好自己的WDM驱动程序后,为了运行该驱动程序,我们必须编译和安装它们。
编译设备驱动程序的方法安装DDK后,在DDK程序组下有Check和Free两个编译环境,Check环境用于编译带调试信息的驱动程序,Free则是编译正式发布版本的环境。
通常情况下设备驱动程序的编译采用命令行的方式。
通过一定的设置可以在VC ++的集成环境下编译。
一般来说,成功编译一个最基本的设备驱动程序需要四个文件,第一个是驱动程序,即C语言源程序文件(例如vdisk.c,注意下面所有的例子都是以vdisk来说明);第二个是RC 文件(例如vdisk.rc);第三个是sources文件;第四个文件是makefile.rc文件。
sources 文件和make文件类似,用来指定需要编译的文件以及需要连接的库文件。
这三个辅助文件都很简单,在DDK samples的每个例程里都有三个这样的文件,依样画瓢就能理解它们的结构和意义。
1.举例分析以下以vdisk程序为例,设vdisk.rc代码为:/vdisk.rc/#include#include#define VER_FILETYPE VFT_DRV#define VER_FILESUBTYPE VFT2_DRV_SYSTEM#define VER_FILEDESCRIPTION_STR "SCSI VDisk Driver"#define VER_INTERNALNAME_STR "vdisk.sys"#define VER_ORIGINALFILENAME_STR "vdisk.sys"#include "common.ver"/end of vdisk.rc/设备驱动程序一般都使用Build实用程序来进行,Build只是NMAKE外面的一个外包装程序。
Build本身其实相当简单,编译的大部分工作实际上由Build传递给NMAKE来进行。
WDM驱动程序的开发与实现
通过三种方式 :读写硬件 IO端 口、响应硬件 中 /
断、 读写内存。在 Wi o sx n w9 系统下 , d 应用程序还 可以直接读写 IO端 口, / 但应用程序和硬件端 口 的通信还是 受到虚 拟机的监控 。而 对于 Wi n — dwN 、 no s0 0 o s T Wi w2 0 及以后的操作系统 . d 应用程 序只能通过设备驱动程序和硬件进行通信。
a dp o u e B a tain e a l. n rd c saUS cu t x mpe o
Ke r s d i e ;n e r p ; DM ; o y wo d : r r i tru t W v pr t
0 引言
在许多实际应用中.软件开发往往需要 和硬 件设备打交道。程序和硬件的通信一般来说可 以
WD 驱动程序 的开发与实现 M
郭 四稳
( 广ห้องสมุดไป่ตู้大学计算机教育软件研究所 , 广东 广州 500 ) 10 6
摘
要 : M 是在 Widw T . WD n o sN 40驱动 程 序 结构 上发 展起 来的 . M 体 系结构 实行 分 层 处 WD
理, 是一种通用的驱动模 式. 提供 了包括 U B IE I 4 H D等在 内的一 系列驱动程序类。 S 、 E3 和 I E 9 文章描述 了 WD M驱动程序 的体 系结构和利用 D i rt i r e u o开发 WD vSd M驱 动程序 的过程 , 给
任何 I0设备有全部的访问权 ,还能访 问任何虚 / 拟地址和控制虚拟内存硬件。
Wid w 0 0是 继 Widw T 40的新 一 n o s2 0 n o sN .
1 WD 的工作原理 M
WDM驱动程序入门(2)——驱动程序的小秘密
WDM驱动程序入门(2)——驱动程序的小秘密好啦,辛辛苦苦终于写完了程序,让我们编译运行吧!按下Ctrl+F5(嘿嘿,让我们先假设你习惯用VC来写程序),我等啊等……疑?怎么毫无动静的?再看看Output窗口,哇!有几百个错误啊!!不禁头大——这是怎么回事呢?原来,WDM程序编译出来的并不是我们常见的.exe,而是.sys文件,在未经设置编译环境之前,是不能直接用VC来编译的(这就是为什么会有几百个错误了)。
这种类型的文件你可以在WINNT/System32/Drivers里面找到很多。
其实驱动程序也是一种PE 文件,它同样由DOS MZ header开头,也有完整的DOS stub和PE header,同样拥有Import table和Export table——hoho……那跟普通的PE文件有什么不一样呢?伟大的领袖毛主席教育我们,实践是检验真理的唯一标准。
那么就让我们先来做个小剖析,加深对.sys文件的认识吧!(如果你对.sys的内部细节没有兴趣的话,可以略过不看。
^_^)首先祭出Delphi里附带的tdump.exe程序(别问我为什么用这个,这只是纯粹的习惯问题)。
让我们键入:C:/WINNT/System32/Drivers>tdump ccport.sys -em -ee参数-em是列出Import table,-ee是列出Export table。
回车之后,屏幕列出一大堆东西:C:/WINNT/SYSTEM32/DRIVERS>tdump ccport.sys -em -ee Turbo Dump Version 5.0.16.12 Copyright ? 1988, 2000 Inprise CorporationDisplay of File CCPORT.SYSIMPORT: NTOSKRNL.EXE={hint:011Fh}.’memcpy’IMPORT: NTOSKRNL.EXE={hint:003Dh}.’IoDeleteDevice’IMPORT: NTOSKRNL.EXE={hint:0030h}.’IoAttachDeviceT oDeviceStack’IMPORT: NTOSKRNL.EXE={hint:008Eh}.’KeSetEvent’IMPORT: NTOSKRNL.EXE={hint:0068h}.’IofCallDriver’IMPORT: NTOSKRNL.EXE={hint:0095h}.’KeWaitForSingle Object’IMPORT: NTOSKRNL.EXE={hint:0074h}.’KeInitializeEvent’IMPORT: NTOSKRNL.EXE={hint:003Fh}.’IoDetachDevice’IMPORT: NTOSKRNL.EXE={hint:00D3h}.’RtlFreeUnicodeS tring’IMPORT: NTOSKRNL.EXE={hint:0077h}.’KeInitializeSpinL ock’IMPORT: NTOSKRNL.EXE={hint:0129h}.’strcpy’IMPORT: NTOSKRNL.EXE={hint:0121h}.’memset’IMPORT: NTOSKRNL.EXE={hint:003Ch}.’IoCreateUnprote ctedSymbolicLink’IMPORT: NTOSKRNL.EXE={hint:0038h}.’IoCreateDevice’IMPORT: NTOSKRNL.EXE={hint:00C2h}.’RtlAnsiStringToU nicodeString’IMPORT: NTOSKRNL.EXE={hint:0069h}.’IofCompleteReq uest’IMPORT: NTOSKRNL.EXE={hint:0124h}.’sprintf’IMPORT: NTOSKRNL.EXE={hint:003Eh}.’IoDeleteSymboli cLink’IMPORT: NTOSKRNL.EXE={hint:0042h}.’IoFreeIrp’IMPORT: NTOSKRNL.EXE={hint:004Dh}.’IoInitializeIrp’IMPORT: NTOSKRNL.EXE={hint:002Dh}.’IoAllocateIrp’IMPORT: NTOSKRNL.EXE={hint:0027h}.’InterlockedExcha nge’IMPORT: NTOSKRNL.EXE={hint:0025h}.’InterlockedCom pareExchange’IMPORT: NTOSKRNL.EXE={hint:0035h}.’IoCancelIrp’IMPORT: NTOSKRNL.EXE={hint:012Ah}.’strlen’IMPORT: NTOSKRNL.EXE={hint:0126h}.’strcat’IMPORT: NTOSKRNL.EXE={hint:0114h}.’atoi’IMPORT: NTOSKRNL.EXE={hint:0128h}.’strcmp’IMPORT: NTOSKRNL.EXE={hint:0034h}.’IoBuildSynchron ousFsdRequest’IMPORT: NTOSKRNL.EXE={hint:00D5h}.’RtlInitAnsiString’IMPORT: HAL.DLL={hint:0006h}.’KfAcquireSpinLock’IMPORT: HAL.DLL={hint:0009h}.’KfReleaseSpinLock’EXPORT ord:0001=’Vcomm_DriverControl’我们可以很清楚地看到,它主要调用了NTOSKRNL.EXE和HAL.DLL文件(实际上你会发现,几乎所有的WDM驱动程序都会调用NTOSKRNL.EXE文件,从它的名字你可以看出为什么了吧?),并且输出了一个函数“Vcomm_DriverControl”。
WDM驱动程序
建立驱动开发环境建立驱动开发环境,所需的软件为DriverStudio3.2 + DDK2003 + VC。
DDK建议使用最新的DDK2003,因为可以减少很多麻烦。
使用DDK2600的话,很多人反映会碰到一个编译出错的问题。
这是我使用DDK2600时碰到的同样的问题,然后在EDNchina网站上发的贴:--------------我在用DriverStudio开发驱动时,碰到了这样的问题:--------------------Configuration: KFileWrite - Win32Free--------------------d:\DESIGN~1\DRIVER~1\DRIVER~4\include\kcsq.h(35): Could not find the file csq.h.d:\DESIGN~1\DRIVER~1\DRIVER~4\include\kcsq.h(35): Could not find the file csq.h.Linking with DDK linker...LINK : fatal error LNK1181: cannot open input file 'ntstrsafe.lib' Error executing link.exe.KFileWrite.sys - 1 error(s), 0 warning(s)关键是这个ntstrsafe.lib.我在网上一搜,碰到这种问题的人还不少呢,虽然解决方法是很多,但都差不了几个字,要么从DDK2003那拷一个,或者是在project-->setting-->link下去掉对ntstrsafe.lib的链接,也不知他们自己到底有没有试,我在project-->setting-->link下压根就没看到ntstrsafe.lib几个字...很郁闷啊--------------网上所说的解决方法是对的,但没有说清楚,使人无法一时明白。
WDM入门教程
WDM入门教程学习和编写WDM 驱动程序对谁而言都是一件具有挑战的事情,需要恒心和毅力。
当你入门后你会发现这是一件多么令人兴奋的事情。
但是如何使用WDM的编译环境从而开始WDM学习的旅程?对一个初学者来说这个门槛可不低。
安装完DDK后,可以用[开始]->[Development kit]->[Windows XX DDK]->[check/free Build Environment]来启动编译环境,由于DDK没用提供IDE环境(当然你可以使用配置后的VC或DriverStudio这另当别论),对于我们这些孕育在Xp时代的程序员来说这无疑是件难事。
为什么?因为编译一个WDM程序除了.cpp .h 源文件外至少还需要:makefile文件sources 文件这两个文件本应该由IDE自动帮我们生成,如VC就为我们的所有工程生成了makefile,sources,xx.rc文件,平时我们根本不需要了解他们就可以编译我们的工程。
可DDK没有工具为我们生成这两个文件,但DDK编译程序的时候又需要他们,俗话说得好“我不如地狱谁入地狱”,我们就来编写这两个文件:一.makefile (没有扩展名,它名字就叫makefile),内容如下:# DO NOT EDIT THIS FILE Edit .\sources. if you want to add a new source# file to this component. This file merely indirects to the real make file# that is shared by all the components of NT.#!INCLUDE $(NTMAKEENV)\makefile.def值得高兴的是,WDM程序使用的所有makefile都这样写,我们只需写一个,编译时把它拷贝到工作目录下就行了二.sources文件就需要我们根据不同的场合修改了,不过基本模板如下:TARGETNAME=驱动程序名// 告诉编译器连接生成的文件名为“驱动程序名”(不含扩展名)TARGETPATH=obj // 固定不变TARGETTYPE=DRIVER // 固定不变(表明,连接成*.sys <驱动程序>文件)DRIVERTYPE=WDM // 为 Win32 Driver Model 驱动INCLUDES=$(BASEDIR)\inc\ddk;$(BASEDIR)\inc // 源程序可能使用的DDK头文件所在的目录// 多个目录用“;” 隔开SOURCES=aa.cpp bb.cpp // 将编译的源文件(不写*.h), 资源文件(*.rc)// 多个文件用空格隔开其中“$(BASEDIR)”指DDK当前的安装目录,例如当前DDK安装在D:上,则$(BASEDIR) 就是“D:\DDK”,所以上面的INCLUDES可以翻译成D:\DDK\inc\ddk; D:\DDK\inc三.不得不注意的3个讨厌问题:1. 编译时必须保证 makefile,sources和源程序在同一目录下2. 编写sources文件时,其中的”=”两边不能有空格3. 如果上面的问题还不够讨厌,那么下面这个问题可以讨厌的让人放弃学习DDK,工程的工作目录的绝对路径中不能出现空格,如“C:\Documents and Settings\MyProgramme\”将不能被DDK编译器编译,而且表面上看来DDK好像是完成的编译,实际上它什么都没做!1:首先安装好WDK,然后进入"开始"->"所有程序"->"Windows Driver Kits"->"WDK XXXX.XXXX.X" ->"Windows XP"->"x86 Checked Build Environment"在弹出来的命令行窗口中输入"Build",让它自动生成所需要的库,等待它执行完2:打开VS2005,在菜单上选择"工具"->"选项"弹出"选项"窗口,选择"项目和解决方案"->"VC++目录","显示以下内容的目录""可执行文件"中添加"F:\WinDDK\7600.16385.0\bin\x86\x86" "F:\WinDDK\7600.16385.0\bin\x86" "F:\WinDDK\7600.16385.0\tools\pfd\bin\bin\x86""包含文件"中添加"F:\WinDDK\7600.16385.0\inc\api" "F:\WinDDK\7600.16385.0\inc\crt" "F:\WinDDK\7600.16385.0\inc\ddk""引用文件"中添加"F:\WinDDK\7600.16385.0\lib\wxp\i386""库文件"中添加"F:\WinDDK\7600.16385.0\lib" "F:\WinDDK\7600.16385.0\lib\wxp\i386""源文件"中添加"F:\WinDDK\7600.16385.0\src"以上添加完毕直接按"确定"关闭"选项"对话框如果编译出现C2144错误的时候,请把以上添加的文件向前移动(就是点击"选项"对话框中的向上的箭头按钮)3:新建工程后配置管理器:新建:Checked4:工程属性:c++:预处理器:_X86_调用约定:__stdcallLINK:输出文件:后缀为sys $(OutDir)\$(ProjectName)。
基于WDM的驱动程序开发研究实现
基于WDM的驱动程序开发研究实现【摘要】:文章首先分析了WDM的工作原理和机制,并结合实例着重探讨了基于WDM的设备驱动程序的设计和实现方法。
【关键词】:WDM; 分层结构; 驱动程序一、引言WDM(Windows Driver Model,Windows驱动程序模式)是Microsoft最新推出的一种驱动程序模型,旨在实现在对新硬件支持的基础上,进一步降低所需驱动程序的数量和复杂性,起到简化驱动程序的开发过程的目的。
WDM属于操作系统的内核模式,其驱动程序由运行于内核模式的系统代码组成。
它采用灵活的分层驱动方法,即在用户应用程序和物理设备之间存在着几个不同的驱动程序层次,且各层上的WDM驱动程序具有不同的优先级。
这种分层机制使得WDM 能够定义更加广泛更加通用的驱动程序,其可包括各种文件系统、网络组件和专用设备等。
二、WDM(一)WDM的分层结构如图1所示,WDM体系结构实行分层处理,即设备驱动被分为:高层驱动程序、中间层驱动程序、底层驱动程序。
每层驱动再把I/O请求划分成更简单的请求,以传给更下层的驱动执行。
最底层的驱动程序在收到I/O请求后,通过硬件抽象层,与硬件发生作用,从而完成I/O请求工作。
在这样的架构下,当外设发生改变时,只要改变程序栈中的一个或几个驱动程序即可,而处于最上层的用户应用程序可完全不变。
对于硬件设备的开发者而言,只需要开发设备驱动程序就可以了,因为底层的驱动程序都由主板厂商和微软提供。
WDM引入设备对象的概念来描述一个设备,主要包含物理设备对象(Physical Device Object,PDO)、功能设备对象(Functional Device Object,FDO)和过滤设备对象(Filter Device Object,Filter DO)。
其中,PDO对应实际的物理设备,FDO和Filter DO是相应驱动程序的处理对象。
一个物理设备有且只有一个PDO和一个FDO,但却可以拥有多个Filter DO。
WDM驱动程序开发文档
WDM驱动程序开发文档WDM(Windows Driver Mode)是MS提供的98和NT 5.0下的通用的驱动程序模型。
相比起以前的KDM和VXD来说,它的性能更高、系统之间移植更加方便。
所以,随着系统的升级(指MS的操作系统),WDM已经逐步取代KDM和VXD,成为MS系统下驱动程序开发的主流。
(关于Windows下的驱动程序编写,查看参考文献1)第一部分从操作系统看驱动程序Windows NT的系统结构决定了NT下访问设备的特殊性。
NT是建立在Mach和Vax思想上的一种客户/服务器模型操作系统,由一个特权执行体以及一系列被称为保护子系统的非特权服务器组成。
整个操作系统被分为用户态模式和核心态模式。
所谓特权,是指处理器的操作方式,大多数的处理器都有一种甚至若干种特权方式。
在特权方式方式下,所有机器指令都可执行并且系统内存可存取。
在非特权方式方式下,某些机器指令不能执行并且系统内存不可存取。
在Windows NT下,核心态就是指处于特权处理器方式下,而用户态总处于非特权处理器方式。
核心态模式又被称为NT执行体,包括了系统服务和硬件描述层(HAL),它们运行于CPU 的特权层Ring0(在驱动程序内部,在不同部分还分为不同权限层)。
系统服务包含了一个操作系统的所有应有服务,文件系统,进程控制,内存管理,设备管理等等。
NT中除了微内核外,另外还包含了一些独特的部分,如对象管理器,配置管理器,执行体支持,本地过程调用,安全监视器,所有这些都建立在HAL之上。
IO管理器实现对设备的管理,包含了文件系统,中间介质和设备驱动。
通过HAL,NT可以防止内核和NT执行体的其它部分受硬件平台不同的影响。
另外NT还将网络管理器加入了核心态模式。
用户态模式包括了一些保护子系统,如OS/2子系统,POSIX子系统,安全子系统,当然还有最常用的Win32子系统,NT都称之为服务器。
它们运行于CPU的用户层Ring3,建立在服务器上的各类应用程序被称为客户。
WDM驱动程序设计
现在Windows98和Windows2000已经成了主流操作系统的主流,原先用来实现驱动程序的VxD技术随着Win95的淡出也慢慢地将退出历史舞台,在Windows98和Windows2000中设备驱动程序将根据Windows驱动程序模型(WDM)来设计。
WDM通过提供一种灵活的方式来简化驱动程序的开发,在实现对新硬件支持的基础上减少并降低所必须开发的驱动程序的数量和复杂性。
WDM驱动程序设计一.WDM简介微软不断推出新的操作系统,现在Windows98和Windows2000已经成了主流,原先用来实现驱动程序的VxD技术随着Win95的淡出也慢慢地将退出历史舞台,在Windows98和Windows2000中设备驱动程序将根据Windows驱动程序模型(WDM)来设计。
WDM通过提供一种灵活的方式来简化驱动程序的开发,在实现对新硬件支持的基础上减少并降低所必须开发的驱动程序的数量和复杂性。
Windows驱动程序模型分两个方面,除了核心模型描述设备驱动程序的标准结构外,WDM还为常见类型的设备实现了一个模块化的、分层次类型的总线驱动程序和类驱动程序。
总线驱动程序实现了支持通用串行总线(USB)、IEEE1394(FireWire)协议等。
类驱动程序是为实现标准Windows功能提供条件。
WDM对标准类接口的支持减少了Windows 95和Windows NT所需的设备驱动程序的数量和复杂性。
在Windows平台上,WDM将成为21世纪主流的驱动模式。
WDM支持USB、IEEE 1394、ACPI等全新的硬件标准。
而且以往在两个平台上同时运行时需要编写两个截然不同的驱动程序,现在只需要编写一个WDM驱动程序就可以了。
WDM驱动程序也是分层的,即不同层上的驱动程序有着不同的优先级,而Windows 9x下的VxD则没有此结构。
WDM还引入了功能设备对象FDO(Functional Device Object)与物理设备对象PDO(Physical Device Object)两个新类来描述硬件,一个PDO对应一个真实硬件。
开发WDM型的USB设备驱动程序
开发WDM型的USB设备驱动程序作者:鲜征征杨皓发布时间:2004-11-21 12:57:25 摘要: 文章介绍了USB和WDM驱动程序的基本概念和结构,结合实例阐述了用NuMega 公司的DriverStudio工具包开发Windows 2000环境下WDM USB设备驱动程序的方法,并给出关键例程主要代码。
关键词:USB WDM 设备驱动程序DriverStudio引言随着微机技术水平的日益提高,传统的计算接口已经不能满足当前计算机高速发展的需求,计算机业界迫切需要新的通用型、高速总线接口。
通用外设接口标准USB应运而生。
USB,全称为通用串行总线(Universal Serial Bus),它是Compaq、IBM等PC大厂商联合开发的一种新型的、基于令牌的、高速的串行总线标准。
开发者要设计USB设备接口,就必须首先了解USB协议,在此基础上有针对性的开发USB设备驱动程序。
USB简介在众多的PC机总线中,USB以其突出的优点独树一帜:① 使用方便。
支持热拔插,不涉及中断请求(IRQ)冲突等问题,能真正做到“即插即用”。
②传输速率高。
目前的USB 2.0协议速度高达480Mbps 。
③易于扩展。
通过使用Hub扩展可连接多达127个外设。
④使用灵活。
USB共有4种传输模式:控制(control)、同步(Synchronization)、中断(interrupt)、批量(bulk),以适应不同设备的需要。
⑤独立供电。
正由于上述优点,开发USB接口的设备已成为一种发展趋势。
一个完整的USB系统包括主机系统和USB 设备。
所有的传输事务都是由主机发起的。
一个主机系统又可以分为以下几个层次结构,如图1所示:图1 USB 互连通信模型USB总线接口包括USB主控制器和根集线器,其中USB主控制器负责处理主机与设备之间电气和协议层的互连,根集线器提供USB设备连接点。
USB系统使用USB主控制器来管理主机和USB设备之间的数据传输,另外它也负责管理USB资源,如带宽等。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
PCI开发板WINDOWS驱动程序说明及开发流程PCI开发板的WINDOWS驱动程序采用DRIVERWORKS提供的WDM驱动程序框架构造支持IO内存和DMA及中断操作采用稳定的DRIVERWORKS2.5版本完全支持PCI结构用户可以在网上下载我们也可以提供以下是DRIVERWORKS的驱动产生向导流程说明在插入PCI开发板前请首先安装DRIVERWORKS2.5和NTDDK安装完成后再正确安装PCI开发板开机进入WINDOWS98界面后系统会自动找到PCI开发板如图选择下一步指定驱动程序的路径后显示系统找到后显示单击下一步系统完成驱动程序安装驱动程序安装完成后在我电脑里的系统属性里会出现表示开发板使用的中断和IO范围及内存范围以下为DRIVERWORKS的驱动程序构造向导流程说明单击DRIVER WIZARD图标显示选择产生一个新的驱动程序输入工程名字和目录,显示点击下一步显示选择WDM驱动程序模式,用户也可以选择NT4.0的驱动模式选择下一步,显示:选择PCI设备,VENDOR ID 1100,DEVICE ID 4252,选择下一步选择下一步:选择驱动属性,选择下一步:选择是否队列化IO请求,用户根据自己需要确定选择是否REGISTRY选择添加一个IO端口,添加中断,如果使用了DMA数据传送,选择添加DMA代码选择设备类的操作函数,用户根据自己需要添加选择是否生成一个应用程序和选项点击FINISH,完成驱动生成向导以下介绍开发板自带测试驱动程序的使用说明执行EXE里的程序后显示程序首先检测是否存在PCI开发板其次检测开发板上的SRAM是否读写正常检查SRAM也是执行IO操作的例子DMA模式选择输入0选择DMA读测试输入1选择DMA 写测试操作选择后开始DMA及中断测试以下是驱动程序的源代码注释及说明用户双击PCIWDM.DSW”文件进入VC6.0编辑状态中如图工程包含两个项目,一个是驱动程序,一个是测试程序PCIWDM是驱动程序,TEST_PCIWDM是测试应用程序注意编译使用前需要设置DRIVERWORKS和NTDDK,选择菜单里面的WRIVERSTUDIO中的DRIVER BUILDING SETTING设置NTDDK路径和CPU类型,类型选择I386,如图编译选择批构件,不要编译IA64的项目,如图编译后生成SYS文件和EXE文件以下是源代码分析:NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_800_Handler(KIrp I) {NTSTATUS status = STATUS_SUCCESS;//LED灯显示程序long j;m_IoPortRange0.outd(0x48,0x1);//灯1亮//DELAY 1秒for (j=0;j<2000000;j++) {m_IoPortRange0.outd(0xf0,0x0);}m_IoPortRange0.outd(0x48,0x2);//灯2亮//DELAY 1秒for (j=0;j<2000000;j++) {m_IoPortRange0.outd(0xf0,0x0);}m_IoPortRange0.outd(0x48,0x3);//灯1,2亮//DELAY 1秒for (j=0;j<2000000;j++) {m_IoPortRange0.outd(0xf0,0x0);}m_IoPortRange0.outd(0x48,0x0);//灯1,2熄rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_801_Handler(KIrp I) { //7段数码管显示程序NTSTATUS status = STATUS_SUCCESS;int i=0;j=0;longdo {//7段数码管从0至F显示if (i==0) m_IoPortRange0.outd(0x40,0x808);if (i==1) m_IoPortRange0.outd(0x40,0x3e3e);if (i==2) m_IoPortRange0.outd(0x40,0x4444);if (i==3) m_IoPortRange0.outd(0x40,0x1414);if (i==4) m_IoPortRange0.outd(0x40,0x3232);if (i==5) m_IoPortRange0.outd(0x40,0x1111);if (i==6) m_IoPortRange0.outd(0x40,0x101);if (i==7) m_IoPortRange0.outd(0x40,0x3c3c);if (i==8) m_IoPortRange0.outd(0x40,0x0);if (i==9) m_IoPortRange0.outd(0x40,0x1010);if (i==0xa) m_IoPortRange0.outd(0x40,0x2020);if (i==0xb) m_IoPortRange0.outd(0x40,0x303);if (i==0xc) m_IoPortRange0.outd(0x40,0x4949);if (i==0xd) m_IoPortRange0.outd(0x40,0x606);if (i==0xe) m_IoPortRange0.outd(0x40,0x4141);if (i==0xf) m_IoPortRange0.outd(0x40,0x6161);i++;for (j=0;j<2000000;j++) {m_IoPortRange0.outd(0xf0,0x0);}}(i<16);whilem_IoPortRange0.outd(0x40,0xffff);rmation() = 0;returnstatus;}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_802_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//按键输入测试程序PTEST_MESSAGE pInput = static_cast<PTEST_MESSAGE>(I.IoctlBuffer()); pInput->Outdata=m_IoPortRange0.ind(0x58);//读入按键状态if(I.IoctlOutputBufferSize() < sizeof(PTEST_MESSAGE)!I.IoctlBuffer())||{0;=rmation()STATUS_INV ALID_PARAMETER;return}pInput =(PTEST_MESSAGE)I.IoctlBuffer();rmation() = 4;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_803_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//16C450串口发送1000字节测试long jj;m_IoPortRange0.outd(0x2c,0x3);//8位方式,1个停止位,无效验k=0x61;intinti=0;val;intj;int{doval=m_IoPortRange0.ind(0x34);if ((val&0x60)==0x60) {m_IoPortRange0.outd(0x20,k);//发送数据k=k++;if{k=0x61;}(k>=0x7b)i++;}} while (i<1000);rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_804_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//16C450接收100个字节PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); pInput->Data=m_IoPortRange0.ind(pInput->Add);if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;rmation()=STATUS_INV ALID_PARAMETER;return}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_805_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//ADC测试PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); m_IoPortRange0.outd(0x44,0x2);//地址切换至ADCm_IoPortRange0.outd(0xb0,pInput->Add);//输入采样通道for (int j=0;j<200;j++) {m_IoPortRange0.outd(0xf0,0x0);//延迟100US}pInput->Data=m_IoPortRange0.ind(0xb0);//读入采样值m_IoPortRange0.outd(0x44,0x0);//地址切换至直接地址寻址方式if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;rmation()=STATUS_INV ALID_PARAMETER;return}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_806_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//开关量输入测试PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); pInput->Data=m_IoPortRange0.ind(0x50);//读入开关量输入状态if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;=rmation()STATUS_INV ALID_PARAMETER;return}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_807_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;// 开关量输出测试m_IoPortRange0.outd(0x54,0x3);//开关量输出for (long j=0;j<5000000;j++) {m_IoPortRange0.outd(0xf0,0x0);//延迟2秒}m_IoPortRange0.outd(0x54,0x0); //关闭开关量输出rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_808_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//SRAM写测试PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); m_MemoryRange0.outd(0x100000+(pInput->Add),pInput->Data);//SRAM写测试rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_809_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//SRAM读测试PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer());pInput->Data=m_MemoryRange0.ind(0x100000+(pInput->Add));//读SRAM数据 if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;rmation()=returnSTATUS_INV ALID_PARAMETER;}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_80A_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;//FLASH读ID测试PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); m_MemoryRange0.outd(0x200000,0xf0f0);m_MemoryRange0.outd(0x200000+(0x555<<2),0xaaaa);m_MemoryRange0.outd(0x200000+(0x2aa<<2),0x5555);m_MemoryRange0.outd(0x200000+(0x555<<2),0x9090);mid=m_MemoryRange0.ind(0x200000);longm_MemoryRange0.outd(0x200000,0xf0f0);m_MemoryRange0.outd(0x200000+(0x555<<2),0xaaaa);m_MemoryRange0.outd(0x200000+(0x2aa<<2),0x5555);m_MemoryRange0.outd(0x200000+(0x555<<2),0x9090);did=m_MemoryRange0.ind(0x200000+(0x1<<2));longpInput->Data=mid + (did<<16);if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;=rmation()STATUS_INV ALID_PARAMETER;return}m_MemoryRange0.outd(0x200000,0xf0f0);pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_80B_Handler(KIrp I){ //FLASH擦除测试NTSTATUS status = STATUS_SUCCESS;long j=0;m_MemoryRange0.outd(0x200000,0xf0f0);m_MemoryRange0.outd(0x200000+(0x555<<2),0xaaaa);m_MemoryRange0.outd(0x200000+(0x2aa<<2),0x5555);m_MemoryRange0.outd(0x200000+(0x555<<2),0x8080);m_MemoryRange0.outd(0x200000+(0x555<<2),0xaaaa);m_MemoryRange0.outd(0x200000+(0x2aa<<2),0x5555);m_MemoryRange0.outd(0x200000+(0x555<<2),0x1010);//延迟40秒for (j=0;j<100000000;j++) {m_IoPortRange0.outd(0xf0,0x0);}m_MemoryRange0.outd(0x200000,0xf0f0);rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_80C_Handler(KIrp I){ //FLASH编程测试NTSTATUS status = STATUS_SUCCESS;PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer()); long j=0;m_MemoryRange0.outd(0x200000+(0x555<<2),0xaaaa);m_MemoryRange0.outd(0x200000+(0x2aa<<2),0x5555);m_MemoryRange0.outd(0x200000+(0x555<<2),0xa0a0);m_MemoryRange0.outd(0x200000+((pInput->Add)<<2),pInput->Data); //延迟20微秒for (j=0;j<100;j++) {m_IoPortRange0.outd(0xf0,0x0);}rmation() = 0;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_80D_Handler(KIrp I){ FLASH读测试NTSTATUS status = STATUS_SUCCESS;PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer());pInput->Data=(m_MemoryRange0.ind(0x200000+((pInput->Add)<<2))) & 0xffff;if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU)!I.IoctlBuffer())||{0;=rmation()STATUS_INV ALID_PARAMETER;return}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_80E_Handler(KIrp I){ DMA读写测试NTSTATUS status = STATUS_SUCCESS;PKS_PASSTHRU pInput = static_cast<PKS_PASSTHRU>(I.IoctlBuffer());m_IoPortRange0.outd(0x4,0);if ((PADAPTER_OBJECT)m_Dma == NULL){Invalidate();STATUS_UNSUCCESSFUL;return}m_DmaBuffer.Initialize(&m_Dma,0x100000);if (m_DmaBuffer.VirtualAddress() == NULL){m_DmaBuffer.Invalidate();STATUS_UNSUCCESSFUL;return}m_PAddr=m_DmaBuffer.LogicalAddress().LowPart;m_LAddr=m_DmaBuffer.VirtualAddress();m_IoPortRange0.outd(0x4,0x0);//写dma传送首地址m_IoPortRange0.outd(0x8,m_PAddr);pp=1;//写dma传送字节数m_IoPortRange0.outd(0xc,0x80000);//开中断m_IoPortRange0.outd(0x4,0x2);//根据模式来判断是dma读还是写kk=pInput->Data;(pInput->Data==0x0)if{m_IoPortRange0.outd(0x44,0x1);m_IoPortRange0.outd(0xa0,0x4);m_IoPortRange0.outd(0xa0,0x0);m_IoPortRange0.outd(0xa0,0x8);m_IoPortRange0.outd(0xa0,0x0);m_IoPortRange0.outd(0xa4,0x8000);m_IoPortRange0.outd(0xa0,0x10);m_IoPortRange0.outd(0x10,0x1);}if (pInput->Data==0x1){m_IoPortRange0.outd(0x44,0x1);m_IoPortRange0.outd(0xa0,0x4);m_IoPortRange0.outd(0xa0,0x0);m_IoPortRange0.outd(0xa0,0x8);m_IoPortRange0.outd(0xa0,0x0);m_IoPortRange0.outd(0xa8,0x8000);m_IoPortRange0.outd(0xa0,0x20);m_IoPortRange0.outd(0x10,0x100);}if(I.IoctlOutputBufferSize() < sizeof(PKS_PASSTHRU) !I.IoctlBuffer())||{0;rmation()=STATUS_INV ALID_PARAMETER;return}pInput =(PKS_PASSTHRU)I.IoctlBuffer();rmation() = 8;status;return}NTSTATUS NewfpgaDevice::NEWFPGA_IOCTL_810_Handler(KIrp I){NTSTATUS status = STATUS_SUCCESS;PKS_MAILBOX_MESSAGE pInput = static_cast<PKS_MAILBOX_MESSAGE>(I.IoctlBuffer());if (pInput->MessageValue==1){m_IoPortRange0.outd(0x4,0x0);m_IoPortRange0.outd(0xa0,0x0);m_IoPortRange0.outd(0x44,0x0);}//传送当前dma传送物理地址pInput->MessageValue=m_IoPortRange0.ind(0x8);< sizeof(PKS_MAILBOX_MESSAGE)if(I.IoctlOutputBufferSize()!I.IoctlBuffer())||{0;=rmation()STATUS_INV ALID_PARAMETER;return}pInput =(PKS_MAILBOX_MESSAGE)I.IoctlBuffer();rmation() = 8;status;return}UNREFERENCED_PARAMETER(Arg1);UNREFERENCED_PARAMETER(Arg2);}BOOLEAN NewfpgaDevice::Isr_Irq(void){//中断服务unsigned int state;state=m_IoPortRange0.ind(0x4);//判断是否是pci开发板的中断if ((state&0x3)!=0x3) return FALSE;if ((state&0x3)==0x3) {//清中断m_IoPortRange0.outd(0x4,0x2);//写dma首地址m_IoPortRange0.outd(0x8,m_PAddr);//写传送字节数{m_IoPortRange0.outd(0xc,0x80000);}if(pp==1)//根据模式来判断dma是读还是写(kk==0){ifm_IoPortRange0.outd(0x10,0x1);}{(kk==1)ifm_IoPortRange0.outd(0x10,0x100);}}// Request deferred procedure call// The arguments to Request may be any values that you choose if (!m_DpcFor_Irq.Request(NULL, NULL)){// TODO: Request is already in the queue// You may want to set flags or perform// other actions in this case}// Return TRUE to indicate that our device caused the interrupt TRUE;return}。