📄 d9054device.cpp
字号:
//
// Routine Description:
// Handler for IRP_MJ_PNP subfcn IRP_MN_REMOVE_DEVICE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
// The system calls this when the device is removed.
// Our PnP policy will take care of
// (1) giving the IRP to the lower device
// (2) detaching the PDO
// (3) deleting the device object
//
NTSTATUS D9054Device::OnRemoveDevice(KIrp I)
{
t << " Entering D9054Device::OnRemoveDevice\n";
m_IoPortRange0.outd(INTCSR,0);
m_Irq.Disconnect();
// Device removed, release the system resources.
Invalidate();
// TODO: Add device-specific code to remove your device
return STATUS_SUCCESS;
// 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);
}
////////////////////////////////////////////////////////////////////////
// D9054Device::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 D9054Device::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());
}
}
////////////////////////////////////////////////////////////////////////
// D9054Device::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 D9054Device::StartIo(KIrp I)
{
t << " Entering StartIo, READ !!!! " << 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;
}
}
////////////////////////////////////////////////////////////////////////
// D9054Device::Create
//
// Routine Description:
// Handler for IRP_MJ_CREATE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS D9054Device::Create(KIrp I)
{
NTSTATUS status;
t << "Entering D9054Device::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 << "D9054Device::Create Status " << (ULONG)status << EOL;
m_pEvent = NULL;
return status;
}
////////////////////////////////////////////////////////////////////////
// D9054Device::Close
//
// Routine Description:
// Handler for IRP_MJ_CLOSE
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS D9054Device::Close(KIrp I)
{
NTSTATUS status;
t << "Entering D9054Device::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 << "D9054Device::Close Status " << (ULONG)status << EOL;
if (m_pEvent)
{
delete m_pEvent;
m_pEvent = NULL;
}
return status;
}
////////////////////////////////////////////////////////////////////////
// D9054Device::Cleanup
//
// Routine Description:
// Handler for IRP_MJ_CLEANUP
//
// Parameters:
// I - Current IRP
//
// Return Value:
// NTSTATUS - Result code
//
// Comments:
//
NTSTATUS D9054Device::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);
}
////////////////////////////////////////////////////////////////////////
// D9054Device::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 D9054Device::SerialRead(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << " Entering SerialRead !!! \n";
// Create a new DMA transfer object for this IRP
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;
PnpNextIrp(I);
}
/* //下面采用应用程序的数据缓冲区作为DMA数据区
status = m_CurrentTransfer->Initiate(
I.Mdl(),
(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice,
LinkTo(OnDmaReady)
);
下面采用公用缓冲区作为DMA数据区
*/
status = m_CurrentTransfer->Initiate(
this,
&m_Dma,
I.Mdl(),
(I.MajorFunction() == IRP_MJ_READ) ? FromDeviceToMemory : FromMemoryToDevice,
LinkTo(OnDmaReady),
&m_Buffer
);
// If the transfer cannot be initiated, complete it with an error status.
if ( ! NT_SUCCESS(status) )
{
DbgPrint("unable to initiate transfer: %x\n", status);
delete m_CurrentTransfer;
m_CurrentTransfer = NULL;
I.Information() = 0;
I.Status() = status;
PnpNextIrp(I);
}
}
////////////////////////////////////////////////////////////////////////
// D9054Device::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 D9054Device::Read(KIrp I)
{
t << "Entering D9054Device::Read, \n" << 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));
}
////////////////////////////////////////////////////////////////////////
// D9054Device::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 D9054Device::SerialWrite(KIrp I)
{
t << " Entering SerialWrite, WRITE !!! \n" << I << EOL;
NTSTATUS status = STATUS_SUCCESS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -