微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 高速PCI信号采集卡设计与实现综合实例之:PCI卡的驱动程序设计

高速PCI信号采集卡设计与实现综合实例之:PCI卡的驱动程序设计

时间:06-04 来源:互联网 点击:

N_REMOVE_DEVICE: //关闭并删除设备

Unlock=FALSE;

status=HandleRemoveDevice(fdo,pIrp);

break;

caseIRP_MN_QUERY_REMOVE_DEVICE: //查询设备是否可被安全删除

status=DefaultPnpHandler(fdo,pIrp);

break;

caseIRP_MN_CANCEL_REMOVE_DEVICE: //忽略以前的QUERY_REMOVE

status=DefaultPnpHandler(fdo,pIrp);

break;

caseIRP_MN_QUERY_STOP_DEVICE: //查询设备是否可被安全关闭

status=DefaultPnpHandler(fdo,pIrp);

break;

caseIRP_MN_CANCEL_STOP_DEVICE: //忽略以前的QUERY_STOP

status=DefaultPnpHandler(fdo,pIrp);

break;

caseIRP_MN_QUERY_CAPABILITIES: //取设备能力

status=DefaultPnpHandler(fdo,pIrp);

break;

…}

returnstatus;

}

这些功能代码函数都在DriverEntry()入口函数中进行了声明。

4.DispatchPower例程

WDM设备驱动程序支持电源管理,一个设备可以改变它的电源使用来响应系统电源状态变化,且在处于空闲状态时可以减少它自己的电源使用。一个休眠的设备可以唤醒系统,如当调制解调器收到到达的呼叫时。

驱动程序的电源管理例程围绕电源IRP_MJ_POWERIRP进行处理,这些例程处理这个IRP,并在需要时产生这个IRP。这个IRP有4个电源管理次功能代码。

·IRP_MN_WAIT_WAKE。

·IRP_MN_POWER_SEQUENCE。

·IRP_MN_SET_POWER。

·IRP_MN_QUERY_POWER。

这部分的代码如下:

NTSTATUSDispatch_Power(

PDEVICE_OBJECTfdo,

PIRPpIrp

)

{

NTSTATUSstatus;

PIO_STACK_LOCATIONstack;

//获取指向被调用的Irp的栈位置的指针

stack=IoGetCurrentIrpStackLocation(pIrp);

switch(stack->MinorFunction)

{

caseIRP_MN_WAIT_WAKE: //唤醒计算机,响应一个外部事件

status=DefaultPowerHandler(fdo,pIrp);

break;

caseIRP_MN_POWER_SEQUENCE: //确定设备是否真正进入特定的电源状态

status=DefaultPowerHandler(fdo,pIrp);

break;

caseIRP_MN_SET_POWER: //设置系统或设备电源状态

status=HandleSetPower(fdo,pIrp);

break;

caseIRP_MN_QUERY_POWER: //查询系统或设备状态变化是否可行

status=HandleQueryPower(fdo,pIrp);

break;

default: //确定设备是否真正进入特定的电源状态

status=DefaultPowerHandler(fdo,pIrp);

break;

}

returnstatus;

}

5.Unload例程

在默认情况下,驱动程序装入之后,在重新引导之前就一直保持在系统中。要使系统可卸载,必须有一个Unload例程。Uload例程在DriverEntry期间声明,然后,每当驱动程序被手动或自动卸载时,I/O管理程序就调用该例程。

该例程函数原型为:

VOIDUnload(PDRIVER_OBJECTpDriverObject)

通常一个Uload例程执行如下工作。

·对于某些种类的硬件,设备状态应当保存在注册表中。那样,在DriverEntry下一次执行时,设备能够恢复到最近已知的状态。

·如果启动了设备中断,Unload例程必须仅用它们,并断开它们与中断对象的连接。

·必须释放属于驱动程式的硬件。

·必须从Win32名字空间中删除符号链接名字,这可以用IoDeleteSymbolicLink完成。

·必须用IoDeleteDevice删除设备对象自身。

·释放驱动程序占据的任何池内存。

驱动中的部分代码如下:

VOIDDriverUnload(PDRIVER_OBJECTpDriverObject)

{

//释放公共缓冲区

if(Gbl_CommonBuffer.PciMem.PhysicalAddr!=(U32)NULL)

{

//释放内存描述列表(MDL)

if(Gbl_CommonBuffer.pMdl!=NULL)

{

IoFreeMdl(Gbl_CommonBuffer.pMdl);

Gbl_CommonBuffer.pMdl=NULL;

}

//释放公共缓冲区

if(Gbl_CommonBuffer.pKernelVa!=NULL)

{

MmFreeContiguousMemory(Gbl_CommonBuffer.pKernelVa);

Gbl_CommonBuffer.pKernelVa=NULL;

}

}

//释放DMA使用的缓冲区

#ifdefined(DMA_SUPPORT)

DriverBufferTerminate();

#endif

}

6.Dispatch例程

驱动程序装载是第一步工作,但是最终驱动程序的作业是响应I/O请求——来自用户模式应用程序的请求或者来自系统其他地方的请求。Windows2000驱动程序通过Dispatch例程来处理这些请求。I/O管理程序调用这些例程以响应请求。

要启用特定的I/O函数代码,驱动函数必须首先“声明”响应这样一个请求的Dispatch例程。声明机制是DriverEntry执行的工作,它把Dispatch例程函数地址保存在驱动程序对象的MajorFunction表的合适位置上。

I/O函数代码是用于表的索引。其中,每个I/O函数代码(表索引)由一个IRP_MJ_XXX形式的惟一符号标示,在NTDDK.h(或WDM.h)包含文件中定义。

所有驱动程序必须支持函数代码IRP_MJ_CREATE,因为编写此代码的目的是响应Win32CreateFile调用

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top