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

📄 pcibridge.c

📁 用C语言设计的EPSON LCD控制器S1D13700驱动。
💻 C
字号:
//===========================================================================
//	PCIBRIDGE.C
//---------------------------------------------------------------------------
//
//  Copyright (c) 2002 Epson Research and Development, Inc.
//  All Rights Reserved.
//
//===========================================================================

#include <stdlib.h>
#include "datatype.h"
#include "pcibridge.h"

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma warning( disable : 4201 )	// Disable "nameless struct/union" warning in winioctl.h.
#include <winioctl.h>
#include "s1d_ioctl.h"




static int			gLastError;				// PCIBridge last error code
static HANDLE		ghPCIDriver;			// Handle to PCI driver
static UInt32		gPCIAddress;			// Pointer to PCI memory

static ISR_STRUCT	gISRInfo;				// Interrupt Service Routine info passed to PCI driver
static DWORD		ghISRId;				// Handle to driver-returned ISR ID (0-31)

static PISR_CALLBACK gpISRCallback;			// Application supplied callback function
static Boolean		gfISRHooked;			// True if device driver has hooked ISR




static void		UnhookInterrupt( void );
static Boolean	DispatchPCIInterrupt( LPVOID hISREvent );




//---------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibMapAddress()
//---------------------------------------------------------------------------
int pcibMapAddress( UInt32 PhysicalAddr, UInt32 *pVirtualAddr, UInt32 *pBlockSize )
{
	BOOL	fRet;
	DWORD	nReturned;
	UInt32	aRetPCI[3];

	gLastError = PCIB_ERR_NONE;

	// Free and release driver, if one's currently in use.  This makes
	// this function and halAquireController() fully rentrant so they
	// can be called multiple times, if required by the application.

	pcibUnmapAddress();

	// Determine the operating system we are running under and act accordingly.

	if ( GetVersion() < 0x80000000 )	// Open the device using NT semantics.
		ghPCIDriver = CreateFile( "\\\\.\\S1D13xxx", GENERIC_READ | GENERIC_WRITE,	0, NULL, OPEN_EXISTING,	FILE_FLAG_OVERLAPPED,		NULL );
	else								// Open the device using Win9x semantics.
		ghPCIDriver = CreateFile( "\\\\.\\S1D13xxx.VXD", 0,							0, NULL, CREATE_NEW,	FILE_FLAG_DELETE_ON_CLOSE,	NULL );

	// If we have an invalid handle then we couldn't open the driver.

	if ( ghPCIDriver != INVALID_HANDLE_VALUE )
	{
		OVERLAPPED OverLapped;
		ZeroMemory( &OverLapped, sizeof(OverLapped) );

		if ( PhysicalAddr == 0 )		// Map in a PCI Board
		{
			char Buffer[32];
			int boardnum = 0;

			// Check the environment for: S1DBOARD=n
			// This is for rare situations where there are multiple PCI boards and a command prompt window
			// can be assigned to a particular PCI board using the environment variable.

			if ( GetEnvironmentVariable("S1DBOARD",Buffer,sizeof(Buffer)) )
				boardnum = atoi( Buffer );

			// Get virtual address into our PCI array ([0]=virtual, [1]=physical, [2]=blocksize (future))

			fRet = DeviceIoControl( ghPCIDriver, IOCTL_SED_MAP_PCI_BOARD, &boardnum, sizeof(boardnum), aRetPCI, sizeof(aRetPCI), &nReturned, &OverLapped );
			gPCIAddress = aRetPCI[0];
		}
		else							// The user insists on a particular physical address
		{
			aRetPCI[0] = PhysicalAddr;
			aRetPCI[1] = ISA_BLOCK_SIZE;
			fRet = DeviceIoControl( ghPCIDriver, IOCTL_SED_MAP_PHYSICAL_MEMORY, aRetPCI, sizeof(aRetPCI), &gPCIAddress, sizeof(gPCIAddress), &nReturned, &OverLapped );
		}

		if ( fRet )
		{
			if ( pVirtualAddr )
				*pVirtualAddr = gPCIAddress;

			if ( pBlockSize )
            {
				if ( nReturned > 2*sizeof(aRetPCI[0]) )
                    *pBlockSize = aRetPCI[2];
                else
				    *pBlockSize = PCI_BLOCK_SIZE;
            }
		}
		else
		{
			gPCIAddress = 0;
			gLastError = PCIE_ERR_ADAPTER_NOT_FOUND;
		}
	}
	else
	{
		ghPCIDriver = NULL;
		gLastError = PCIB_ERR_DRIVER_NOT_FOUND;
	}

	return (gLastError == PCIB_ERR_NONE);
}



