📄 blockdmadevice.cpp
字号:
// Restore any context to the hardware device that
// was saved during the handling of a power down request.
// See the OnDeviceSleep function.
// Do NOT complete this IRP.
//
return status;
// The following macro simply allows compilation at Warning Level 4
// If you reference this parameter in the function simply remove the macro.
UNREFERENCED_PARAMETER(I);
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::OnDeviceSleep
//
// Routine Description:
// Handler for IRP_MJ_POWER with minor function IRP_MN_SET_POWER
// for a request to go to a low power state from a high power state
//
// Parameters:
// I - IRP containing POWER request
//
// Return Value:
// NTSTATUS - Status code indicating success or failure
//
// Comments:
// This routine implements the OnDeviceSleep function.
// This function was called by the framework from the IRP_MJ_POWER
// dispatch handler in KPnpDevice prior to forwarding to the PDO.
// The hardware has yet to be powered down and this driver can now
// access the hardware device.
// This routine runs at passive level.
//
NTSTATUS BlockDMADevice::OnDeviceSleep(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering BlockDMADevice::OnDeviceSleep\n";
// TODO: Service the device.
// Save any context to the hardware device that will be required
// during a power up request. See the OnDevicePowerUp function.
// Do NOT complete this IRP. The base class handles forwarding
// this IRP to the PDO.
//
return status;
// The following macro simply allows compilation at Warning Level 4
// If you reference this parameter in the function simply remove the macro.
UNREFERENCED_PARAMETER(I);
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::CancelQueuedIrp
//
// Routine Description:
// This routine is called when an IRP is canceled while queued.
//
// Parameters:
// I - IRP being canceled
//
// Return Value:
// None
//
// Comments:
//
// TODO: You may want to write additional cancel routines
// to use during different stages of IRP processing.
VOID BlockDMADevice::CancelQueuedIrp(KIrp I)
{
KDeviceQueue dq(DeviceQueue());
// Test if the IRP is the current IRP.
if ( (PIRP)I == CurrentIrp() )
{
// If so, NULL it out, release the global cancel spinlock, then
// complete it as canceled and start the next IRP. Note that
// if we got here, the IRP was still in a cancelable state when
// it was canceled, and most likely is just about to start being
// processed on the device.
CurrentIrp() = NULL;
CancelSpinLock::Release(I.CancelIrql());
t << "IRP canceled " << I << EOL;
I.Information() = 0;
I.Status() = STATUS_CANCELLED;
PnpNextIrp(I);
}
// See if the IRP can be removed from the device queue.
else if (dq.RemoveSpecificEntry(I))
{
// If so, release the global cancel spinlock and complete it
// as canceled.
CancelSpinLock::Release(I.CancelIrql());
t << "IRP canceled " << I << EOL;
I.Information() = 0;
I.PnpComplete(this, STATUS_CANCELLED);
}
else
{
// If we got here the IRP wasn't the current IRP, and wasn't in the
// device queue. This could happen if the IRP was removed by the
// device queue's cleanup routine, just as it was being canceled.
// In this case we have no work to do, since the cleanup routine
// will cancel the IRP. Simply release the global cancel spinlock.
CancelSpinLock::Release(I.CancelIrql());
}
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::StartIo
//
// Routine Description:
// StartIo is called when an IRP is taken off the device queue
// used by the system for serializing I/O. StartIo is called at
// dispatch level.
//
// Parameters:
// I - IRP removed from queue
//
// Return Value:
// None
//
// Comments:
//
VOID BlockDMADevice::StartIo(KIrp I)
{
t << "Entering StartIo, " << I << EOL;
// Before processing the Irp, we need to check to see if it has been
// canceled. We also want to set the Irp into an non-cancelable state
// (cancel routine set to NULL) so we can process it. You may want to set
// a different cancel routine here, or at other points within this function.
// When performing these operations, it is necessary to hold the global
// cancel spin lock and take special precautions to ensure the Irp is still
// valid. This is accomplished using the routine KIrp::TestAndSetCancelRoutine().
if ( !I.TestAndSetCancelRoutine(
LinkTo(CancelQueuedIrp),
NULL,
CurrentIrp()) )
{
// The Irp has been canceled we stop processing and exit. Since
// it was in a cancelable state previously, it will be completed by
// the cancel routine that had been set on it.
return;
}
// Start processing request.
// Switch on the IRP's function:
switch (I.MajorFunction())
{
case IRP_MJ_READ:
SerialRead(I);
break;
case IRP_MJ_WRITE:
SerialWrite(I);
break;
case IRP_MJ_DEVICE_CONTROL:
switch (I.IoctlCode())
{
default:
// We queued a request that shouldn't have been queued
// (should never get here)
ASSERT(FALSE);
break;
}
break;
default:
// The driver queued an Irp that isn't handled
// by StartIo. This shouldn't happen.
ASSERT(FALSE);
PnpNextIrp(I);
break;
}
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::Create
//
// Routine Description:
// Handler for IRP_MJ_CREATE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS BlockDMADevice::Create(KIrp I)
{
NTSTATUS status;
t << "Entering BlockDMADevice::Create, " << I << EOL;
// TODO: Add driver specific create handling code here
// Generally a create IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "BlockDMADevice::Create Status " << (ULONG)status << EOL;
return status;
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::Close
//
// Routine Description:
// Handler for IRP_MJ_CLOSE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS BlockDMADevice::Close(KIrp I)
{
NTSTATUS status;
t << "Entering BlockDMADevice::Close, " << I << EOL;
// TODO: Add driver specific close handling code here
// Generally a close IRP is targeted at our FDO, so we don't need
// to pass it down to the PDO. We have found for some devices, the
// PDO is not expecting this Irp and returns an error code.
// The default wizard code, therefore completes the Irp here using
// PnpComplete(). The following commented code could be used instead
// of PnpComplete() to pass the Irp to the PDO, which would complete it.
//
// I.ForceReuseOfCurrentStackLocationInCalldown();
// status = m_Lower.PnpCall(this, I);
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "BlockDMADevice::Close Status " << (ULONG)status << EOL;
return status;
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::Cleanup
//
// Routine Description:
// Handler for IRP_MJ_CLEANUP
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS BlockDMADevice::CleanUp(KIrp I)
{
t << "Entering CleanUp, " << I << EOL;
// TODO: Insert your code to respond to the CLEANUP message.
// This code cleans up the single Wizard created queue. If you
// have created additional queues, or have any outstanding Irps
// stored in some other fashion in your driver, you should clean
// these up as well for the file object specified in the cleanup Irp.
KDeviceQueue dq(DeviceQueue());
dq.PnpCleanUp(this, I.FileObject());
return I.PnpComplete(this, STATUS_SUCCESS);
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::SerialRead
//
// Routine Description:
// Handler for serialized READ
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is called when the IRP is removed from the
// STARTIO queue. This guarantees that multiple requests are
// never processed simultaneously.
//
// This routine is called at dispatch level.
//
void BlockDMADevice::SerialRead(KIrp I)
{
//第一步 启动DMA 读传输
t<<"第1步 启动DMA 读传输 Serial Read begin "<<EOL;
NTSTATUS status = STATUS_SUCCESS;
m_ReadWrite=1;
m_CurrentTransfer= new (NonPagedPool) KDmaTransfer(this,&m_Dma);
if( m_CurrentTransfer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
I.Information()=0;
I.Status()=status;
PnpNextIrp(I);
}
//第一次启动OnDmaReady
// status = m_CurrentTransfer->Initiate(I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
// ?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady));
status = m_CurrentTransfer->Initiate(this,&m_Dma,I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady),&m_Buffer);
if(!NT_SUCCESS(status)){
delete m_CurrentTransfer;
m_CurrentTransfer=NULL;
I.Information()=0;
I.Status()=status;
PnpNextIrp(I);
}
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::Read
//
// Routine Description:
// Handler for IRP_MJ_READ
//
// Parameters:
// I Current IRP
//
// Return Value:
// NTSTATUS Result code
//
// Comments:
// This routine handles read requests.
// The requests are queued to the StartIo
// queue. This enforces serialization so that
// multiple requests are not processed
// simultaneously.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS BlockDMADevice::Read(KIrp I)
{
t << "Entering BlockDMADevice::Read, " << I << EOL;
// TODO: Check the incoming request. Replace "FALSE" in the following
// line with a check that returns TRUE if the request is not valid.
if (FALSE) // If (Request is invalid)
{
// Invalid parameter in the Read request
I.Information() = 0;
return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
}
// Always ok to read 0 elements.
if (I.ReadSize() == 0)
{
I.Information() = 0;
return I.PnpComplete(this, STATUS_SUCCESS);
}
// Queue the IRP for processing in StartIO
// The read function is performed in SerialRead
return QueueIrp(I, LinkTo(CancelQueuedIrp));
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::SerialWrite
//
// Routine Description:
// Handler for serialized WRITE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is called when the IRP is removed from the
// STARTIO queue. This guarantees that multiple requests are
// never processed simultaneously.
//
void BlockDMADevice::SerialWrite(KIrp I)
{
//第一步 启动DMA 写传输
t<<"第1步 启动DMA 写传输 Serial Write begin "<<EOL;
NTSTATUS status = STATUS_SUCCESS;
m_ReadWrite=2;
m_CurrentTransfer= new (NonPagedPool) KDmaTransfer(this,&m_Dma);
if( m_CurrentTransfer == NULL) {
status = STATUS_INSUFFICIENT_RESOURCES;
I.Information()=0;
I.Status()=status;
PnpNextIrp(I);
}
//第一次启动OnDmaReady
status = m_CurrentTransfer->Initiate(this,&m_Dma,I.Mdl(),(I.MajorFunction()==IRP_MJ_READ)
?FromDeviceToMemory:FromMemoryToDevice , LinkTo(OnDmaReady),&m_Buffer);
if(!NT_SUCCESS(status)){
delete m_CurrentTransfer;
m_CurrentTransfer=NULL;
I.Information()=0;
I.Status()=status;
PnpNextIrp(I);
}
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::Write
//
// Routine Description:
// Handler for IRP_MJ_WRITE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
// This routine handles write requests.
// The requests are queued to the StartIo
// queue. This enforces serialization so that
// multiple requests are not processed
// simultaneously.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS BlockDMADevice::Write(KIrp I)
{
t << "Entering BlockDMADevice::Write, " << I << EOL;
// TODO: Check the incoming request. Replace "FALSE" in the following
// line with a check that returns TRUE if the request is not valid.
if (FALSE)
{
// Invalid parameter in the Write request
I.Information() = 0;
return I.PnpComplete(this, STATUS_INVALID_PARAMETER);
}
// Always ok to write 0 elements.
if (I.WriteSize() == 0)
{
I.Information() = 0;
return I.PnpComplete(this, STATUS_SUCCESS);
}
// Queue the IRP for processing in StartIO
// The write function is performed in SerialWrite
return QueueIrp(I, LinkTo(CancelQueuedIrp));
}
////////////////////////////////////////////////////////////////////////
// BlockDMADevice::DeviceControl
//
// Routine Description:
// Handler for IRP_MJ_DEVICE_CONTROL
//
// Parameters:
// I - Current IRP
//
// Return Value:
// None
//
// Comments:
// This routine is the first handler for Device Control requests.
// Some function codes may be handled immediately,
// while others may be serialized through the StartIo routine.
//
// The KPnpDevice class handles restricting IRP flow
// if the device is stopping or being removed.
//
NTSTATUS BlockDMADevice::DeviceControl(KIrp I)
{
NTSTATUS status;
t << "Entering BlockDMADevice::Device Control, " << I << EOL;
switch (I.IoctlCode())
{
case BLOCKDMA_IOCTL_800:
status = BLOCKDMA_IOCTL_800_Handler(I);
break;
case BLOCKDMA_IOCTL_801:
status = BLOCKDMA_IOCTL_801_Handler(I);
break;
case BLOCKDMA_IOCTL_802:
status = BLOCKDMA_IOCTL_802_Handler(I);
break;
case BLOCKDMA_IOCTL_803:
status = BLOCKDMA_IOCTL_803_Handler(I);
break;
case BLOCKDMA_IOCTL_804:
status = BLOCKDMA_IOCTL_804_Handler(I);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -