📄 pcicarddevice.cpp
字号:
// PcicardDevice.cpp
// Implementation of PcicardDevice device class
//
// Generated by DriverWizard version DriverStudio 2.7.0 (Build 562)
// Requires Compuware's DriverWorks classes
//
#pragma warning(disable:4065) // Allow switch statement with no cases
#include <vdw.h>
#include "..\PcicardDeviceinterface.h"
#include "Pcicard.h"
#include "PcicardDevice.h"
#include "..\Pcicardioctl.h"
#pragma hdrstop("Pcicard.pch")
extern KTrace t; // Global driver trace object
GUID PcicardDevice_Guid = PcicardDevice_CLASS_GUID;
PcicardDevice::PcicardDevice(PDEVICE_OBJECT Pdo, ULONG Unit) :
KPnpDevice(Pdo, &PcicardDevice_Guid)
{
t << "Entering PcicardDevice::PcicardDevice (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.
}
PcicardDevice::~PcicardDevice()
{
t << "Entering PcicardDevice::~PcicardDevice() (destructor)\n";
}
char *PNPMinorFunctionName(ULONG mn)
{
static char* minors[] = {
"IRP_MN_START_DEVICE",
"IRP_MN_QUERY_REMOVE_DEVICE",
"IRP_MN_REMOVE_DEVICE",
"IRP_MN_CANCEL_REMOVE_DEVICE",
"IRP_MN_STOP_DEVICE",
"IRP_MN_QUERY_STOP_DEVICE",
"IRP_MN_CANCEL_STOP_DEVICE",
"IRP_MN_QUERY_DEVICE_RELATIONS",
"IRP_MN_QUERY_INTERFACE",
"IRP_MN_QUERY_CAPABILITIES",
"IRP_MN_QUERY_RESOURCES",
"IRP_MN_QUERY_RESOURCE_REQUIREMENTS",
"IRP_MN_QUERY_DEVICE_TEXT",
"IRP_MN_FILTER_RESOURCE_REQUIREMENTS",
"<unknown minor function>",
"IRP_MN_READ_CONFIG",
"IRP_MN_WRITE_CONFIG",
"IRP_MN_EJECT",
"IRP_MN_SET_LOCK",
"IRP_MN_QUERY_ID",
"IRP_MN_QUERY_PNP_DEVICE_STATE",
"IRP_MN_QUERY_BUS_INFORMATION",
"IRP_MN_DEVICE_USAGE_NOTIFICATION",
"IRP_MN_SURPRISE_REMOVAL",
"IRP_MN_QUERY_LEGACY_BUS_INFORMATION"
};
if (mn > 0x18) // IRP_MN_QUERY_LEGACY_BUS_INFORMATION
return "<unknown minor function>";
else
return minors[mn];
}
NTSTATUS PcicardDevice::DefaultPnp(KIrp I)
{
t << "Entering PcicardDevice::DefaultPnp with IRP minor function="
<< PNPMinorFunctionName(I.MinorFunction()) << EOL;
I.ForceReuseOfCurrentStackLocationInCalldown();
return m_Lower.PnpCall(this, I);
}
NTSTATUS PcicardDevice::DefaultPower(KIrp I)
{
t << "Entering PcicardDevice::DefaultPower\n";
I.IndicatePowerIrpProcessed();
I.CopyParametersDown();
return m_Lower.PnpPowerCall(this, I);
}
NTSTATUS PcicardDevice::SystemControl(KIrp I)
{
t << "Entering PcicardDevice::SystemControl\n";
I.ForceReuseOfCurrentStackLocationInCalldown();
return m_Lower.PnpCall(this, I);
}
VOID PcicardDevice::Invalidate()
{
// For each memory mapped region, release the underlying system resoruce.
m_MemoryRange.Invalidate();
// For each I/O port mapped region, release the underlying system resource.
m_IoPortRange.Invalidate();
// For the interrupt, release the underlying system resource.
m_Irq.Invalidate();
}
NTSTATUS PcicardDevice::OnStartDevice(KIrp I)
{
t << "Entering PcicardDevice::OnStartDevice\n";
NTSTATUS status = STATUS_SUCCESS;
I.Information() = 0;
// The default Pnp policy has already cleared the IRP with the lower device
// Initialize the physical device object.
// Get the list of raw resources from the IRP
PCM_RESOURCE_LIST pResListRaw = I.AllocatedResources();
// Get the list of translated resources from the IRP
PCM_RESOURCE_LIST pResListTranslated = I.TranslatedResources();
// 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());
// For each memory mapped region, initialize the memory mapped range
// using the resources provided by NT. Once initialized, each memory
// range's base virtual address in system space can be obtained by calling
// member Base(). Each memory range's physical address in CPU space can
// obtained by calling CpuPhysicalAddress(). To access the memory mapped
// range use member functions such as inb/outb, or the array element operator.
status = m_MemoryRange.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(1)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
// For each I/O port mapped region, initialize the I/O port range using
// the resources provided by NT. Once initialized, use member functions such as
// inb/outb, or the array element operator to access the ports range.
status = m_IoPortRange.Initialize(
pResListTranslated,
pResListRaw,
PciConfig.BaseAddressIndexToOrdinal(0)
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
// Initialize and connect the interrupt
status = m_Irq.InitializeAndConnect(
pResListTranslated,
LinkTo(Isr_Irq),
this
);
if (!NT_SUCCESS(status))
{
Invalidate();
return status;
}
// Setup the DPC to be used for interrupt processing
m_DpcFor_Irq.Setup(LinkTo(DpcFor_Irq), this);
// TODO: Add device-specific code to start your device.
// The base class will handle completion
return status;
}
NTSTATUS PcicardDevice::OnStopDevice(KIrp I)
{
NTSTATUS status = STATUS_SUCCESS;
t << "Entering PcicardDevice::OnStopDevice\n";
// Device stopped, release the system resources.
m_IoPortRange.outb(1,1);
m_Irq.Disconnect(); //断开中断服务例程
Invalidate();
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);
}
NTSTATUS PcicardDevice::OnRemoveDevice(KIrp I)
{
t << "Entering PcicardDevice::OnRemoveDevice\n";
// 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);
}
NTSTATUS PcicardDevice::Create(KIrp I)
{
NTSTATUS status;
t << "Entering PcicardDevice::Create, " << I << EOL;
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "PcicardDevice::Create Status " << (ULONG)status << EOL;
m_pEvent=NULL;
m_bNotifyApp = TRUE;
return status;
}
NTSTATUS PcicardDevice::Close(KIrp I)
{
NTSTATUS status;
t << "Entering PcicardDevice::Close, " << I << EOL;
if (m_pEvent)
delete m_pEvent;
m_pEvent = NULL;
status = I.PnpComplete(this, STATUS_SUCCESS, IO_NO_INCREMENT);
t << "PcicardDevice::Close Status " << (ULONG)status << EOL;
return status;
}
NTSTATUS PcicardDevice::CleanUp(KIrp I)
{
t << "Entering CleanUp, " << I << EOL;
// TODO: Insert your code to respond to the CLEANUP message.
return I.PnpComplete(this, STATUS_SUCCESS);
}
NTSTATUS PcicardDevice::Read(KIrp I)
{
t << "Entering PcicardDevice::Read, " << I << EOL;
if (SynchronizeInterrupt(&m_Irq, LinkTo(ReadDataFromDevice), PIRP(I)) )
return I.Complete(STATUS_SUCCESS);
else
return I.Complete(STATUS_UNSUCCESSFUL);
}
NTSTATUS PcicardDevice::Write(KIrp I)
{
t << "Entering PcicardDevice::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);
}
NTSTATUS status = STATUS_SUCCESS;
PUCHAR pBuffer = (PUCHAR)I.BufferedWriteSource();
ULONG dwTotalSize = I.WriteSize(CURRENT);
ULONG dwBytesSent = dwTotalSize;
unsigned char val;
val=*pBuffer;
t <<" pBuffer-----"<< *pBuffer << EOL;
m_IoPortRange.outb(1,val);
I.Information() = dwBytesSent;
return I.PnpComplete(this, status);
}
NTSTATUS PcicardDevice::DeviceControl(KIrp I)
{
NTSTATUS status;
t << "Entering PcicardDevice::Device Control, " << I << EOL;
switch (I.IoctlCode())
{
case PCICARD_IOCTL_EVENT:
status = PCICARD_IOCTL_EVENT_Handler(I);
break;
default:
// Unrecognized IOCTL request
status = STATUS_INVALID_PARAMETER;
break;
}
// If the IRP's IOCTL handler deferred processing using some driver
// specific scheme, the status variable is set to STATUS_PENDING.
// In this case we simply return that status, and the IRP will be
// completed later. Otherwise, complete the IRP using the status
// returned by the IOCTL handler.
if (status == STATUS_PENDING)
{
return status;
}
else
{
return I.PnpComplete(this, status);
}
}
NTSTATUS PcicardDevice::PCICARD_IOCTL_EVENT_Handler(KIrp I)
{
HANDLE hEvent = *(HANDLE*)I.IoctlBuffer(); //应用程序创建的事件句柄
if (m_pEvent) delete m_pEvent;
m_pEvent = new (NonPagedPool) KEvent(hEvent, OBJECT_TYPE_ALL_ACCESS);
//构造系统事件函数
return I.Complete(STATUS_SUCCESS);
}
VOID PcicardDevice::DpcFor_Irq(PVOID Arg1, PVOID Arg2)
{
BOOLEAN Notify;
BOOLEAN SynchStatus;
if (m_pEvent)
{
SynchStatus = SynchronizeInterrupt(
&m_Irq,
LinkTo(TestAndClearNotifyApp),
&Notify
); //调用中断同步例程TestAndClearNotifyApp
if (SynchStatus)
{
t << "DPC, App notify=" << ULONG(Notify) << "\n";
if (Notify)
m_pEvent->Set(); //设置事件
}
else
t << "Dpc error synchronizing\n";
}
}
BOOLEAN PcicardDevice::Isr_Irq(void)
{
int state; //定义中断状态寄存器的变量
int enable; //定义中断使能寄存器的变量
state=m_IoPortRange.inb(0); // 获取寄存器的值
enable=m_IoPortRange.inb(1);
if ((state && (!enable)) == 0) //READ INTERRUPT_REG
{
// Return FALSE to indicate that this device did not cause the interrupt.
return FALSE;
}
m_IoPortRange.outb(0,0); //清除中断
if (!m_DpcFor_Irq.Request(NULL, NULL))
{
}
// Return TRUE to indicate that our device caused the interrupt
return TRUE;
}
BOOLEAN PcicardDevice::TestAndClearNotifyApp(PVOID p)
{
*(BOOLEAN*)p = m_bNotifyApp;
m_bNotifyApp = FALSE;
//m_bNotifyApp初试化状态为TRUE,当有中断发生时,驱动程序设置事件,通知应
//用程序取数据;在应用程序取数据之前,设置m_bNotifyApp为FALSE,这样一来,
//即使再有中断发生,驱动程序也不再通知应用程序了;只有应用程序取数据之后,
//设置m_bNotifyApp为TRUE,再有中断发生,驱动程序才会通知应用程序。
t << "TestAndClearNotifyApp previous state was=" << ULONG(m_bNotifyApp) << "\n";
return TRUE;
}
BOOLEAN PcicardDevice::ReadDataFromDevice(PVOID pIrp)
{
KIrp I = (PIRP)pIrp;
PUCHAR pBuffer = (PUCHAR) I.BufferedReadDest();
ULONG dwTotalSize = I.ReadSize(CURRENT); // Requested read size
ULONG dwBytesRead = dwTotalSize; // Count of bytes read
ULONG Offset=0x0;
ULONG Count=1024;
m_MemoryRange.inb(Offset,pBuffer,Count);
I.Information() = Count;
m_bNotifyApp = TRUE; //取数据之后,设置m_bNotifyApp为TRUE。
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -