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

📄 pcidpplugnplay.c

📁 一个amccs5933芯片的驱动程序开发源程序和部分文档
💻 C
字号:
//*****************************************************************************
// 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 PCIDPPlugNPlay.c.  It contains the dynamic loading functionality
// of the VxD as well as the Win32 interface to the services.



#pragma code_seg("_LTEXT")	//match PCIDP assembly module code segment
#pragma data_seg("_LDATA")	//match PCIDP assembly module data segment


#define _DECLARE_GLOBALS_
#include "PCIDPInc.h"
#undef _DECLARE_GLOBALS_

#include "Pci.h"
#include "pcidp.h"


unsigned long DeviceIocontrol(PDIOCPARAMETERS Params){

	unsigned long ReturnStatus;

	Params->lpcbBytesReturned = 0;	//start out with no return data.

	switch (Params->dwIoControlCode){

	case DIOC_OPEN:					//invoked when ring 3 calls CreateFile
		ReturnStatus = 0;			//success
		break;

	case DIOC_CLOSEHANDLE:	//invoked with ring 3 calls CloseHandle
		ReturnStatus = 0;			//success
		break;

	case IOCTL_PCIDP00_MAP_BASE_REGS:
		ReturnStatus = PCIDPMapBaseRegs(Params);
		break;

	case IOCTL_PCIDP00_UNMAP:
		ReturnStatus = PCIDPUnMap(Params);
		break;

	case IOCTL_PCIDP00_MAP_DMA_MEM:
		ReturnStatus = PCIDPMapDMAMem(Params);
		break;

	case IOCTL_PCIDP00_UNMAP_DMA:
		ReturnStatus = PCIDPUnMapDMA(Params);
		break;

	case IOCTL_PCIDP00_GET_PCI_CONFIG_REGS:
		ReturnStatus = PCIDPGetPCIRegs(Params);
		break;

	case IOCTL_PCIDP00_SET_PCI_CONFIG_REGS:
		ReturnStatus = PCIDPSetPCIRegs(Params);
		break;

	case IOCTL_PCIDP00_REGISTER_INTERRUPT:
		ReturnStatus = PCIDPRegisterInterrupt(Params);
		break;

	case IOCTL_PCIDP00_UNREGISTER_INTERRUPT:
		ReturnStatus = PCIDPUnregisterInterrupt(Params);
		break;

	case IOCTL_PCIDP00_HELLO:
		ReturnStatus = PCIDPHello(Params);
		break;

	case IOCTL_PCIDP00_GET_VERSION:
		ReturnStatus = PCIDPGetDriverVersion(Params);
		break;

	default:
		ReturnStatus = ERROR_INVALID_FUNCTION;
		break;
	}

	return ReturnStatus;
}


