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

📄 pcidp.c

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
// OR IMPLIED.  THIS CODE IS COPYRIGHTED AND MAY NOT BE MODIFIED OR DISTRIBUTED
// WITHOUT THE WRITTEN CONSENT OF THE PRODUCER.
//
// Copyright (C) 2002, Foxen Solutions
// Copyright (C) 2002, FXN
//
// All Rights Reserved.
//*****************************************************************************
//
// ----------------------------------------------------------------------------
// This is PCIDP.c.  It is the Windows 2000 kernal mode driver for the PCI-DP 
// CY7C09449PV-AC board.
//
// NOTE: Best viewed with Tabs set to 2.
// ----------------------------------------------------------------------------

// Issues to resolve are marked //todo

// Include the appropriate header files.
#include "PCIDPInc.h"
#include "PCIDP.h"

#include "initguid.h"
#include "PCIDPGUID.h"


// ----------------------------------------------------------------------------
// DriverEntry is the entry point for the PCIDP kernel mode driver. Windows 
// 2000 calls this routine to initialize this driver.
// ----------------------------------------------------------------------------
NTSTATUS DriverEntry(
	IN OUT PDRIVER_OBJECT DriverObject,
	IN PUNICODE_STRING RegistryPath
){

	// Debug entry point
	//DbgPrint("[PCIDP]->Entering DriverEntry...\n");	//debug
	//DbgBreakPoint();	//debug

	// Initialize the driver object with this driver's entry points.
	DriverObject->MajorFunction[IRP_MJ_CREATE] = PCIDPCreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = PCIDPCreateClose;
  DriverObject->DriverExtension->AddDevice = PCIDPAddDevice;
  DriverObject->MajorFunction[IRP_MJ_PNP] = PCIDPDispatchPnp;
  DriverObject->MajorFunction[IRP_MJ_POWER] = PCIDPDispatchPower;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PCIDPDeviceControl;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PCIDPCleanup;
	DriverObject->DriverUnload = (PDRIVER_UNLOAD)PCIDPUnload;
	//DriverObject->DriverStartIo = (PDRIVER_STARTIO)PCIDPStartIo; //to have OS manage queued IRPs

	// Initialize any other driver global data.

	// Save a copy of the registry path pointed to by RegistryPath.

	// Register for driver reinitialization.
	// IoRegisterDriverReinitialization();

	return STATUS_SUCCESS;
}



