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

📄 pcidpprivate.c

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 C
字号:
//*****************************************************************************
// 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 PCIDPPrivate.c.  It contains those routines whose access status
// is private within the PCIDP kernel driver.


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


NTSTATUS StartDevice(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
){
	NTSTATUS NTStatus;
	BOOLEAN Status;
	ULONG LIdx;
	ULONG DIdx;
	CM_RESOURCE_LIST* Resources;
	MEMORY_CACHING_TYPE CacheType;
	KINTERRUPT_MODE InterruptMode;
	BOOLEAN Shareable;
	KIRQL InterruptLevel;
	PIO_STACK_LOCATION IrpStack;
	PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

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

	IoSetDeviceInterfaceState(&ObjExt->SymbolicLinkName, TRUE);

	// Let the lower level drivers handle the IRP first.
	IoCopyCurrentIrpStackLocationToNext(IN Irp);

	IoSetCompletionRoutine(
		IN Irp,
		IN DeviceCompletionRoutine,
		IN NULL,			//Context
		IN TRUE,			//InvokeOnSuccess
		IN TRUE,			//InvokeOnError
		IN TRUE				//InvokeOnCancel
	);

	NTStatus = IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
	if(NTStatus == STATUS_PENDING){
		KeWaitForSingleObject(
			IN &ObjExt->WaitEvent,
			IN Executive,				//WaitReason
			IN KernelMode,			//WaitMode
			IN FALSE,						//Alertable
			IN NULL							//Timeout
		);
		NTStatus = Irp->IoStatus.Status;
	}

	// Processed after the lower level drivers have successfully finished with the IRP.
	if(NT_SUCCESS(NTStatus)){
		IrpStack = IoGetCurrentIrpStackLocation(IN Irp);
		Resources = IrpStack->Parameters.StartDevice.AllocatedResourcesTranslated;

		// Get the I/O port attributes.
		Status = GetResources(Resources, CmResourceTypePort, &LIdx, &DIdx);
		if(Status == TRUE){
			ObjExt->IOAccess = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Port.Start;
			ObjExt->IOAccessLength = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Port.Length;
		}
		else{
			//ObjExt->IOAccess = 0;
			ObjExt->IOAccessLength = 0;
			NTStatus = STATUS_INSUFFICIENT_RESOURCES;
			//Irp->IoStatus.Status = NTStatus;
			return NTStatus;
		}

		// Map to the memory base space in order to support driver services.
		Status = GetResources(Resources, CmResourceTypeMemory, &LIdx, &DIdx);
		if(Status == TRUE){
			if(
				Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags &
				CM_RESOURCE_MEMORY_COMBINEDWRITE
			)
				CacheType = MmWriteCombined;
			else if(
				Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags &
				CM_RESOURCE_MEMORY_CACHEABLE
			)
				CacheType = MmCached;
			else
				CacheType = MmNonCached;

			ObjExt->MemoryAccess = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Memory.Start;
			ObjExt->MemoryAccessLength = Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Memory.Length;

			ObjExt->MemoryBase = (ULONG*)MmMapIoSpace(
				IN ObjExt->MemoryAccess,
				IN ObjExt->MemoryAccessLength,
				IN CacheType
			);
			if(ObjExt->MemoryBase == NULL){
				NTStatus = STATUS_SOME_NOT_MAPPED;
				//Irp->IoStatus.Status = NTStatus;
				return NTStatus;
			}
		}
		else{
			NTStatus = STATUS_INSUFFICIENT_RESOURCES;
			//Irp->IoStatus.Status = NTStatus;
			return NTStatus;
		}

		// Map the PCI board's IRQ to a system vector.
		// todo: resolve the interrupt pin source
		ObjExt->InterruptObject = 0;
		//if((ULONG)CardInfo.u.type0.InterruptPin != 0){	//use IRP_MN_READ_CONFIG

			// Connect the driver to the IRQ.
			Status = GetResources(Resources, CmResourceTypeInterrupt, &LIdx, &DIdx);
			if(Status == TRUE){
				if(
					Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Flags ==
					CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE
				)
					InterruptMode = LevelSensitive;
				else
					InterruptMode = Latched;

				if(
					Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].ShareDisposition ==
					CmResourceShareShared
				)
					Shareable = TRUE;
				else
					Shareable = FALSE;

				InterruptLevel = (KIRQL)Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Level;
				NTStatus = IoConnectInterrupt(
					OUT &ObjExt->InterruptObject,
					IN PCIDPISR,								//pointer to ISR
					IN DeviceObject,						//context to send to ISR
					IN NULL,										//optional spinlock
					IN Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Vector,		//mapped interrupt vector
					IN InterruptLevel,					//DIRQL	u.Interrupt.Level
					IN InterruptLevel,					//DIRQL	u.Interrupt.Level
					IN InterruptMode,						//latched/level interrupt
					IN Shareable,								//shareable interrupt
					IN Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].u.Interrupt.Affinity,	//processor enable mask
					IN FALSE										//floating save (false for X86)
				);
				if(NTStatus != STATUS_SUCCESS){
					ObjExt->InterruptObject = 0;
					//Irp->IoStatus.Status = NTStatus;
					return NTStatus;
				}

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

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

	return NTStatus;
}


NTSTATUS StopDevice(IN PDEVICE_OBJECT DeviceObject){

	PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

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

	// Disconnect the driver from the interrupt if enabled.
	if(ObjExt->InterruptObject)
		IoDisconnectInterrupt(ObjExt->InterruptObject);

	// Delete all allocated entries in the linked list.
	DeleteAllEntries(ObjExt);

	// Unmap physical memory.
	MmUnmapIoSpace(ObjExt->MemoryBase, ObjExt->MemoryAccessLength);

	return STATUS_SUCCESS;
}


NTSTATUS CancelStopDevice(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
){
	NTSTATUS NTStatus;
	PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

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

	// Let the lower level drivers handle the IRP first.
	IoCopyCurrentIrpStackLocationToNext(IN Irp);

	IoSetCompletionRoutine(
		IN Irp,
		IN DeviceCompletionRoutine,
		IN NULL,			//Context
		IN TRUE,			//InvokeOnSuccess
		IN TRUE,			//InvokeOnError
		IN TRUE				//InvokeOnCancel
	);

	NTStatus = IoCallDriver(ObjExt->NextLowerDeviceObject, Irp);
	if(NTStatus == STATUS_PENDING){
		KeWaitForSingleObject(
			IN &ObjExt->WaitEvent,
			IN Executive,				//WaitReason
			IN KernelMode,			//WaitMode
			IN FALSE,						//Alertable
			IN NULL							//Timeout
		);
		NTStatus = Irp->IoStatus.Status;
	}

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

	return NTStatus;
}


NTSTATUS RemoveDevice(IN PDEVICE_OBJECT DeviceObject){

	PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

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

	// Free up DMA contiguous memory.
	MmUnlockPages(ObjExt->MDL);
	IoFreeMdl(ObjExt->MDL);
	MmFreeContiguousMemory(ObjExt->VirtualDMAAddress);

	RtlFreeUnicodeString(&ObjExt->SymbolicLinkName);

	IoDetachDevice(ObjExt->NextLowerDeviceObject);

	IoDeleteDevice(DeviceObject);

	return STATUS_SUCCESS;
}


NTSTATUS DeviceCompletionRoutine(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp,
	IN PVOID Context
){
	PPCIDP_EXTENSION ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;

	KeSetEvent(&ObjExt->WaitEvent, IO_NO_INCREMENT, FALSE);
	return STATUS_MORE_PROCESSING_REQUIRED;
}


BOOLEAN GetResources(
	CM_RESOURCE_LIST* Resources,
	UCHAR CmResourceType, 
	ULONG* pLIdx, 
	ULONG* pDIdx
){
	ULONG LIdx;
	ULONG DIdx;
	ULONG PRLCount;
	BOOLEAN Found = FALSE;

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

	for(LIdx=0; LIdx<Resources->Count; LIdx++){

		PRLCount = Resources->List[LIdx].PartialResourceList.Count;
		for(DIdx=0; DIdx<PRLCount; DIdx++){
			if(
				Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx].Type ==
				CmResourceType
			){
				//DbgPrint("[PCIDP]->&Resources: 0x%x...\n", &Resources->List[LIdx].PartialResourceList.PartialDescriptors[DIdx]);	//debug
				//DbgBreakPoint();	//debug
				Found = TRUE;
				break;
			}
		}
		if(Found == TRUE)
			break;
	}

	*pLIdx = LIdx;
	*pDIdx = DIdx;
	return Found;
}



// These routines are the linked list utilities.  They protect the linked list 
// with a spin lock, limiting access to one thread at a time.  The linked list 
// contains those pending IRPs.
BOOLEAN GetNextEntry(
	PPCIDP_EXTENSION ObjExt,
	PLINKED_LIST* FirstLink,
	PLINKED_LIST* CurrentLink,
	PREGISTERED_INTERRUPT* Entry
){

	BOOLEAN Status = FALSE;
	KIRQL LListIrql;
	PLINKED_LIST CurrentLnk;

	KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);

	if(*FirstLink == NULL){
		if(ObjExt->LLData.InsertedCount > 0){
			*FirstLink = ObjExt->LLData.CurrentLink;
			*CurrentLink = *FirstLink;
			CurrentLnk = *CurrentLink;
			if(CurrentLnk->Status == LL_INSERTED){
				CurrentLnk->Status = LL_CHECKEDOUT;
				ObjExt->LLData.InsertedCount--;
				*Entry = &(CurrentLnk->RegisteredInterrupt);
				Status = TRUE;
				goto GetNextExit;
			}
		}
	}

	if(*FirstLink != NULL){
		CurrentLnk = *CurrentLink;
		CurrentLnk = CurrentLnk->Next;
		while(CurrentLnk != *FirstLink){
			if(CurrentLnk->Status == LL_INSERTED){
				CurrentLnk->Status = LL_CHECKEDOUT;
				ObjExt->LLData.InsertedCount--;
				*Entry = &(CurrentLnk->RegisteredInterrupt);
				Status = TRUE;
				break;
			}
			CurrentLnk = CurrentLnk->Next;
		}
		*CurrentLink = CurrentLnk;
	}

	GetNextExit:
	//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;	//debug
	KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);

	return Status;
}


BOOLEAN PutBackEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST CurrentLink){

	BOOLEAN Status;
	KIRQL LListIrql;

	KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
	if(CurrentLink->Status == LL_CHECKEDOUT){ 
		CurrentLink->Status = LL_INSERTED;
		ObjExt->LLData.InsertedCount++;
		Status = TRUE;
	}
	else
		Status = FALSE;

	KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
	//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug
	//ObjExt->MemoryBase[0x1C58]++;//debug
	return Status;
}


BOOLEAN FreeEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST CurrentLink){

	BOOLEAN Status;
	KIRQL LListIrql;

	KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
	if(CurrentLink->Status == LL_CHECKEDOUT || CurrentLink->Status == LL_ACQUIRED){
		CurrentLink->Status = LL_AVAILABLE;
		ObjExt->LLData.CurrentLink = CurrentLink->Prev;
		Status = TRUE;
	}
	else
		Status = FALSE;

	KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
	//ObjExt->MemoryBase[0x1C59]++;//debug

	return Status;
}


PLINKED_LIST GetFreeEntry(PPCIDP_EXTENSION ObjExt){

	PLINKED_LIST FirstLink;
	PLINKED_LIST ReturnLink = NULL;
	KIRQL LListIrql;

	KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
	if(ObjExt->LLData.IsEmpty == FALSE) {
		FirstLink = ObjExt->LLData.CurrentLink;
		do{
			ObjExt->LLData.CurrentLink = ObjExt->LLData.CurrentLink->Next;
			if(ObjExt->LLData.CurrentLink->Status == LL_AVAILABLE){
				ObjExt->LLData.CurrentLink->Status = LL_ACQUIRED;
				ReturnLink = ObjExt->LLData.CurrentLink;

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

				break;
			}
		} while(FirstLink != ObjExt->LLData.CurrentLink);
	}
	KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);

	if(ReturnLink == NULL){
		ReturnLink = ExAllocatePool(NonPagedPool, sizeof(LINKED_LIST));
		if(ReturnLink != NULL){
			ReturnLink->Status = LL_NEW;

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

		}
	}

	return ReturnLink;
}


BOOLEAN InsertEntry(PPCIDP_EXTENSION ObjExt, PLINKED_LIST Entry){

	BOOLEAN Status = TRUE;
	PLINKED_LIST CurrentLink;
	KIRQL LListIrql;

	KeAcquireSpinLock(&ObjExt->LListSpin, &LListIrql);
	if(Entry->Status == LL_NEW){
		Entry->Status = LL_INSERTED;
		ObjExt->LLData.FreeMax++;
		ObjExt->LLData.InsertedCount++;
		if(ObjExt->LLData.IsEmpty == TRUE) {
			Entry->Prev = Entry;
			Entry->Next = Entry;
			ObjExt->LLData.CurrentLink = Entry;
			ObjExt->LLData.IsEmpty = FALSE;

			//ObjExt->MemoryBase[0x1C66]++;	//debug
		}
		else {
			CurrentLink = ObjExt->LLData.CurrentLink;
			Entry->Prev = CurrentLink;
			Entry->Next = CurrentLink->Next;

			CurrentLink->Next->Prev = Entry;
			CurrentLink->Next = Entry;

			//ObjExt->MemoryBase[0x1C67]++;	//debug
		}
	}
	else if(Entry->Status == LL_ACQUIRED){
		Entry->Status = LL_INSERTED;
		ObjExt->LLData.InsertedCount++;

		//ObjExt->MemoryBase[0x1C68]++;	//debug
	}
	else
		Status = FALSE;

	KeReleaseSpinLock(&ObjExt->LListSpin, LListIrql);
	//ObjExt->MemoryBase[0x1C5A] = ObjExt->LLData.FreeMax;//debug
	//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug

	return Status;
}


BOOLEAN DeleteAllEntries(PPCIDP_EXTENSION ObjExt){

	PLINKED_LIST CurrentLink = ObjExt->LLData.CurrentLink;

	while(ObjExt->LLData.IsEmpty == FALSE) {

		if(CurrentLink->Status == LL_INSERTED)
			ObjExt->LLData.InsertedCount--;

		if(CurrentLink->Next == CurrentLink) {
			ObjExt->LLData.IsEmpty = TRUE;
		}
		else {
			CurrentLink->Prev->Next = CurrentLink->Next;
			CurrentLink->Next->Prev = CurrentLink->Prev;
			CurrentLink = CurrentLink->Prev;
		}
		ObjExt->LLData.FreeMax--;
		//ObjExt->MemoryBase[0x1C5A] = ObjExt->LLData.FreeMax;//debug
		//ObjExt->MemoryBase[0x1C57] = ObjExt->LLData.InsertedCount;//debug

		ExFreePool(ObjExt->LLData.CurrentLink);
	}

	return(!ObjExt->LLData.IsEmpty);
}


⌨️ 快捷键说明

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