dragonshx
驱动牛犊
驱动牛犊
  • 注册日期2002-04-23
  • 最后登录2006-05-19
  • 粉丝0
  • 关注0
  • 积分50分
  • 威望5点
  • 贡献值0点
  • 好评度5点
  • 原创分0分
  • 专家分0分
阅读:11634回复:24

用driverworks开发PCI驱动程序

楼主#
更多 发布于:2003-04-07 08:58
PCI卡WDM驱动程序的设计与开发
(技术文档)
dragonshx
2003-3-4
一. 开发环境的安装与设置。
二. 驱动程序框架的建立
三. 在WDM驱动程序中I/0读写,内存读写,DMA控制以及中断处理的具体实现。
四. Inf文件的编写及应注意的几点;
五. 如何调试驱动程序
当前PCI类型的卡在数据采集,数据处理以及其他如声卡,显卡方面的应用已经十分广泛。而且由于PCI桥芯片功能的不断完善,开发PCI类型卡已经变的比较方便。所以当前很多基于微机操作的工程开发项目都使用了PCI类型的卡。
WDM类型驱动程序是微软最新推出的驱动程序标准,它与操作系统的协作变得更加友好,执行效率也更高。而且微软最新的操作系统如winxp和win2000也只兼容这种驱动程序。
Driverstudio是Numega公司推出的一套开发驱动程序的完整工具包,几乎包含了开发驱动所用到的大部分工具,它不但可以用来开发虚拟设备驱动(vxd)而且也可以开发WDM(Windows Driver Model)驱动,并且还包含了一个用于调试设备驱动的工具SOFTICE。
一. 开发环境的安装与设置
目前在国内很多网站都可以下载Driverstudio,如驱动开发网(网址)等,见到的已经有2.7版本的。软件的安装比较简单,只要按照提示一步一步进行操作即可,只是其中在安装SOFTICE时需要指出显卡的类型,如果不太清楚,一般情况下选择通用的即可,点击测试按钮,测试成功就可以继续向下安装。用Driverstudio开发驱动程序需要其他另外两个工具软件的支持――visual c++ 和win2000 DDK。最好是在安装Driverstudio之前先进行这两个软件的安装,因为在安装Driverstudio过程中需要指出DDK的安装位置。
安装完成以后进入\\\\NnMega\\driverstudio\\DriverWorks\\lib\\i386目录下查看,在checked和free子目录下没有任何链接库文件,在驱动程序开发中用到的一些库文件需要在安装完成后由开发人员自己编译链接形成。具体是进入\\\\NnMega\\driverstudio\\DriverWorks\\Source目录,利用vc打开VdwLibs.dsw工程文件,选择菜单build\\batch build,在弹出的对话框中,将四项全部选中,然后进行编译链接,所需要的链接库文件就已形成。
另外,在vc环境中编译和链接驱动程序工程文件时需要设置两个环境变量,点击菜单driverstudio\\driver build settings。需要设置的项包括BASEDIR和CPU,点击edit按钮可对这两项进行设置,将BASEDIR设为DDK安装的根目录,CPU设为i386。
二. 驱动程序框架的形成
利用driverstudio生成驱动程序框架和利用vc中wizard生成应用程序框架类似,只要进行必要的选择即可。对于PCI卡驱动程序,在第三步选择硬件总线时选择PCI,填写所开发硬件卡的开发商ID和产品ID这些一般是在硬件开发时由开发人员自己设定的。当卡插入计算机后,操作系统会通过扫描总线来检测目前计算机安装的所有总线硬件设备,并可以读出硬件的开发商ID和产品ID,通过这两个标志操作系统选择调用合适的驱动程序。另外,在这一步中的子系统ID和修订ID可以不用填写。在第五步中可以选择驱动程序需要具备的一些主要功能,如读、写以及其他的一些设备控制功能。在步骤8中,可以根据pci卡需要利用的资源指定驱动程序添加的变量,如,在笔者开发的硬件卡上,共占用了两个I/O空间和两个内存空间,并可执行DMA和硬件中断,所以在该步骤的resource标签下添加两个I/O端口读取变量和两个内存读取变量,一个DMA操作变量和一个中断处理变量。在Interface标签下,可以选择应用程序和驱动程序接口的方式:符号链接和interface接口方式。这主要影响应用程序在打开设备获得句柄时CreateFile()函数中的名称,假设使用符号链接的方式,设备名称为MyDevice,则在CreateFile()函数中第一个参数为“\\\\\\\\.\\\\MyDevice”;如果使用interface接口方式,则在打开设备时首先需要定义一个CdeviceInterfaceClass类的对象,构造函数中包含要打开设备的GUID,然后定义一个CdeviceInterface类的对象,构造函数中包含前面CdeviceInterfaceClass类的对象,然后在CreateFile()函数中通过CdeviceInterface类的对象打开设备。在步骤九中,可以添加许多通过对设备进行实际控制的函数,例如打开设备后可以对设备进行复位,启动,清空卡上内存等操作。后面还有其它几步,这里就不详细介绍了。至此,一个WDM类型的驱动程序框架就已经基本形成了。
三. WDM驱动程序中I/0读写,内存读写,DMA控制以及中断处理的具体实现。
在DriverWorks形成的WDM驱动程序中,在上一节已经提到过,如果硬件设备需要占用I/0、内存等资源时可以定义一些相应的变量。下面以I/O读写为例简要介绍实现原理。如果硬件占用两段I/O资源,则可以定义两个KioRange类的对象作为设备类的成员变量,在OnStartDevice(KIrp I)函数中,将会对这两个变量进行初始化,使之和实际的资源相联系。具体实现代码如下:
NTSTATUS LllllDevice::OnStartDevice(KIrp I)
{
┄┄┄

PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources();

PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources();
status = m_IoPortRange0.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(0)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}

status = m_IoPortRange1.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(0)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
┄┄┄

}
其中m_IoPortRange0、m_IoPortRange1为定义的两个成员变量。在这个函数中完成初始化后就可以在需要时通过对KioRange类的成员函数inb,outb等的调用对设备进行I/O操作。
对内存的读写与I/O读写类似。
当PCI卡驱动程序需要处理硬件中断时,可以在驱程中设置一个中断处理程序来实现,一般情况下,中断处理程序运行在较高的级别上,会屏蔽掉其它与它同级或级别较低的中断,所以要尽量减少中断处理程序运行的时间,这可以通过调用一个延迟调用过程实现。
首先在设备类中定义一个Kinterrupt类对象,然后定义一个中断处理程序函数,这个函数可以是一个单独的也可以作为设备类的成员函数,笔者使用的是后者:
MEMBER_ISR(MyDevice, Isr_Irq);
其中Isr_Irq即为中断处理函数。在OnStartDevice(KIrp I)中可以利用InitializeAndConnect()函数初始化并将中断与处理函数绑定。
status = m_Irq.InitializeAndConnect(
pResListTranslated,
LinkTo(Isr_Irq),
this
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
当需要在中断处理函数中采用延迟调用机制时,首先需要在设备类中定义KdeferredCall类的一个对象,然后定义一个延迟调用函数:
MEMBER_DPC(MyDevice, DpcFor_Irq);
在OnStartDevice(KIrp I)中初始化该变量并与延迟调用函数绑定:
m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);
在需要调用延迟调用函数时使用KdeferredCall类的成员函数BOOLEAN Request( PVOID arg1,   PVOID arg2)
DMA方式其实质是数据传输方式的一种,和内存读写和I/O读写没有实质的区别,所以可以用在对设备进行读和写操作的任何过程中,只不过这种与设备交换数据的过程不需要CPU的支持。
当驱动程序需要DMA操作时,首先在设备类中定义一个KdmaAdapter类的对象作为成员变量m_Dma,然后在在OnStartDevice(KIrp I)中初始化该变量:m_Dma.Initialize(&dd, m_Lower.TopOfStack());其中dd为设备描述符,m_Lower为设备对象。
在设备类中定义一个KcommonDmaBuffer类的对象m_comDmaBuf,并在OnStartDevice(KIrp I)中进行初始化m_comDmaBuf.Initialize(m_Dma,512,FALSE);
定义一个KdmaTransfer类的对象m_DmaTrans,该变量既可以作为全局静态变量,也可以作为设备类的成员变量。
再定义一个回调函数,因为在DMA传输中,总是将一次传输分成多个片断进行,所以需要有一个回调函数启动第一次传输和在一个片断传输完成后启动另外一次传输。回调函数的定义如下:DEVMEMBER_DMAREADY(MyDevice, Dma_Callback);
在回调函数的实现中,首先检查DMA传输是否完成,这可以通过调用成员函数BytesRemaining(void)实现,如果返回值为0,则调用成员函数terminate()结束本次DMA传输,如果返回值不为0,则传输继续进行。回调函数只通知设备开始传输,然后立即返回,并不等待传输完成。
当需要DMA传输时,驱动程序调用KdmaTransfer类的成员函数启动传输:
NTSTATUS Status = m_DmaTrans.Initiate(   I.MDL
   FromDeviceToMemory,
   Dma_Callback,
   FALSE);
