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

📄 pcidppublic.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 PCIDPPublic.c.  It contains those PCIDP kernel routines published 
// for use by an application using the IoDeviceControl system service.

#include "PCIDPInc.h"
#include "PCIDP.h"



// ----------------------------------------------------------------------------
// PCIDPGetDriverVersion
// ----------------------------------------------------------------------------
VOID PCIDPGetDriverVersion(
	IN OUT PIRP Irp,
	OUT PVOID IoBuffer,
	IN ULONG OutputBufferLength
){

	// Define variables.
	NTSTATUS NTStatus;
	PPCIDP00_GET_VERSION_RECV IoOutput;

	// Initialize variables.
	IoOutput = (PPCIDP00_GET_VERSION_RECV)IoBuffer;

	// Check for adequate output buffer space.
	if(OutputBufferLength >= sizeof(PCIDP00_GET_VERSION_RECV)){
		NTStatus = STATUS_SUCCESS;
		IoOutput->Version = 0x20020822;
		Irp->IoStatus.Information = sizeof(PCIDP00_GET_VERSION_RECV);
	}

	else
		NTStatus = STATUS_INVALID_BUFFER_SIZE;

	Irp->IoStatus.Status = NTStatus;
}


// ----------------------------------------------------------------------------
// PDIDPMapBaseRegs
// ----------------------------------------------------------------------------
VOID PCIDPMapBaseRegs(
	IN PDEVICE_OBJECT DeviceObject,
	IN OUT PIRP Irp,
	IN OUT PVOID IoBuffer,
	IN ULONG InputBufferLength,
	IN ULONG OutputBufferLength
){

	// Define variables.
	//ULONG PCIAddress;
	ULONG Length;
	ULONG LengthOut;
	//ULONG BusNumber;
	ULONG VirtualAddress;
	//ULONG MappedLength;
	//ULONG MapIndex;
	UNICODE_STRING PhysicalMemoryUnicodeString;
	OBJECT_ATTRIBUTES ObjectAttributes;
	//BOOLEAN HALStatus;
	//PHYSICAL_ADDRESS LongLength;
	//PHYSICAL_ADDRESS FullPCIAddress;
	//PHYSICAL_ADDRESS FullPCIAddressEnd;
	//PHYSICAL_ADDRESS FullLogicalAddress;
	//PHYSICAL_ADDRESS FullLogicalAddressEnd;
	PHYSICAL_ADDRESS SectionOffset;
	NTSTATUS NTStatus;
	HANDLE PhysicalMemoryHandle;
	PVOID PhysicalMemorySection;
	ULONG MemorySpace;
	ULONG MemorySpaceEnd;
	PPCIDP00_MAP_BASE_REGS_SEND IoInput;
	PPCIDP00_MAP_BASE_REGS_RECV IoOutput;
	PPCIDP_EXTENSION ObjExt;

	// Initialize variables.
	NTStatus = STATUS_SUCCESS;
	PhysicalMemoryHandle  = NULL;
	PhysicalMemorySection = NULL;
	MemorySpace = 0;
	MemorySpaceEnd = 0;
	IoInput = (PPCIDP00_MAP_BASE_REGS_SEND)IoBuffer;
	IoOutput = (PPCIDP00_MAP_BASE_REGS_RECV)IoBuffer;
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	// Make sure the buffer lengths are of sufficient size to handle
	// the transactions.
	if((InputBufferLength < sizeof(PCIDP00_MAP_BASE_REGS_SEND)) ||
		 (OutputBufferLength < sizeof(PCIDP00_MAP_BASE_REGS_RECV))){
		NTStatus = STATUS_INVALID_BUFFER_SIZE;
		goto ExitA;
	}

	// Check for a valid Base Address Register index and that its value
	// is zero or one, currently, the only supported registers.
	if(IoInput->RegNumber > 1){
		NTStatus = STATUS_INVALID_PARAMETER;
		goto ExitA;
	}

	// First check to see if the address is for I/O space. If it is, we
	// can't map it.  Just return the I/O Address so the application can
	// use an I/O access driver to read and write from this space.
	if(IoInput->RegNumber == 1){
		IoOutput->IOSpace = 1;
		IoOutput->Length = ObjExt->IOAccessLength;
		IoOutput->Address = (ULONG)ObjExt->IOAccess.LowPart;
		Irp->IoStatus.Information = sizeof(PCIDP00_MAP_BASE_REGS_RECV);
		goto ExitA;
	}

	// Create the full path name for the physical memory object.
	RtlInitUnicodeString(
		IN &PhysicalMemoryUnicodeString,
		IN L"\\Device\\PhysicalMemory"
	);

	// Initialize the physical memory object attributes.
	InitializeObjectAttributes(
		OUT &ObjectAttributes,						// Object attributes structure
		IN &PhysicalMemoryUnicodeString,	// Full path name of the object
		IN OBJ_CASE_INSENSITIVE,					// Object attribute
		IN (HANDLE) NULL,									// Root directory is N/A
		IN (PSECURITY_DESCRIPTOR) NULL		// Security descriptor is N/A
	);

	// Get a handle to the physical memory object.
	NTStatus = ZwOpenSection(
		OUT &PhysicalMemoryHandle,				// Handle to the physical memory object
		IN SECTION_ALL_ACCESS,						// Allow full access to the memory
		IN &ObjectAttributes							// Object attributes structure
	);
	if(NTStatus != STATUS_SUCCESS) goto ExitA;

	// Validate access on the object's handle and get a pointer to the object's
	// body.
	NTStatus = ObReferenceObjectByHandle(
		IN PhysicalMemoryHandle,
		IN SECTION_ALL_ACCESS,
		IN (POBJECT_TYPE) NULL,
		IN KernelMode,
		OUT &PhysicalMemorySection,
		OUT (POBJECT_HANDLE_INFORMATION) NULL
	);
	if(NTStatus != STATUS_SUCCESS) goto ExitB;

	// Translate the address from a PCI address to a system logical address.
	// Initialize the PCI full physical addresses that will be translated.
	//FullPCIAddress.HighPart = 0;
	//FullPCIAddress.LowPart = ObjExt->BaseAddresses[IoInput->RegNumber];
	//FullPCIAddressEnd = RtlLargeIntegerAdd (
	//	IN FullPCIAddress,
	//	IN RtlConvertUlongToLargeInteger(IoInput->Length)
	//);

	// Translate the full PCI physical addresses into corresponding full system
	// logical addresses.
	//NTStatus = STATUS_ACCESS_DENIED;
	//HALStatus = HalTranslateBusAddress(
	//	IN PCIBus,										// bus type
	//	IN ObjExt->BusNumber,					// bus number
	//	IN FullPCIAddress,						// bus address
	//	IN &MemorySpace,							// I/O or memory space
	//	OUT &FullLogicalAddress				// system logical address
	//);
	//if(HALStatus == FALSE) goto ExitB;

	//HALStatus = HalTranslateBusAddress(
	//	IN PCIBus,										// bus type
	//	IN ObjExt->BusNumber,					// bus number
	//	IN FullPCIAddressEnd,					// bus address
	//	IN &MemorySpaceEnd,						// I/O or memory space
	//	OUT &FullLogicalAddressEnd		// system logical address
	//);
	//	if(HALStatus == FALSE) goto ExitB;

	// Calculate the length of the memory to be mapped.
	//LongLength = RtlLargeIntegerSubtract(
	//	IN FullLogicalAddressEnd,
	//	IN FullLogicalAddress
	//);
	//Length = LongLength.LowPart;
	//LengthOut = LongLength.LowPart;
	Length = ObjExt->MemoryAccessLength;
	LengthOut = ObjExt->MemoryAccessLength;

	// Now map the system logical address in this process' virtual address
	// space.
	VirtualAddress = 0;
	//SectionOffset = FullLogicalAddress;
	SectionOffset = ObjExt->MemoryAccess;

	NTStatus = ZwMapViewOfSection(
		IN PhysicalMemoryHandle,						//section handle
		IN (HANDLE) -1,											//process handle
		IN OUT (PVOID*)&VirtualAddress,			//base address (virtual address)
		IN 0L,															//zero bits
		IN Length,													//commit size
		IN OUT &SectionOffset,							//section offset
		IN OUT &LengthOut,									//view size
		IN ViewShare,												//inherit disposition (0)
		IN 0,																//allocation type
		IN PAGE_READWRITE | PAGE_NOCACHE		//protect
	);

	// Mapping the section above rounded the logical address down to 
	// the nearest 64 K boundary. Now return a virtual address pointing 
	// to our request area by adding in the offset from the beginning 
	// of the section.
	if(NTStatus == STATUS_SUCCESS){
		IoOutput->IOSpace = 0;
		//IoOutput->Address = VirtualAddress +
		//	((ULONG)FullLogicalAddress.LowPart - (ULONG)SectionOffset.LowPart);
		//IoOutput->Length = LengthOut -
		//	((ULONG)FullLogicalAddress.LowPart - (ULONG)SectionOffset.LowPart);
		IoOutput->Address = VirtualAddress +
			((ULONG)ObjExt->MemoryAccess.LowPart - (ULONG)SectionOffset.LowPart);
		IoOutput->Length = LengthOut -
			((ULONG)ObjExt->MemoryAccess.LowPart - (ULONG)SectionOffset.LowPart);
		Irp->IoStatus.Information = sizeof(PCIDP00_MAP_BASE_REGS_RECV);
	}


	ExitB:
		ZwClose(PhysicalMemoryHandle);

	ExitA:
	Irp->IoStatus.Status = NTStatus;
}


