windows98/2000 驱动程序编写方法

71
http://qsyang.yeah.n 现现现现现现现现现现现 1 Windows98/2000 现现现现现现现现 现现 () 现现现

Upload: percy

Post on 23-Feb-2016

81 views

Category:

Documents


0 download

DESCRIPTION

Windows98/2000 驱动程序编写方法. (下). 杨全胜. 4.Driver Works 的使用. 1 )生成简单框架. 工程文件名. 工程文件目录. 选择驱动类型. 创建功能驱动程序. 创建过滤器驱动程序. 本例不驱动硬件. 选择相应总线. 驱动类名称. 驱动类文件名. 选择需要处理的消息句柄. 添加和应用程序之间通信的控制代码. 测试用应用程序名称. 驱动类. 设备类. 驱动类文件. 设备类文件. 驱动安装指导文件. 测试用的控制台程序文件. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

1

Windows98/2000 驱动程序编写方法(下)杨全胜

Page 2: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

2

4.Driver Works 的使用1 )生成简单框架

Page 3: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

3

工程文件名工程文件目录

Page 4: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

4

选择驱动类型

Page 5: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

5

创建功能驱动程序 创建过滤器驱动程序

Page 6: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

6

选择相应总线

本例不驱动硬件

Page 7: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

7

驱动类名称驱动类文件名

Page 8: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

8

选择需要处理的消息句柄

Page 9: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

9

Page 10: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

10

Page 11: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

11

Page 12: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

12

添加和应用程序之间通信的控制代码

Page 13: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

13

Page 14: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

14

Page 15: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

15

测试用应用程序名称

Page 16: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

16

Page 17: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

17

Page 18: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

18

驱动类设备类

Page 19: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

19

驱动类文件设备类文件

测试用的控制台程序文件

驱动安装指导文件

Page 20: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

20

此时已经具备了一个驱动程序以及做测试用的应用程序的基本框架,我们可以在 VC集成环境下区修改有关程序,增加相关的具体操作代码,然后就可以编译和调试了。

Page 21: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

21

该驱动程序框架包含了几个最基本的类,这些类是:class Sample : public KDriver // 驱动程序类,用于初始化驱动程序{ SAFE_DESTRUCTORSpublic: // 以下成员函数注意和 WDM 中有关例程联系起来看 virtual NTSTATUS DriverEntry(PUNICODE_STRING RegistryPath); virtual NTSTATUS AddDevice(PDEVICE_OBJECT Pdo); void LoadRegistryParameters(KRegistryKey &Params);

int m_Unit;

// The following data members are loaded from the registry during DriverEntryULONG m_bBreakOnEntry;

};

Page 22: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

22

class SampleDevice : public KPnpDevice // 是设备类 KDvice 的派生类,用于在 WDM 环境下支持即插即用设备{

// Constructorspublic:

SAFE_DESTRUCTORS;SampleDevice(PDEVICE_OBJECT Pdo, ULONG Unit);~SampleDevice();

// Member Functions 注意和 PNP 的次功能代码联系起来看public:

DEVMEMBER_DISPATCHERSvirtual NTSTATUS OnStartDevice(KIrp I);virtual NTSTATUS OnStopDevice(KIrp I);virtual NTSTATUS OnRemoveDevice(KIrp I);virtual NTSTATUS DefaultPnp(KIrp I);virtual NTSTATUS DefaultPower(KIrp I);virtual NTSTATUS OnDevicePowerUp(KIrp I);virtual NTSTATUS OnDeviceSleep(KIrp I);void SerialRead(KIrp I);void SerialWrite(KIrp I);

Page 23: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

23

NTSTATUS SAMPLE_IOCTL_Read_Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_Write_Handler(KIrp I);NTSTATUS SAMPLE_IOCTL_ReadWrite_Handler(KIrp I);

#ifdef _COMMENT_ONLYvirtual NTSTATUS Create(KIrp I);virtual NTSTATUS Close(KIrp I);virtual NTSTATUS DeviceControl(KIrp I);virtual NTSTATUS SystemControl(KIrp I);virtual NTSTATUS Read(KIrp I);virtual NTSTATUS Write(KIrp I);

#endif// Member Data

protected:// Unit number for this device (0-9)ULONG m_Unit;KPnpLowerDevice m_Lower;SampleDevice_DriverManagedQueue m_DriverManagedQueue;

// TODO: Create additional driver managed queues. These might be// of the same class (SampleDevice_DriverManagedQueue),// or you might choose to derive another class.};

Page 24: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

24

先编译驱动程序工程

在 VC 的集成环境中

下面我们讲解编译、执行和调试这个驱动程序。

Page 25: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

25

Page 26: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

26

再编译测试应用程序工程

Page 27: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

27

Page 28: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

28

下面使用 DriverStudio 带的工具加载驱动程序和查看调试信息。 驱动程序监视,可实时看到驱动程序发出的调试输出语句

驱动程序装载器,可动态调用驱动程序

Page 29: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

29

驱动程序监视器界面

Page 30: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

30

驱动程序装载器界面

Page 31: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

31

Page 32: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

32

Page 33: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

33

Page 34: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

34

Page 35: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

35

Page 36: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

36

Page 37: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

37

下面我们来修改有关代码,以便增加驱动程序和应用程序之间相互通信的内容。需要增加的内容包括:a. 使用 Read 和 Write 方式分别从驱动程序读入字符和 向驱动程序写字符。b. 使用 IO 控制代码方式分别从驱动程序读入字符和 向驱动程序写字符。c. 使用 IO 控制代码方式向驱动程序写字符串再从驱动程序中读出该字符串,并返回反馈串信息。 注意:程序中暗红色显示的部分是我们添加或修改过的语句,其他是 DriverWorks 自动生成的。语句中“ t<< xxxxx” 这样的语句是向调试软件输出信息,该信息可以再 DriverMonitor 或其他调试监视器中看到。

2 )完成应用程序和驱动程序之间的信息交换

Page 38: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

38

a. 使用 Read 和 Write 方式分别读写SampleDevice.cppvoid SampleDevice::SerialRead(KIrp I){

t << "Entering SampleDevice::SerialRead, " << I << EOL;NTSTATUS status = STATUS_SUCCESS;PUCHAR pBuffer = (PUCHAR) I.BufferedReadDest();// 取得返回数据 BUFF 的指针ULONG dwTotalSize = I.ReadSize(CURRENT); // Requested read sizechar buff[512];int n =512, j = (n % 26);for (int i=0; i<n; i++, j=(j + 1)%26){ buff[i] = 'a' + j; }buff[dwTotalSize]=‘\0’; // 指定串尾strcpy((char *)pBuffer,buff);

// 把给应用程序的数据拷贝给返回 BUFFt << “The string you will read is \”“ << buff << ”\“” << EOL; // 输出调试信息ULONG dwBytesRead = strlen(buff); // Count of bytes read I.Information() = dwBytesRead; // 返回给应用程序的信息的字节个数I.Status() = status;m_DriverManagedQueue.PnpNextIrp(I);

}

Page 39: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

39

void SampleDevice::SerialWrite(KIrp I){

t << "Entering SampleDevice::SerialWrite, " << I << EOL;NTSTATUS status = STATUS_SUCCESS;PUCHAR pBuffer =

(PUCHAR)I.BufferedWriteSource();// 取得存放应用程序写给驱动程序的数据的 BUFF 的指针ULONG dwTotalSize = I.WriteSize(CURRENT);// 获得应用程序写给驱动程序的信息的字节数。ULONG dwBytesSent = dwTotalSize;char buff[512];strcpy(buff, (char *)pBuffer); // 应用程序写给驱动程序的数据在 I.BufferedWriteSource() 返回的指针中。buff[dwBytesSent] = '\0'; t << "Write to driver is \"" << buff << "\"" << EOL;I.Information() = dwBytesSent; // 返回用户实际写的字节数I.Status() = status;m_DriverManagedQueue.PnpNextIrp(I);

}

Page 40: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

40

Test_Sample.cppvoid doRead(int n) // 从驱动程序中读数据{

char *buf;ULONG nRead;int i, j;buf = (char *) malloc(n);if (buf == NULL){

printf("Failed to allocate buffer for read");Exit(1);

}// Read data from driverprintf("Reading from device - ");ReadFile(hDevice, buf, n, &nRead, NULL);// 参数分别是设备句柄、输入缓冲地址、缓冲大小(字节数)、实际读的数据字节数、覆盖结构指针。