//---------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibUnmapAddress()
//---------------------------------------------------------------------------
void pcibUnmapAddress( void )
{
	DWORD nReturned;

	// Free up any active interrupt objects to ensure handles are sync'd with resources.

	UnhookInterrupt();

	// Only free up these resources, if they are currently allocated and in use.

	if ( ghPCIDriver )
	{
		// We already have a handle to the driver and the memory we wish to free.
		// Simply call the driver with the appropriate values to free the our memory.

		if ( gPCIAddress )
		{
			OVERLAPPED OverLapped;
			ZeroMemory( &OverLapped, sizeof(OverLapped) );

			DeviceIoControl( ghPCIDriver, IOCTL_SED_UNMAP_LINEAR_MEMORY, &gPCIAddress, sizeof(gPCIAddress), NULL, 0, &nReturned, &OverLapped );
			gPCIAddress = 0;
		}

		// Close the handle. This also dynamically UNLOADs the driver under Win9x.

		CloseHandle( ghPCIDriver );
		ghPCIDriver = NULL;
	}
}



//---------------------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibAddInterruptRegister()
//---------------------------------------------------------------------------------------
Boolean pcibAddInterruptRegister( UInt32 EnableRegOffset, UInt32 StatusRegOffset, UInt32 BitMask, UInt32 AccessSize, Boolean fRawStatus )
{
	gLastError = PCIB_ERR_NONE;

	if ( gISRInfo.nIntInfoItems < MAX_INT_REGS )
	{
		INT_STRUCT *pIntInfo = &gISRInfo.aIntInfo[gISRInfo.nIntInfoItems];

		// Set our process ID if this is the first time here.

		if ( gISRInfo.nIntInfoItems == 0 )
			gISRInfo.dwProcessID = GetCurrentProcessId();

		// Add this interrupt register information to interrupt register array.

		pIntInfo->EnableReg	= EnableRegOffset;
		pIntInfo->StatusReg	= StatusRegOffset;
		pIntInfo->BitMask	= BitMask;
		pIntInfo->AccessSize= AccessSize;
		pIntInfo->Flags		= (fRawStatus) ? INTFLAG_RAWSTATUS : INTFLAG_NONE;

		gISRInfo.nIntInfoItems++;
	}
	else
		gLastError = PCIB_ERR_IRQ_FAILURE;

	return (gLastError == PCIB_ERR_NONE);
}



//---------------------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibHookInterrupt()
//---------------------------------------------------------------------------------------
Boolean pcibHookInterrupt( PISR_CALLBACK pISRCallback )
{
	DWORD		nReturned;

	gLastError = PCIB_ERR_NONE;

	// If the PCI driver has not been acquired, exit with an error.

	if ( !ghPCIDriver )
	{
		gLastError = PCIB_ERR_ADAPTER_NOT_MAPPED;
		return FALSE;
	}

	// If the caller passes a NULL callback, kill the ISR hook and return successful.

	if ( pISRCallback == NULL )
	{
		UnhookInterrupt();
		return TRUE;
	}

	// If an ISR is already hooked and active, allow the caller to change the callback ISR.

	if ( gfISRHooked )
	{
		gpISRCallback = pISRCallback;
		return TRUE;
	}

	gLastError = PCIB_ERR_IRQ_FAILURE;								// Assume code below fails, set to no error is everything is OK.

	// Now, ask the driver to hook in the new ISR callback.

	gfISRHooked = DeviceIoControl( ghPCIDriver, IOCTL_SED_HOOK_ISR_CALLBACK, (LPVOID)&gISRInfo, sizeof(gISRInfo), &ghISRId, sizeof(ghISRId), &nReturned, NULL );

	if ( gfISRHooked )
	{
		HANDLE	 hISREvent;				// ISR thread completion/unblock event

		// Create the ISR complete/unblock event handle.

		hISREvent = CreateEvent( NULL, TRUE, FALSE, NULL );		// Manual reset, Initial State = non-signaled, Unnamed object

		if ( hISREvent )
		{
			HANDLE	hISRThread;				// Thread handle to ISR dispatcher code
			DWORD	dwISRThreadId;			// Thread ID of ISR dispatcher code

			gpISRCallback = pISRCallback;

			// Create the ISR dispatcher thread itself.
			// (handle cannot be inherited, use default stack size, pass event handle to thread, thread to run immediately).

			hISRThread = CreateThread( NULL, 0, (LPTHREAD_START_ROUTINE)DispatchPCIInterrupt, hISREvent, 0, &dwISRThreadId );

			if ( hISRThread )
			{
				// Raise the thread priority up to "very high".

				SetThreadPriority( hISRThread, THREAD_PRIORITY_TIME_CRITICAL );	// DSM FIXIT: Juro says not needed???
				CloseHandle( hISRThread );					// Release the thread handle.
				gLastError = PCIB_ERR_NONE;							// Flag that everything is OK.
			}
			else
				CloseHandle( hISREvent );
		}
	}

	if ( gLastError != PCIB_ERR_NONE )
		UnhookInterrupt();

	return (gLastError == PCIB_ERR_NONE);
}



//---------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibGetLastError() - Get last error code.
//---------------------------------------------------------------------------
int pcibGetLastError( void )
{
	return gLastError;
}



//---------------------------------------------------------------------------
// PUBLIC FUNCTION: pcibGetLastErrorText() - Get last error text.
//---------------------------------------------------------------------------
const char * pcibGetLastErrorText( void )
{
	static const char * const apszErrors[] =
	{
		"No error",					// PCIB_ERR_NONE
		"Adapter not found",		// PCIE_ERR_ADAPTER_NOT_FOUND
		"Driver not found",			// PCIB_ERR_DRIVER_NOT_FOUND
		"IRQ failure",				// PCIB_ERR_IRQ_FAILURE
		"Adapter not mapped",		// PCIB_ERR_ADAPTER_NOT_MAPPED
		"Unknown error"				// PCIB_ERR_UNKNOWN_ERROR - MUST BE LAST!!!
	};

	if ( gLastError < 0 || gLastError > PCIB_ERR_UNKNOWN_ERROR )
		return apszErrors[PCIB_ERR_UNKNOWN_ERROR];

	return apszErrors[gLastError];
}




//---------------------------------------------------------------------------
// PRIVATE FUNCTION: UnhookInterrupt()
//---------------------------------------------------------------------------
static void UnhookInterrupt( void )
{
	DWORD		nReturned;

	// Remove the active application ISR callback, if any.

	gpISRCallback = NULL;

	// If the ISR is still hooked, ask the driver to take it down.

	if ( gfISRHooked )
	{
		gfISRHooked = FALSE;

		// There is previously hooked ISR, ask the driver to unhook it if the driver is still alive.
		if ( ghPCIDriver )
			DeviceIoControl( ghPCIDriver, IOCTL_SED_UNHOOK_ISR_CALLBACK, (LPVOID)&gISRInfo, sizeof(gISRInfo), &ghISRId, sizeof(ghISRId), &nReturned, NULL );
	}
}



//---------------------------------------------------------------------------
// PRIVATE FUNCTION: DispatchPCIInterrupt()
//---------------------------------------------------------------------------
static Boolean DispatchPCIInterrupt( LPVOID hISREvent )
{
	DWORD			nReturned;
	OVERLAPPED		OverLapped;

	OverLapped.hEvent		= (HANDLE)hISREvent;
	OverLapped.Offset		= 0;
	OverLapped.OffsetHigh	= 0;

	while ( gfISRHooked )
	{
		if ( !WriteFile(ghPCIDriver, &ghISRId, sizeof(ghISRId), &nReturned, &OverLapped) )
		{
			if ( GetLastError() != ERROR_IO_PENDING )
				continue;

			WaitForSingleObject( OverLapped.hEvent, INFINITE );
			ResetEvent( OverLapped.hEvent );
		}

		if ( !gfISRHooked )
			break;

		if ( gpISRCallback )
			gpISRCallback();
	}

	CloseHandle( OverLapped.hEvent );

	return TRUE;
}

⌨️ 快捷键说明

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