681 lines
18 KiB
C
681 lines
18 KiB
C
// ----------------------------------------------------------------------------
|
||
// Copyright (c) 1992 Olivetti
|
||
//
|
||
// File: eisafunc.c
|
||
//
|
||
// Description: Eisa code support functions.
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
#include "fwp.h"
|
||
#include "oli2msft.h"
|
||
#include "arceisa.h"
|
||
#include "inc.h"
|
||
#include "string.h"
|
||
#include "debug.h"
|
||
|
||
extern EISA_BUS_INFO EisaBusInfo[];
|
||
extern BL_FILE_TABLE BlFileTable [BL_FILE_TABLE_SIZE];
|
||
|
||
// Function prototypes.
|
||
|
||
|
||
VOID
|
||
EisaFlushCache
|
||
(
|
||
IN PVOID Address,
|
||
IN ULONG Length
|
||
);
|
||
|
||
VOID
|
||
EisaInvalidateCache
|
||
(
|
||
IN PVOID Address,
|
||
IN ULONG Length
|
||
);
|
||
|
||
ARC_STATUS
|
||
EisaDoLockedOperation
|
||
(
|
||
IN ULONG BusNumber,
|
||
IN EISA_LOCK_OPERATION Operation,
|
||
IN PVOID Semaphore,
|
||
IN SEMAPHORE_SIZE SemaphoreSize,
|
||
IN PVOID OperationArgument,
|
||
OUT PVOID OperationResult
|
||
);
|
||
|
||
ARC_STATUS
|
||
EisaCheckLockPassingParameters
|
||
(
|
||
IN ULONG BusNumber,
|
||
IN EISA_LOCK_OPERATION Operation,
|
||
IN PVOID Semaphore,
|
||
IN SEMAPHORE_SIZE SemaphoreSize,
|
||
IN PVOID OperationArgument,
|
||
OUT PVOID OperationResult
|
||
);
|
||
|
||
VOID
|
||
EisaFlushWriteBuffers
|
||
(
|
||
VOID
|
||
);
|
||
|
||
ARC_STATUS
|
||
EisaGenerateTone
|
||
(
|
||
IN ULONG Frequency,
|
||
IN ULONG Duration
|
||
);
|
||
|
||
BOOLEAN_ULONG
|
||
EisaYield
|
||
(
|
||
VOID
|
||
);
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaFlushCache:
|
||
//
|
||
// DESCRIPTION: This function flushes the instruction and data caches
|
||
// starting at the address specified in "Address" for
|
||
// number of bytes specified in "Length".
|
||
//
|
||
// ARGUMENTS: Address - Starting virtual address of a range of virtual
|
||
// addresses that are to be flushed from the instruction
|
||
// and data caches. If Address is 0 the entire instruction
|
||
// and data caches are flushed.
|
||
//
|
||
// Length - The length of range of virtual addresses that
|
||
// are to be flushed from the instruction and data caches.
|
||
//
|
||
// RETURN: none
|
||
//
|
||
// ASSUMPTIONS:
|
||
//
|
||
// CALLS: GetICacheSize, GetDCacheSize, FlushInvalidateDCacheIndex
|
||
//
|
||
// GLOBALS: none.
|
||
//
|
||
// NOTES:
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
VOID
|
||
EisaFlushCache
|
||
(
|
||
IN PVOID Address,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
ULONG CacheSize;
|
||
ULONG CacheLineSize;
|
||
|
||
if ( !Length ) // flush entire cache ?
|
||
{ // yes, get cache sizes and flush
|
||
|
||
GetDCacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
|
||
FlushInvalidateDCacheIndex( (PVOID)KSEG0_BASE, CacheSize );
|
||
|
||
return; // return to caller
|
||
}
|
||
|
||
//
|
||
// User specified a specific address to flush. So take the users starting
|
||
// virtual address and size and flush data cache.
|
||
//
|
||
|
||
Address = (PVOID)((ULONG)Address & 0x1FFFFFFF | KSEG0_BASE);
|
||
FlushInvalidateDCacheIndex( Address, Length );
|
||
|
||
return; // return
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaInvalidateCache:
|
||
//
|
||
// DESCRIPTION: This functions sets the invalid bit in the cache line for
|
||
// the specified range of addresses.
|
||
//
|
||
// ARGUMENTS: Address - Starting virtual address of a range of virtual
|
||
// addresses that are to be invalidated in the instruction
|
||
// and data caches. If Address is 0 the entire instruction
|
||
// and data caches are invalidated.
|
||
//
|
||
// Length - The length of range of virtual addresses that
|
||
// are to be invalidated in the instruction and data caches.
|
||
//
|
||
// RETURN: none
|
||
//
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: GetICacheSize, GetDCacheSize, InvalidateICacheIndex,
|
||
// FlushInvalidateDCacheIndex
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES:
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
VOID
|
||
EisaInvalidateCache
|
||
(
|
||
IN PVOID Address,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
ULONG CacheSize;
|
||
ULONG CacheLineSize;
|
||
|
||
if ( !Length ) // invalidate entire cache ?
|
||
{ // yes, get cache sizes and invalidate
|
||
|
||
GetDCacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
|
||
FlushInvalidateDCacheIndex( (PVOID)KSEG0_BASE, CacheSize );
|
||
|
||
GetICacheSize( (ULONG)&CacheSize, (ULONG)&CacheLineSize );
|
||
InvalidateICacheIndex( (PVOID)KSEG0_BASE, CacheSize );
|
||
|
||
return; // return to caller
|
||
}
|
||
|
||
//
|
||
// User specified a specific address to invalidate. So take the users
|
||
// starting virtual address and size and invalidate both instruction and
|
||
// data caches.
|
||
//
|
||
|
||
Address = (PVOID)((ULONG)Address & 0x1FFFFFFF | KSEG0_BASE);
|
||
FlushInvalidateDCacheIndex( Address, Length );
|
||
InvalidateICacheIndex( Address, Length );
|
||
|
||
return; // return to caller
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaDoEISALockedOperation:
|
||
//
|
||
// DESCRIPTION: A CPU or a bus master can assert LOCK* to guarantee
|
||
// exclusive memory access during the time LOCK* is
|
||
// asserted. Assertion of LOCK* allows bit test and set
|
||
// operations (as used for semaphores) to be executed
|
||
// as a unit (atomically), with the bus lock preventing
|
||
// multiple devices from simultaneously modifying the
|
||
// semaphore bit. The MIPS family of microprocessors
|
||
// does not assert LOCK* during the execution of any
|
||
// function. As such, the system firmware provides an
|
||
// abstracted programmatic interface through which option
|
||
// module firmware (OMF) can assert and negate LOCK*.
|
||
//
|
||
// EISA option module firmware's LOCK* requests are
|
||
// performed by the EISA LOCK function. If there are
|
||
// multiple EISA buses in the system, the buses may share
|
||
// the LOCK hardware among the different EISA buses.
|
||
//
|
||
// ARGUMENTS: BusNumber The bus that contains the device that
|
||
// is sharing semaphore. This number is
|
||
// the Key of the buses' component
|
||
// structure.
|
||
//
|
||
// Opeation The type of locked operation to be
|
||
// performed.
|
||
//
|
||
// Semaphore A pointer to the varialbe in EISA or
|
||
// system memory.
|
||
//
|
||
// SemaphoreSize The size of the semaphore.
|
||
//
|
||
// OperationArgument The value to change the Semaphore to.
|
||
//
|
||
// OperationResult A pointer to a memory location that
|
||
// will receive the value of Semaphore
|
||
// before Operation.
|
||
//
|
||
// RETURN: ESUCCESS all done
|
||
// EINVAL passing parameters error
|
||
//
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: EisaCheckLockPassingParameters
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES:
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
ARC_STATUS
|
||
EisaDoLockedOperation
|
||
(
|
||
IN ULONG BusNumber,
|
||
IN EISA_LOCK_OPERATION Operation,
|
||
IN PVOID Semaphore,
|
||
IN SEMAPHORE_SIZE SemaphoreSize,
|
||
IN PVOID OperationArgument,
|
||
OUT PVOID OperationResult
|
||
)
|
||
{
|
||
ARC_STATUS Status;
|
||
|
||
//
|
||
// validate the passing parameters to avoind exceptions.
|
||
//
|
||
|
||
if ( Status = EisaCheckLockPassingParameters( BusNumber, Operation,
|
||
Semaphore, SemaphoreSize, OperationArgument, OperationResult ))
|
||
{
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// assert lock on the BUS.
|
||
//
|
||
|
||
WRITE_REGISTER_UCHAR( EISA_LOCK_VIRTUAL_BASE,
|
||
READ_REGISTER_UCHAR( EISA_LOCK_VIRTUAL_BASE ) | 0x01 );
|
||
|
||
//
|
||
// Now check to see what type of operation the caller is asking us
|
||
// to perform.
|
||
//
|
||
|
||
if (Operation == Exchange)
|
||
{
|
||
//
|
||
// User wants to exchange the current semaphore value with the
|
||
// one passed. So, lets get the semaphore size and do the
|
||
// exchange.
|
||
//
|
||
|
||
switch(SemaphoreSize)
|
||
{
|
||
case ByteSemaphore:
|
||
*(PUCHAR)OperationResult = *(PUCHAR)Semaphore;
|
||
*(PUCHAR)Semaphore = *(PUCHAR)OperationArgument;
|
||
break;
|
||
|
||
case HalfWordSemaphore:
|
||
*(PUSHORT)OperationResult = *(PUSHORT)Semaphore;
|
||
*(PUSHORT)Semaphore = *(PUSHORT)OperationArgument;
|
||
break;
|
||
|
||
case WordSemaphore:
|
||
*(PULONG)OperationResult = *(PULONG)Semaphore;
|
||
*(PULONG)Semaphore = *(PULONG)OperationArgument;
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// The operation on the semaphore is now complete. Now we need to
|
||
// negate the LOCK* signal.
|
||
//
|
||
|
||
WRITE_REGISTER_UCHAR( EISA_LOCK_VIRTUAL_BASE,
|
||
READ_REGISTER_UCHAR( EISA_LOCK_VIRTUAL_BASE ) & 0xFE );
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaCheckLockPassingParameters:
|
||
//
|
||
// DESCRIPTION: The functions checks the lock function passing
|
||
// parameters. This is neccessary to avoin exceptions.
|
||
//
|
||
// ARGUMENTS: BusNumber The bus that contains the device that
|
||
// is sharing semaphore. This number is
|
||
// the Key of the buses' component
|
||
// structure.
|
||
//
|
||
// Opeation The type of locked operation to be
|
||
// performed.
|
||
//
|
||
// Semaphore A pointer to the varialbe in EISA or
|
||
// system memory.
|
||
//
|
||
// SemaphoreSize The size of the semaphore.
|
||
//
|
||
// OperationArgument The value to change the Semaphore to.
|
||
//
|
||
// OperationResult A pointer to a memory location that
|
||
// will receive the value of Semaphore
|
||
// before Operation.
|
||
//
|
||
// RETURN: ESUCCESS parameters are correct.
|
||
// EINVAL at least one parameter was not correct.
|
||
//
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: EisaCheckBusNumber
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES: none
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
ARC_STATUS
|
||
EisaCheckLockPassingParameters
|
||
(
|
||
IN ULONG BusNumber,
|
||
IN EISA_LOCK_OPERATION Operation,
|
||
IN PVOID Semaphore,
|
||
IN SEMAPHORE_SIZE SemaphoreSize,
|
||
IN PVOID OperationArgument,
|
||
OUT PVOID OperationResult
|
||
)
|
||
{
|
||
ARC_STATUS Status = EINVAL;
|
||
ULONG Size = 1 << SemaphoreSize; // semaphore size (# bytes)
|
||
|
||
//
|
||
// check the bus number
|
||
//
|
||
|
||
if ( EisaCheckBusNumber( BusNumber ) != ESUCCESS );
|
||
|
||
//
|
||
// check lock operation
|
||
//
|
||
|
||
else if ( Operation >= LockMaxOperation );
|
||
|
||
//
|
||
// check semaphore size
|
||
//
|
||
|
||
else if ( SemaphoreSize >= MaxSemaphore );
|
||
|
||
//
|
||
// make sure that there is physical memory at the specified locations
|
||
//
|
||
|
||
else if ( EisaCheckVirtualAddress( BusNumber, Semaphore, Size ));
|
||
else if ( EisaCheckVirtualAddress( BusNumber, OperationArgument, Size ));
|
||
else if ( EisaCheckVirtualAddress( BusNumber, OperationResult, Size ));
|
||
|
||
//
|
||
// check pointers boundaries
|
||
//
|
||
|
||
else if ( ((ULONG)Semaphore | (ULONG)OperationArgument |
|
||
(ULONG)OperationResult) & ((1 << SemaphoreSize)-1) );
|
||
|
||
//
|
||
// if we got here, the parameters are correct
|
||
//
|
||
|
||
else
|
||
{
|
||
Status = ESUCCESS;
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaFlushWriteBuffers:
|
||
//
|
||
// DESCRIPTION: This function flushes any external write buffers.
|
||
//
|
||
// ARGUMENTS: none.
|
||
//
|
||
// RETURN: none
|
||
//
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: FlushWriteBuffers
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES:
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
VOID
|
||
EisaFlushWriteBuffers
|
||
(
|
||
VOID
|
||
)
|
||
{
|
||
FlushWriteBuffers(); // flush external write buffers.
|
||
return; // return to caller.
|
||
}
|
||
|
||
#endif // 0
|
||
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaGenerateTone:
|
||
//
|
||
// DESCRIPTION: This function generate tones of a specified
|
||
// frequency and duration an the system speaker.
|
||
//
|
||
// ARGUMENTS: Frequency the frequency of the tone in hertz
|
||
// Duration The duration of the tone in msec
|
||
//
|
||
// RETURN: ESUCCESS Operation completed successfully
|
||
// ENODEV System can not generate tones
|
||
//
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: none
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES: The routine uses the timer1-counter2 and the system
|
||
// control port B of the 1st EISA bus to generate the
|
||
// specified tone.
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
ARC_STATUS
|
||
EisaGenerateTone
|
||
(
|
||
IN ULONG Frequency,
|
||
IN ULONG Duration
|
||
)
|
||
{
|
||
//
|
||
// define local variables
|
||
//
|
||
|
||
PUCHAR EisaIoStart, Ctrl, Data, Port61; // general I/O address
|
||
|
||
//
|
||
// exit if duration is null
|
||
//
|
||
|
||
if ( !Duration )
|
||
{
|
||
return ESUCCESS;
|
||
}
|
||
|
||
//
|
||
// initialize local variables
|
||
//
|
||
|
||
EisaIoStart = EisaBusInfo[ 0 ].IoBusInfo->VirAddr;
|
||
Ctrl = EisaIoStart + EISA_TIMER1_CTRL;
|
||
Data = EisaIoStart + EISA_TIMER1_COUNTER2;
|
||
Port61 = EisaIoStart + EISA_SYS_CTRL_PORTB;
|
||
|
||
//
|
||
// make sure that the speaker is disabled
|
||
//
|
||
|
||
EisaOutUchar( Port61, ( EisaInUchar( Port61 ) &
|
||
~( EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER )) & 0x0F );
|
||
|
||
//
|
||
// if frequency value is valid, program timer1-counter2 and enable speaker
|
||
//
|
||
|
||
if (Frequency>=EISA_SPEAKER_MIN_FREQ && Frequency<=EISA_SPEAKER_MAX_FREQ)
|
||
{
|
||
//
|
||
// initialize timer1 counter2 in 16-bit , mode 3
|
||
//
|
||
|
||
// NOTE: CriticalSection not supported in JAZZ.
|
||
// EisaBeginCriticalSection();
|
||
EisaOutUchar( Ctrl, 0xB6 );
|
||
EisaOutUchar( Data, (UCHAR)(EISA_SPEAKER_CLOCK/Frequency));
|
||
EisaOutUchar( Data, (UCHAR)(EISA_SPEAKER_CLOCK/Frequency >> 8));
|
||
// NOTE: CriticalSection not supported in JAZZ.
|
||
// EisaEndCriticalSection();
|
||
|
||
//
|
||
// enable speaker gate and speaker output
|
||
//
|
||
|
||
EisaOutUchar( Port61, ( EisaInUchar( Port61 ) |
|
||
EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER ) & 0x0F );
|
||
}
|
||
|
||
//
|
||
// ... wait
|
||
//
|
||
|
||
while ( Duration-- )
|
||
{
|
||
ArcEisaStallProcessor( 1000 ); // 1 msec
|
||
}
|
||
|
||
//
|
||
// disable speaker before returning
|
||
//
|
||
|
||
EisaOutUchar( Port61, ( EisaInUchar( Port61 ) &
|
||
~( EISA_SPEAKER_GATE | EISA_SPEAKER_TIMER )) & 0x0F );
|
||
|
||
//
|
||
// all done
|
||
//
|
||
|
||
return ESUCCESS;
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
|
||
|
||
// ----------------------------------------------------------------------------
|
||
// PROCEDURE: EisaYield:
|
||
//
|
||
// DESCRIPTION: System utilities and option module firmware
|
||
// must surrender the processor so that the system
|
||
// module firmware can check for pending input.
|
||
// To surrender the prcessor, call this function.
|
||
//
|
||
// ARGUMENTS: none
|
||
//
|
||
// RETURN: TRUE Indicates that the BREAK key was
|
||
// pressed. Yield continues to return
|
||
// TREUE until the BREAK key is read
|
||
// from the console input device.
|
||
// FALSE Inidicates that the BREAK key has
|
||
// not been pressed.
|
||
// ASSUMPTIONS: none
|
||
//
|
||
// CALLS: none
|
||
//
|
||
// GLOBALS: none
|
||
//
|
||
// NOTES: none
|
||
// ----------------------------------------------------------------------------
|
||
//
|
||
|
||
// NOTE: Not used on JAZZ.
|
||
#if 0
|
||
|
||
BOOLEAN_ULONG
|
||
EisaYield
|
||
(
|
||
VOID
|
||
)
|
||
{
|
||
//
|
||
// call all device strategy routines with FC_POLL command
|
||
//
|
||
|
||
EisaOmfPoll();
|
||
|
||
//
|
||
// read any char available from the console in into the console in buffer
|
||
//
|
||
|
||
if ( !BlFileTable[ 0 ].Flags.Open )
|
||
{
|
||
//
|
||
// the console in device is not available, return no Ctrl-C.
|
||
//
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
//
|
||
// read any available data from the console in device
|
||
//
|
||
|
||
ConsoleInFill();
|
||
|
||
//
|
||
// and scan buffer checking contrl-C
|
||
//
|
||
|
||
return ConsoleInCtrlC();
|
||
}
|
||
|
||
#endif // 0
|