首 页 用户登录 | ![]() |
|||
|
|||
按字母检索 | A | B | C | D | E | F | G | H | I | J | K | L | M | N | O | P | Q | R | S | T | U | V | W | X | Y | Z |
按声母检索 | A | B | C | D | E | F | G | H | J | K | L | M | N | O | P | Q | R | S | T | W | X | Y | Z | 数字 | 符号 |
|
![]() |
您的位置: 5VAR论文频道 → 论文中心 → 理工论文 → 电子通信 |
|
|||||
采用VXD技术实现实的通信 | |||||
收集整理:佚名 来源:本站整理 时间:2009-01-10 22:25:23 点击数:[] ![]() |
|||||
向该虚拟IRQ的句柄(该句柄在后来的VPICD服务中需要提供)。VPICD_IRQ_Descriptor结构体的组成为: typedef struct VPICD_IRQ_Descriptor{ USHORT VID_IRQ_Number; //IRQ号(0~15) USHORT VID_Options; //标志位选项 ULONG VID_Hw_Int_Proc; //硬件中断服务程序的地址 ULONG VID_Virt_Int_Proc; //虚拟中断服务程序 ULONG VID_Mask_Change_Proc //Mask Change调用例程 ULONG VID_IRET_Proc; //IRET调用例程 ULONG VID_IRET_Time_Out; //在Vm的进程优先级提升之前的最大等待时间 ULONG VID_Hw_Int_Ref; //硬件中断服务程序的数据存放地址 }VID; 其中只用到三位。在本例中需要声明一个名为irq4的全局变量为VID结构,并付给如下初值:VID irq4={4,0,hwproc,0,0,0,0,500,0},表示将要虚拟化IRQ4,改变其中断处理函数为void hwproc(void),该函数的原型如下: void hwproc(void){ _asm{ mov dx,0x3f8 in al,dx mov byte ptr [readin],al clc } return; } 在这个中断处理中,仅仅从COM1的数据寄存器(地址为3F8h)中读取接收到的数值,并把该数值存放在一个类型为BYTE、名为readin的内存中。 (2)OnSysDynamicDeviceExit()函数 BOOL OnSysDynamicDeviceExit() { VPICD_Force_Default_Behavior(irqhandle); //解除IRQ4虚拟化 return TRUE; } //OnSysDynamicDeviceExit 该数提供了用于善后处理VXD在卸载时需要完成的事件。在本例中,和VXD初始化对应,需要解除对COM1的中断IRQ4的虚拟化。作者也是用98DDK在vpicd.h中提供的外包函数void static_inline VPICD_Force_Default_Behavior(HIRQ hirp)。该函数唯一需要的参数便是使用VPICD_Virtualize_IRQ函数传回的IRQ句柄。 (3)OnDeviceIoControl()函数 DWORD OnDeviceIoControl(PDIOCPARAMETERS p){ Switch (p->dwIoControlCode) { case 1: //端口写功能 if(!p->lpvOutBufferp->cbOutBuffer<1) { //输出缓存的有效性检查 return ERROR_INVALID_PARAMETER; } if(serial_out((DWORD)(p->lpvInBuffer))) { //数据发送 *(BYTE*)(p->lpvOutBuffer)=*(BYTE*)(p->lpvInBuffer); } else{ *(BYTE*)(p->lpvOutBuffer)=0; } open_int(); //打开com1中断 return 0; case 2: //端口读功能 if(*(BYTE*)reading= =0x00) { //数据读入 *(BYTE*)(p->lpvOutBuffer)=0x00; return 0; } *(BTYE*)(p->lpvOutBuffer)=*(BYTE*)(readin); return 0; } return 0; } return 0; } OnDeviceIoControl函数用来处理Win32应用程序对VXD的呼叫。Win32应用程序的呼叫会让VMM32送给该VXD一个系统信息,并传递进一个DIOCPARAMETERS结构的指针。该结构里包含Win32应用程序呼叫时传递进来的各个参数。这个结构的组成如下: Typedef stunct DIOCParams{ DWORD Internall; //指向客户寄存器的指针 DWORD VMHande; //该VM的句柄 DWORD Internal2; //指向DDB结构的指针 DWORD dwIoConrolCode; //DeviceIoControl例程中呼叫的控制码 DWOD lpvInBuffer; //DeviceIoControl例程呼叫所传递进来的输入缓冲区地址 DWORD cbInBuffer; //输入缓冲区的大小 DWORD lpvOutBuffer; //DeviceIoControl例程呼叫所传递进来的输出缓冲区地址 DWORD cbOutBuffer; //输出缓冲区的大小 DWORD lpcbBytesReturned; //拷贝到输出缓冲区中的字节数(可以为NULL) DWORD lpOverlapped; //DeviceIoControl例程呼叫所传递进来的重叠I/O块结构 DWORD hDevice; //Ring3层呼叫应用程序句柄 DWORD tagProcess; //例程标签 } DIOPARAMETERS; 其中,dwIoControlCode指明了Win32应用程序需要VXD提供的哪一项服务。在本例中采用一个switch-case语句作为服务入口,如下所示。其中服务1为让串口送出一个字节,服务2为读取一个已经由串口接收的字节。函数open_int()是用来初始化串口以便接收字节数据;函数BOOL serial_out(DWORD pBuffer)是让串口发出一个字节。它们的函数体分别如下: BOOL serial_out(DWORD pBuffer){ if(pBuffer= =NULL){ return FALSE; } _asm { pushfd cli push eax push edx mov dx,0x3fb ;设置COM1的波特率 mov al,0x83 out dx,al mov dx,0x3f8 mov al,12 out dx,al mov dx,0x3f9 mov al,0 out dx,al mov dx,0x3fb ;设置COM1的线控项 mov al,3 out dx,al mov dx,0x3f9 ;CMM1关中断 mov al,0 out dx,al mov dx,0x3fa ;关闭com1的FIFO功能 mov al,0 out dx,al mov dx,0x3f8 ;字节发送 mov al,byte ptr [pBuffer] out dx,al pop edx pop eax popfd sti } return TRUE; } serial_out这个函数体的实现是用汇编语言实现的。因为涉及到很多的端口提供以及CPU的标志(flag)和压栈操作,因此考虑到用汇编语言编写会简化代码。因为此串口传输中,用到了关闭中断的指令(cli),所以,当写操作所要求完成的任务很多时,此关中断指令会让程序的实时性很好地体现出来,但cli指令有效时间过长会导致系统问题,所以还是要谨慎使用。 Void open_int(void){ _asm{ mov dx,0x3f9 ;COM1开中断 mov al,0x05 out dx,al } return; } open_int函数用来把PC串口的中断设备按照需要设立起来。函数体很简单,仅改变了地址为3F9h的内容,意为设置Rx data ready和 Tags: |
提供人:佚名 | |
【返回上一页】【打 印】【关闭窗口】 |
![]() |
5VAR论文频道 |
![]() |
5VAR论文频道 |
![]() |
关于本站 -
网站帮助 -
广告合作 -
下载声明 -
网站地图
Copyright © 2006-2033 5Var.Com. All Rights Reserved . |