Initiate()函数将分配适配器,建立传输的初始段并调用回调函数,紧接着将是回调函数完成的工作。
当一个片段传输完成后,一般硬件将会产生一个中断,此时驱动程序将会进入中断处理程序,在中断处理程序中调用KdmaTransfer类的成员函数m_DmaTrans.Continue(  UseTransferSize,0)结束本次传输开始建立下一次传输的片段,并且再一次调用回调函数。最终DMA传输将在回调函数中结束。
四. Inf文件的编写及应注意的几点;
要实现PCI卡的即插即用,则必须编写驱动程序的安装信息文件。最简便的方法是利用windriver对该PCI卡生成inf文件,然后打开文件将其中所有“wdpnp.sys”字符串替换为自己编写的驱动程序名,并将vendorID和deviceID换成所设计卡对应的ID即可。此时的inf文件就已经可以使用了,至于其中更具体的信息,请参考相关的文献说明,这里就不详细说明了。
五. 如何调试驱动程序
对于驱动程序的调试,最好采用driverstudio提供的SOFTICE工具,它的功能比较强大,当驱动程序安装以后,对SOFTICE进行设置,首先需要将启动模式设为系统引导(boot),因为驱动程序在操作系统启动时就已经加载了,所以若在系统启动后再启动SOFTICE将无法跟踪驱动程序。
在symbol loder程序中,选择edit\\initial softice settings菜单,在对话框的symbol标签下添加softice在初始化时需要装载的符号文件,在打开要调试的模块后,选择module\\settings菜单,设置默认的源文件搜索路径,然后选择module\\load菜单,重新装载模块就可对驱动进行跟踪调试了。
利用softice调试时一些主要的命令包括:

Ctrl+D 调出softice
File filename 调出要调试的文件
Ss ‘ ’查找单引号中的字符串
Alt+c 在命令窗口和代码窗口间切换光标
F9 设置取消断点
F10 单步调试

最新喜欢:

duguxunduguxu...
fwzfwz1
驱动中牛
驱动中牛
  • 注册日期2002-11-01
  • 最后登录2007-06-01
  • 粉丝0
  • 关注0
  • 积分80分
  • 威望8点
  • 贡献值0点
  • 好评度8点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-04-18 19:38
dragonshx可否将你用ds开发的dma源代码发一份。
60分相赠!!!可否!!
有了驱动,人才有了力量。
yff_7781
驱动牛犊
驱动牛犊
  • 注册日期2002-09-29
  • 最后登录2005-04-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-07-31 17:10
好有水平! :P
theseus
驱动牛犊
驱动牛犊
  • 注册日期2003-03-30
  • 最后登录2003-11-13
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-08-21 20:31
能不能详细的介绍DMA操作,这似乎很难呢。
------------------------------------------------------------ 痛并快乐
wangxin_china
驱动中牛
驱动中牛
  • 注册日期2003-03-28
  • 最后登录2008-09-30
  • 粉丝0
  • 关注0
  • 积分8分
  • 威望18点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-10-25 09:57
我也想学习学习,你可以给我点资料么?
tech_mail@eyou.com
wumengyun
驱动牛犊
驱动牛犊
  • 注册日期2003-11-06
  • 最后登录2003-12-20
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-11-08 21:22
给源代码学习一下,
longriver2003
驱动小牛
驱动小牛
  • 注册日期2003-09-14
  • 最后登录2005-03-12
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2003-11-09 19:13
崇拜!能否给源代码一看?谢谢!longriver@126.com
给分才有动力!所以我坚决给分!
kornecor
驱动牛犊
驱动牛犊
  • 注册日期2003-08-25
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2003-12-19 21:07
请给源代码我学习学习吧!感激不尽!
kornecor@163.net
QQ:16884178
happybob51
驱动牛犊
驱动牛犊
  • 注册日期2003-10-20
  • 最后登录2004-08-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2004-01-13 17:12
好东西大家分享嘛,放到网上或发到我的邮箱里:
happybob100@vip.sina.com
fanchao41
驱动小牛
驱动小牛
  • 注册日期2003-12-18
  • 最后登录2005-02-05
  • 粉丝2
  • 关注1
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2004-02-11 11:09
能不能也给我来一份?谢谢
fanchao41@163.com
xdh1200
驱动牛犊
驱动牛犊
  • 注册日期2004-02-18
  • 最后登录2004-05-23
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2004-03-26 14:22
写的太好了,对我很后帮助,谢谢了
zhijianhu
驱动牛犊
驱动牛犊
  • 注册日期2003-11-26
  • 最后登录2007-08-02
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2004-04-03 11:30
兄台,可不可以email一份学习学习 :zhijianhu@263.net :)
ppoopp
驱动牛犊
驱动牛犊
  • 注册日期2004-05-05
  • 最后登录2013-11-19
  • 粉丝0
  • 关注0
  • 积分192分
  • 威望71点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2004-05-08 10:50
问一个菜的问题,你开发的PCI驱动可以在PC上安装并使用吗,有没有提示没有数字签名就用不了之类的问题?
cloud-ww
驱动牛犊
驱动牛犊
  • 注册日期2004-04-02
  • 最后登录2004-06-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2004-06-01 19:32
好!
谢谢! :P
xuxe97
驱动牛犊
驱动牛犊
  • 注册日期2001-12-09
  • 最后登录2018-05-29
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望10点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
  • 社区居民
14楼#
发布于:2004-06-10 10:27
给一份源代码学习一下? xuxe@neusoft.com  谢谢!
许享恩
cool_alay
驱动牛犊
驱动牛犊
  • 注册日期2004-07-08
  • 最后登录2004-10-16
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2004-08-19 10:39
的确是有用得很啊,
尤其是对刚刚接触驱动程序的人,
好人,顶一下!!!!!!!!!!!!!!!
frogwang
驱动牛犊
驱动牛犊
  • 注册日期2004-04-19
  • 最后登录2005-08-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2004-09-20 17:41
看了颇有收获,谢谢了!^_^
我思故我在!
sleepgutar
驱动牛犊
驱动牛犊
  • 注册日期2004-05-16
  • 最后登录2004-10-11
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2004-09-27 12:58
我这也有一些简单源码 ;)
正在努力学习中 喜欢beatles
llg523
驱动牛犊
驱动牛犊
  • 注册日期2004-09-17
  • 最后登录2005-11-22
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望1点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2004-09-29 09:00
It so good !  Thank you very much!!
zsh_7769
驱动小牛
驱动小牛
  • 注册日期2004-04-15
  • 最后登录2005-12-06
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2004-10-09 15:02
牛b,也给我一份原代码学习一下吧,先谢过了!
zsh_7769@163.com
上一页
游客

返回顶部