libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1465回复:5

200分,救救我吧,帮我看看我的程序,为什么关机经常蓝屏

楼主#
更多 发布于:2004-02-27 15:50
下面是我写的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;
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
arthurtu
驱动巨牛
驱动巨牛
  • 注册日期2001-11-08
  • 最后登录2020-12-19
  • 粉丝0
  • 关注0
  • 积分26分
  • 威望161点
  • 贡献值0点
  • 好评度35点
  • 原创分0分
  • 专家分0分
  • 社区居民
沙发#
发布于:2004-02-27 19:20
ReleaseResource呢?

试试shutdown什么也不干?
nosegay
驱动牛犊
驱动牛犊
  • 注册日期2003-12-25
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2004-02-27 19:53
我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地板#
发布于:2004-03-01 09:38
我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊



new 是C++里分配内存的操作符,可以使用这个,没什么关系的。
请大虾们找重看看我的中断处理程序和中断延迟处理程序,我觉得这两个的问题最大。

谢谢了!
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
seaquester
驱动大牛
驱动大牛
  • 注册日期2002-05-22
  • 最后登录2016-06-16
  • 粉丝0
  • 关注0
  • 积分500分
  • 威望115点
  • 贡献值0点
  • 好评度107点
  • 原创分0分
  • 专家分52分
地下室#
发布于:2004-03-01 11:32
[quote]我是菜鸟,刚学,不过书上不是写分配内存不能用new操作符吗?特别是非分页内存,你里面好象有new啊



new 是C++里分配内存的操作符,可以使用这个,没什么关系的。
请大虾们找重看看我的中断处理程序和中断延迟处理程序,我觉得这两个的问题最大。

谢谢了! [/quote]


To nosegay:
没错,Driver里面不能使用new, 不过libin2309的代码是用DriverWorks写的,DriverWorks自己实现了new。有兴趣的话可以看看DriverWorks提供的源代码。
八风舞遥翩,九野弄清音。 鸣高常向月,善舞不迎人。
libin2309
驱动大牛
驱动大牛
  • 注册日期2002-11-20
  • 最后登录2005-12-29
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望2点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2004-03-01 15:14
是不是中断例程里需要有个同步的机制?比如自旋锁,似乎不是一定需要?
我是一只小小鸟,永远也飞也飞不高,但我永远在飞!
游客

返回顶部