nahum
驱动牛犊
驱动牛犊
  • 注册日期2004-06-02
  • 最后登录2004-06-03
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1065回复:0

利用WinDriver 开发Windows 设备驱动程序

楼主#
更多 发布于:2004-06-03 11:57
1  引言
在Windows 环境下,开发用户自制硬件的设备驱动程序,
最近一直是讨论的热门话题。编写驱动程序,一般为访问I/ O
和中断处理,尽管Win32 应用程序可以直接访问I/ O ,但却不
能提供中断服务。这是因为Windows 操作系统对设备的处
理,采用32 位Ring0 VxDs ,一般的模型是:由一个VxD 掌管所
有中断并执行所有数据传输,应用程序则使用function calls 的
方式对VxDs 发出需求。要编写Windows 设备驱动程序,一般
要写开发VxD。Microsoft 为开发者提供了设备驱动程序工具
箱(DDK) ,但它提供的许多VMM服务都使用寄存器的调用方
式,要使用汇编语言编写VxD。对开发者来说,是非常烦琐
的。目前已出现许多优秀的开发工具,帮助程序员开发设备
驱动程序,这里介绍由KRFTech 公司设计的WinDriver 工具。
你可从http :/ / www. krftech. com/ dnload. html 下载该工具,免费
30 天使用。WinDriver 是开发驱动程序的工具箱,让你能迅速地开发
以PCI/ ISA/ ISA PnP/ EISA为基础的驱动程序,使用WinDriver
的优点是:开发者并不需要熟悉任何操作系统内核编程或
DDK及任何驱动程序。WinDriver 同时允许开发者在自己熟
悉的开发环境下,利用使用者模式(User Mode) 来开发所需的
驱动程序―如使用VC ,Boland C ++ Builder ,Dephi 或VB 等任
何Win32 编译器。使用WinDriver 开发的驱动程序均可用于
Windows 9x ,NT/ 2000 ,Windows CE ,Linux和Solaris。
该工具箱提供的向导(Driver Wizard) 可以迅速地生成由
VC或Boland C ++ Builder 写的API 函数代码。在你的C ++
程序中,可直接调用这些API 函数,这些函数通过工具提供的
Windrvr. VXD/ SYS来存取硬件。下面为你介绍如何用VB 来
编写驱动程序。2  用VB 设计驱动程序
该工具一个模式文件windrvr. cls ,在该文件里,用VB 将
WinDriver 提供的低层API 函数全部编写出来,包括系统内部
所用数据结构的定义。我们借此文件,参考系统生成的C ++
程序,可以用VB 设计驱动程序。最近,我们成功地用VB 开
发出自制硬件ISA 卡的设备驱动程序。下面以我们的硬件资
源为例,介绍使用VB 的开发过程。
我们设计的ISA 卡占用中断号为5 ,端口地址为&H600
至&H602。
2. 1  访问I/ O
创建一个应用程序,加入模式文件windrvr. cls ,再加入一
个新的模式文件,用来编写访问I/ O 的设备驱动程序。将下
列代码加入到你新建的模式文件里。
Public Const Mycard ―IORange1 = 0
Public Const Mycard ―Interrupt1 = 1
Public Const Mycard ―Items = 2
Public Const Mycard ―Interrupt1 ―Irq = &H5
′中断号
Public Const MYD―IORange1 ―ADDR = &H600
′端口起始地址
Public Const MYD―IORange1 ―BYTES = &H3
′地址长度
Public Mycard ―ErrorString As String
Public Type Mycard ―Handle
hWD As Long ′设备号
cardReg As WD―CARD―REGISTER
′卡资源信息结构
Interrupt1 As WD ―INTERRUPT ′中断结构
End Type
Public hMycard As Mycard ―Handle
Sub Mycard ―SetCardElements ()
′internal function used by Mycard ―Open()
hMycard. cardReg. Card. dwItems = Mycard ―Items
hMycard. cardReg. Card. Item
(Mycard ―IORange1) . Item = ITEM―IO
hMycard. cardReg. Card. Item
(Mycard ―IORange1) . fNotSharable = False
hMycard. cardReg. Card. Item
(Mycard ―IORange1) . dw1 =MYD―IORange1 ―ADDR
hMycard. cardReg. Card. Item
(Mycard ―IORange1) . dw2 = MYD―IORange1 ―BYTES
hMycard. cardReg. Card. Item
(Mycard ―Interrupt1) . Item = ITEM―INTERRUPT
hMycard. cardReg. Card. Item
(Mycard ―Interrupt1) . fNotSharable = False
hMycard. cardReg. Card. Item
(Mycard ―Interrupt1) . dw1 = Mycard ―Interrupt1 ―Irq
hMycard. cardReg. Card. Item
(Mycard ―Interrupt1) . dw2 = INTERRUPT―LEVEL ―SENSITIVE
End Sub
Public Function Mycard ―Open() As Boolean
Dim ver As WD―Version
hMycard. cardReg. hCard = 0
hMycard. hWD = WD―Open()
If hMycard. hWD = INVALID―HANDLE―VALUE Then
Mycard ―ErrorString = ″ERROR - Cannot open
WinDriver device″
GoTo Error
End If
WD―Version hMycard. hWD , ver
If ver. dwVer < WD―VER Then
Mycard ―ErrorString
= ″ERROR - incorrect WinDriver version″
GoTo Error
End If
Call Mycard ―SetCardElements ′hMycard
hMycard. cardReg. fCheckLockOnly = False
WD―CardRegister hMycard. hWD ,
hMycard. cardReg
If (hMycard. cardReg. hCard = 0) Then
Mycard ―ErrorString
= ″ERROR - could not lock device″
GoTo Error
End If
Mycard Open = True
GoTo finish
Error :
If (hMycard. cardReg. hCard < > 0) Then
WD―CardUnregister hMycard. hWD , hMycard. cardReg
End If
If (hMycard. hWD < > INVALID―HANDLE―VALUE) Then
WD―Close hMycard. hWD
End If
Mycard ―Open = False
finish :
End Function
Sub Mycard ―Close ()
If (hMycard. cardReg. hCard < > 0) Then
WD―CardUnregister hMycard. hWD , hMycard. cardReg
End If
WD―Close (hMycard. hWD)
End Sub
Function Mycard ―ReadByte
(hMYD As Mycard ―Handle , PortAddr As Long) As Byte
Dim trans As WD―Transfer
trans. cmdTrans = RP ―BYTE
trans. dwPort = PortAddr
WD―Transfer hMYD. hWD , trans
Mycard ―ReadByte = trans. dwDataTransfer
End Function
Sub Mycard ―WriteByte (hMYD As Mycard ―Handle ,
ByVal PortAddr As Long , ByVal data As Byte)
Dim trans As WD―Transfer
trans. cmdTrans = WP ―BYTE
trans. dwPort = PortAddr
trans. dwDataTransfer = data
WD―Transfer hMYD. hWD , trans
End Sub
Sub StrCopy(lic As WD―License , str As String)
Dim l As Integer
Dim i As Integer
Dim a As Byte
l = Len(str)
For i = 0 To l - 1
a = Asc ( (Mid $(str , i + 1 , 1) ) )
lic. cLicense (i) = a
Next i
End Sub
Sub RegisterWinDriver ()
Dim hWD As Long
Dim lic As WD―License
Dim s1 As String
hWD = WD―Open
If hWD < > INVALID―HANDLE―VALUE Then
s1 = ″xxxxxxxxxxxxxxx″ ′你收到的注册码
Call StrCopy(lic , s1)
Call WD―License (hWD , lic)
Call WD―Close (hWD)
End If
End Sub
说明: 其中Mycard―SetCardElements 过程,设置硬件的资
源,每一段I/ O、内存DMA 和中断号为一个资源,每个资源都
作为一项进行设置,然后才可以访问;函数Mycard―Open 返回
打开的设备号,供以后使用;过程Mycard―Close 关闭打开的设
备;过程Mycard―WriteByte 向设备中指定地址写一个字节数
据;函数Mycard―ReadByte 向设备中指定地址读出一个字节数
据( 类似可写出读写字指令、读写长整型指令) ; 过程
RegisterWinDriver 用来将你收到的注册码写入VxD ,无此注册
码,软件过期不可用。
在应用程序中,首先打开设备,对硬件设备资源进行设
置,注册软件,然后就可调用I/ O 读写函数或过程访问设备。
最后,程序退出时关闭设备。
2. 2  中断处理
经过分析Driver Wizard 生成的VC 示例, 我们明白了
WinDriver 对中断处理的原理:首先开放中断,然后创建一个子
线程,等待中断到来,调用中断处理程序,主线程里做其它一
般处理工作。将下面代码加入到一个你的模式文件里。在这
里调用三个API 函数需要声明,CreateThread 用来生成线程,在
线程里等待中断处理; WaitForSingleObject 调用&HFFFFFFFF
使线程运行停下来;CloseHandle 关闭线程(该函数在windrvr.
cls 已声明) 。
Declare Function CreateThread Lib ″kernel32″
(ByVal lpSecurityAttributes As Long ,
ByVal dwStackSize As Long ,
ByVal lpStartAddress As Long ,
ByVal lpParameter As Long ,
ByVal dwCreationFlags As Long ,
lpThreadId As Long) As Long
Public Declare Function WaitForSingleObject
Lib ″kernel32″(ByVal hHandle As Long ,
ByVal dwMilliseconds As Long) As Long
′Declare Function CloseHandle Lib ″kernel32″
′(
ByVal hObject As Long) As LongPublic
hThread As Long
速访问,如下实例:
# include ″sybasesql . h″ / / 引入头文件
void main()
{ SybaseSQL
s (″servername″,″username″,″password″,″database″)
;
/ / 创建SybaseSQL 对象
if (s. sqlcode = = - 1)
{ printf (″%s″,s. sqlerr) ; / / 打印登录出错信息
return ;
}
int i ,j ;
char buf [128 ] ;
SqlRet sqlret ; / / 定义获取数据的对象
i = s. TransSqlExe (″select 3 from test INSERT test
VALUES (′test1′,′12311′,′wqotq′)
″,sqlret) ;
/ / 调用的以事务方式执行Sql 语句的函数
if (i ! = - 1)
{ for (i = 0 ;i < sqlret . GetCol () ;i ++ )
{ printf (″%s \\ t″,s. colname[ i ]) ; / / 输出表头
}
printf (″\\ n″)
;
for (i = 0 ;i < sqlret . GetRow() ;i ++ )
{ for (j = 0 ;j < sqlret . GetCol () ;j ++ ) / / 输出结果记录
{ sqlret . GetItem(i ,j ,buf) ; / / 获得执行结果放入缓冲区中
printf (″%s \\ t″,buf) ;
}
printf (″\\ n″)
;
}
else
printf (″%s″,s. sqlerr) ; / / 打印执行SQL 语句的出错信息
}
4  结论
对象SybaseSQL 将DB - Library 的一些重要函数进行了封
装,使得用户能够很方便地使用,而不必再去重复编写一些复
杂的代码。从软件工程的角度来看,大大地提高了软件的生
产效率,该代码的复用率也是很高的。所以,以面向对象的方
法来编写程序,将大大提高代码的复用度,提高软件的生产效
率。
游客

返回顶部