// ----------------------------------------------------------------------------
// PCIDPUnMap unmaps a region of virtual memory from physical memory 
// that was mapped earlier using the PCIDPMapBaseRegs routines.
// ----------------------------------------------------------------------------
VOID PCIDPUnMap(
	IN PDEVICE_OBJECT DeviceObject,
	IN OUT PIRP Irp,
	IN PVOID IoBuffer,
	IN ULONG InputBufferLength
){

	// Define variables.
	ULONG i;
	NTSTATUS NTStatus;
	PPCIDP00_UNMAP_SEND IoInput;
	PPCIDP_EXTENSION ObjExt;

	// Initialize variables.
	NTStatus = STATUS_SUCCESS;
	IoInput = (PPCIDP00_UNMAP_SEND)IoBuffer;
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	if(InputBufferLength >= sizeof(PCIDP00_UNMAP_SEND)){

		// Don't try to unmap from I/O space but it's not a failure either.
		// Do unmap from memory space.
		if(IoInput->VirtualAddress != (ULONG)ObjExt->IOAccess.LowPart){
			NTStatus = ZwUnmapViewOfSection(
				IN (HANDLE) -1,
				IN (PVOID)IoInput->VirtualAddress
			);
		}
	}

	else
		NTStatus = STATUS_INVALID_BUFFER_SIZE;

	Irp->IoStatus.Status = NTStatus;
}



// ----------------------------------------------------------------------------
// PDIDPMapDMAMem
// ----------------------------------------------------------------------------
VOID PCIDPMapDMAMem(
	IN PDEVICE_OBJECT DeviceObject,
	IN OUT PIRP Irp,
	OUT PVOID IoBuffer,
	IN ULONG OutputBufferLength
){

	NTSTATUS NTStatus;
	PPCIDP00_MAP_DMA_MEM_RECV IoOutput;
	PPCIDP_EXTENSION ObjExt;

	// Initialize variables.
	IoOutput = (PPCIDP00_MAP_DMA_MEM_RECV)IoBuffer;
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	if(OutputBufferLength >= sizeof(PCIDP00_MAP_DMA_MEM_RECV)){
		if(ObjExt->MDL){
			IoOutput->LinearAddress = (unsigned long)MmMapLockedPages(
				ObjExt->MDL, 
				UserMode
			);
			if(IoOutput->LinearAddress != 0){
				IoOutput->PhysicalAddress = ObjExt->PhysicalDMAAddress;
				Irp->IoStatus.Information = sizeof(PCIDP00_MAP_DMA_MEM_RECV);
				NTStatus = STATUS_SUCCESS;
			}
			else
				NTStatus = STATUS_NO_MEMORY;
		}
		else
			NTStatus = STATUS_NO_MEMORY;

	}
	else
		NTStatus = STATUS_INVALID_BUFFER_SIZE;

	Irp->IoStatus.Status = NTStatus;
}


// ----------------------------------------------------------------------------
// PCIDPCancelMapDMA
// ----------------------------------------------------------------------------
VOID PCIDPCancelMapDMA(
	IN PDEVICE_OBJECT DeviceObject,
	IN OUT PIRP Irp,
	IN PVOID IoBuffer,
	IN ULONG InputBufferLength
){
	KIRQL CancelSpin;
	PPCIDP00_UNMAP_DMA_SEND IoInput;
	PPCIDP_EXTENSION ObjExt;
  PLINKED_LIST LLEntry;
	NTSTATUS NTStatus;

	// Initialize variables.
	IoInput = (PPCIDP00_UNMAP_DMA_SEND)IoBuffer;
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	//ObjExt->MemoryBase[0x1C5E]++;	//debug

	// Get an empty linked list entry.
	LLEntry = GetFreeEntry(ObjExt);
	if(LLEntry != NULL){

		// Set up a cancel routine that unmaps the DMA should the application fail
		// to do so.
		IoMarkIrpPending (Irp);
		IoAcquireCancelSpinLock (&CancelSpin);
		IoSetCancelRoutine (Irp, PCIDPCancelMapDMARoutine);
		IoReleaseCancelSpinLock (CancelSpin);

		// Add this IRP to the linked list
		// Save the linear address required to unmap DMA memory in Type.
		LLEntry->RegisteredInterrupt.Irp = Irp;
		LLEntry->RegisteredInterrupt.Type = (ULONG)IoInput->LinearAddress;
		InsertEntry(ObjExt, LLEntry);

		//ObjExt->MemoryBase[0x1C5F]++;	//debug
		//ObjExt->MemoryBase[0x1C60] = (ULONG)IoInput->LinearAddress;	//debug

		// Return with I/O pending.
		NTStatus = STATUS_PENDING;
	}
	else
		NTStatus = STATUS_NO_MEMORY;

	// Return with current status.
	Irp->IoStatus.Status = NTStatus;
}


// ----------------------------------------------------------------------------
// PDIDPUnMapDMA
// ----------------------------------------------------------------------------
VOID PCIDPUnMapDMA(
	IN PDEVICE_OBJECT DeviceObject,
	IN OUT PIRP Irp,
	IN PVOID IoBuffer,
	IN ULONG InputBufferLength
){

	// Define variables.
	ULONG i;
	NTSTATUS NTStatus;
	PPCIDP00_UNMAP_DMA_SEND IoInput;

⌨️ 快捷键说明

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