Windows95的设备驱动程序的编写.docx
《Windows95的设备驱动程序的编写.docx》由会员分享,可在线阅读,更多相关《Windows95的设备驱动程序的编写.docx(18页珍藏版)》请在冰豆网上搜索。
Windows95的设备驱动程序的编写
Windows95的设备驱动程序的编写
1为什么需要设备驱动程序
从Windows3.1开始,对于硬件设备的访问便采取了一种设
备驱动程序的方法,客户通过设备驱动程序来获得硬件
的参数或者设置,但是由于16位的操作系统基于原来的
DOS,所以客户程序仍然可以通过一些BIOS或者DOS的DPMI
中断调用来实现对硬件的操作。
32位的操作系统如Windows95&NT不再基于16位DOS,所以
用户如果需要实现对硬件中断、DMA、I/O或者是绝对存
储访问,都不可避免地必须通过设备驱动程序。
Windows
95操作系统能够实现多线程、多进程的应用,系统通过
一个虚拟机管理器VMM32、VXD(Virtualmachinemanager),通过
它和其他的设备驱动程序合作,来实现多个进程间的协
调工作,防止一个进程的运行导致另一个进程的崩溃。
2什么是设备驱动程序
设备驱动程序被用来管理系统资源(硬件或者软件)的
可执行二进制代码,通过设备驱动程序,多个进程可以
同时使用这些资源,从而可以实现多进程并行运行。
设
备驱动程序一般是以“VxD”为后缀名,其意思是虚拟
化某些设备(Virtual″something″Device)。
在一般概念上,
设备驱动程序和虚拟设备是同义的,我们下面就将两者
混用。
386以上的微处理器有4个优先级别:
0级、1级、2级、
3级,一般操作系统运行于优先级0级上,而用户程序
运行在3级上。
VxD运行于0级上,其在内存中的位置也
是处在操作系统保护的空间之内的。
Windows95是继承Windows3.x而来,所以两者的设备驱动程
序采取的是同一种模式,也就是说,一般为Windows3.x写
的设备驱动程序,可以不加改动地运行于Windows95下;
但是也有一些区别:
一般Windows95下面的驱动程序是以
“VxD”为后缀名,而Windows3.x是以“386”为后缀名;
Windows3.x的设备驱动程序必须在Windows启动时静态载入
,而Windows95的设备驱动程序可以在程序运行过程中动
态载入。
WindowsNT采用的一种完全不同的模式,所以Windows95&
3.x下的设备驱动程序是不能和WindowsNT的设备驱动程序
兼容的。
另外,Windows还提供一些运行在优先级3上的驱动程序
,主要是串口的通信程序和并口的打印机程序,这些程
序以“DRV”为后缀名。
但是一般说来,运行于优先级别
3上面的I/O比运行于0级的慢。
3设备驱动程序编写简介
设备驱动程序的编写有一定规范,需要对于32位的汇编
和C语言比较熟悉;一般完全由汇编语言编写,但是也
可以用C与汇编的混合语言实现;首先需要有Microsoft
DDK(DeviceDriverKit),一般工具是MASM611和VC20以上
版本。
通常设备驱动程序由五个段组成,它们分别是:
VxD-
CODE、VxD-DATA、VxD-ICODE、VxD-IDATA和VxD-REAL-
INIT。
VxD-CODE是保护模式下的代码段,一般这个段包
括设备驱动程序的控制程序、回收函数、服务程序和接
口函数,这个段也命名为-LTEXT;VxD-DATA是保护模式
下的数据段,一般包括设备驱动程序的描述表,以及一
些全局变量,这个段也命名为-LDATA;VxD-ICODE是保护
模式下的初始化代码段,包括一些初始化时使用的服务
程序,虚拟机管理器(VMM)在初始化结束之后就将这个段
取消,这个段也命名为-ITEXT;VxD-IDATA是保护模式下
的初始化数据段,包括一些初始化时使用的数据,虚拟
机管理器(VMM)在初始化结束之后就将这个段取消,这个
段也命名为-IDATA;VxD-REAL-INIT包括实模式下的初
始化数据和代码段,虚拟机管理器(VMM)最先就是装入这
个代码段,在进程返回之后这个段取消,再装入其他代
码段,这个段又命名为-RTEXT。
需要注意的是,除了实模式下的初始化数据和代码段外
,其他四个段都是32位保护模式下平板模式(flatmodel)的段。
每个设备驱动程序必须首先声明一个虚拟机的名字、版
本号、初始化过程、虚拟机控制程序(相当于程序入口)
;有些设备驱动程序还可以声明设备标志号和接口函数
(API)。
虚拟机一般用Declare-Virtual-Device宏来声明,
例如下例:
Declare-Virtual-DeviceVSAMPLED,4,0,VSAMPLED-Control,\
VSAMPLED-Device-ID,VSAMPLED-Init-Order,\
VSAMPLED-V86-API-Handler,VSAMPLED-PM-API-Handler
意思是样例虚拟机,名字叫做VSAMPLED,版本是40,
控制程序是VSAMPLED-Control,VSAMPLED-Device-ID申明了
虚拟机的标志符,VSAMPLED-Init-Order说明初始化的过
程,另外后面两项说明中支持V86模式和保护模式下的两
种接口函数。
通过这些声明,我们就可以确定一个唯一
的虚拟机,系统就可以将它和别的虚拟机区别。
每个虚拟机需要一个虚拟机控制程序。
虚拟机管理器
(VMM)通过这个程序来向该虚拟机传递控制信息,系统通
过控制消息来控制虚拟机的执行,例如初始化虚拟机、
虚拟机状态的改变等工作。
一个虚拟机需要提供一些服务功能,这些功能可以被虚
拟机管理器(VMM)或者其他的虚拟机来使用。
但是,虚拟
机不像WindowsDLLs一样提供出口函数(exportfunctions),虚
拟机管理器(VMM)通过0x20号中断来实现与虚拟机的连接
,中断的句柄通过一个服务号来决定到底哪个虚拟机支
持这个服务功能。
一个虚拟机通过BeginProc和EndProc两个宏来定义它的服务
功能,很像汇编语言。
例如下例:
BeginProcVSMAPLED-Service-Routine,Service
mainbodyoftheservice......
EndProcVSAMPLED-Service-Routine
一般BeginProc的名字后面有一个参数:
Service或者Async-
Service,后者是说明这个服务程序可以被异步地调用,
多用在中断服务程序一类中,异步服务程序必须是可以
重入的,所以它不能调用不能重入的服务程序。
二、图像采集卡设备驱动程序
由于实际工作的需要,我们设计一块图像采集卡来实现
图像的实时采集,由于图像数据传输量大,实时性要求
强,所以我们采用PCI总线;软件的平台采用Windows95。
1系统硬件简介
系统采用Philips公司的SAA7110作为前端图像采集量化器
,而PCI接口芯片采用以色列ZORAN公司的ZR36120作为接口
工芯片,两个芯片都是可编程的芯片。
ZR36120是为多媒体应用设计的一个控制器,它既具有PCI
总线操作的功能,又具有多媒体控制功能,比如图像数
据的滤波,是一个多媒体控制器(MultimediaControllerforPCI
Bus)。
它具有两组寄存器,一组是符合PCI20的配置寄
存器(ConfigurationRegisters);另外一组是基于用户应用的
寄存器,命名为ASR(Application-specificRegisters),这组寄
存器主要是面向用户实际应用的,包括一些图像数据格
式、滤波器的选择、中断方式的设置、DMA通道的选择及
地址等等内容的寄存器,ASR的访问是采用存储器映射方
式的。
2软件设计
系统需要对硬件进行操作,其中包括:
(1)DMA内存的分配。
图像的数据是通过DMA方式传送到主
机的,所以必须根据图像尺寸大小来分配内存给DMA通道
。
将DMA内存地址通知PCI接口芯片和客户程序,PCI接口
芯片所需要的地址是绝对物理地址,客户程序使用的地
址是虚拟地址(平板模式的32位下就是线性地址),如何
将两者对应起来?
(2)接口芯片ZR36120和图像采集芯片SAA7110的初始化。
需
要对ZR36120的配置寄存器读写,使用I/O方式或者是BIOS
中断方式;另外ZR36120的ASR采用存储器映射方式来实现
读写。
所有这些问题的解决都不可回避地必须采用设备驱动程
序来实现对硬件的操作,在优先级3上运行的用户程序
是无法实现这些功能的。
?
DMA内存的分配
首先必须在Windows95的System.ini文件中加入
DMABUFFERSIZE=2048K(这儿是2M,大小根据DMA操作的实际大小
决定)。
系统就会在启动时留下相应大小的内存以供用
户以后DMA操作使用。
用户在自己程序中分配一段内存,现在问题是如何将这
段内存与系统的DMA内存联系起来。
MicrosoftDDK的内核提
供了VDMAD-Request-Buffer这个系统调用,向系统申请一
定大小的DMA内存,DMA缓冲区的线性地址通过ESI传入,
缓冲区的大小通过ECX传入。
得到的DMA区域的物理地址
通过EDX传出,而标志号由EBX传出
。
申请DMA区域后,我们必须用VDMAD-Lock-DMA-REGION
将该区域锁定,以便我们后面使用。
分配好DFMA内存后,还必须能够实现DMA内存与用户空间
数据的交换。
DDK提供VDMAD-Copy-From-Buffer这个系统
调用来实现数据由DMA区域传到用户数据区中。
其中传入
的参数中:
ESI存放用户数据区域性地址,ECX存放数据
区大小,EBX中存放标志号,EDI中存放偏移量。
如果操
作成功,CF位复位;失败的话,CF位置位。
另外提供
VDMAD-Copy-To-Buffer实现将用户区数据拷贝到DMA缓冲
区中,其输入输出参数与前者一模一样。
?
存储器映射方式
ZR36120的ASR必须采用存储器映射的方式来实现读写。
所
谓存储器映射,就是一些芯片将自己的一些寄存器映射
在某段内存上,系统可以象平时访问内存一样取访问它
们;但是这段内存映射的必须是主机上一段空白的内存
段,不得和已存的内存相冲突,比如0xF00000000;而映射
的这段地址是物理地址,客户程序中读写的是线性地址
,我们必须将这段物理地址转化为线性地址。
DDK中提供-MapPhysToLinear这个调用来实现将物理地址映
射为线性地址,但是这个调用只能是用于将外设的物理
地址转化为线性地址,而不是计算机本身的内存空间;
传入的参数是三个,第一个参数是物理地址的起始地址
,第二个参数是长度,第三个是标志位,一般为0;返
回的参数是优先级0下面的线性地址。
例如:
VMMcall-MapPhysToLinear,<0f0000000h,1000h,0>
就是将起台物理地址为0xF0000000的长度为0x1000的一段寄
存器映射到内存上面。
?
端口操作
Windows95没有将端口保护起来,这可能主要是为串口通
信设备和并口打印设备的需要而考虑的。
所以应用程序
可以通过调用系统函数或者是直接用汇编语言来实现对
端口的操作。
例如VC中就有-outp,-outpw,-outpd,-inp,
-inpw,-inpd等函数分别实现端口的输入输出。
但是由
于在优先级0级上的速度快,另外可以多进程操作,一
般硬件的端口操作最好还是在设备驱动程序中完成。
根
据PCI总线20的标准,PCI总线的配置寄存器
(configuraiotnregisters)包括256个字节,其中前64比特构成
配置寄存器头(configuraiotnheader),主要包括主机(Host)与
客户(Client)的一些接口信息,如器件号,厂商号,所用
的中断号,口地址的范围(I/O方式),存储器的地址(存
储器映射方式)……。
对于PCI配置寄存器(configuration
registers)的读写,有两种方式:
第一种,通过BIOS中断
0x1A的子功能号0xB1完成,这是Intel为兼容以前的系统所
设计。
第二种,通过对两个口地址0xcf8和0xcfc进行双字
的读写来实现对配置寄存器读写,这种方法是为了同未
来的系统兼容设计的,特点是简单明了。
我们这儿详细
介绍第二种方法:
口地址0xcf8是配置寄存器的地址寄存
器,它的32位操作的每一位的意义如下:
busnumber、
functionnumber和devicenumber都是在计算机启动时由系统分
配,registernumber就是我们所需要进行读写的寄存器号,
最低两位为0,8比特刚好构成256个字节的配置寄存器
地址空间。
口地址0xcfc就是数据寄存器,写完地址寄存
后,对该口进行双字读就得到配置寄存器里面的值,写
入一个双字就完成对相应配置寄存器的写操作。
明白各
操作位的意义后,我们就可以利用两条汇编指令IN和
OUT来实现我们的目的,注意的是这儿的操作必须是双字
操作,例如必须是:
INEAX,DX或者OUTDX,EAX一类的指
令,而不能将一个双字操作转化为两次字的操作或者四
次字节操作。
?
客户程序对设备驱动程序的调用
以上介绍的是设备驱动程序的编写,下面我们详细分析
一下客户程序(一般的用户程序,最常见是用C和C++
编写)如何调用设备驱动程序的。
如果开发的是标准的API函数的话,客户程序可以通过
调用系统标准的函数库来进行操作。
但是如果定义的不
是系统提供的标准函数的话,接口函数就是用户面向自
己的硬件或者软件开发,那么一般不会采用标准的接口
函数,这就无法从标准的函数库中得到调用,但是这也
是最常出现的情形,下面我们就C语言中的调用情况加
以详细说明。
把一个硬件设备虚拟化后,这个硬件设备就是作为一个
文件系统而被系统调用;UNIX采用这样的方式,现在
Windows