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

📄 pcidppublic.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 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 = 0x20010615;
		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 non-zero.
	if(IoInput->RegNumber > 5){
		NTStatus = STATUS_INVALID_PARAMETER;
		goto ExitA;
	}

	if((ObjExt->BaseAddresses[IoInput->RegNumber] & 0xFFFFFFFE) == 0){
		NTStatus = STATUS_INVALID_ADDRESS;
		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((ObjExt->BaseAddresses[IoInput->RegNumber] & 1) == 1){
		IoOutput->IOSpace = 1;
		IoOutput->Length = IoInput->Length;
		IoOutput->Address = ObjExt->BaseAddresses[IoInput->RegNumber] & 0xFFFFFFFE;
		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;

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

	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);
		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.
		for(i=0; i<6; i++){
			if(IoInput->VirtualAddress == (ObjExt->BaseAddresses[i] & 0xFFFFFFFE))
				break;
		}

		if(i>=6){
			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.

⌨️ 快捷键说明

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