高速PCI信号采集卡设计与实现综合实例之:PCI卡的驱动程序设计
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调用
高速PCI信号采集卡 驱动程序 WDM驱动程序 过滤驱动程序 FPGA 相关文章:
- 高速PCI信号采集卡设计与实现综合实例之: 产品定型和设计文档备案(06-04)
- 高速PCI信号采集卡设计与实现综合实例之:产品稳定性和可靠性测试(06-04)
- 高速PCI信号采集卡设计与实现综合实例之:设计需求分析与功能定义(06-04)
- 高速PCI信号采集卡设计与实现综合实例之:样机的调试方法和技巧(06-04)
- 高速PCI信号采集卡设计与实现综合实例之:硬件系统实现(06-04)
- 高速PCI信号采集卡设计与实现综合实例之: FPGA内部结构设计(06-04)