System Simulator Call (SSC)
This document provides a high level description of
console,
disk
and
miscellaneous SSC calls.
The main data types are:
-
U32 unsigned int, 4 bytes long
-
DWORD unsigned int, 4 bytes long
-
U64 unsigned int, 8 bytes long
-
SSC_HANDLE U32
-
SSC_BOOL U32
CONSOLE
The three main calls to set up and interact with the console are:
Before using the keyboard calls, an interrupt bit in IRR0-3 must be associated
with the keyboard interrupt. This is done by using the SscConnectInterrupt
call. The interrupt bit cannot be in group 0 (interrupts 0-15).
SscConnectInterrupt(interrupt, bit_position)
SscConnectInterrupt associates an interrupt with a bit in IRR0-3. The input
parameters specify the interrupt and the bit_position. The following interrupts
are legal:
SSC_DISK_INTERRUPT
SSC_MOUSE_INTERRUPT
SSC_KEYBOARD_INTERRUPT
SSC_CLOCK_TIMER_INTERRUPT
SSC_PROFILE_TIMER_INTERRUPT
SSC_APC_INTERRUPT
SSC_DPC_INTERRUPT
The following assembly instructions show the calling sequence:
mov |
r32 = SSC_KEYBOARD_INTERRUPT |
mov |
r33 = INTERRUPT_BIT_POS |
mov |
r15 = CONST_SscConnectInterrupt |
break |
SSCI_KCALL_CODE |
SSC_set_KB_mode(on)
This call initializes the console and keyboard and sets up mailboxes for
gambit and the console. The only parameter for this call is a flag to turn
on the keyboard and console. In order to initialize the console, the value
passed in must be zero. A sample calling sequence in assembly is shown
below:
mov |
r32 = 0x0 |
mov |
r15 = CONST_SSC_set_KB_mode |
break |
SSCI_KCALL_CODE |
SSC_char_out(char)
This call puts a character onto the console. The input character char must
be passed in register r32 as shown in the following example:
ld1 |
r32 = [r4], r2 |
mov |
r15 = CONST_SSC_char_out |
break |
SSCI_KCALL_CODE |
add |
r4 = 0x1, r4 |
SSC_char_in
This call returns the next character in the keyboard buffer. The character
is returned in register r32.
mov |
r15 = CONST_SSC_char_in |
break |
SSCI_KCALL_CODE |
cmp.ne.unc |
p4, p0 = 0xa, r32 |
DISK ACCESS
The following calls facilitate access to the disk and other devices.
SSC_HANDLE and SSC_BOOL are of type U32. All size and offset fields must
be specified in bytes.
Before using the disk calls, an interrupt bit in IRR0-3 must be associated
with the disk interrupt. This is done by using the SscConnectInterrupt
call.
SSC_HANDLE SscDiskOpenVolume(U64 VolumeName,
DWORD AccessMode)
This call opens a device or file. The access modes allowed are read, write
and read|write. The call returns the volume handle in register r8. The
following example shows how a disk file can be opened for reading.
movl |
r32 = vol_name |
mov |
r33 = ssc_read |
mov |
r15 = CONST_SscDiskOpenVolume |
break |
SSCI_KCALL_CODE |
SSC_BOOL SscDiskCloseVolume(SSC_HANDLE
VolumeHandle)
This call closes a device or file identified the given volume handle. SSC_HANDLE
is a 32 bit quantity. The call returns true if successful in register r8.
mov |
r32 = r3 |
// r3 has the volume handle |
mov |
r15 = CONST_SscDiskCloseVolume |
break |
SSCI_KCALL_CODE |
SSC_BOOL SscDiskReadVolume(SSC_HANDLE VolumeHandle,
DWORD NReq, U64 RequestPtr, U64 VolumeOffset)
SscDiskReadVolume reads 512 byte multiples of data from the specified device
or file. If successful, the call returns TRUE in register r8.
The request_ptr is of type SSC_DISK_REQUEST.
typedef struct _SSC_DISK_REQUEST {
U64 DiskBufferAddress;
U32 DiskByteCount;
} *PSSC_DISK_REQUEST, SSC_DISK_REQUEST;
read_file:
mov |
r32 = r8 |
// r8 has handle from gambit, gambit_handle <> os_handle |
mov |
r33 = 0x1 |
// reading in only one buff/cnt pair |
movl |
r4 = ssc_disk_req |
movl |
r34 = disk_buf |
// address of the buffer |
st8 |
[r4] = r34 |
mov |
r34 = r4 |
mov |
r35 = 0x0 |
// Volume offset, we want to read from the beginning |
mov |
r15 = CONST_SscDiskReadVolume |
break |
SSCI_KCALL_CODE |
SSC_BOOL SscDiskWriteVolume(SSC_HANDLE
VolumeHandle, DWORD NReq, U64 RequestPtr, U64 VolumeOffset)
SscDiskWriteVolume writes 512 byte multiples of data to the specified device
or file. If successful, the call returns TRUE in register r8. A sample
calling sequence is shown below.
mov |
r32 = r8 |
// r8 has handle from gambit, gambit_handle <> os_handle |
mov |
r33 = 0x1 |
// reading in only one buff/cnt pair |
movl |
r34 = ssc_disk_req |
mov |
r35 = 0x0 |
// Volume offset, we want to read from the beginning |
mov |
r15 = CONST_SscDiskWriteVolume |
break |
SSCI_KCALL_CODE |
SSC_BOOL SscDiskGetCompletion(U64 DiskCompletionPtr)
This call determines if any I/O transaction was completed. If a transaction
was completed, the volume handle and the number of bytes transfered are
returned. The call returns TRUE if an I/O was indeed completed. This call
can be used in an interrupt handler. It should be called more than once
on interrupt, because one interrupt may report one or more an one I/O completion.
Only one I/O transaction can be in progress for a given volume handle.
typedef struct _SSC_DISK_COMPLETION {
SSC_HANDLE VolumeHandle;
DWORD XferBytes;
} *PSSC_DISK_COMPLETION, SSC_DISK_COMPLETION;
write_file:
mov |
r32 = r8 |
// r8 has handle from gambit, gambit_handle <> os_handle |
mov |
r33 = 0x1 |
// reading in only one buff/cnt pair |
movl |
r34 = ssc_disk_req |
mov |
r35 = 0x0 |
// Volume offset, we want to read from the beginning |
mov |
r15 = CONST_SscDiskWriteVolume |
break |
SSCI_KCALL_CODE |
SSC_BOOL SscDiskWaitIoCompletion(U64
DiskCompletionPtr)
SscDiskWaitIoCompletion will synchronize with a previously made read or
write call. If an interrupt has already been delivered, the call will return
false and no completion values will be returned. If the call is successful,
no interrupt will be delivered.
mov |
r32 = ssc_disk_completion |
st4 |
[r32] = r3 |
// r3 has the volume handle |
mov |
r15 = CONST_SscDiskWaitIoCompletion |
break |
SSCI_KCALL_CODE |
Miscellaneous SSCs
SscExit (U32 status)
SscExit exits the OS application and returns the status to simdb. If simdb
was in console, gui or batch mode, simdb prints the status. If simdb was
invoked with the "-d" option, the application exits and simdb terminates.
Currently, the application exit status is not returned to the system by
simdb.
mov |
r32 = 5 |
// return exit status of 5 |
mov |
r15 = CONST_SscExit |
break |
SSC_KCALL_CODE |
VOID SscSetPeriodicInterruptInterval(DWORD InterruptSource, ULONG IntervalInNanoSeconds)
The SscSetPeriodicInterruptInterval call can be used to cause an interrupt
periodically. The source of the interrupt is specified by InterruptSource.
The interrupt is posted every IntervalInNanoSeconds. This call can be used
to generate clock timer and profile timer interrupts periodically.
The interrupt source must be either SSC_CLOCK_TIMER_INTERRUPT or SSC_PROFILE_TIMER_INTERRUPT.
An interval value of zero will stop existing periodic interrupts for the
given source.
The interrupt source must have been connected by issuing the SscConnectInterrupt
call.
mov |
r32 = SSC_CLOCK_TIMER_INTERRUPT |
// Clock timer |
mov |
r33 = interval_in_nanosecs |
// Interval |
mov |
r15 = CONST_SscSetPeriodicInterruptInterval |
break |
SSCI_KCALL_CODE |
VOID SscGenerateInterrupt(DWORD InterruptSource)
The SscGenerateInterrupt call can be used to cause Gambit to deliver an
interrupt. The source of the interrupt is specified by InterruptSource.
Gambit sets the corresponding bit in IRR0-3. The interrupt source must
have been connected by issuing the SscConnectInterrupt call.
Valid values for InterruptSource are:
-
SSC_DISK_INTERRUPT
-
SSC_MOUSE_INTERRUPT
-
SSC_KEYBOARD_INTERRUPT
-
SSC_CLOCK_TIMER_INTERRUPT
-
SSC_PROFILE_TIMER_INTERRUPT
-
SSC_APC_INTERRUPT
-
SSC_DPC_INTERRUPT
For example:
mov |
r32 = SSC_KEYBOARD_INTERRUPT |
mov |
r33 = INTERRUPT_BIT_POS |
mov |
r15 = CONST_SscConnectInterrupt |
break |
SSCI_KCALL_CODE |
... |
mov |
r32 = SSC_KEYBOARD_INTERRUPT |
mov |
r15 = CONST_SscGenerateInterrupt |
break |
SSCI_KCALL_CODE |
VOID SscQueryRealTimeClock (U64 TimeFieldsPtr)
TimeFieldsPtr is a pointer to the TIME_FIELDS structure that specifies
the current time.
typedef struct _TIME_FIELDS {
DWORD year;
DWORD month;
DWORD day;
DWORD hour;
DWORD minute;
DWORD second;
DWORD milliseconds;
DWORD week_day;
} SSC_TIME_FIELDS, *PSSC_TIME_FIELDS;
The SscQueryRealTimeClock call returns the current time in this
structure.
movl |
r32 = ssc_time_fields_ptr |
mov |
r15 = CONST_SscQueryRealTimeClock |
break |
SSCI_KCALL_CODE |
int SscDbgLoadImageSymbols(U32 LoadType, U64 LoadPtr, U64 LoadBase, U32
ProcessId)
SscDbgLoadImageSymbols reinitializes the virtual symbol table and loads
the new symbol table from the file pointed to by the LoadPtr.
mov |
r32 = 0x0 |
// not implemented yet |
movl |
r33 = file_name |
// pointer to the file name to load symbols |
mov |
r34 = 0x0 |
// not implemented yet |
mov |
r35 = 0x0 |
// not implemented yet |
mov |
r15 = CONST_SscDbgLoadImageSymbols |
break |
SSCI_KCALL_CODE |
int SscDbgSymbolToAddr(U64 Symbol, U64 Address)
movl |
r32 = symbol_name |
// pointer to the symbol name |
movl |
r33 = address |
// pointer to receive address |
mov |
r15 = CONST_SscDbgSymbolToAddr |
break |
SSCI_KCALL_CODE |
int SscDbgAddrToSymbol(U64 Symbol, U64 Address)
movl |
r32 = symbol_name |
// pointer to receive the symbol+offset |
movl |
r33 = address |
// pointer to address |
mov |
r15 = CONST_SscDbgAddrToSymbol |
break |
SSCI_KCALL_CODE |