阅读:761回复:0
重起?
在驱动程序中,我写了一个模拟Dma传输的程序,并没有涉及任何的硬件操作,只是在
启动例程StartDMA(),中设置了一个1秒的定时器,1秒后程序调用定时器回调函数,回调函数然后 调用m_CurrentTransfer->Continue(UseTransferSize)函数,触发OnDmaReady()函数调用, 但是在程序运行时,在 sofitice中出现如下的错误: Break Due to KeBufCheckEx(unhandle kernel mode exception) Error = A (IROQL_NOT_Less_or_EQAOL) P1=60 D2=2 P3=0 P4=F47A0EC0 然后机器自动重新启动了。当屏蔽掉OnDmaReady()中的(ULONG) pXfer->BytesRemaining() == I.ReadSize()这段代码时 程序就不会出现任何的错误。我实在是弄不清这是什么的原因,请大家帮我检查一下我的程序错在那里?我的主要代码如下: NTSTATUS C6416Device::OnStartDevice(KIrp I) { NTSTATUS status = STATUS_SUCCESS; I.Information() = 0; PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources(); PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources(); #define MAX_DMA_LENGTH 0x100000 // 0x100000 is 1 MB DEVICE_DESCRIPTION dd; RtlZeroMemory(&dd, sizeof(dd)); dd.Version = DEVICE_DESCRIPTION_VERSION; dd.Master = TRUE; dd.ScatterGather = FALSE; dd.DemandMode = TRUE; dd.AutoInitialize = FALSE; dd.Dma32BitAddresses = TRUE; dd.IgnoreCount = FALSE; dd.DmaChannel = 0; dd.InterfaceType = PCIBus; dd.DmaWidth = Width32Bits; // PCI default width dd.DmaSpeed = Compatible; dd.MaximumLength = MAX_DMA_LENGTH; m_Dma.Initialize(&dd, m_Lower.PDO()); m_Buffer.Initialize(&m_Dma,1024); return status; } NTSTATUS C6416Device::OnStopDevice(KIrp I) { NTSTATUS status = STATUS_SUCCESS; Invalidate(); return status; } NTSTATUS C6416Device::OnRemoveDevice(KIrp I) { Device removed, release the system resources. Invalidate(); return STATUS_SUCCESS; } NTSTATUS C6416Device::Create(KIrp I) { NTSTATUS status; status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); return status; } NTSTATUS C6416Device::Close(KIrp I) { NTSTATUS status; status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT); return status; } NTSTATUS C6416Device::CleanUp(KIrp I) { m_DriverManagedQueue.PnpCleanUp(this, I.FileObject()); return I.PnpComplete(this, STATUS_SUCCESS); } void C6416Device::SerialRead(KIrp I) { NTSTATUS status = STATUS_SUCCESS; m_CurrentTransfer = new(NonPagedPool) KDmaTransfer(this, &m_Dma); if ( m_CurrentTransfer == NULL ) { status = STATUS_INSUFFICIENT_RESOURCES; DbgPrint(\"unable to allocate transfer object: %x\\n\", status); I.Information() = 0; I.Status() = status; m_DriverManagedQueue.PnpNextIrp(I); } status = m_CurrentTransfer->Initiate( this, &m_Dma, I.Mdl(), (I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice, LinkTo(OnDmaReady), &m_Buffer ); if ( ! NT_SUCCESS(status) ) { DbgPrint(\"unable to initiate transfer: %x\\n\", status); delete m_CurrentTransfer; m_CurrentTransfer = NULL; I.Information() = 0; I.Status() = status; m_DriverManagedQueue.PnpNextIrp(I); } } NTSTATUS C6416Device::Read(KIrp I) { if (I.ReadSize() == 0) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } return m_DriverManagedQueue.QueueIrp(I); } void C6416Device::SerialWrite(KIrp I) { NTSTATUS status = STATUS_SUCCESS; KMemory Mem(I.Mdl()); PVOID pSBuffer = Mem.MapToSystemSpace(); PVOID pDBuffer = m_Buffer.VirtualAddress(); ULONG dwTotalSize = I.WriteSize(CURRENT); ULONG dwBytesSent = 0; if (dwTotalSize > 1024) dwBytesSent = 1024; else dwBytesSent = dwTotalSize; RtlCopyMemory(pDBuffer, pSBuffer, dwBytesSent); I.Information() = dwBytesSent; I.Status() = status; m_DriverManagedQueue.PnpNextIrp(I); } NTSTATUS C6416Device::Write(KIrp I) { if (I.WriteSize() == 0) { I.Information() = 0; return I.PnpComplete(this, STATUS_SUCCESS); } return m_DriverManagedQueue.QueueIrp(I); } NTSTATUS C6416Device::DeviceControl(KIrp I) { NTSTATUS status; switch (I.IoctlCode()) { default: status = STATUS_INVALID_PARAMETER; break; } if (status == STATUS_PENDING) { return status; } else { return I.PnpComplete(this, status); } } VOID C6416Device_DriverManagedQueue::StartIo(KIrp I) { C6416Device *pDev = (C6416Device *) KDevicePTR(I.DeviceObject()); switch (I.MajorFunction()) { case IRP_MJ_READ: pDev->SerialRead(I); break; case IRP_MJ_WRITE: pDev->SerialWrite(I); break; case IRP_MJ_DEVICE_CONTROL: switch (I.IoctlCode()) { default: ASSERT(FALSE); break; } break; default: ASSERT(FALSE); I.Status() = STATUS_INVALID_PARAMETER; PnpNextIrp(I); break; } } VOID C6416Device::IsrProxyTimer(PVOID Arg1, PVOID Arg2) { m_CurrentTransfer->Continue(UseTransferSize); } VOID C6416Device::StartDMA(ULONG PAddress,ULONG NBytes) { LONGLONG DueTime = -10000000; // 100ns units (1sec) m_IsrProxyTimer.Set( DueTime, LinkTo(IsrProxyTimer), this ); } VOID C6416Device::OnDmaReady(KDmaTransfer* pXfer, KIrp I) { if (pXfer->BytesRemaining() == 0) { pXfer->Terminate(); I.Information() = I.ReadSize(CURRENT); I.Status() = STATUS_SUCCESS; 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); } |
|
|