⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcicarddevice.cpp

📁 一个PCI板卡的设备驱动程序 用visual c++ 编写
💻 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 + -