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

📄 pcidppublic.c

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 C
📖 第 1 页 / 共 2 页
字号:
	PPCIDP_EXTENSION ObjExt;
	PMDL Mdl;
	PREGISTERED_INTERRUPT RegisteredInt;
	KIRQL CancelSpin;
	PLINKED_LIST CurrentLink;
	PLINKED_LIST FirstLink;

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

	if(InputBufferLength >= sizeof(PCIDP00_UNMAP_DMA_SEND)){
		if(ObjExt->MDL){
			MmUnmapLockedPages((PVOID)IoInput->LinearAddress, ObjExt->MDL);
			NTStatus = STATUS_SUCCESS;

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

			// Cancel the CancelMapDMA pending irp.
			CurrentLink = NULL;
			FirstLink = NULL;
			while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &RegisteredInt) == TRUE){

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

				if(IoInput->LinearAddress == RegisteredInt->Type){

					// Found an entry.  Disable the cancel routine, complete the I/O for
					// this IRP, then delete the linked	list entry.
					IoAcquireCancelSpinLock (&CancelSpin);
					IoSetCancelRoutine(RegisteredInt->Irp, NULL);
					IoReleaseCancelSpinLock (CancelSpin);
					//IoReleaseCancelSpinLock (RegisteredInt->Irp->CancelIrql);
					RegisteredInt->Irp->IoStatus.Status = STATUS_SUCCESS ;
					RegisteredInt->Irp->IoStatus.Information = 0 ;
					IoCompleteRequest(RegisteredInt->Irp, IO_NO_INCREMENT);

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

					FreeEntry(ObjExt, CurrentLink);
				}
				else
					PutBackEntry(ObjExt, CurrentLink);
			}
		}
		else
			NTStatus = STATUS_NO_MEMORY;

	}
	else
		NTStatus = STATUS_INVALID_BUFFER_SIZE;

	Irp->IoStatus.Status = NTStatus;
}



// ----------------------------------------------------------------------------
// PCIDPGetPCIRegs
// ----------------------------------------------------------------------------
VOID PCIDPGetPCIRegs(
	IN PDEVICE_OBJECT DeviceObject,
	IN PFILE_OBJECT FileObject,
	IN OUT PIRP Irp,
	OUT PVOID IoBuffer,
	IN ULONG OutputBufferLength
){

	// Define variables.
	NTSTATUS NTStatus;
	PPCIDP_EXTENSION ObjExt;
	PIO_STACK_LOCATION NextIrpStack;

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

	// Check for adequate output buffer space.
	if(OutputBufferLength >= sizeof(PCIDP00_GET_PCI_CONFIG_REGS_RECV)){

		// Now get the PCI register space.
		NextIrpStack = IoGetNextIrpStackLocation(Irp);
		NextIrpStack->MajorFunction = IRP_MJ_PNP;
		NextIrpStack->MinorFunction = IRP_MN_READ_CONFIG;
		NextIrpStack->Flags = 0;
		NextIrpStack->Parameters.ReadWriteConfig.WhichSpace = 0;
		NextIrpStack->Parameters.ReadWriteConfig.Buffer = IoBuffer;
		NextIrpStack->Parameters.ReadWriteConfig.Offset = 0;
		NextIrpStack->Parameters.ReadWriteConfig.Length = OutputBufferLength;
		NextIrpStack->DeviceObject = ObjExt->NextLowerDeviceObject;
		NextIrpStack->FileObject = FileObject;

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

	else{
		NTStatus = STATUS_INVALID_BUFFER_SIZE;
		Irp->IoStatus.Status = NTStatus;
		Irp->IoStatus.Information = 0;
	}
}



// ----------------------------------------------------------------------------
// PCIDPSetPCIRegs
// ----------------------------------------------------------------------------
VOID PCIDPSetPCIRegs(
	IN PDEVICE_OBJECT DeviceObject,
	IN PFILE_OBJECT FileObject,
	IN OUT PIRP Irp,
	IN PVOID IoBuffer,
  IN ULONG InputBufferLength
){

	// Define variables.
	NTSTATUS NTStatus;
	PPCIDP_EXTENSION ObjExt;
	PIO_STACK_LOCATION NextIrpStack;

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

	// Check for adequate input buffer space.
	if(InputBufferLength >= sizeof(PCIDP00_SET_PCI_CONFIG_REGS_SEND)){

		// Now set the PCI register space.
		NextIrpStack = IoGetNextIrpStackLocation(Irp);
		NextIrpStack->MajorFunction = IRP_MJ_PNP;
		NextIrpStack->MinorFunction = IRP_MN_WRITE_CONFIG;
		NextIrpStack->Flags = 0;
		NextIrpStack->Parameters.ReadWriteConfig.WhichSpace = 0;
		NextIrpStack->Parameters.ReadWriteConfig.Buffer = IoBuffer;
		NextIrpStack->Parameters.ReadWriteConfig.Offset = 0;
		NextIrpStack->Parameters.ReadWriteConfig.Length = InputBufferLength;
		NextIrpStack->DeviceObject = ObjExt->NextLowerDeviceObject;
		NextIrpStack->FileObject = FileObject;

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

	else{
		NTStatus = STATUS_INVALID_BUFFER_SIZE;
		Irp->IoStatus.Status = NTStatus;
		Irp->IoStatus.Information = 0;
	}
}



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

	// Define variables.
	NTSTATUS NTStatus;
	PPCIDP00_REGISTER_INTERRUPT_SEND IoInput;
	PPCIDP_EXTENSION ObjExt;
	KIRQL CancelSpin;
	PULONG MemoryBase;
  PLINKED_LIST LLEntry;
	ULONG Type;
	ULONG HINTPattern;

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

	// Check that call was made via the PCIDP API.
	if((IoInput->InterruptType & 0xF0C00000) != 0xF0C00000){
		NTStatus = STATUS_ACCESS_DENIED;
		goto ExitA;
	}
	Type = IoInput->InterruptType & 0x000003FF;

	// Check to make sure the board has the interrupt pin enabled.
	if(ObjExt->InterruptObject == 0){
		NTStatus = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
		goto ExitA;
	}

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

	// Check for a valid interrupt type.
	switch(Type){
	case PCIMasterAbort:
	case PCITargetAbort:
	case I2OOutboundPostFIFONotEmpty:
	case DMAComplete:
	case LocalToHostExternalSignal:
	case LocalToHostMailbox:
	case I2OPCIFIFOOverflow:
		break;

	default:
		NTStatus = STATUS_INVALID_PARAMETER;
		goto ExitA;
	}

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

		// Set up a cancel routine and mark the IRP pending.
		IoMarkIrpPending (Irp);
		IoAcquireCancelSpinLock (&CancelSpin);
		IoSetCancelRoutine (Irp, PCIDPCancelInterrupt);
		IoReleaseCancelSpinLock (CancelSpin);

		// Add this IRP to the linked list
		LLEntry->RegisteredInterrupt.Irp = Irp;
		LLEntry->RegisteredInterrupt.Type = Type;
		InsertEntry(ObjExt, LLEntry);

		// Enable the interrupt on the board and clear the status bit.
		HINTPattern = MemoryBase[HINT] & 0xFFFF0000;	//get enabled ints
		HINTPattern |= Type;					//bit to clear status
		HINTPattern |= (Type << 16);	//bit to enable the interrupt
		MemoryBase[HINT] = HINTPattern;

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

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



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

	// Define variables.
	NTSTATUS NTStatus;
	PPCIDP00_UNREGISTER_INTERRUPT_SEND IoInput;
	PPCIDP_EXTENSION ObjExt;
	KIRQL CancelSpin;
	PULONG MemoryBase;
	PREGISTERED_INTERRUPT Interrupt;
	PIO_STACK_LOCATION ThisIrpStack;
	PIO_STACK_LOCATION LLIrpStack;
	PLINKED_LIST CurrentLink;
	PLINKED_LIST FirstLink;
	ULONG Count;
	ULONG Type;

	// Initialize variables.
	IoInput = (PPCIDP00_UNREGISTER_INTERRUPT_SEND)IoBuffer;
	ObjExt = (PPCIDP_EXTENSION)DeviceObject->DeviceExtension;
	MemoryBase = ObjExt->MemoryBase;
	Count = 0;

	// Check that call was made via the PCIDP API.
	if((IoInput->InterruptType & 0xF0C00000) != 0xF0C00000){
		NTStatus = STATUS_ACCESS_DENIED;
		goto ExitA;
	}
	Type = IoInput->InterruptType & 0x000003FF;

	// Check to make sure the board has the interrupt pin enabled.
	if(ObjExt->InterruptObject == 0){
		NTStatus = STATUS_BIOS_FAILED_TO_CONNECT_INTERRUPT;
		goto ExitA;
	}

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

	// Check for a valid interrupt type.
	switch(Type){
	case PCIMasterAbort:
	case PCITargetAbort:
	case I2OOutboundPostFIFONotEmpty:
	case DMAComplete:
	case LocalToHostExternalSignal:
	case LocalToHostMailbox:
	case I2OPCIFIFOOverflow:
		break;

	default:
		NTStatus = STATUS_INVALID_PARAMETER;
		goto ExitA;
	}


	// Search the driver's events linked list for an an entry containing the 
	// user provided interrupt type.
	NTStatus = STATUS_SUCCESS;
	ThisIrpStack = IoGetCurrentIrpStackLocation(Irp);

	CurrentLink = NULL;
	FirstLink = NULL;
	while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &Interrupt) == TRUE){
		if(Type == Interrupt->Type){
			Count++;
			LLIrpStack = IoGetCurrentIrpStackLocation(Interrupt->Irp);

			// Cancel the IRP, then delete its linked list entry.
			if (LLIrpStack->FileObject == ThisIrpStack->FileObject) {
				IoAcquireCancelSpinLock (&CancelSpin);
				Interrupt->Irp->Cancel = TRUE;
				Interrupt->Irp->CancelIrql = CancelSpin;
				Interrupt->Irp->CancelRoutine = NULL;
				Interrupt->Irp->IoStatus.Status = STATUS_CANCELLED;
				Interrupt->Irp->IoStatus.Information = 0;
				IoReleaseCancelSpinLock (CancelSpin);

				IoCompleteRequest(Interrupt->Irp, IO_NO_INCREMENT);

				FreeEntry(ObjExt, CurrentLink);
			}
			else
				PutBackEntry(ObjExt, CurrentLink);
		}
		else
			PutBackEntry(ObjExt, CurrentLink);
	}

	// Disable the interrupt type if no other thread is currently
	// registered.
	if(Count == 1)
		MemoryBase[HINT] &= (~Type) << 16;
		

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



⌨️ 快捷键说明

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