阅读:2188回复:2
to flying
最近由于调试板子需要,自己照着书用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 |
|
最新喜欢:![]()
|
沙发#
发布于:2005-04-19 19:54
我也遇到了类似的问题
顶一下 |
|
|
板凳#
发布于:2010-04-08 00:01
请问问题是如何解决的呢?能否介绍一下呢?
|
|