📄 luojincdriv01device.cpp
字号:
#pragma warning(disable:4065) // Allow switch statement with no cases
#include <vdw.h>
#include "LuojincDriv01.h"
#include "LuojincDriv01Device.h"
#include "..\LuojincDriv01ioctl.h"
#pragma hdrstop("LuojincDriv01.pch")
extern KDebugOnlyTrace t; // Global driver trace object
LuojincDriv01Device::LuojincDriv01Device(PDEVICE_OBJECT Pdo, ULONG Unit) :
KPnpDevice(Pdo, NULL)
{
t << "Entering LuojincDriv01Device::LuojincDriv01Device (constructor)\n";
// Check constructor status
if ( ! NT_SUCCESS(m_ConstructorStatus) )
{
return;
}
// Remember our unit number
m_Unit = Unit;
// Initialize the lower device
m_Lower.Initialize(this, Pdo);
// Inform the base class of the lower edge device object
SetLowerDevice(&m_Lower);
// Initialize the PnP Policy settings to the "standard" policy
SetPnpPolicy();
// TODO: Customize the PnP Policy for this device by setting
// flags in m_Policies.
// Initialize the Power Policy settings to the "standard" policy
SetPowerPolicy();
// TODO: Customize the Power Policy for this device by setting
// flags in m_PowerPolicies.
}
LuojincDriv01Device::~LuojincDriv01Device()
{
t << "Entering LuojincDriv01Device::~LuojincDriv01Device() (destructor)\n";
}
inline NTSTATUS LuojincDriv01Device::DefaultPnp(KIrp I)
{
t << "Entering LuojincDriv01Device::DefaultPnp\n" << I << EOL;
I.ForceReuseOfCurrentStackLocationInCalldown();
return m_Lower.PnpCall(this, I);
}
inline NTSTATUS LuojincDriv01Device::DefaultPower(KIrp I)
{
t << "Entering LuojincDriv01Device::DefaultPower\n" << I << EOL;
I.IndicatePowerIrpProcessed();
I.CopyParametersDown();
return m_Lower.PnpPowerCall(this, I);
}
inline NTSTATUS LuojincDriv01Device::SystemControl(KIrp I)
{
t << "Entering LuojincDriv01Device::SystemControl\n";
I.ForceReuseOfCurrentStackLocationInCalldown();
return m_Lower.PnpCall(this, I);
}
inline VOID LuojincDriv01Device::Invalidate()
{
// For each memory mapped region, release the underlying system resoruce.
m_MemoryRange0.Invalidate();
m_MemoryRange2.Invalidate();
m_MemoryRange3.Invalidate();
// For each I/O port mapped region, release the underlying system resource.
m_IoPortRange1.Invalidate();
// For the interrupt, release the underlying system resource.
m_Irq.Invalidate();
m_pDmaAdapter->DmaOperations->FreeCommonBuffer(
m_pDmaAdapter,m_MapRegisterCount*sizeof(PLX9656_DESCRIPTOR),
*m_pCommBufferPa,m_pCommBufferVa,FALSE);
m_pDmaAdapter->DmaOperations->PutDmaAdapter(m_pDmaAdapter);
}
inline NTSTATUS LuojincDriv01Device::OnStartDevice(KIrp I)
{
t << "Entering LuojincDriv01Device::OnStartDevice\n";
NTSTATUS status = STATUS_SUCCESS;
I.Information() = 0;
PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources();
PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources();
#define MAX_DMA_LENGTH 0x800000 // 0x100000 is 1 MB
DEVICE_DESCRIPTION dd;
RtlZeroMemory(&dd, sizeof(dd));
dd.Version = DEVICE_DESCRIPTION_VERSION;
dd.Master = TRUE;
dd.ScatterGather = FALSE;
dd.DemandMode = FALSE;
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;
//申请DMA适配器
PIRP pCurrentIrp=PIRP(I);
PIO_STACK_LOCATION pIoStackLocation = IoGetCurrentIrpStackLocation(pCurrentIrp);
m_pDeviceObject = pIoStackLocation->DeviceObject;
m_MapRegisterCount =(MAX_DMA_LENGTH / PAGE_SIZE) + 1;
m_pDmaAdapter=NULL;
m_pDmaAdapter =IoGetDmaAdapter( m_pDeviceObject,&dd, &m_MapRegisterCount);
if(m_pDmaAdapter==NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
//申请非分页连续内存
m_pCommBufferVa=NULL;
m_pCommBufferVa=(PUCHAR)m_pDmaAdapter->DmaOperations->AllocateCommonBuffer
(m_pDmaAdapter,m_MapRegisterCount*sizeof(PLX9656_DESCRIPTOR),m_pCommBufferPa,false);
if(m_pCommBufferVa==NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
// Create an instance of KPciConfiguration so we can map Base Address
// Register indicies to ordinals for memory or I/O port ranges.
KPciConfiguration PciConfig(m_Lower.TopOfStack());
status = m_MemoryRange0.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(0)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
status = m_MemoryRange2.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(2)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
status = m_MemoryRange3.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(3)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
status = m_IoPortRange1.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(1)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
status = m_Irq.InitializeAndConnect(
pResListTranslated,
LinkTo(Isr_Irq),
this
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);
return status;
}
inline NTSTATUS LuojincDriv01Device::OnStopDevice(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering LuojincDriv01Device::OnStopDevice\n";
Invalidate();
return status;
UNREFERENCED_PARAMETER(I);
}
inline NTSTATUS LuojincDriv01Device::OnRemoveDevice(KIrp I)
{
t << "Entering LuojincDriv01Device::OnRemoveDevice\n";
Invalidate();
return STATUS_SUCCESS;
UNREFERENCED_PARAMETER(I);
}
inline NTSTATUS LuojincDriv01Device::OnDevicePowerUp(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering LuojincDriv01Device::OnDevicePowerUp\n";
return status;
UNREFERENCED_PARAMETER(I);
}
inline NTSTATUS LuojincDriv01Device::OnDeviceSleep(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering LuojincDriv01Device::OnDeviceSleep\n";
return status;
UNREFERENCED_PARAMETER(I);
}
inline VOID LuojincDriv01Device::CancelQueuedIrp(KIrp I)
{
KDeviceQueue dq(DeviceQueue());
// Test if the IRP is the current IRP.
if ( (PIRP)I == CurrentIrp() )
{
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))
{
CancelSpinLock::Release(I.CancelIrql());
t << "IRP canceled " << I << EOL;
I.Information() = 0;
I.PnpComplete(this, STATUS_CANCELLED);
}
else
{
CancelSpinLock::Release(I.CancelIrql());
}
}
inline VOID LuojincDriv01Device::StartIo(KIrp I)
{
t << "Entering StartIo, " << I << EOL;
if ( !I.TestAndSetCancelRoutine(
LinkTo(CancelQueuedIrp),
NULL,
CurrentIrp()) )
{
return;
}
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())
{
case ReadMemConfigReg:
ReadMemConfigRegFunc(I);
break;
case ReadIoConfigReg:
ReadIoConfigRegFunc(I);
break;
case WriteMemConfigReg:
WriteMemConfigRegFunc(I);
break;
case WriteIoConfigReg:
WriteIoConfigRegFunc(I);
break;
case ReadLocalSpace0:
ReadLocalSpace0Func(I);
break;
case ReadLocalSpace1:
ReadLocalSpace1Func(I);
break;
case WriteLocalSpace0:
WriteLocalSpace0Func(I);
break;
case WriteLocalSpace1:
WriteLocalSpace1Func(I);
break;
case GetDriverInfo:
GetDriverInfoFunc(I);
break;
case SetDriverInfo:
SetDriverInfoFunc(I);
break;
default:
ASSERT(FALSE);
break;
}
break;
default:
ASSERT(FALSE);
PnpNextIrp(I);
break;
}
}
inline NTSTATUS LuojincDriv01Device::Create(KIrp I)
{
NTSTATUS status;
t << "Entering LuojincDriv01Device::Create, " << I << EOL;
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "LuojincDriv01Device::Create Status " << (ULONG)status << EOL;
return status;
}
inline NTSTATUS LuojincDriv01Device::Close(KIrp I)
{
NTSTATUS status;
t << "Entering LuojincDriv01Device::Close, " << I << EOL;
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "LuojincDriv01Device::Close Status " << (ULONG)status << EOL;
return status;
}
inline NTSTATUS LuojincDriv01Device::CleanUp(KIrp I)
{
t << "Entering CleanUp, " << I << EOL;
KDeviceQueue dq(DeviceQueue());
dq.PnpCleanUp(this, I.FileObject());
return I.PnpComplete(this, STATUS_SUCCESS);
}
inline void LuojincDriv01Device::SerialRead(KIrp I)
{
t << "Entering LuojincDriv01Device::SerialRead, " << I << EOL;
NTSTATUS status = STATUS_SUCCESS;
// Declare a memory object
KMemory Mem(I.Mdl());
// Use the memory object to create a pointer to the caller's buffer
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG dwTotalSize = I.ReadSize(CURRENT); // Requested read size
ULONG dwBytesRead = 0; // Count of bytes read
I.Information() = dwBytesRead;
I.Status() = status;
// NextIrp completes this IRP and starts
// processing for the next IRP in the queue.
PnpNextIrp(I);
}
inline NTSTATUS LuojincDriv01Device::Read(KIrp I)
{
t << "Entering LuojincDriv01Device::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));
}
inline void LuojincDriv01Device::SerialWrite(KIrp I)
{
t << "Entering LuojincDriv01Device::SerialWrite, " << I << EOL;
NTSTATUS status = STATUS_SUCCESS;
// Declare a memory object
KMemory Mem(I.Mdl());
// Use the memory object to create a pointer to the caller's buffer
PUCHAR pBuffer = (PUCHAR) Mem.MapToSystemSpace();
ULONG dwTotalSize = I.WriteSize(CURRENT);
ULONG dwBytesSent = 0;
I.Information() = dwBytesSent;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -