mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
353 lines
6.4 KiB
353 lines
6.4 KiB
#if defined(ALPHA)
|
|
|
|
/*++
|
|
|
|
Copyright (c) 1993 Digital Equipment Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
jnfsstub.s
|
|
|
|
|
|
Abstract:
|
|
|
|
A streamlined copy of jenassem.s, for the FailSafe Booter.
|
|
|
|
Author:
|
|
|
|
John DeRosa 21-October-1992
|
|
|
|
|
|
Environment:
|
|
|
|
Executes in kernel mode.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "ksalpha.h"
|
|
#include "selfmap.h"
|
|
#include "jnsndef.h"
|
|
|
|
/*****************************************************************
|
|
|
|
Simple functions to perform PALcode calls and memory barriers.
|
|
|
|
******************************************************************/
|
|
|
|
|
|
LEAF_ENTRY(AlphaInstIMB)
|
|
|
|
callpal imb
|
|
ret zero, (ra)
|
|
|
|
.end AlphaInstIMB
|
|
|
|
|
|
|
|
LEAF_ENTRY(AlphaInstMB)
|
|
|
|
mb
|
|
ret zero, (ra)
|
|
|
|
.end AlphaInstMB
|
|
|
|
|
|
|
|
LEAF_ENTRY(AlphaInstHalt)
|
|
|
|
callpal halt
|
|
ret zero, (ra) # should never return, but...
|
|
|
|
.end AlphaInstHalt
|
|
|
|
|
|
|
|
#if 0
|
|
LEAF_ENTRY(DisableInterrupts)
|
|
|
|
callpal di
|
|
ret zero, (ra)
|
|
|
|
.end DisableInterrupts
|
|
#endif
|
|
|
|
|
|
|
|
LEAF_ENTRY(RegisterExceptionHandler)
|
|
|
|
lda a0, FailSafeEntry # Restart main code on unexpected exceptions
|
|
callpal wrentry
|
|
ret zero, (ra)
|
|
|
|
.end RegisterExceptionHandler
|
|
|
|
NESTED_ENTRY(FwExecute, 0x60, ra)
|
|
|
|
|
|
/*
|
|
|
|
Routine Description:
|
|
|
|
This is the entry point for the Execute service.
|
|
|
|
It behaves in two different ways depending on where it is called from:
|
|
|
|
1) If called from the Firmware, it saves the stack pointer
|
|
in a fixed location and then saves all the saved registers
|
|
in the stack. This is the stack that will be used to restore
|
|
the saved state when returning to the firmware.
|
|
|
|
2) If called from a loaded program, the program to be loaded
|
|
and executed can overwrite the current program and its
|
|
stack. Therefore a temporary stack is set.
|
|
|
|
Arguments:
|
|
|
|
a0 IN PCHAR Path,
|
|
a1 IN ULONG Argc,
|
|
a2 IN PCHAR Argv[],
|
|
a3 IN PCHAR Envp[]
|
|
|
|
Return Value:
|
|
|
|
ARC_STATUS returned by FwPrivateExecute.
|
|
Always returns to the Firmware.
|
|
|
|
*/
|
|
|
|
lda t0, FwSavedSp
|
|
subq sp, 0x60 # make room in the stack
|
|
stl sp, (t0) # save new stack pointer
|
|
|
|
stq ra, (sp) # return address on top of stack
|
|
stq s0, 0x8(sp) # save s registers
|
|
stq s1, 0x10(sp)
|
|
stq s2, 0x18(sp)
|
|
stq s3, 0x20(sp)
|
|
stq s4, 0x28(sp)
|
|
stq s5, 0x30(sp)
|
|
stq fp, 0x38(sp)
|
|
stq gp, 0x40(sp)
|
|
jsr ra, FwPrivateExecute # go do the work.
|
|
|
|
RestoreFwState:
|
|
ldq ra, (sp) # restore return address
|
|
ldq s0, 0x8(sp) # restore s registers
|
|
ldq s1, 0x10(sp)
|
|
ldq s2, 0x18(sp)
|
|
ldq s3, 0x20(sp)
|
|
ldq s4, 0x28(sp)
|
|
ldq s5, 0x30(sp)
|
|
ldq fp, 0x48(sp)
|
|
ldq gp, 0x40(sp)
|
|
addq sp, 0x60 # restore stack pointer
|
|
ret zero, (ra) # return to firmware control
|
|
|
|
.end FwExecute
|
|
|
|
NESTED_ENTRY(FwInvoke, 0x40, ra)
|
|
|
|
/*++
|
|
ARC_STATUS
|
|
FwInvoke(
|
|
IN ULONG ExecAddr,
|
|
IN ULONG StackAddr,
|
|
IN ULONG Argc,
|
|
IN PCHAR Argv[],
|
|
IN PCHAR Envp[]
|
|
)
|
|
|
|
|
|
Routine Description:
|
|
|
|
This routine invokes a loaded program.
|
|
|
|
Arguments:
|
|
|
|
ExecAddr - Supplies the address of the routine to call.
|
|
|
|
StackAddr - Supplies the address to which the stack pointer is set.
|
|
|
|
Argc, Argv, Envp - Supply the arguments and environment to pass to
|
|
Loaded program.
|
|
|
|
The stack pointer is saved in register s0 so that when the loaded
|
|
program returns, the old stack pointer can be restored.
|
|
|
|
|
|
Return Value:
|
|
|
|
ESUCCESS is returned if the address is valid.
|
|
EFAULT indicates an invalid address.
|
|
|
|
--*/
|
|
|
|
|
|
subq sp, 0x40 # make room on the stack
|
|
stq ra, (sp) # save ra on top of stack
|
|
stq s0, 0x8(sp) # save s0
|
|
and a0, 3, t1 # return EFAULT if unaligned address
|
|
ldiq v0, 0x6
|
|
bne zero, 1f # branch if address alignment error
|
|
|
|
mov a0, t12 # save program address in t12
|
|
|
|
mov sp, s0 # save stack pointer
|
|
mov a1, sp # ..and load new one for program
|
|
mov a2, a0 # argc becomes first argument
|
|
mov a3, a1 # argv becomes second argument
|
|
mov a4, a2 # envp becomes third argument
|
|
|
|
jsr ra, (t12) # call program
|
|
|
|
// here if loaded program returns.
|
|
|
|
mov s0, sp # restore stack pointer
|
|
mov zero, v0 # return ESUCCESS value
|
|
ldq s0, 0x8(sp) # restore things
|
|
ldq ra, (sp)
|
|
1:
|
|
addq sp, 0x40
|
|
ret zero, (ra)
|
|
|
|
.end FwInvoke
|
|
|
|
#if 0
|
|
|
|
//
|
|
// This function was used to zero out memory in the jnfs.c module.
|
|
// We do not need to do this anymore.
|
|
//
|
|
|
|
/****
|
|
|
|
VOID
|
|
WildZeroMemory(
|
|
IN ULONG StartAddress,
|
|
IN ULONG Size
|
|
)
|
|
Routine Description:
|
|
|
|
This routine zeroes the specified range of memory.
|
|
|
|
At some point this may be changed to a more clever algorithm,
|
|
For now, it simply does store quads.
|
|
|
|
Arguments:
|
|
|
|
a0 - supplies the base physical address of the range of memory
|
|
to zero. It must be a multiple of the data cache line
|
|
size.
|
|
|
|
a1 - supplies length of memory to zero, in bytes. This must
|
|
be a multiple of the data cache line size.
|
|
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
LEAF_ENTRY(WildZeroMemory)
|
|
|
|
mov a0, t0 # start address
|
|
mov a1, t1 # number of bytes to move
|
|
|
|
1:
|
|
subqv t1, 0x20 # zero a D-cache block = 32 bytes
|
|
stq zero, (t0)
|
|
stq zero, 0x8(t0)
|
|
stq zero, 0x10(t0)
|
|
stq zero, 0x18(t0)
|
|
addqv t0, 0x20 # move to next cache block
|
|
bgt t1, 1b # t1 = 0 when done.
|
|
|
|
ret zero, (ra)
|
|
|
|
.end WildZeroMemory
|
|
|
|
#endif
|
|
|
|
|
|
/************************************************************
|
|
|
|
These are stubs. When the real code appears in the Alpha build
|
|
tree, these should be deleted. Consult the "hacked" file.
|
|
|
|
*************************************************************/
|
|
|
|
LEAF_ENTRY(DebugPrompt)
|
|
|
|
callpal halt # surprise!
|
|
ret zero, (ra) # should never return, but...
|
|
|
|
.end DebugPrompt
|
|
|
|
|
|
|
|
|
|
/* ----
|
|
|
|
VOID
|
|
FwStallExecution
|
|
(
|
|
ULONG Microseconds
|
|
);
|
|
|
|
|
|
This routine utilizes the Alpha cycle counter to delay a requested number of
|
|
microseconds.
|
|
|
|
|
|
---- */
|
|
|
|
LEAF_ENTRY( FwStallExecution)
|
|
|
|
beq a0, 20f // exit if zero delay requested
|
|
|
|
// lda t0, 20000(zero) // force small delays to 20 milliseconds
|
|
// subl a0, 5, t1
|
|
// cmoveq t1, t0, a0
|
|
|
|
10: bsr t3, 100f // call 1 microsecond delay subroutine
|
|
|
|
subl a0, 1, a0 // decrement requested microseconds
|
|
zap a0, 0xf0, a0 // unsigned long a0
|
|
|
|
bgt a0, 10b
|
|
|
|
20: ret zero, (ra)
|
|
|
|
//
|
|
// 1 microsecond delay subroutine
|
|
//
|
|
|
|
100: ldl t0, CyclesPerMicrosecond // init 1 microsecond delay
|
|
|
|
rpcc t1 // get entry time rpcc value
|
|
zap t1, 0xf0, t1 // clear <63:32>
|
|
|
|
200: rpcc t2 // get current rpcc value
|
|
zap t2, 0xf0, t2 // clear <63:32>
|
|
|
|
subl t2, t1, t2 // compute unsigned 32b difference
|
|
zap t2, 0xf0, t2
|
|
|
|
subl t0, t2, t2 // (requested delay - delay so far) > 0?
|
|
|
|
bgt t2, 200b
|
|
|
|
ret zero, (t3)
|
|
|
|
.end FwStallExecution
|
|
|
|
|
|
|
|
#endif // ALPHA
|
|
|