// ----------------------------------------------------------------------------
// PCIDPAddDevice.  Called by the Windows 2000 Plug and Play manager to add a 
// device that is controlled by this driver.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPAddDevice(
	IN PDRIVER_OBJECT  DriverObject,
	IN PDEVICE_OBJECT  PhysicalDeviceObject 
){
	NTSTATUS NTStatus;
	PDEVICE_OBJECT DeviceObject;
	PPCIDP_EXTENSION ObjExt;
	PHYSICAL_ADDRESS MaxAddress;
	PHYSICAL_ADDRESS PhysicalAddress;

	// Debug entry point
	//DbgPrint("[PCIDP]->Entering AddDevice...\n");	//debug
	//DbgBreakPoint();	//debug

	// Create the device space that will be associated with this driver.
	//todo: how to set up security attributes so the app. can call this driver
	//      (because of the FILE_DEVICE_SECURE_OPEN parameter).
	NTStatus = IoCreateDevice(
		IN  DriverObject,             // The driver object
		IN  sizeof(PCIDP_EXTENSION),	// Size (bytes) of the device ext.
		IN  NULL,											// The device name; let the OS name it
		IN  FILE_DEVICE_PCIDP00,			// The device type
		IN  FILE_DEVICE_SECURE_OPEN,  // Device characteristics
		IN  FALSE,                    // Exclusive Device flag
		OUT &DeviceObject             // New created device object
	);
	if(NTStatus != STATUS_SUCCESS)
		goto Exit;

	// Initialize the driver's extended object.
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
	RtlZeroMemory(ObjExt, sizeof(PCIDP_EXTENSION));

	//ObjExt->BusNumber = BusNumber; - not needed
	//ObjExt->SlotNumber = SlotNumber; - not needed
	//ObjExt->BoardNumber = BoardNumber; - not needed
	//ObjExt->BaseAddresses[0] = CardInfo.u.type0.BaseAddresses[0]; - not needed
	//ObjExt->BaseAddresses[1] = CardInfo.u.type0.BaseAddresses[1]; - not needed
	//ObjExt->BaseAddresses[2] = CardInfo.u.type0.BaseAddresses[2]; - not needed
	//ObjExt->BaseAddresses[3] = CardInfo.u.type0.BaseAddresses[3]; - not needed
	//ObjExt->BaseAddresses[4] = CardInfo.u.type0.BaseAddresses[4]; - not needed
	//ObjExt->BaseAddresses[5] = CardInfo.u.type0.BaseAddresses[5]; - not needed
	//ObjExt->MemoryAccess - enum resources (Start)
	//ObjExt->IOAccess - enum resources (Start)
	//ObjExt->MemoryAccessLength - enum resources (Start)
	//ObjExt->IOAccessLength - enum resources (Start)
	//ObjExt->MemoryBase - initialized by MmMapIoSpace call (Start)
	//ObjExt->IOBase - not needed
	//ObjExt->InterruptObject - initialized by IoConnectInterrupt call (Start)
	//ObjExt->InterruptData - used in DpcISR and ISR

	ObjExt->LLData.IsEmpty = TRUE;
	ObjExt->LLData.CurrentLink = NULL;
	ObjExt->LLData.InsertedCount = 0;
	ObjExt->LLData.FreeMax = 0;

	//ObjExt->LListSpin - initialized by KeInitializeSpinLock call (AddDevice)
	//ObjExt->VirtualDMAAddress - initialized by MmAllocateContiguousMemory (AddDevice)
	//ObjExt->PhysicalDMAAddress - initialized by MmGetPhysicalAddress (AddDevice)
	//ObjExt->MDL - initialized by IoAllocateMdl (AddDevice)
	//ObjExt->SymbolicLinkName - initialized by IoRegisterDeviceInterface (AddDevice)
	//ObjExt->PhysicalDeviceObject - not needed
	//ObjExt->NextLowerDeviceObject - initialized by IoAttachDeviceToDeviceStack (AddDevice)
	//ObjExt->WaitEvent - initialized by KeInitializeEvent (AddDevice)


	// Now create a symbolic link an application can use to gain access to the
	// driver's services for this device.
	NTStatus = IoRegisterDeviceInterface(
		IN PhysicalDeviceObject,					//The PDO
		IN &GUID_PCIDP_INTERFACE,					//GUID for the interface class
		IN NULL,													//Reference string (not used)
		OUT &ObjExt->SymbolicLinkName			//returned symbolic link name
	);
	if(NTStatus != STATUS_SUCCESS)
		if(NTStatus != STATUS_OBJECT_NAME_EXISTS)
			goto ExitA;

	// Attach the device object to its device stack.
	ObjExt->NextLowerDeviceObject = IoAttachDeviceToDeviceStack(
		DeviceObject,
		PhysicalDeviceObject
	);
	if(ObjExt->NextLowerDeviceObject == NULL){
		NTStatus = STATUS_UNSUCCESSFUL;		//todo: more meaningful error code or log event file
		goto ExitA;
	}

	// Set up an synchro event for the start device IRP.
	KeInitializeEvent(&ObjExt->WaitEvent, SynchronizationEvent, FALSE);

	// Allocate a contiguous span of memory for DMA usage.
	MaxAddress.LowPart = 0xFFFFFFFF;
	MaxAddress.HighPart = 0;		
	ObjExt->VirtualDMAAddress = MmAllocateContiguousMemory(
		IN (ULONG)DMASize,	//16K
		IN MaxAddress				//Full 32 bit address range
	);

	//DbgPrint("[PCIDP]->AddDevice, VirtDMAAddr=0x%x...\n", ObjExt->VirtualDMAAddress);	//debug

	if(ObjExt->VirtualDMAAddress != NULL){
		PhysicalAddress = MmGetPhysicalAddress(
			ObjExt->VirtualDMAAddress
		);
		ObjExt->PhysicalDMAAddress = PhysicalAddress.LowPart;

		//DbgPrint("[PCIDP]->AddDevice, PhyDMAAddr=0x%x...\n", ObjExt->PhysicalDMAAddress);	//debug

		ObjExt->MDL = IoAllocateMdl(
			ObjExt->VirtualDMAAddress, 
			DMASize, 
			FALSE, 
			FALSE, 
			NULL
		);

		if(ObjExt->MDL){

			//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags);	//debug
   
			//MmBuildMdlForNonPagedPool(ObjExt->MDL);

			//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags);	//debug
   
			MmProbeAndLockPages(
				ObjExt->MDL,
				KernelMode,
				IoModifyAccess
			);

			//DbgPrint("[PCIDP]->AddDevice, MDLFlags=0x%x...\n", ObjExt->MDL->MdlFlags);	//debug
   
		}
	}

	// Could not allocate memory for DMA but that is not
	// a show-stopper.
	else
		ObjExt->PhysicalDMAAddress = 0;

	// To get here means we were successful.
	DeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
	goto Exit;

	ExitA:
		IoDeleteDevice (DeviceObject);

	Exit:

		// Debug exit point
		//DbgPrint("[PCIDP]->Leaving AddDevice, status=0x%x...\n", NTStatus);	//debug
		//DbgBreakPoint();	//debug

		return NTStatus;
}



