用户登录  |  用户注册
首 页商业源码原创产品编程论坛
当前位置:PB创新网文章中心解决方案电子通信

采用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和

上一页  [1] [2] [3]  下一页

Tags:

作者:佚名

文章评论评论内容只代表网友观点,与本站立场无关!

   评论摘要(共 0 条,得分 0 分,平均 0 分) 查看完整评论
PB创新网ourmis.com】Copyright © 2000-2009 . All Rights Reserved .
页面执行时间:20,750.00000 毫秒
Email:ourmis@126.com QQ:2322888 蜀ICP备05006790号