📄 pcibridge.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 + -