// ----------------------------------------------------------------------------
// PCIDPDispatchPower.  Power management dispatch routine called by the Windows 
// 2000 power manager.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDispatchPower( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp 
){
	PPCIDP_EXTENSION ObjExt;
	NTSTATUS NTStatus;

	// Debug entry point
	//DbgPrint("[PCIDP]->Entering DispatchPower...\n");	//debug
	//DbgBreakPoint();	//debug

	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	PoStartNextPowerIrp(Irp);
	IoSkipCurrentIrpStackLocation(Irp);
	NTStatus = PoCallDriver(ObjExt->NextLowerDeviceObject, Irp);

	// Debug exit point
	//DbgPrint("[PCIDP]->Leaving DispatchPower, status=0x%x...\n", NTStatus);	//debug
	//DbgBreakPoint();	//debug

	return STATUS_SUCCESS;
}



// ----------------------------------------------------------------------------
// PCIDPDispatchPnp.  Plug and Play dispatch routine called by the Windows 2000 
// PnP manager.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDispatchPnp( 
	IN PDEVICE_OBJECT DeviceObject, 
	IN PIRP Irp 
){

	PIO_STACK_LOCATION IrpStack;
	NTSTATUS NTStatus;
	PPCIDP_EXTENSION ObjExt;

	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	// Get a pointer to the current location in the Irp. This is where
	// the function codes and parameters are located.
	IrpStack = IoGetCurrentIrpStackLocation(IN Irp);

	// Debug entry point
	//DbgPrint("[PCIDP]->Entering DispatchPnp, function=0x%x...\n",IrpStack->MinorFunction);	//debug
	//DbgBreakPoint();	//debug

	// Determine the PnP I/O request packet.
	switch (IrpStack->MinorFunction){

	case IRP_MN_START_DEVICE:
		NTStatus = StartDevice(DeviceObject, Irp);
		Irp->IoStatus.Status = NTStatus;
		//PoSetPowerState(DeviceObject, DevicePowerState, PowerDeviceD0);
		IoCompleteRequest(Irp, IO_NO_INCREMENT);	//back up the stack so complete it.
		break;

	case IRP_MN_QUERY_STOP_DEVICE:
		//NTStatus = STATUS_UNSUCCESSFUL;
		//Irp->IoStatus.Status = NTStatus;
		//IoCompleteRequest(Irp, IO_NO_INCREMENT);
		NTStatus = STATUS_SUCCESS;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case IRP_MN_STOP_DEVICE:
		NTStatus = StopDevice(DeviceObject);
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case IRP_MN_CANCEL_STOP_DEVICE:
		NTStatus = CancelStopDevice(DeviceObject, Irp);
		Irp->IoStatus.Status = NTStatus;
		IoCompleteRequest(Irp, IO_NO_INCREMENT);	//back up the stack so complete it.
		break;

	case IRP_MN_QUERY_REMOVE_DEVICE:
		NTStatus = STATUS_UNSUCCESSFUL;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case IRP_MN_REMOVE_DEVICE:
		NTStatus = RemoveDevice(DeviceObject);
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case IRP_MN_SURPRISE_REMOVAL:
		NTStatus = STATUS_SUCCESS;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case IRP_MN_DEVICE_USAGE_NOTIFICATION:
		NTStatus = STATUS_UNSUCCESSFUL;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	case 8:
	case 0xFF:
	case IRP_MN_QUERY_LEGACY_BUS_INFORMATION:
		NTStatus = STATUS_UNSUCCESSFUL;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;

	default:
		NTStatus = STATUS_UNSUCCESSFUL;
		Irp->IoStatus.Status = NTStatus;
	  IoSkipCurrentIrpStackLocation(Irp);	//send it on down the stack
		IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
		break;
	}

	// Debug exit point
	//DbgPrint("[PCIDP]->Leaving DispatchPnp, status=0x%x...\n", NTStatus);	//debug
	//DbgBreakPoint();	//debug

	return NTStatus;
}



