阅读:1516回复:5
200分,救救我吧,帮我看看我的程序,为什么关机经常蓝屏
下面是我写的ISA卡的NT式的驱动用DS2。7写的,在WIN2000下运行,程序运行中很少蓝屏,但在关机的时候经常蓝屏,下面是设备类.c 文件,哪位帮我看看,到底有什么错误!
// JiemaDevice.cpp // Implementation of JiemaDevice device class // // Generated by DriverWizard version DriverStudio 2.7.0 (Build 562) // Requires Compuware's DriverWorks classes // #include <vdw.h> #include "Jiema.h" #include "JiemaDevice.h" #include "..\jiemaioctl.h" #pragma warning(disable:4065) // Allow switch statement with no cases extern KTrace t; // Global driver trace object //////////////////////////////////////////////////////////////////////// // JiemaDevice::~JiemaDevice // // Routine Description: // This is the destructor for the JieDevice // // Parameters: // None // // Return Value: // None // // Comments: // Disconnect and release resources here. // // Although the use of SAFE_DESTRUCTORS in the class definition cures // improper emission of the destructor into the INIT section most of the // time, certain rare cases can still cause improper behavior. To avoid // these cases, the destructor must preceed the INIT section, causing it // to be referenced first by the default compiler section. // JiemaDevice::~JiemaDevice() { t<<"enter the desconstructor\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); if(m_pEvent!=NULL) { t<<"删除事件对象\n"; delete m_pEvent; m_pEvent=NULL; } if(Me!=NULL) { t<<"删除内存对象Me\n"; delete Me; Me=NULL; } if(Buf!=NULL) { t<<"删除内存对象Buf\n"; delete Buf; Buf=NULL; } ReleaseResources(*m_RegPath); delete m_RegPath; } #pragma code_seg("INIT") //////////////////////////////////////////////////////////////////////////////// // JiemaDevice::JiemaDevice // // Routine Description: // The device constructor is typically responsible for allocating // any physical resources that are associated with the device. // // Parameters: // Unit - Unit number. This is a number to append to the device's // base device name to distinguish multiple units of this // device type. // // Return Value: // None // // Comments: // The device constructor often reads the registry to setup // various configurable parameters. JiemaDevice::JiemaDevice(ULONG Unit) : KDevice() { t<<"enter the constructor \n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); if ( ! NT_SUCCESS(m_ConstructorStatus) ) { t << "Failed to create device JiemaDevice unit number " << Unit << " status " << (ULONG) m_ConstructorStatus << EOL; return; } m_Unit = Unit; m_RegPath = CreateRegistryPath(L"JieDevice", Unit); if (m_RegPath == NULL) { // Error, cannot allocate memory for registry path t << "Failed to create registry path\n"; m_ConstructorStatus = STATUS_INSUFFICIENT_RESOURCES; return; } // Claim and initialize resources assigned to this device m_ConstructorStatus = InitResources(); } //////////////////////////////////////////////////////////////////////// // JiemaDevice::Invalidate // // Routine Description: // Calls Invalidate methods for system resources // // Parameters: // None // // Return Value: // None // // Comments: // This function is called from InitResources (in error conditions). // It calls the Invalidate member funcitons for each resource to free // the underlying system resource if allocated. It is safe to call // Invalidate more than once for a resource, or for an uninitialized resource. VOID JiemaDevice::Invalidate() { t<<"enter the Invalidate()\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); m_IoPortRange1.Invalidate(); m_IoPortRange2.Invalidate(); m_IoPortRange3.Invalidate(); m_IoPortRange4.Invalidate(); m_Irq.Invalidate(); } //////////////////////////////////////////////////////////////////////////////// // 查询注册表,获得中断号 //////////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Add_Irq(KResourceRequest *theRequest, KRegistryKey *Params) { t<<"enter the request of theIrq\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); ULONG theIRQ = 0; Params->QueryValue(L"Irq", &theIRQ); return theRequest->AddIrq( theIRQ, theIRQ, 0, CmResourceShareDeviceExclusive, CM_RESOURCE_INTERRUPT_LATCHED ); } //////////////////////////////////////////////////////////////////////////////// // 查询注册表,获得解码数据的端口地址 // 端口对象1:第1-16路 // m_IoPortRange1:0x250-0x26f //////////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Add_IoPortRange1(KResourceRequest *theRequest, KRegistryKey *Params) { t<<"enter the request of the port1\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); PHYSICAL_ADDRESS theAddr; theAddr.HighPart = theAddr.LowPart = 0; // 查询注册表,获得硬件使用的端口的地址. Params->QueryValue(L"IoPortRange1_high", (PULONG) &theAddr.HighPart); Params->QueryValue(L"IoPortRange1_low", (PULONG) &theAddr.LowPart); return theRequest->AddPort( theAddr, theAddr, 32, 2, 0, CmResourceShareDeviceExclusive ); } //////////////////////////////////////////////////////////////////////////////// // 查询注册表,获得解码数据的端口地址 // 端口对象2:第17-24路 // m_IoPortRange2:0x3a0-0x3af //////////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Add_IoPortRange2(KResourceRequest *theRequest, KRegistryKey *Params) { t<<"enter the request of the port2\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); PHYSICAL_ADDRESS theAddr; theAddr.HighPart = theAddr.LowPart = 0; // 查询注册表,获得硬件使用的端口的地址. Params->QueryValue(L"IoPortRange2_high", (PULONG) &theAddr.HighPart); Params->QueryValue(L"IoPortRange2_low", (PULONG) &theAddr.LowPart); return theRequest->AddPort( theAddr, theAddr, 16, 2, 0, CmResourceShareDeviceExclusive ); } //////////////////////////////////////////////////////////////////////////////// // 查询注册表,获得解码数据的端口地址 // 端口对象3:第25-28路,选路信息 // 选路信息:0x3e8-0x3e9 // m_IoPortRange3:0x3e0-0x3e7 //////////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Add_IoPortRange3(KResourceRequest *theRequest, KRegistryKey *Params) { t<<"enter the request of the port3\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); PHYSICAL_ADDRESS theAddr; theAddr.HighPart = theAddr.LowPart = 0; // 查询注册表,获得硬件使用的端口的地址. Params->QueryValue(L"IoPortRange3_high", (PULONG) &theAddr.HighPart); Params->QueryValue(L"IoPortRange3_low", (PULONG) &theAddr.LowPart); return theRequest->AddPort( theAddr, theAddr, 16, 2, 0, CmResourceShareDeviceExclusive ); } //////////////////////////////////////////////////////////////////////////////// // 查询注册表,获得时间码数据的端口地址 // 端口对象4: //m_IoPortRange4:0x390-0x395 //////////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Add_IoPortRange4(KResourceRequest *theRequest, KRegistryKey *Params) { t<<"enter the request of the port4\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); PHYSICAL_ADDRESS theAddr; theAddr.HighPart = theAddr.LowPart = 0; // 查询注册表,获得硬件使用的端口的地址. Params->QueryValue(L"IoPortRange4_high", (PULONG) &theAddr.HighPart); Params->QueryValue(L"IoPortRange4_low", (PULONG) &theAddr.LowPart); return theRequest->AddPort( theAddr, theAddr, 16, 2, 0, CmResourceShareDeviceExclusive ); } //////////////////////////////////////////////////////////////////////// // 初始化函数,建立设备的资源请求对象,向系统申请资源 ///////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::InitResources(void) { t<<"enter the InitResources\n"; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); NTSTATUS status; KRegistryKey Params(*m_RegPath); if (!NT_SUCCESS(Params.LastError())) { // 发生错误,不能打开设备的注册表键 t << "Failed to create registry key: " << PWSTR(*m_RegPath) << EOL; t << "(Did you run REGINI on the .ini file created by the wizard?)\n"; return STATUS_UNSUCCESSFUL; } // 创建资源请求对象,调用ADD例程来构造资源列表 t << "create ISA device resource request object\n"; KResourceRequest theRequest(Isa, (ULONG) 0, (ULONG) 0); Add_IoPortRange1(&theRequest, &Params); Add_IoPortRange2(&theRequest, &Params); Add_IoPortRange3(&theRequest, &Params); Add_IoPortRange4(&theRequest, &Params); Add_Irq(&theRequest, &Params); // 向系统请求需要的资源 status = theRequest.Submit(this, *m_RegPath); if (!NT_SUCCESS(status)) { t<<"resource conflict\n"; return status; } KResourceAssignment AssignedIoPortRange1(&theRequest, CmResourceTypePort, 0); // 确认分配成功 if (!AssignedIoPortRange1.Status()) { // 发生错误,不能分配 Invalidate(); return STATUS_UNSUCCESSFUL; } status = m_IoPortRange1.Initialize( Isa, 0, AssignedIoPortRange1.Start().QuadPart, AssignedIoPortRange1.Length(), TRUE ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } KResourceAssignment AssignedIoPortRange2(&theRequest, CmResourceTypePort, 1); // 确认分配成功 if (!AssignedIoPortRange2.Status()) { // 发生错误,不能分配 Invalidate(); return STATUS_UNSUCCESSFUL; } status = m_IoPortRange2.Initialize( Isa, 0, AssignedIoPortRange2.Start().QuadPart, AssignedIoPortRange2.Length(), TRUE ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } KResourceAssignment AssignedIoPortRange3(&theRequest, CmResourceTypePort, 2); // 确认分配成功 if (!AssignedIoPortRange3.Status()) { // 发生错误,不能分配 Invalidate(); return STATUS_UNSUCCESSFUL; } status = m_IoPortRange3.Initialize( Isa, 0, AssignedIoPortRange3.Start().QuadPart, AssignedIoPortRange3.Length(), TRUE ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } KResourceAssignment AssignedIoPortRange4(&theRequest, CmResourceTypePort, 3); // 确认分配成功 if (!AssignedIoPortRange4.Status()) { // 发生错误,不能分配 Invalidate(); return STATUS_UNSUCCESSFUL; } status = m_IoPortRange4.Initialize( Isa, 0, AssignedIoPortRange4.Start().QuadPart, AssignedIoPortRange4.Length(), TRUE ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } // 申请中断 if (theRequest.Assignments() == NULL) { t << "Resource assignment failed for IRQ\n"; Invalidate(); return STATUS_RESOURCE_TYPE_NOT_FOUND; } else { status =m_Irq.Initialize( theRequest.Assignments() ); if (!NT_SUCCESS(status)) { Invalidate(); return status; } } ); // 建立中断的延迟过程调用 m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this); m_IoPortRange4.outw(12,0x11);//用来启动CPLD的状态机。 Buf=new(NonPagedPool)UCHAR(68);//申请非分页内存,在中断延迟里用来存放读端口得到的数 据。 Me=new(NonPagedPool)KMemory(Buf,68);//申请非分页内存,将来影射到用户虚拟地址,传递给 应用层。 t<<"succeed acquire all resource\n"; return STATUS_SUCCESS; } #pragma code_seg() //////////////////////////////////////////////////////////////////////// // JiemaDevice::DeviceControl // // Routine Description: // Handler for IRP_MJ_DEVICE_CONTROL // // Parameters: // I - Current IRP // // Return Value: // NTSTATUS - Result code // // Comments: // This routine is the first handler for Device Control requests. // // Some function codes may be handled immediately, // while others may be serialized. // NTSTATUS JiemaDevice::DeviceControl(KIrp I) { NTSTATUS status; t << "Entering JiemaDevice::Device Control, " << I; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); switch (I.IoctlCode()) { case EVENT_IOCTL_800: status = EVENT_IOCTL_800_Handler(I); break; case JIEMA_IOCTL_801: status = JIEMA_IOCTL_801_Handler(I); break; case IOCTL_WRITE_YIMA: status = XUANLU_IOCTL_804_Handler(I); break; default: status = STATUS_INVALID_PARAMETER; break; } if (status == STATUS_PENDING) { return status; } else { return I.Complete(status); } } ////////////////////////////////////////////////////////////////////////// ////接收来自应用层发来的事件对象,在中断延迟里设置事件对象为有效,和应用通信。 ////采用缓冲I/O方式 ////////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::EVENT_IOCTL_800_Handler(KIrp I) { t << "Entering JiemaDevice::EVENT_IOCTL_800_Handler, " << I << EOL; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); HANDLE hEvent=*(HANDLE*)I.IoctlBuffer(); m_pEvent=new(NonPagedPool)KEvent(hEvent); NTSTATUS status=(m_pEvent!=NULL)?STATUS_SUCCESS:STATUS_INSUFFICIENT_RESOURCES; I.Information() =0; I.Status() = status; return status; } ///////////////////////////////////////////////////////////////////// 把驱动层分配的核心虚拟地址Buf映射到用户虚拟地址,传递到应用层。 ///////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::JIEMA_IOCTL_801_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering JiemaDevice::JIEMA_IOCTL_801_Handler, " << I << EOL; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); UserSpaceAddress=Me->MapToUserSpace(); t<<"映射后的地址是:"<<(ULONG)UserSpaceAddress<<"\n"; *(PVOID*)I.IoctlBuffer()=UserSpaceAddress; I.Information() =sizeof(PVOID); return status; } ///////////////////////////////////////////////////////////////////// ////向选路信息端口写入选路信息,口地址:0x3e8 ////采用直接I/O方式传输数据:METHOD_IN_DIRECT ///////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::XUANLU_IOCTL_804_Handler(KIrp I) { NTSTATUS status = STATUS_SUCCESS; t << "Entering JiemaDevice::XUANLU_IOCTL_802_Handler, " << I << EOL; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); KMemory Mem(I.Mdl()); PUSHORT pBuffer =(PUSHORT)Mem.MapToSystemSpace();//输出缓冲区 ULONG dwTotalSize=I.IoctlOutputBufferSize(CURRENT)/2; stop=pBuffer[85]; m_IoPortRange3.outw(8,pBuffer,dwTotalSize);//,pBuffer+85,1 if(stop==6) //启动传输,打开中断连接 { m_Irq.Connect( LinkTo(Isr_Irq), this ); } if(stop==4)//停止传输,断开中断连接 { m_Irq.Disconnect(); } I.Information() = dwTotalSize*2; return status; } //////////////////////////////////////////////////////////////// // 清除未处理的IRP和排队的IRP //////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::CleanUp(KIrp I) { t << "Entering CleanUp, " << I; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); KDeviceQueue dq(DeviceQueue()); dq.CleanUp(I.FileObject()); return I.Complete(STATUS_SUCCESS); } ////////////////////////////////////////////////////////////////// ////打开设备句柄 ///////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Create(KIrp I) { t << "Entering Create, " << I; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); I.Information() = 0; return I.Complete(STATUS_SUCCESS); } //////////////////////////////////////////////////////////////////////// //// 关闭设备句柄 /////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Close(KIrp I) { t << "Entering Close, " << I; DbgPrint("the irql is %x\n",KeGetCurrentIrql()); I.Information() = 0; return I.Complete(STATUS_SUCCESS); } //////////////////////////////////////////////////////////////////////// ///系统关闭例程 //////////////////////////////////////////////////////////////////////// NTSTATUS JiemaDevice::Shutdown(KIrp I) { if(m_pEvent!=NULL) { t<<"删除事件对象\n"; delete m_pEvent; m_pEvent=NULL; } if(Me!=NULL) { t<<"删除内存对象Me\n"; delete Me; Me=NULL; } if(Buf!=NULL) { t<<"删除内存对象Buf\n"; delete Buf; Buf=NULL; } ReleaseResources(*m_RegPath); delete m_RegPath; return I.Complete(STATUS_SUCCESS); } /////////////////////////////////////////////////////////////////////// // 中断延迟处理程序 // 用事件对象来通知应用程序,中断到来,数据准备好,可以读数据了 //////////////////////////////////////////////////////////////////////// VOID JiemaDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2) { m_IoPortRange1.inw(0); m_IoPortRange1.inw(2); if(stop!=4) { if(Buf!=NULL) { for (ULONG i=4;i<32;i=i+2) { m_IoPortRange1.inw(i,(PUSHORT)Buf+i/2-2,1); } for(ULONG j=0;j<16;j=j+2) { m_IoPortRange2.inw(j,(PUSHORT)Buf+14+j/2,1); } for(ULONG l=0;l<7;l=l+2) { m_IoPortRange3.inw(l,(PUSHORT)Buf+22+l/2,1); } m_IoPortRange3.inw(10,(PUSHORT)Buf+26,1); m_IoPortRange3.inw(12,(PUSHORT)Buf+27,1); for(ULONG w=0;w<12;w=w+2) { m_IoPortRange4.inw(w,((PUSHORT)Buf)+28+w/2,1); } if(m_pEvent->state()==FALSE) { m_pEvent->Set(); //通知应用层,数据存放好了,可以来取了。 } } } } //////////////////////////////////////////////////////////////////////// // 中断处理程序 // 确认中断的发生,统计中断次数 //////////////////////////////////////////////////////////////////////// BOOLEAN JiemaDevice::Isr_Irq(void) { m_DpcFor_Irq.Request(NULL, NULL); return TRUE; } 其中: Buf,Me,stop,UserSpaceAddress 为类JiemaDevice的成员变量。如下定义: PUCHAR Buf; KMemory* Me; ULONG stop; PVOID UserSpaceAddress; |
|
|
沙发#
发布于:2004-02-27 19:20
ReleaseResource呢?
试试shutdown什么也不干? |
|
板凳#
发布于:2004-02-27 19:53
我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊
|
|
地板#
发布于:2004-03-01 09:38
我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊 new 是C++里分配内存的操作符,可以使用这个,没什么关系的。 请大虾们找重看看我的中断处理程序和中断延迟处理程序,我觉得这两个的问题最大。 谢谢了! |
|
|
地下室#
发布于:2004-03-01 11:32
[quote]我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊 new 是C++里分配内存的操作符,可以使用这个,没什么关系的。 请大虾们找重看看我的中断处理程序和中断延迟处理程序,我觉得这两个的问题最大。 谢谢了! [/quote] To nosegay: 没错,Driver里面不能使用new, 不过libin2309的代码是用DriverWorks写的,DriverWorks自己实现了new。有兴趣的话可以看看DriverWorks提供的源代码。 |
|
|
5楼#
发布于:2004-03-01 15:14
是不是中断例程里需要有个同步的机制?比如自旋锁,似乎不是一定需要?
|
|
|