unsigned long PnPNewDevice(
	unsigned long Devnode,
	unsigned long LoadType
){

	unsigned long	ReturnStatus = CR_OUT_OF_MEMORY;
	int i;
	PCI_COMMON_CONFIG CardInfo;


	switch (LoadType){

	// The VxD loader has a PCIDP board for the driver to bind with.
	case DLVXD_LOAD_DRIVER:

		// Loop until we a find an empty driver object extension.
		for(i=0; i<BoardLimit; i++){

			// Found one.  Allocate some memory for the extension.
			if(ObjExt[i] == 0){

				ObjExt[i] = (PVOID)_HeapAllocate(sizeof(PCIDP_EXTENSION), HEAPZEROINIT);
				if(ObjExt[i] == 0) break;	//skip out if it fails
				ObjExt[i]->Devnode = Devnode;
				ObjExt[i]->LLData.IsEmpty = TRUE;
				ObjExt[i]->LLData.CurrentLink = NULL;
				ObjExt[i]->LLData.InsertedCount = 0;
				ObjExt[i]->LLData.FreeMax = 0;
				//ObjExt->InterruptObject - initialized in PnPStart

				ReturnStatus = CM_Call_Enumerator_Function(
					Devnode, 
					PCI_ENUM_FUNC_GET_DEVICE_INFO,
					0,
					&CardInfo,
					sizeof(CardInfo),
					0
				);
				if(ReturnStatus != CR_SUCCESS) break;

				// Save some PCI configuration data in the device object extension
				ObjExt[i]->BaseAddresses[0] = CardInfo.u.type0.BaseAddresses[0];
				ObjExt[i]->BaseAddresses[1] = CardInfo.u.type0.BaseAddresses[1];
				ObjExt[i]->BaseAddresses[2] = CardInfo.u.type0.BaseAddresses[2];
				ObjExt[i]->BaseAddresses[3] = CardInfo.u.type0.BaseAddresses[3];
				ObjExt[i]->BaseAddresses[4] = CardInfo.u.type0.BaseAddresses[4];
				ObjExt[i]->BaseAddresses[5] = CardInfo.u.type0.BaseAddresses[5];
				ObjExt[i]->IOBase = (CardInfo.u.type0.BaseAddresses[1] & 0xFFFFFFFE);

				// Set up the IRQ resource.
				if(CardInfo.u.type0.InterruptPin != 0){
					ObjExt[i]->InterruptObject = 1;	//interrupt is available to register
				}
				else
					ObjExt[i]->InterruptObject = 0;	//no interrupt available to register

				// Now register this driver as the PnP handler for the PCIDP board.
				ReturnStatus = CM_Register_Device_Driver(
					Devnode, 
					PnPHandler, 
					(ULONG) ObjExt[i], 
					CM_REGISTER_DEVICE_DRIVER_DISABLEABLE | 
					CM_REGISTER_DEVICE_DRIVER_REMOVABLE
				);
				if(ReturnStatus != CR_SUCCESS) break;
					
				// To get here means we were successful in the set up so break out.
				break;
			}
		}

		// The registration failed, deallocate the object extension and return
		// empty handed.
    if(ReturnStatus != CR_SUCCESS && ObjExt[i] != 0){
			_HeapFree((PVOID)ObjExt[i], 0);
			ObjExt[i] = 0;
		}
 
		break;

	default:
		ReturnStatus = CR_DEFAULT;
		break;
	}

	return ReturnStatus;
}


CONFIGRET CM_HANDLER PnPHandler(
	CONFIGFUNC Function, 
	SUBCONFIGFUNC SubFunction, 
	DEVNODE Devnode, 
	DWORD RefData, 
	ULONG Flags
){

	CONFIGRET ReturnStatus;

	switch (Function){

	// Do not grant permission to invalidate or remove device node.
	case CONFIG_TEST:
		ReturnStatus = CR_FAILURE;
		break;

	// Accept whatever resources are provided.
	case CONFIG_FILTER:
		ReturnStatus = CR_SUCCESS;
		break;
		
	// There are no children to enumerate.
	case CONFIG_ENUMERATE:
		ReturnStatus = CR_SUCCESS;
		break;
		
	// Can't argue with this one, system shutting down.
	case CONFIG_REMOVE:
		ReturnStatus = PnPStop(Devnode);
		break;

	case CONFIG_START:
		ReturnStatus = PnPStart(Devnode);
		break;

	// Shouldn't get this one, but if so same as a shutdown.
	case CONFIG_STOP:
		ReturnStatus = PnPStop(Devnode);
		break;

	// Any others (there shouldn't be).
	default:
		ReturnStatus = CR_DEFAULT;
	}

	return ReturnStatus;
}