// ----------------------------------------------------------------------------
// PCIDPDeviceControl. Called by the Windows 2000 I/O system to perform a 
// device I/O control function.
// ----------------------------------------------------------------------------
NTSTATUS PCIDPDeviceControl(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
){

	PIO_STACK_LOCATION IrpStack;
	PVOID IoBuffer;
	ULONG InputBufferLength;
	ULONG OutputBufferLength;
	NTSTATUS NTStatus;

	// Debug entry point
	//DbgPrint("[PCIDP]->Entering DeviceControl...\n");	//debug
	//DbgBreakPoint();	//debug

	// Initialize the return values with some defaults.
	Irp->IoStatus.Status = STATUS_SUCCESS;
	Irp->IoStatus.Information = 0;

	// Get a pointer to the current location in the Irp. This is where
	// the function codes and parameters are located.
	IrpStack = IoGetCurrentIrpStackLocation(IN Irp);

	// Get the pointer to the input/output buffer and it's length(s).
	IoBuffer           = Irp->AssociatedIrp.SystemBuffer;
	InputBufferLength  = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;


	// Determine which I/O control code was specified.
	switch (IrpStack->Parameters.DeviceIoControl.IoControlCode){

	case IOCTL_PCIDP00_MAP_BASE_REGS:
		PCIDPMapBaseRegs(
			IN DeviceObject,
			IN OUT Irp,
			IN OUT IoBuffer,
			IN InputBufferLength,
			IN OutputBufferLength
		);
		break;

	case IOCTL_PCIDP00_UNMAP:
		PCIDPUnMap(
			IN DeviceObject,
			IN OUT Irp,
			IN IoBuffer,
			IN InputBufferLength
		);
		break;

	case IOCTL_PCIDP00_MAP_DMA_MEM:
		PCIDPMapDMAMem(
			IN DeviceObject,
			IN OUT Irp,
			OUT IoBuffer,
			IN OutputBufferLength
		);
		break;

	case IOCTL_PCIDP00_CANCEL_MAP_DMA:
		PCIDPCancelMapDMA(
			IN DeviceObject,
			IN OUT Irp,
			IN IoBuffer,
			IN InputBufferLength
		);
		break;

	case IOCTL_PCIDP00_UNMAP_DMA:
		PCIDPUnMapDMA(
			IN DeviceObject,
			IN OUT Irp,
			IN IoBuffer,
			IN InputBufferLength
		);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -