📄 hal_platform.c
字号:
//===========================================================================
// HAL_PLATFORM.C
//---------------------------------------------------------------------------
//
// Copyright (c) 2002 Epson Research and Development, Inc.
// All Rights Reserved.
//
//===========================================================================
#include <stdlib.h>
#include "hal_private.h"
#include "hal_platform.h"
#include "pcibridge.h"
#if defined(_WIN32)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
static HANDLE ghHalMutex; // Process synchronization mutex handle
#ifdef HAL_SIMULATE
static HANDLE ghSharedMemory; // Handle to shared memory
static VOID *gpSharedMemory; // Pointer to shared memory
#endif
#elif defined(_MSDOS)
#include "dos32.h"
#endif
#define DEFAULT_BLOCK_SIZE 0x00400000UL // Total size of PCI virtual memory block
static void ExitHandler( void );
static int Pci2Hal( Boolean fPCIResult );
static UInt32 Get13xxxBaseAddress( Boolean fEnable );
static int AllocateSharedMemory( UInt32 PhysicalAddr, UInt32 *pVirtualAddr, UInt32 *pBlockSize );
static void FreeSharedMemory( void );
//----------------------------------------------------------------------------
// PLATFORM FUNCTION: halpDelayUS()
//----------------------------------------------------------------------------
Boolean halpDelayUS( UInt32 microseconds )
{
#ifdef _WIN32
static UInt32 NsPerTick = 0;
__int64 nanoseconds = microseconds*1000i64;
__int64 Count, Target;
// Init the ns/Tick constant if this is the first time here.
if ( !NsPerTick )
{
if ( QueryPerformanceFrequency((PLARGE_INTEGER)&Count) )
NsPerTick = (UInt32)(1000000000i64/Count);
else
return FALSE;
}
// Exit OK if requested delay is too short.
if ( nanoseconds < NsPerTick )
return TRUE;
// Get the starting initial counter value now.
if ( !QueryPerformanceCounter((PLARGE_INTEGER)&Target) )
return FALSE;
// Calculate the terminal count of ticks required for requested delay.
Target += nanoseconds/NsPerTick;
// Loop until the counter exceeds the number of ticks in the requested delay.
do
{
QueryPerformanceCounter( (PLARGE_INTEGER)&Count );
} while ( Count < Target );
return TRUE;
#elif defined(MV850E)
volatile UInt32 i;
volatile UInt32 adjust;
adjust = (microseconds * 10L) / 18L;
for (i = 0; i < adjust; ++i)
continue;
return TRUE;
#elif defined(_MSDOS)
UInt32 nTicks = (((microseconds+1UL)/2UL)*105UL)/(88UL/2UL);
dos32Delay838NS( nTicks );
return TRUE;
#else //_WIN32
#pragma message(">>>>> Function halpDelayUS() must be written for this platform. <<<<<")
return FALSE;
#endif
}
//---------------------------------------------------------------------------
// PLATFORM FUNCTION: halpMapPhysicalToVirtual()
//---------------------------------------------------------------------------
int halpMapPhysicalToVirtual( UInt32 PhysicalAddr, UInt32 *pVirtualAddr, UInt32 *pBlockSize )
{
static Boolean fExitHandler = FALSE;
// Always register the atexit routine at least once, so any allocated
// resources are guaranteed to be released and freed.
if ( !fExitHandler )
{
fExitHandler = TRUE;
atexit( ExitHandler );
}
#if defined(_WIN32)
#ifndef HAL_SIMULATE
return Pci2Hal( pcibMapAddress(PhysicalAddr,pVirtualAddr,pBlockSize) );
#else
return AllocateSharedMemory( PhysicalAddr, pVirtualAddr, pBlockSize );
#endif
#else
#if defined(_MSDOS)
{
MIDStruct MemData;
dos32Initialize( &MemData );
if ( MemData.fV86Mode || !MemData.fA20State )
return ERR_FAILED;
if ( !PhysicalAddr )
PhysicalAddr = Get13xxxBaseAddress( TRUE );
}
#endif
// On non-Windows system, a physical address of zero is bad karma.
if ( PhysicalAddr == 0 )
return ERR_FAILED;
if ( pVirtualAddr )
*pVirtualAddr = PhysicalAddr;
if ( pBlockSize )
*pBlockSize = DEFAULT_BLOCK_SIZE;
return ERR_NONE;
#endif
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpAddInterruptRegister()
//---------------------------------------------------------------------------------------
int halpAddInterruptRegister( UInt32 EnableReg, UInt32 StatusReg, UInt32 BitMask, UInt32 AccessSize, Boolean fRawStatus )
{
#ifdef _WIN32
#ifndef HAL_SIMULATE
EnableReg += HalInfo.dwRegisterOffset;
StatusReg += HalInfo.dwRegisterOffset;
return Pci2Hal( pcibAddInterruptRegister(EnableReg,StatusReg,BitMask,AccessSize,fRawStatus) );
#else
EnableReg, StatusReg, BitMask, AccessSize, fRawStatus;
return ERR_IRQ_FAILURE; // Not simulated.
#endif
#else
// On non-Windows system, new code to handle interrupts must be written.
#pragma message(">>>>> halpAddInterruptRegister() must be written for this platform. <<<<<")
return ERR_IRQ_FAILURE;
#endif
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpSetISRCallback()
//---------------------------------------------------------------------------------------
int halpSetISRCallback( void(*pISRCallback)(void) )
{
#ifdef _WIN32
#ifndef HAL_SIMULATE
return Pci2Hal( pcibHookInterrupt(pISRCallback) );
#else
pISRCallback;
return ERR_IRQ_FAILURE; // Not simulated.
#endif
#else
// On non-Windows system, new code to handle interrupts must be written.
#pragma message(">>>>> halpSetISRCallback() must be written for this platform. <<<<<")
return ERR_IRQ_FAILURE;
#endif
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpDirectRead()
//---------------------------------------------------------------------------------------
UInt32 halpDirectRead( int Size, UInt32 Address )
{
#if !defined(_MSDOS)
if ( Size == sizeof(UInt8) )
{
return *(pUInt8)Address;
}
else if ( Size == sizeof(UInt16) )
{
return *(pUInt16)Address;
}
else if ( Size == sizeof(UInt32) )
{
return *(pUInt32)Address;
}
#else //_MSDOS
if ( Size == sizeof(UInt8) || Size == sizeof(UInt16) || Size == sizeof(UInt32) )
{
return dos32ReadAbsolute( Address, Size );
}
#endif //_MSDOS
return 0;
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpDirectWrite()
//---------------------------------------------------------------------------------------
void halpDirectWrite( int Size, UInt32 Address, UInt32 Value, UInt32 Count )
{
if ( Count )
{
#if !defined(_MSDOS)
if ( Size == sizeof(UInt8) )
{
pUInt8 pWrite = (pUInt8)Address;
do
*pWrite++ = (UInt8)Value;
while ( --Count );
}
else if ( Size == sizeof(UInt16) )
{
pUInt16 pWrite = (pUInt16)Address;
do
*pWrite++ = (UInt16)Value;
while ( --Count );
}
else if ( Size == sizeof(UInt32) )
{
pUInt32 pWrite = (pUInt32)Address;
do
*pWrite++ = Value;
while ( --Count );
}
#else //_MSDOS
if ( Size == sizeof(UInt8) || Size == sizeof(UInt16) || Size == sizeof(UInt32) )
{
do
{
dos32WriteAbsolute( Address, Value, Size );
Address += Size;
}
while ( --Count );
}
#endif //_MSDOS
}
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpDirectReadData()
//---------------------------------------------------------------------------------------
void halpDirectReadData( int Size, UInt32 Address, void* pData, UInt32 Count )
{
if ( Count && pData )
{
#if !defined(_MSDOS)
if ( Size == sizeof(UInt8) )
{
pUInt8 pRead = (pUInt8)Address;
pUInt8 pWrite = pData;
do
*pWrite++ = *pRead++;
while ( --Count );
}
else if ( Size == sizeof(UInt16) )
{
pUInt16 pRead = (pUInt16)Address;
pUInt16 pWrite = pData;
do
*pWrite++ = *pRead++;
while ( --Count );
}
else if ( Size == sizeof(UInt32) )
{
pUInt32 pRead = (pUInt32)Address;
pUInt32 pWrite = pData;
do
*pWrite++ = *pRead++;
while ( --Count );
}
#else //_MSDOS
#pragma message(">>>>> halpDirectReadData() must be written for this platform. <<<<<")
#endif //_MSDOS
}
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpDirectWriteData()
//---------------------------------------------------------------------------------------
void halpDirectWriteData( int Size, UInt32 Address, const void* pData, UInt32 Count )
{
if ( Count && pData )
{
#if !defined(_MSDOS)
if ( Size == sizeof(UInt8) )
{
const UInt8* pRead = pData;
pUInt8 pWrite = (pUInt8)Address;
do
*pWrite++ = *pRead++;
while ( --Count );
}
else if ( Size == sizeof(UInt16) )
{
const UInt16* pRead = pData;
pUInt16 pWrite = (pUInt16)Address;
do
*pWrite++ = *pRead++;
while ( --Count );
}
else if ( Size == sizeof(UInt32) )
{
const UInt32* pRead = pData;
pUInt32 pWrite = (pUInt32)Address;
do
*pWrite++ = *pRead++;
while ( --Count );
}
#else //_MSDOS
#pragma message(">>>>> halpDirectWriteData() must be written for this platform. <<<<<")
#endif //_MSDOS
}
}
//---------------------------------------------------------------------------------------
// PLATFORM FUNCTION: halpSetProcessExclusivity()
//---------------------------------------------------------------------------------------
void halpSetProcessExclusivity( Boolean fExclusive )
{
#ifdef _WIN32
if ( fExclusive )
{
if ( !ghHalMutex )
ghHalMutex = CreateMutex( NULL, FALSE, HALCHIPID"HalMutex" );
if ( ghHalMutex )
WaitForSingleObject( ghHalMutex, INFINITE );
}
else
{
if ( ghHalMutex )
ReleaseMutex( ghHalMutex );
}
#else
#pragma message(">>>>> halpSetProcessExclusivity() must be written for this platform. <<<<<")
#endif
}
//---------------------------------------------------------------------------
// PRIVATE FUNCTION: ExitHandler() - Free up resources at exit time.
//---------------------------------------------------------------------------
static void ExitHandler( void )
{
#if defined(_WIN32)
#ifndef HAL_SIMULATE
pcibUnmapAddress();
#else
FreeSharedMemory();
#endif
if ( ghHalMutex )
CloseHandle( ghHalMutex ), ghHalMutex = NULL;
#elif defined(_MSDOS)
dos32Terminate();
#endif
}
#ifdef _WIN32
//---------------------------------------------------------------------------
// PRIVATE FUNCTION: Pci2Hal() - Map PCI to HAL return code. >>>WIN32 ONLY<<<
//---------------------------------------------------------------------------
static int Pci2Hal( Boolean fPCIResult )
{
int Result = ERR_NONE;
if ( !fPCIResult )
{
switch ( pcibGetLastError() )
{
case PCIE_ERR_ADAPTER_NOT_FOUND: Result = ERR_PCI_ADAPTER_NOT_FOUND; break;
case PCIB_ERR_DRIVER_NOT_FOUND: Result = ERR_PCI_DRIVER_NOT_FOUND; break;
case PCIB_ERR_IRQ_FAILURE: Result = ERR_IRQ_FAILURE; break;
case PCIB_ERR_ADAPTER_NOT_MAPPED: Result = ERR_NOT_ACQUIRED; break;
default: Result = ERR_FAILED; break;
}
}
return Result;
}
#endif //_WIN32
#ifdef _MSDOS
#define VENDEV 0x002014EBL // device_Id + vendor_Id
#define CONFIG_ADDRESS 0x0CF8
#define CONFIG_DATA 0x0CFC
#define PCI_ENABLE (1L<<31)
//---------------------------------------------------------------------------
// PRIVATE FUNCTION: Get13xxxBaseAddress() - Find S1D13xxx PCI. >>>MSDOS ONLY<<<
//---------------------------------------------------------------------------
static UInt32 Get13xxxBaseAddress( Boolean fEnable )
{
UInt32 b, d, f, f2, x;
UInt32 Addr = 0UL;
for (b = 0; b < (1L<<24); b += (1L<<16))
{
for (d = 0; d < (1L<<16); d += (1L<<11))
{
outpd( CONFIG_ADDRESS, PCI_ENABLE | b | d | 0x0C );
if ( (x = inpd(CONFIG_DATA)) == -1 )
continue;
f2 = (x & 0x00800000L) ? (1L<<11) : (1L<<8);
for (f = 0; f < f2; f += (1L<<8))
{
outpd( CONFIG_ADDRESS, PCI_ENABLE | b | d | f | 0x00 );
x = inpd( CONFIG_DATA );
if ( x == VENDEV )
{
if ( fEnable ) // Enable decoding (may be enabled by BIOS)
{
outpd( CONFIG_ADDRESS, PCI_ENABLE | b | d | f | 0x04 );
x = inpd( CONFIG_DATA );
outpd( CONFIG_DATA, x | 2 );
}
// Read DWREG[5] to get the physical ("base") address
outpd( CONFIG_ADDRESS, PCI_ENABLE | b | d | f | 0x10 );
Addr = inpd( CONFIG_DATA );
}
}
}
}
return Addr;
}
#endif //_MSDOS
#if defined(_WIN32) && defined(HAL_SIMULATE)
//---------------------------------------------------------------------------
// PRIVATE FUNCTION: AllocateSharedMemory() >>>HAL_SIMULATE ONLY<<<
//---------------------------------------------------------------------------
static int AllocateSharedMemory( UInt32 PhysicalAddr, UInt32 *pVirtualAddr, UInt32 *pBlockSize )
{
DWORD dwLastError;
// We can't simulate a specific user-specified physical address.
if ( PhysicalAddr )
return ERR_FAILED;
// If we haven't allocated shared memory yet, do it now.
if ( gpSharedMemory == NULL )
{
ghSharedMemory = CreateFileMapping( INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, DEFAULT_BLOCK_SIZE, HALCHIPID"HalSharedMemory" );
dwLastError = GetLastError(); // Remember result code for later.
// If we allocated shared memory successfully, then get a pointer to it.
if ( ghSharedMemory != NULL && ghSharedMemory != INVALID_HANDLE_VALUE )
{
gpSharedMemory = MapViewOfFile( ghSharedMemory, FILE_MAP_ALL_ACCESS, 0, 0, 0 );
if ( gpSharedMemory == NULL )
{
CloseHandle( ghSharedMemory );
ghSharedMemory = NULL;
}
}
// If we failed to allocation shared memory, exit with error condition.
if ( gpSharedMemory == NULL )
return ERR_FAILED;
// If we are the first to allocate shared memory, then initialize it to ZERO.
if ( dwLastError != ERROR_ALREADY_EXISTS )
ZeroMemory( gpSharedMemory, DEFAULT_BLOCK_SIZE );
}
if ( pVirtualAddr )
*pVirtualAddr = (UInt32)gpSharedMemory;
if ( pBlockSize )
*pBlockSize = DEFAULT_BLOCK_SIZE;
return ERR_NONE;
}
//---------------------------------------------------------------------------
// PRIVATE FUNCTION: FreeSharedMemory() >>>HAL_SIMULATE ONLY<<<
//---------------------------------------------------------------------------
static void FreeSharedMemory( void )
{
// Only free up these resources, if they are currently allocated and in use.
if ( gpSharedMemory )
{
UnmapViewOfFile( gpSharedMemory );
gpSharedMemory = NULL;
}
if ( ghSharedMemory )
{
CloseHandle( ghSharedMemory );
ghSharedMemory = NULL;
}
}
#endif //defined(_WIN32) && defined(HAL_SIMULATE)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -