ddnewbie
驱动牛犊
驱动牛犊
  • 注册日期2003-07-25
  • 最后登录2009-04-13
  • 粉丝0
  • 关注0
  • 积分201分
  • 威望21点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
阅读:2086回复:2

to flying

楼主#
更多 发布于:2004-04-02 14:44
最近由于调试板子需要,自己照着书用DS 2.7写了个PCI驱动程序,其工作原理是:当PCI卡上有数据要求传送时向主机发出中断请求,驱动程序的ISR接收到之后,向应用程序发送一个事件通知,然后由应用程序调用DeviceIoControl(),启动DMA传送数据,将数据传送到主机内存。
现在ISR等正常了,应用程序能够收到驱动程序发出的事件通知,但是当应用在收到事件通知之后去调用DeviceIoControl时,机器会出现重新启动的现象。

用SoftICE在DMA_READ分发例程上设断点,发现在执行KDmaTransfer.Initiate()时,驱动程序出错了,它进入了KIrp.h中的KIrp类定义处,(如①所示)SoftICE会出现如下提示:“Break due to page Fault. Fault=0000”。然后如果此时在SoftICE中按<F10>,计算机就会出现重启,如果按<F5>,则SoftICE中会反复出现 “Break due to page Fault. Fault=0000”的信息。

我怀疑是因为I.Mdl()的问题,有可能是因为在用户层上的指针在内核下出错。但是该段代码我放在Serail Read例程中调试通过了的。现在放在DMA_READ例程中就出问题了。
DMA_READ 在ioctl.h文件中的定义如下:
#define My_DMA_READ CTL_CODE(FILE_DEVICE_UNKNOWN, 0x80C, METHOD_IN_DIRECT, FILE_ANY_ACCESS)

一个多星期了,我试了很多种方法,在应用程序中开个线程也试了,也是不行。
查了Windows 2000DDK文档和DriverWorks帮助文档,所讲的都是和武安河主编的《Windows 2000/XP WDM设备驱动程序开发》书上说的一样,驱动程序通过KIrp::IoctlBuffer访问这个缓冲区,但是现在就是不行。可能我的思维已陷入了一个死胡同,请各位大侠们帮忙看看,指点小弟一把,不甚感激!

下面给出部分程序代码:
//---------------------------------------------------------
=====App中调用DMA_READ方法:
//---------------------------------------------------------
UCHAR *pBuffer;
ULONG bufSize;
ULONG tmp;

pBuffer = NULL;
bufSize = 0x200000;
pBuffer = new UCHAR[bufSize];
if(pBuffer == NULL)
return -1;
DeviceIoControl(hDevice, //设备句柄,在前面已用同步方式打开
My_DMA_READ,
NULL,
0,
pBuffer;,
bufSize,
&tmp,
NULL);

...
//---------------------------------------------------------
=====DMA_READ分发例程如下:
//---------------------------------------------------------
NTSTATUS MyDevice::My_DMA_READ_Handler(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;

// 为当前IRP创建一DMATransfer对象
m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma); //m_CurrentTransfer 在MyDevice类的Public:中已申明为指针
if ( m_CurrentTransfer == NULL )
{
status = STATUS_INSUFFICIENT_RESOURCES;
DbgPrint("unable to allocate transfer object: %x\n", status); I.Information() = 0;
I.Status() = status;
}
//采用应用程序的数据缓冲区作为DMA数据区
status = m_CurrentTransfer->Initiate( <-- 驱动程序出错位置
I.Mdl(),
FromDeviceToMemory,
LinkTo(OnDmaReady)
);
// 初始化失败,则返回错误状态
if ( ! NT_SUCCESS(status) )
{
DbgPrint("unable to initiate transfer: %x\n", status);
delete m_CurrentTransfer;
m_CurrentTransfer = NULL;
I.Information() = 0;
I.Status() = status;
}
return status;
}
//---------------------------------------------------------
=====进入KIrp.h中光标停留位置:
Class KIrp
{
public:

#if DBG
VOID ValidateStackLocation(EStackLocation loc)
{
if(loc == CURRENT)
{
ASSERT (m_Irp->CurrentLocation <= m_Irp->StackCount);
}
else // loc == NEXT <--① (进入时光标停留位置)
{
ASSERT (m_Irp->CurrentLocation > 1);
}
}
#else
VOID ValidateStackLocation(EStackLocation loc)
{
UNREFERENCED_PARAMETER(loc)
}
#endif

// Data
public :
PIRP m_Irp;
}
//---------------------------------------------------------
现在我被卡在这里了,也不知该如何下手。真的很着急,还请各位高手多加指点,先谢了!


请问最后问题解决了吗?如何解决的?
关注ing

最新喜欢:

yjx2003yjx200...
[img]D:gs.jpg[/img]
yjx2003
驱动牛犊
驱动牛犊
  • 注册日期2004-06-18
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分32分
  • 威望6点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2005-04-19 19:54
我也遇到了类似的问题

顶一下
请向您的朋友推荐《名人传记》电子期刊 http://list.cn99.com/cgi-bin/getlsts?listname=zhuanji
ghb912
驱动牛犊
驱动牛犊
  • 注册日期2009-11-01
  • 最后登录2011-04-27
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望201点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2010-04-08 00:01
请问问题是如何解决的呢?能否介绍一下呢?
游客

返回顶部