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

📄 pcidp.c

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 C
📖 第 1 页 / 共 2 页
字号:
//*****************************************************************************
// THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
// OR IMPLIED. THIS CODE IS LABELED "OPEN SOFTWARE" AND MAY BE FREELY USED, 
// REPRODUCED, MODIFIED, AND/OR REDISTRIBUTED WITH THE STIPULATION THAT THIS 
// NOTICE REMAIN INTACT. REDISTRIBUTION OF ANY KIND IMPLIES THAT ALL
// MODIFICATIONS FALL UNDER THIS "OPEN SOFTWARE" LABEL.
//
// Copyright (C) 2000, Foxen Solutions
// Copyright (C) 2000, FXN
//
// All Rights Reserved.
//*****************************************************************************
//
// ----------------------------------------------------------------------------
// This is PCIDP.c.  It is the kernal mode driver for the PCI-DP CY7C09449PV-AC
// board.
//
// NOTE: Best viewed with Tabs set to 2.
// ----------------------------------------------------------------------------

// Issues to resolve are marked with **

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


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

	NTSTATUS NTStatus;
	UNICODE_STRING ParamPath;
	WCHAR ParamSubKey[] = L"\\Parameters";
	WCHAR DeviceWin32Name[] = L"\\DosDevices\\PCIDP00";
	UNICODE_STRING DeviceWin32NameUnicode;
	WCHAR DeviceNTName[] = L"\\Device\\PCIDP00_CY7C09449PV";
	UNICODE_STRING DeviceNTNameUnicode;
	PDEVICE_OBJECT DeviceObject = NULL;
	pPCIDP_EXTENSION ObjExt;
	RTL_QUERY_REGISTRY_TABLE ParametersTable[3];
	BOOLEAN FoundPCICard;
	ULONG BusNumber;
	ULONG PCIVendorIDDefault = 0x12BE;
	ULONG PCIDeviceIDDefault = 0x3042;
	ULONG PCIVendorID;
	ULONG PCIDeviceID;
	PCI_SLOT_NUMBER SlotNumber;
	ULONG FunctionNumber;
	ULONG	DeviceNumber;
	PCI_COMMON_CONFIG CardInfo;
	ULONG InfoSize;
	KIRQL PCIIrql;
	KAFFINITY PCIAffinity;
	PHYSICAL_ADDRESS BusAddress;
	PHYSICAL_ADDRESS TranslatedAddress;
	ULONG MappedVector;
	ULONG AddressSpace;
	ULONG IOBaseSize = 8;
	USHORT BoardNumber;
	BOOLEAN BoolStatus;
	PHYSICAL_ADDRESS MaxAddress;
	PHYSICAL_ADDRESS PhysicalAddress;
	ULONG i;


	// --------------------------------------------------------------------------
	// Block 1: Start out by obtaining the PCI Vendor and Device IDs.
	// --------------------------------------------------------------------------
	// Allocate system space for the new registry path buffer.
	ParamPath.MaximumLength = RegistryPath->Length + sizeof(ParamSubKey);
	ParamPath.Length = ParamPath.MaximumLength;
	ParamPath.Buffer = (unsigned short*)ExAllocatePool(
		PagedPool, 
		ParamPath.Length
	);
	if (ParamPath.Buffer == NULL){
		NTStatus = STATUS_NO_MEMORY;
		goto Exit;
	}

	// Copy Registry Path to ParamPath
	RtlCopyMemory(
		ParamPath.Buffer,
		RegistryPath->Buffer,
		RegistryPath->Length
	);

	// Concatenate Sub Key to ParamPath
	RtlCopyMemory(
		&ParamPath.Buffer[RegistryPath->Length/2],
		ParamSubKey,
		sizeof(ParamSubKey)
	);

	//Initialize the parameters table with the vendor and device data.
	RtlZeroMemory(&ParametersTable[0], sizeof(ParametersTable));

	ParametersTable[0].Flags = RTL_QUERY_REGISTRY_DIRECT;
	ParametersTable[0].Name = L"PCIVendorID";
	ParametersTable[0].EntryContext = &PCIVendorID;
	ParametersTable[0].DefaultType = REG_DWORD;
	ParametersTable[0].DefaultData = &PCIVendorIDDefault;
	ParametersTable[0].DefaultLength = sizeof(PCIVendorID);

	ParametersTable[1].Flags = RTL_QUERY_REGISTRY_DIRECT;
	ParametersTable[1].Name = L"PCIDeviceID";
	ParametersTable[1].EntryContext = &PCIDeviceID;
	ParametersTable[1].DefaultType = REG_DWORD;
	ParametersTable[1].DefaultData = &PCIDeviceIDDefault;
	ParametersTable[1].DefaultLength = sizeof(PCIDeviceID);

	// Now get the registry data.
	NTStatus = RtlQueryRegistryValues(
		IN RTL_REGISTRY_ABSOLUTE,
		IN ParamPath.Buffer,
		IN OUT &ParametersTable[0],
		IN NULL, 
		IN NULL
	);
	if(NTStatus != STATUS_SUCCESS)
		goto ExitA;


	// --------------------------------------------------------------------------
	// Block 2: Locate each PCI board using the PCI Vendor and DeviceType IDs.
	// Then initialize a driver device object for each board.
	// --------------------------------------------------------------------------
	BoardNumber = 0;
	FoundPCICard = FALSE;
	SlotNumber.u.bits.Reserved = 0;

	// Loop BusNumber 0 - 3.
	for(BusNumber = 0; BusNumber < 4; BusNumber++){

		// Loop FunctionNumber 0 - 7. 
		for(FunctionNumber = 0;	FunctionNumber < 8; FunctionNumber++){
			SlotNumber.u.bits.FunctionNumber = FunctionNumber;

			// Loop DeviceNumber 0 - 31.
			for(DeviceNumber = 0;	DeviceNumber < 32; DeviceNumber++){
				SlotNumber.u.bits.DeviceNumber = DeviceNumber;

				// Try to get the PCI Configuration space.
				InfoSize = HalGetBusData(
					IN PCIConfiguration,
					IN BusNumber,
					IN SlotNumber.u.AsULONG,
					OUT (PVOID)&CardInfo,
					IN (ULONG)(sizeof(CardInfo)) 
				);                                                                                                      // ID only

				// Did we get any data?
				if(InfoSize > 2){

					// Check for valid device and vendor IDs.
					if(CardInfo.VendorID == PCIVendorID && 
						 CardInfo.DeviceID == PCIDeviceID){

						// We found a valid card.  Create a device object for it.
						DeviceNTName[14] = (USHORT) (0x30 + BoardNumber);
						RtlInitUnicodeString(&DeviceNTNameUnicode, DeviceNTName);

						NTStatus = IoCreateDevice(
							IN  DriverObject,             // The driver object
							IN  sizeof(PCIDP_EXTENSION),	// Size (bytes) of the device ext.
							IN  &DeviceNTNameUnicode,     // The device name
							IN  FILE_DEVICE_PCIDP00,			// The device type
							IN  0,                        // Ignored by this device
							IN  FALSE,                    // Exclusive Device flag
							OUT &DeviceObject             // New created device object
						);
						if(NTStatus != STATUS_SUCCESS)
							goto ExitA;

						// Initialize the driver's extended object.
						ObjExt = (pPCIDP_EXTENSION)DeviceObject->DeviceExtension;
						RtlZeroMemory(ObjExt, sizeof(PCIDP_EXTENSION));
						ObjExt->LLData.IsEmpty = TRUE;
						ObjExt->LLData.CurrentLink = NULL;
						ObjExt->LLData.InsertedCount = 0;
						ObjExt->LLData.FreeMax = 0;
						ObjExt->BusNumber = BusNumber;
						ObjExt->SlotNumber = SlotNumber;
						ObjExt->BoardNumber = BoardNumber;
						ObjExt->BaseAddresses[0] = CardInfo.u.type0.BaseAddresses[0];
						ObjExt->BaseAddresses[1] = CardInfo.u.type0.BaseAddresses[1];
						ObjExt->BaseAddresses[2] = CardInfo.u.type0.BaseAddresses[2];
						ObjExt->BaseAddresses[3] = CardInfo.u.type0.BaseAddresses[3];
						ObjExt->BaseAddresses[4] = CardInfo.u.type0.BaseAddresses[4];
						ObjExt->BaseAddresses[5] = CardInfo.u.type0.BaseAddresses[5];
						//ObjExt->MemoryBase - initialized by MmMapIoSpace call
						//ObjExt->IOBase - initialized by MmMapIoSpace call
						//ObjExt->InterruptObject - initialized by IoConnectInterrupt call
						//ObjExt->LListSpin - initialized by KeInitializeSpinLock call

						// Translate the bus address for the memory space base address
						// to the system logical address.  Then map it into nonpaged 
						// system space.  Save the result in device extended space for 
						// use with other services.
						BusAddress.HighPart = 0;
						BusAddress.LowPart = CardInfo.u.type0.BaseAddresses[0];
						AddressSpace = 0;         //address space is memory
						BoolStatus = HalTranslateBusAddress(
							IN PCIBus,              //bus type
							IN BusNumber,           //bus number
							IN BusAddress,          //bus address
							IN OUT &AddressSpace,   //address space is Memory
							OUT &TranslatedAddress  //translated address
						);
						if(BoolStatus == FALSE){
							NTStatus = STATUS_SOME_NOT_MAPPED;
							goto ExitB;
						}

						if(AddressSpace == 0)   //address space of 0 means map it
							ObjExt->MemoryBase = (ULONG*)MmMapIoSpace(
								IN TranslatedAddress,   //address to map
								IN MemoryBaseSize,      //length in bytes
								IN FALSE                //memory cache
							);
						else
							ObjExt->MemoryBase = (ULONG*)TranslatedAddress.LowPart;

						// Save the I/O space base address for use with other services.
						ObjExt->IOBase = (CardInfo.u.type0.BaseAddresses[1] & 0xFFFFFFFE);

						// Create a symbolic link, i.e. a name that a Win32 app
						// can specify to open the device.
						DeviceWin32Name[18] = (USHORT) (0x30 + BoardNumber);
						RtlInitUnicodeString(
							IN &DeviceWin32NameUnicode, 
							IN DeviceWin32Name
						);
						NTStatus = IoCreateSymbolicLink(
							IN &DeviceWin32NameUnicode, 
							IN &DeviceNTNameUnicode
						);
						if(NTStatus != STATUS_SUCCESS)
							goto ExitB;

						// Map the PCI board's IRQ to a system vector.
						if((ULONG)CardInfo.u.type0.InterruptPin != 0){
							MappedVector = HalGetInterruptVector(
								IN PCIBus,
								IN BusNumber,
								IN (ULONG)CardInfo.u.type0.InterruptLine,  //interrupt level
								IN 0,                                      //interrupt vector
								OUT &PCIIrql,
								OUT &PCIAffinity
							);

							// Connect the driver to the IRQ.
							NTStatus = IoConnectInterrupt(
								OUT &ObjExt->InterruptObject,
								IN PCIDPISR,				//pointer to ISR
								IN DeviceObject,		//context to send to ISR
								IN NULL,						//optional spinlock
								IN MappedVector,		//mapped interrupt vector
								IN PCIIrql,					//DIRQL
								IN PCIIrql,					//DIRQL
								//IN Latched,				//latched/level interrupt
								IN LevelSensitive,	//latched/level interrupt
								IN TRUE,						//shareable interrupt
								IN PCIAffinity,			//processor enable mask
								IN FALSE						//floating save (false for X86)
							);
							if(NTStatus != STATUS_SUCCESS)
								goto ExitC;

							// Register the PCIDPForDpcIsr routine with this device
							// driver.
							IoInitializeDpcRequest(
								IN DeviceObject,
								IN PCIDPForDpcIsr
							);

							// Set up the spin lock for the linked list holding pending IRPs.
							KeInitializeSpinLock(&ObjExt->LListSpin);
						}

						// Otherwise, interrupts are not enabled on the board.
						else
							ObjExt->InterruptObject = 0;

						// 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
						);

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

							ObjExt->MDL = IoAllocateMdl(
								ObjExt->VirtualDMAAddress, 
								DMASize, 
								FALSE, 
								FALSE, 
								NULL
							);
   
							if(ObjExt->MDL){
								MmBuildMdlForNonPagedPool(ObjExt->MDL);
								MmProbeAndLockPages(
									ObjExt->MDL,
									KernelMode,
									IoModifyAccess
								);
							}							
						}
						else
							ObjExt->PhysicalDMAAddress = 0;

						// Reset interrupts and Initialize shared memory.
						ObjExt->MemoryBase[HINT] = 0x3FF;
						for(i=0x1000; i<0x2000; i++)
							ObjExt->MemoryBase[i] = 0xCDCDCDCD;

						FoundPCICard = TRUE;
						BoardNumber++;

						// Debug.  Some object extension parameters.
						//ObjExt->MemoryBase[0x1C40] = ObjExt->BoardNumber;
						//ObjExt->MemoryBase[0x1C41] = ObjExt->BaseAddresses[0];
						//ObjExt->MemoryBase[0x1C42] = ObjExt->BaseAddresses[1];
						//ObjExt->MemoryBase[0x1C43] = (ULONG)ObjExt->MemoryBase;
						//ObjExt->MemoryBase[0x1C44] = ObjExt->IOBase;
						//ObjExt->MemoryBase[0x1C45] = (ULONG)ObjExt->VirtualDMAAddress;
						//ObjExt->MemoryBase[0x1C46] = ObjExt->PhysicalDMAAddress;
						//ObjExt->MemoryBase[0x1C47] = (ULONG)ObjExt->MDL;
						//ObjExt->MemoryBase[0x1C48] = (ULONG)ObjExt->InterruptObject;

						//ObjExt->MemoryBase[0x1C50] = 0; //IRQ entry count
						//ObjExt->MemoryBase[0x1C51] = 0; //IRQ false alarm count
						//ObjExt->MemoryBase[0x1C52] = 0; //IRQ DMAComplete int. count
						//ObjExt->MemoryBase[0x1C53] = 0; //DPC entry count
						//ObjExt->MemoryBase[0x1C54] = 0; //DPC queue not empty count
						//ObjExt->MemoryBase[0x1C55] = 0; //DPC next entry count
						//ObjExt->MemoryBase[0x1C56] = 0; //DPC type match count

						//ObjExt->MemoryBase[0x1C57] = 0; //LL Inserted Count
						//ObjExt->MemoryBase[0x1C58] = 0; //LL PutBack
						//ObjExt->MemoryBase[0x1C59] = 0; //LL FreeUp
						//ObjExt->MemoryBase[0x1C5A] = 0; //LL FreeMax
						//ObjExt->MemoryBase[0x1C5B] = 0; //CMDR Entry
						//ObjExt->MemoryBase[0x1C5C] = 0; //CMDR GetEntry Cnt
						//ObjExt->MemoryBase[0x1C5D] = 0; //CMDR Unmap locked pages
						//ObjExt->MemoryBase[0x1C5E] = 0; //CMD Entry
						//ObjExt->MemoryBase[0x1C5F] = 0; //CMD LL Insert
						//ObjExt->MemoryBase[0x1C60] = 0; //CMD Lin Addr
						//ObjExt->MemoryBase[0x1C61] = 0; //DMAUnmap Entry
						//ObjExt->MemoryBase[0x1C62] = 0; //DMAUnmap GetEntry Cnt
						//ObjExt->MemoryBase[0x1C63] = 0; //DMAUnmap Finish IRP
						//ObjExt->MemoryBase[0x1C64] = 0; //GetFreeEntry - Allocate pool
						//ObjExt->MemoryBase[0x1C65] = 0; //GetFreeEntry - Existing entry
						//ObjExt->MemoryBase[0x1C66] = 0; //Insert - First New
						//ObjExt->MemoryBase[0x1C67] = 0; //Insert - Subsequent Nex
						//ObjExt->MemoryBase[0x1C68] = 0; //Insert - Existing
					}
				}
			}
		}
	}

	if(FoundPCICard == FALSE){
		NTStatus = STATUS_NO_SUCH_DEVICE;
		goto ExitA;
	}


	// Report interrupt, port, and memory usage.
	//NTStatus = ReportResources(DriverObject);
	//if(NTStatus != STATUS_SUCCESS)
	//	goto ExitD;
	
	// Initialize the driver object with this driver's entry points.
	DriverObject->MajorFunction[IRP_MJ_CREATE] = PCIDPCreateClose;
	DriverObject->MajorFunction[IRP_MJ_CLOSE] = PCIDPCreateClose;
	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PCIDPDeviceControl;
	DriverObject->MajorFunction[IRP_MJ_CLEANUP] = PCIDPCleanup;
	DriverObject->DriverUnload = (PDRIVER_UNLOAD)PCIDPUnload;

	// All finished with a successful initialization.  Set the status and return.
	NTStatus = STATUS_SUCCESS;
	goto ExitA;


	// Exit points for errors found during initializaiton.

	// Disconnect the driver from the interrupt and free up DMA memory.
	ExitD:
		IoFreeMdl(ObjExt->MDL);
		MmFreeContiguousMemory(ObjExt->VirtualDMAAddress);
		if(ObjExt->InterruptObject)
			IoDisconnectInterrupt(ObjExt->InterruptObject);

	// Delete the symbolic link.
	ExitC:
		IoDeleteSymbolicLink(&DeviceWin32NameUnicode);

	// Delete the	created device object and unmap physical memory.
	ExitB:
		IoDeleteDevice (DeviceObject);
		MmUnmapIoSpace(ObjExt->MemoryBase, MemoryBaseSize);

	// Free allocated pooled memory.
	ExitA:
		ExFreePool(ParamPath.Buffer);

	// Final exit
	Exit:
		return NTStatus;
}



// ----------------------------------------------------------------------------
// PCIDPDeviceControl is called by the 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;

	// 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(

⌨️ 快捷键说明

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