Page 41: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

41

printf("%d bytes read from device (%d requested).\n", nRead, nRead);

// Print what was readwhile(i < nRead){

// j = min((i+26),n);// for(; i < j; i++)// {// printf("%c, ", buf[i]);// }// printf("\n");

printf("%c, ",buf[i++]);}printf("\n");free(buf);

}

这几句删除

Page 42: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

42

void doWrite(int n) // 向驱动程序中写数据{

char *buf;ULONG nWritten;int i, j;buf = (char *) malloc(n);if (buf == NULL){

printf("Failed to allocate buffer for write");Exit(1);

}// start with the mod26 letter of the number of bytes to writej = (n % 26);// load buffer with dummy data (abcdefg...)for (i=0; i<n; i++, j=(j + 1)%26){

buf[i] = 'a' + j;}

Page 43: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

43

// Write data to driverprintf("Writing to device - ");WriteFile(hDevice, buf, n, &nWritten, NULL);// 写数据 , 参数的含义是驱动程序句柄、写缓冲、写缓冲大小、实际驱动程序得到的信息的字节数、覆盖结构指针。printf("%d bytes written to device (%d attempted).\n",

nWritten, n);i = 0; // Print what was writtenwhile(i < n){

j = min((i+26),n);for(; i < j; i++) {

printf("%c, ", buf[i]);}printf("\n");

}free(buf);

}

Page 44: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

44

b. 使用 IO 控制代码方式分别读写SampleDevice.cppNTSTATUS SampleDevice::SAMPLE_IOCTL_Read_Handler(KIrp I){ // 对应用程序读驱动程序的请求作响应

NTSTATUS status = STATUS_SUCCESS;t << "Entering SampleDevice::SAMPLE_IOCTL_Read_Handler, " << I

<< EOL;char buff1[512]; ULONG fwLength=0;strcpy(buff1,"Welcome to driver!");fwLength = strlen(buff1)+1;if (I.IoctlOutputBufferSize() >= fwLength) {// 如果读入缓冲够长

strcpy((PCHAR)I.IoctlBuffer(),buff1); // 将信息拷给应用程序读入缓冲I.Information() = fwLength; // 返回信息长度

}else {

I.Information() = 0; // 否则信息长度为 0 t << "buff size too small" << EOL;

}return status;

}

Page 45: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

45

NTSTATUS SampleDevice::SAMPLE_IOCTL_Write_Handler(KIrp I){ // 接受从应用程序中来的信息

NTSTATUS status = STATUS_SUCCESS;t << "Entering SampleDevice ::

SAMPLE_IOCTL_Write_Handler , " << I << EOL;char buff[512];ULONG fwLength=0;strcpy(buff,(PCHAR)I.IoctlBuffer()); // 拷贝从应用程序得到的命令串到驱动程序局部数据区t << “InputPut Data is \”“ << buff << ”\“” <<EOL; // 显示从应用程序得到的命令串。I.Information() = 0;return status;

}

Page 46: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

46

Test_Sample.cppvoid Test_SAMPLE_IOCTL_Read(void){

CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from deviceULONG nOutput; // Count written to bufOutput// Call device IO Control interface (SAMPLE_IOCTL_Read) in driverprintf("Issuing Ioctl to device - ");strcpy(bufInput,"This is a sample."); if (!DeviceIoControl(hDevice,SAMPLE_IOCTL_Read, NULL, 0,

bufOutput, IOCTL_OUTBUF_SIZE, &nOutput, NULL)){

printf("ERROR: DeviceIoControl returns %0x.", GetLastError());

Exit(1);}else printf("Return from driver is \"%s\"(%d)",bufOutput,nOutput);

}

Page 47: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

47

void Test_SAMPLE_IOCTL_Write(void){

CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to deviceCHARbufOutput[IOCTL_OUTBUF_SIZE];// Output from deviceULONG nOutput; // Count written to bufOutput// Call device IO Control interface (SAMPLE_IOCTL_Write) in driverprintf("Issuing Ioctl to device - ");strcpy(bufInput,"Now let us write this string."); if (!DeviceIoControl(hDevice, SAMPLE_IOCTL_Write, bufInput,

strlen(bufInput), NULL, 0, &nOutput, NULL)) // 该函数参数分别是设备句柄、 IO 控制命令、写缓冲、写缓冲大小、读缓冲、读缓冲大小、实际读的字节数、覆盖结构指针(注意,这里的 bufInput 是指 Input 到设备,所以对应用软件这是写缓冲, bufOutput 是从设备 output 到应用程序,是读缓冲。{

printf("ERROR: DeviceIoControl returns %0x.", GetLastError());

Exit(1);}

}

Page 48: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

48

c. 使用 IO 控制代码方式写并且读SampleDevice.cpp

NTSTATUS SampleDevice::SAMPLE_IOCTL_ReadWrite_Handler(KIrp I){

NTSTATUS status = STATUS_SUCCESS;t << "Entering

SampleDevice::SAMPLE_IOCTL_ReadWrite_Handler, " << I << EOL;

char buff[512],buff1[512]; ULONG fwLength=0;strcpy(buff,(PCHAR)I.IoctlBuffer());// 拷贝应用程序来的信息t << "InputPut Data is \"" << buff << "\"" <<EOL; strcpy(buff1,"this is feedback from driver! Application give

me this string \"");strcat(buff1,buff);strcat(buff1,“\”“); // 以上是组织反馈的信息

Page 49: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

49

fwLength = strlen(buff1)+1;if (I.IoctlOutputBufferSize() >= fwLength){

strcpy((PCHAR)I.IoctlBuffer(),buff1);// 拷贝反馈信息I.Information() = fwLength; // 设置反馈信息字节数

}else{

I.Information() = 0;t << "buff size too small" << EOL;

}return status;

}

Page 50: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

50

Test_Sample.cppvoid Test_SAMPLE_IOCTL_ReadWrite(void){

bufOutput is written by the device to return data to this application

CHAR bufInput[IOCTL_INBUF_SIZE]; // Input to device

CHAR bufOutput[IOCTL_OUTBUF_SIZE]; // Output from deviceULONG nOutput;// Count written to bufOutput

// Call device IO Control interface (SAMPLE_IOCTL_ReadWrite) in driver

printf("Issuing Ioctl to device - ");strcpy(bufInput,"This is a sample.");if (!DeviceIoControl(hDevice, SAMPLE_IOCTL_ReadWrite, bufInput, strlen(bufInput),bufOutput, IOCTL_OUTBUF_SIZE, &nOutput,

NULL) ){

printf("ERROR: DeviceIoControl returns %0x.", GetLastError());

Exit(1);}else

printf("Feedback is \"%s\"(%d)",bufOutput,nOutput); }

Page 51: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

51

Page 52: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

52

Page 53: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

53

3 )直接对端口寄存器读写 DriverStudio提供了 KIoRange 类来将外部总线的 I/O地址空间范围映射到处理器总线的地址空间范围。该类的成员函数主要有

KIoRange 构造函数 (4 种格式 )Initialize 初始化和重新初始化一个实例 (3种格式 )~KIoRange 析构函数Invalidate 从已初始化状态删除该对象IsValid 测试该对象是否已经初始化inb 读一个或多个字节 (2 种形式 )Outb 写一个或多个字节 (2 种形式 )Inw 读一个或多个字 (2 种形式 )Outw 写一个或多个字 (2 种形式 )ind 读一个或多个双字 (2 种形式 )outd 写一个或多个双字 (2 种形式 )

Page 54: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

54

