阅读:1453回复:1
驱动DMA回调函数?
在驱动程序中,定义了一个驱动程序的队列用来序列化DMA的IRP_MJ_READ请求,是如下定义的:
class WzyDevice_DriverManagedQueue : public KDriverManagedQueueEx { public: SAFE_DESTRUCTORS; VOID StartIo(KIrp I); }; 在设备类的Read(KIrp I) 函数中调用队列的m_DriverManagedQueue.QueueIrp(I)函数把IRP插入驱动队列。 NTSTATUS WzyDevice::Read(KIrp I) { if (I.ReadSize() == 0) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } return m_DriverManagedQueue.QueueIrp(I); } 但是,当在DMA的准备就绪回调历程中,不进行任何的操作,只是完成 这个IRP时程序执行到这里机器就会自动重新启动。在softice中有如下的错误: Break Due to KeBufCheckEx(unhandle kernel mode exception) Error = A (IROQL_NOT_Less_or_EQAOL) P1=60 D2=2 P3=0 P4=F47A0EC0 准备就绪回调历程如下: VOID WzyDevice::OnDmaReady(KDmaTransfer* pXfer, KIrp I) { NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; I.Status() = status; m_DriverManagedQueue.PnpNextIrp(I); } 或是这样的编写准备就绪回调历程: VOID WzyDevice::OnDmaReady(KDmaTransfer* pXfer, KIrp I) { if (pXfer->BytesRemaining() == 0) { pXfer->Terminate(); I.Information() = I.ReadSize(CURRENT); I.Status() = STATUS_SUCCESS; m_DriverManagedQueue.PnpNextIrp(I); m_CurrentTransfer = NULL; delete pXfer; return; } PTRANSFER_DESCRIPTOR ptd; while (pXfer->SequenceTransferDescriptors(&ptd)) { t << \"Physical address 0x\" << ptd->td_PhysAddr.LowPart << \". Length is 0x\" << ptd->td_Length << \".\" << EOL; } if ((ULONG) pXfer->BytesRemaining() == I.ReadSize()) StartDMA(ptd->td_PhysAddr.LowPart,ptd->td_Length); } DMA的启动历程中只是设置一个定时器并不进行任何的有关硬件的操作; VOID WzyDevice::StartDMA(ULONG PAddress,ULONG NBytes) { LONGLONG DueTime = -10000000; // 100ns units(1sec) m_IsrProxyTimer.Set( DueTime, LinkTo(IsrProxyTimer), this ); } VOID WzyDevice::IsrProxyTimer(PVOID Arg1, PVOID Arg2) { m_CurrentTransfer->Continue(UseTransferSize); } 这样来反复的调用dma准备就绪回调函数,当程序执行到准备就绪回调函数时,也是出现和上面的相同的错误和情况。 当采用系统自动创建的IRP队列时,不采用驱动程序自己定义的队列时(即KDriverManagedQueueEx不用这个定义的队列时),采用上述两种方法编写dma准备就绪回调函数就没没有何的错误,程序就能够正确执行。 请问这是什么原因阿?请高手们指点一下,谢谢。一下有程序程序的原码。 |
|
|
沙发#
发布于:2008-08-06 21:24
同问 同问
|
|