CONFIGRET PnPStart(DEVNODE Devnode){

	CONFIGRET ReturnStatus;
  CMCONFIG Config;
	unsigned long LinearAddress;
	unsigned long PhysicalAddress;
	VID IRQDesc;
	
	int Node = FindIndex(Devnode);
	if(Node == -1){
		ReturnStatus = CR_INVALID_DEVNODE;
		goto ExitPnpStart;
	}

	// Now get the allocated resources.
  ReturnStatus = CM_Get_Alloc_Log_Conf(
		&Config, 
		Devnode,
		CM_GET_ALLOC_LOG_CONF_ALLOC
	);
	if(ReturnStatus != CR_SUCCESS)
		goto ExitPnpStart;
		
	// Map to the board's shared memory and register space for use
	// within other services.  No sense loading the driver if we
	// can't map.
	if(Config.wNumMemWindows == 0){
		ReturnStatus = CR_OUT_OF_MEMORY;
		goto ExitPnpStart;
	}

	LinearAddress = (unsigned long)_MapPhysToLinear(
		Config.dMemBase[0],
		Config.dMemLength[0],
		0
	);
	if(LinearAddress == -1){
		ObjExt[Node]->MemoryBase = 0;
		ReturnStatus = CR_FAILURE;
		goto ExitPnpStart;
	}
	else
		ObjExt[Node]->MemoryBase = (unsigned long*)LinearAddress;

	// Allocate 16K (4 pages) of contiguous memory for DMA operations.
	// Failure to do so means the driver cannot support DMA transfers 
	// (which is reported to the user at the API level).
	PhysicalAddress = _PageCommitContig(
		0,					//ignored since no linear address need be associated 
		4,					//number of pages 
		PCC_NOLIN,	//no linear address space associated with this memory 
		0,					//4K alignment 
		0,					//no address restrictions
		-1					//no address restrictions
	);
	if(PhysicalAddress == -1)
		PhysicalAddress = 0;

	// Save the physical address for use with the Map DMA service.
	ObjExt[Node]->PhysicalDMAAddress = PhysicalAddress;

	// Register the interrupt.
	if(ObjExt[Node]->InterruptObject == 1 && Config.wNumIRQs){

		// Set up the structure to pass to VPICD_Virtualize_IRQ
		IRQDesc.VID_IRQ_Number = Config.bIRQRegisters[0];
		IRQDesc.VID_Options = VPICD_OPT_CAN_SHARE | VPICD_OPT_REF_DATA;
		IRQDesc.VID_Hw_Int_Proc =	(DWORD)PCIDPISR;
		IRQDesc.VID_EOI_Proc = 0;
		IRQDesc.VID_Virt_Int_Proc = 0;
		IRQDesc.VID_Mask_Change_Proc = 0;
		IRQDesc.VID_IRET_Proc = 0;
		IRQDesc.VID_IRET_Time_Out = 500;
		IRQDesc.VID_Hw_Int_Ref = (ULONG)ObjExt[Node];

		// Now pass the structure to VPICD and get back the IRQ handle.
		ObjExt[Node]->InterruptObject = VPICD_Virtualize_IRQ(&IRQDesc);

		// Make sure the IRQ is unmasked on the PIC. Otherwise, the interrupt
		// will never occur.
		if(ObjExt[Node]->InterruptObject)
			VPICD_Physically_Unmask(ObjExt[Node]->InterruptObject);
		
	}
	else
		ObjExt[Node]->InterruptObject = 0;


ExitPnpStart:
	return ReturnStatus;
}


CONFIGRET PnPStop(DEVNODE Devnode){

	int i;
	pREGISTERED_INTERRUPT RegisteredInt;
	pLINKED_LIST CurrentLink;
	pLINKED_LIST FirstLink;
	unsigned long LinearAddress;
	int Node = FindIndex(Devnode);

	if(Node != -1){

		// Close all ring 0 events.
		CurrentLink = NULL;
		FirstLink = NULL;
		while(GetNextEntry(ObjExt[Node], &FirstLink, &CurrentLink, &RegisteredInt) == TRUE){
			VWIN32_CloseVxDHandleW(RegisteredInt->Event);
			PutBackEntry(ObjExt[Node], CurrentLink);
		}

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

		// Unvirtualize the IRQ.
		if(ObjExt[Node]->InterruptObject)
			VPICD_Force_Default_Behavior(ObjExt[Node]->InterruptObject);

		// Deallocate the DMA space.
		// Nothing to do. The space is allocated for the life of the system.

		// Unmap from the board's shared memory and register space.
		// Nothing to do. The linear address space is allocated for the life
		// of the system.

		// Lastly, deallocate the device object extension.
		_HeapFree((PVOID)ObjExt[Node], 0);
		ObjExt[Node] = 0;
	}

	return CR_SUCCESS;
}


unsigned long PCIDPISR_C(
	unsigned long IRQHandle,
	unsigned long HWRefData
){
	
	unsigned long Status;
	pPCIDP_EXTENSION ObjExt = (pPCIDP_EXTENSION)HWRefData;
	pINTERRUPT_DATA IntData;
	PULONG MemoryBase;
	ULONG HINTStatusReg;

	// Check the masked HINT for an active interrupt.  If it's not set, 
	// the PCIDP card did not cause the interrupt, so exit quick.
	MemoryBase = ObjExt->MemoryBase;

	// Debug
	//MemoryBase[0x1010]++;

	HINTStatusReg = MemoryBase[HINT] & 0x03FF;
	if(HINTStatusReg == 0){

		// Debug
		//MemoryBase[0x1011]++;

		Status = 0;
		goto ExitA;
	}

	// Initialize variables.
	IntData = &ObjExt->InterruptData;

	// This board caused the interrupt. Now determine what type of interrupt
	// was triggered.
	if(HINTStatusReg & PCIMasterAbort){
		IntData->Type[IntData->QueNext] = PCIMasterAbort;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	if(HINTStatusReg & PCITargetAbort){
		IntData->Type[IntData->QueNext] = PCITargetAbort;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	if(HINTStatusReg & I2OOutboundPostFIFONotEmpty){
		IntData->Type[IntData->QueNext] = I2OOutboundPostFIFONotEmpty;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	if(HINTStatusReg & DMAComplete){
		IntData->Type[IntData->QueNext] = DMAComplete;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;

		// Debug
		//MemoryBase[0x1012]++;

	}

	if(HINTStatusReg & LocalToHostExternalSignal){
		IntData->Type[IntData->QueNext] = LocalToHostExternalSignal;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	if(HINTStatusReg & LocalToHostMailbox){
		IntData->Type[IntData->QueNext] = LocalToHostMailbox;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	if(HINTStatusReg & I2OPCIFIFOOverflow){
		IntData->Type[IntData->QueNext] = I2OPCIFIFOOverflow;
		IntData->QueNext++;
		if(IntData->QueNext == InterruptQueSize) IntData->QueNext = 0;
	}

	// Clear all set interrupts as indicated in the status part of the
	// HINT register while preserving the enabled part of the HINT.  This
	// is done by writing a 1 to each active bit which just happens to
	// be value in HINTStatusReg.
	MemoryBase[HINT] |= HINTStatusReg;

	// Lastly, request the defered interrupt handler be queued for processing.
	// This is done by setting Status to HWRefData (success) which tells PCIDPISR
	// (the caller to this routine) to finish up the interrupt handling. 
	Status = HWRefData;
	
	ExitA:
	return Status;
}


void PCIDPForDpcIsr_C(unsigned long HWRefData){

	pPCIDP_EXTENSION ObjExt = (pPCIDP_EXTENSION)HWRefData;
	pINTERRUPT_DATA IntData;
	pREGISTERED_INTERRUPT RegisteredInt;
	pLINKED_LIST CurrentLink;
	pLINKED_LIST FirstLink;

	// Debug
	//PULONG MemoryBase;

	// Initialize variables.
	IntData = &ObjExt->InterruptData;
	CurrentLink = NULL;
	FirstLink = NULL;


	// Debug
	//MemoryBase = ObjExt->MemoryBase;
	//MemoryBase[0x1013]++;

	//Service all of the recorded interrupts by checking to see if the interrupt 
	//type has been registered by the user.
	while(IntData->QueNew != IntData->QueNext){

		// Debug
		//MemoryBase[0x1014]++;

		while(GetNextEntry(ObjExt, &FirstLink, &CurrentLink, &RegisteredInt) == TRUE){

			// Debug
			//MemoryBase[0x1015]++;

			if(IntData->Type[IntData->QueNew] == RegisteredInt->Type){

				// Debug
				//MemoryBase[0x1016]++;

				// Found an entry.  Have the event flag signaled.
				VWIN32_SetWin32EventW(RegisteredInt->Event);
			}

			PutBackEntry(ObjExt, CurrentLink);
		}

		IntData->QueNew++;
		if(IntData->QueNew == InterruptQueSize) IntData->QueNew = 0;
	}
}


int FindIndex(DEVNODE Devnode){

	int i;

	for(i=0; i<BoardLimit; i++){
		if(ObjExt[i] != 0){
			if(ObjExt[i]->Devnode == Devnode)
				break;
		}
	}

	if(i<BoardLimit) return i;
	else return -1;
}



#pragma code_seg()
#pragma data_seg()

⌨️ 快捷键说明

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