KIoRange::KIoRange (只介绍WDM形式)FORM 3 (WDM):KIoRange(   ULONGLONG CpuPhysicalAddress, //转换成外围设备地址的 CPU 总线上的物理地址   BOOLEAN InCpuIoSpace, // 如果 IO范围是在 CPU 总线的 IO空间中为 TRUE ,否则为FALSE   ULONG Count, // 以字节计的区域的大小   BOOLEAN MapToSystemVirtual =TRUE// 指定是否需要构造函数创建一个非页系统空间的地址空间映射,如果驱动程序读写设备中的数据,就需要这种映射);FORM 4 (WDM): ( 注意 : 这种形式不被 DriverStudio 2.0 支持。 )KIoRange(   PCM_RESOURCE_LIST pTranslatedResourceList, // 指向转换资源表的指针   ULONG Ordinal=0, // 指定 pTranslatedResourceList 指向的资源列表中的一个特殊端口资源   BOOLEAN MapToSystemVirtual =TRUE);FORM 5 (WDM):KIoRange(   PCM_RESOURCE_LIST pTranslatedResourceList, // 可通过 KIrp::TranslatedResources 获得   PCM_RESOURCE_LIST pRawResourceList, // 指向原始资源表的指针   ULONG Ordinal=0,   BOOLEAN MapToSystemVirtual =TRUE); 构造 KIoRange 类。

Page 55: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

55

KIoRange::Initialize (只介绍WDM形式)FORM 2 (WDM):NTSTATUS Initialize(   ULONGLONG CpuPhysicalAddress,   BOOLEAN InCpuIoSpace,   ULONG Count,   BOOLEAN MapToSystemVirtual=TRUE);FORM 3 (WDM): ( 注意 : 这种形式不被 DriverStudio 2.0 支持。 )NTSTATUS Initialize(   PCM_RESOURCE_LIST pTranslatedResourceList,   ULONG Ordinal=0,   BOOLEAN MapToSystemVirtual =TRUE);FORM 4 (WDM):Initialize(   PCM_RESOURCE_LIST pTranslatedResourceList,   PCM_RESOURCE_LIST pRawResourceList,   ULONG Ordinal=0,   BOOLEAN MapToSystemVirtual =TRUE);初始化或重新初始化 KIoRange 的实例。

Page 56: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

56

KIoRange::inbFORM 1:UCHAR inb( ULONG ByteOffset );FORM 2:VOID inb(   ULONG ByteOffset,   PUCHAR Buffer,   ULONG Count);从映射空间读一个或多个字节。

Page 57: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

57

KIoRange::outbFORM 1:VOID outb(   ULONG ByteOffset,// 以字节为单位的目标位置到 IO空间开始位置的偏移值   UCHAR Data // 要写的一个字节数据);FORM 2:VOID outb(   ULONG ByteOffset,   PUCHAR Buffer,// 指向包含要写数据的缓冲的指针   ULONG Count // 缓冲中要写数据的字节数);写一个或多个字节到映射的 IO空间。

Page 58: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

58

• 写端口( 索引信息 , 地址70H ) m_ParPortIos.outb(0,0x02); // 准备读分钟信息

• 读端口(读分钟信息,地址 71H )UCHAR data = m_ParPortIos.inb(1);

下面我们来访问 CMOS 的数据。• 首先定义类 KIoRange 的一个实例,以定义相关地址空间。

KIoRange m_ParPortIos;• 初始化实例(指定 CMOS 的端口首地址,并映射)

status = m_ParPortIos.Initialize( 0x70, // CMOS端口首地址是 70H

TRUE, // 在 CPU I/O空间内 8, // 设备读写数据的字节宽度 TRUE // 映射到系统空间 );

Page 59: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

59

4 )截获中断和挂接中断服务例程 DriverStudio提供了 KInterrupt 类来截获和挂接中断。 该类的成员函数主要有KInterrupt 构造函数 (3种格式 )Initialize 在无效状态下初始化一个对象 (3种格式 )Connect 绑定 ISR (中断服务例程)到中断InitializeAndConnect 一步完成初始化与绑定工作,要用资源列表作为输入。~KInterrupt 析构函数Invalidate 在初始化状态下删除对象IsValid 检查对象是否初始化Disconnect 使中断和 ISR 与中断分离Synchronize 当得到一个中断自旋锁时请求同步功能

Page 60: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

60

KInterrupt::KInterrupt(只介绍WDM形式)FORM 3: (WDM)KInterrupt(   KIRQL irql, // 即插即用设备提供的 IRQL值   ULONG vector, // 即插即用设备提供的向量值   KINTERRUPT_MODE Mode,//LevelSensitive 或 Latched 中选一 .

   BOOLEAN bShareVector=FALSE, // 该向量是否被几个设备共享   KAFFINITY affinity=1, //this is the processor affinity mask.

   BOOLEAN bSaveFloat =FALSE // 是否需要在中断到来使保存浮点处理器上下文, X86平台下必须使 FALSE);构造类 Kinterrupt 的实例。

Page 61: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

61

KInterrupt::Initialize (只介绍WDM形式)FORM 2: (WDM)VOID   Initialize(   KIRQL irql,   ULONG vector,   KINTERRUPT_MODE Mode,   BOOLEAN bShareVector=FALSE,   KAFFINITY affinity=1,   BOOLEAN bSaveFloat=FALSE);初始化对象。只在对象没有初始化的时候使用。

Page 62: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

62

KInterrupt::ConnectFORM 1:NTSTATUS Connect(   PKSERVICE_ROUTINE Isr, // 作为 ISR服务的函数的地址   PVOID Context //当系统调用 ISR 的时候传递给他的无类型的参数);FORM 2:NTSTATUS Connect(   PKSERVICE_ROUTINE Isr,   PVOID Context,   PKSPIN_LOCK pSpin,    KIRQL SynchIrql);绑定一个中断到 ISR( 中断处理程序)。

Page 63: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

63

KInterrupt::InitializeAndConnectNTSTATUS InitializeAndConnect(   PCM_RESOURCE_LIST pResourceList, // 指向资源列表的指针   PKSERVICE_ROUTINE Isr,   PVOID IsrContext,   ULONG Ordinal=0,   BOOLEAN bSaveFloat=FALSE);初始化一个中断并绑定到一个 ISR上。对于 WDM 驱动程序, pResourceList 必须是一个转换资源表,例如是 KIrp::TranslatedResources 的返回值。

Page 64: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

64

下面我们来举例说明。• 首先定义类 KInterrupt 的一个实例 KInterrupt m_TheInterrupt; • 在设备类中声明一个成员函数 TheIsr 作为中断服务例程 ISR 。

class SampleDevice : public KPnpDevice{ …… public:

MEMBER_ISR (SampleDevice, TheIsr); ……

#ifdef _COMMENT_ONLY BOOLEAN TheIsr ( void ) { return TRUE ; };

#endif ……}

Page 65: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

65

• 在 OnStartDevice 例程中获取包括中断的设备资源并初始化中断和挂接 ISR SampleDevice ::OnStartDevice(KIrp I){……PCM_RESOURCE_LIST pResList =

I.TranslatedResources(); // 获取设备资源// 初始化中断并挂接中断服务例程 TheIsrstatus =

m_TheInterrupt.InitializeAndConnect(pResList, LinkTo(TheIsr), this);

……}

Page 66: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

66

5 )如何写 Win32 类型的驱动程序的测试程序 DriverStudio 自动生成的驱动程序的测试程序是一个控制台程序,下面我们将利用该控制台程序来写一个 Win32的程序。 第一步,在由 DriverStudio 自动生成一个驱动程序工作区 (Workspace) 中添加一个新的子工程,该子工程指定为一个 MFC 的 EXE 程序。 右键点击

Page 67: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

67

Page 68: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

68

第二步,手工在新的工程中添加几个文件这几个程序需要手工添加进去,实际上这几个程序都在 DriverStudio 自动生成的原来的两个工程文件中 ( 这个例子是 MyIOPort和 Test_MyIOPort 工程 ) 。将他们添加到新工程中,方法是右键点击新工程中的相关文件夹,在弹出菜单中选择 Add Files to Folder… ,然后找到要添加的文件并添加。

Page 69: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

69

第三步,打开 OpenByIntf.cpp 文件,在开始第一行添加#include "stdafx.h" 第四步, 1

2

3 4

5C:\PROGRAM FILES\COMPUWARE\SOFTICE DRIVER SUITE\DRIVERWORKS\INCLUDE

Page 70: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

70

第五步, 1

2

3

4

setupapi.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib

可以直接从自动生成的控制台工程的设置中拷贝这些库的名称

Page 71: Windows98/2000 驱动程序编写方法

http://qsyang.yeah.net

现代微机原理与接口技术

71

最后,在控制台程序的 Test_XXXX.CPP 程序基础上进行必要的修改。注意要保留的是打开设备、关闭设备、读写设备有关的函数。界面部分应该全部换成 Windows 界面的代码,而不是保留控制台代码。