d7fba9784e
Most of the changes were to fix broken macros in platfrom_tlaser.s palcode/Makefile: Completly new makefile to build palcode palcode/ev5_alpha_defs.h: fixed a broken define palcode/ev5_impure.h: macro fixes palcode/platform_srcmax.s: manual macro expansion of broken macros... this file isn't needed to build tlaser palcode palcode/platform_tlaser.s: lots of fixups to make the code assemble
1894 lines
48 KiB
ArmAsm
1894 lines
48 KiB
ArmAsm
// build_fixed_image: not sure what means
|
||
// real_mm to be replaced during rewrite
|
||
// remove_save_state remove_restore_state can be remooved to save space ??
|
||
#define egore 0
|
||
#define acore 0
|
||
#define beh_model 0
|
||
#define ev5_p2 1
|
||
#define ev5_p1 0
|
||
#define ldvpte_bug_fix 1
|
||
#define spe_fix 0
|
||
#define osf_chm_fix 0
|
||
#define build_fixed_image 0
|
||
#define enable_p4_fixups 0
|
||
#define osf_svmin 1
|
||
#define enable_physical_console 0
|
||
#define fill_err_hack 0
|
||
#define icflush_on_tbix 0
|
||
#define max_cpuid 1
|
||
#define perfmon_debug 0
|
||
#define rax_mode 0
|
||
|
||
#define hw_rei_spe hw_rei
|
||
|
||
#include "ev5_defs.h"
|
||
#include "ev5_impure.h"
|
||
#include "ev5_alpha_defs.h"
|
||
#include "ev5_paldef.h"
|
||
#include "ev5_osfalpha_defs.h"
|
||
#include "fromHudsonMacros.h"
|
||
#include "fromHudsonOsf.h"
|
||
#include "dc21164FromGasSources.h"
|
||
#include "cserve.h"
|
||
|
||
#define ldlp ldl_p
|
||
#define ldqp ldq_p
|
||
#define stqp stq_p
|
||
#define stqpc stqp
|
||
|
||
#define pt_entInt pt_entint
|
||
#define pt_entArith pt_entarith
|
||
#define mchk_size ((mchk_cpu_base + 7 + 8) &0xfff8)
|
||
#define mchk_flag CNS_Q_FLAG
|
||
#define mchk_sys_base 56
|
||
#define mchk_cpu_base (CNS_Q_LD_LOCK + 8)
|
||
#define mchk_offsets CNS_Q_EXC_ADDR
|
||
#define mchk_mchk_code 8
|
||
#define mchk_ic_perr_stat CNS_Q_ICPERR_STAT
|
||
#define mchk_dc_perr_stat CNS_Q_DCPERR_STAT
|
||
#define mchk_sc_addr CNS_Q_SC_ADDR
|
||
#define mchk_sc_stat CNS_Q_SC_STAT
|
||
#define mchk_ei_addr CNS_Q_EI_ADDR
|
||
#define mchk_bc_tag_addr CNS_Q_BC_TAG_ADDR
|
||
#define mchk_fill_syn CNS_Q_FILL_SYN
|
||
#define mchk_ei_stat CNS_Q_EI_STAT
|
||
#define mchk_exc_addr CNS_Q_EXC_ADDR
|
||
#define mchk_ld_lock CNS_Q_LD_LOCK
|
||
#define osfpcb_q_Ksp pcb_q_ksp
|
||
#define pal_impure_common_size ((0x200 + 7) & 0xfff8)
|
||
|
||
#define RTCADD 0x160000
|
||
#define RTCDAT 0x170000
|
||
|
||
/* Serial Port (COM) Definitions: */
|
||
#define DLA_K_BRG 12 /* Baud Rate Divisor = 9600 */
|
||
|
||
#define LSR_V_THRE 5 /* Xmit Holding Register Empty Bit */
|
||
|
||
#define LCR_M_WLS 3 /* Word Length Select Mask */
|
||
#define LCR_M_STB 4 /* Number Of Stop Bits Mask */
|
||
#define LCR_M_PEN 8 /* Parity Enable Mask */
|
||
#define LCR_M_DLAB 128 /* Divisor Latch Access Bit Mask */
|
||
|
||
#define LCR_K_INIT (LCR_M_WLS | LCR_M_STB)
|
||
|
||
#define MCR_M_DTR 1 /* Data Terminal Ready Mask */
|
||
#define MCR_M_RTS 2 /* Request To Send Mask */
|
||
#define MCR_M_OUT1 4 /* Output 1 Control Mask */
|
||
#define MCR_M_OUT2 8 /* UART Interrupt Mask Enable */
|
||
|
||
#define MCR_K_INIT (MCR_M_DTR | \
|
||
MCR_M_RTS | \
|
||
MCR_M_OUT1 | \
|
||
MCR_M_OUT2)
|
||
#define SLOT_D_COM1 (0x140000)
|
||
#define COM1_RBR (SLOT_D_COM1 | (0x0 << 1)) /* Receive Buffer Register Offset */
|
||
#define COM1_THR (SLOT_D_COM1 | (0x0 << 1)) /* Xmit Holding Register Offset */
|
||
#define COM1_IER (SLOT_D_COM1 | (0x1 << 1)) /* Interrupt Enable Register Offset
|
||
*/
|
||
#define COM1_IIR (SLOT_D_COM1 | (0x2 << 1)) /* Interrupt ID Register Offset */
|
||
#define COM1_LCR (SLOT_D_COM1 | (0x3 << 1)) /* Line Control Register Offset */
|
||
#define COM1_MCR (SLOT_D_COM1 | (0x4 << 1)) /* Modem Control Register Offset */
|
||
#define COM1_LSR (SLOT_D_COM1 | (0x5 << 1)) /* Line Status Register Offset */
|
||
#define COM1_MSR (SLOT_D_COM1 | (0x6 << 1)) /* Modem Status Register Offset */
|
||
#define COM1_SCR (SLOT_D_COM1 | (0x7 << 1)) /* Scratch Register Offset */
|
||
#define COM1_DLL (SLOT_D_COM1 | (0x8 << 1)) /* Divisor Latch (LS) Offset */
|
||
#define COM1_DLH (SLOT_D_COM1 | (0x9 << 1)) /* Divisor Latch (MS) Offset */
|
||
|
||
|
||
#define BYTE_ENABLE_SHIFT 5
|
||
#define PCI_MEM 0x400
|
||
|
||
#ifdef SIMOS
|
||
#define OutPortByte(port,val,a,b)
|
||
#define InPortByte(port,val,a)
|
||
#else
|
||
|
||
#define OutPortByte(port,val,tmp0,tmp1) \
|
||
LDLI (tmp0, port); \
|
||
sll tmp0, BYTE_ENABLE_SHIFT, tmp0; \
|
||
lda tmp1, PCI_MEM(zero); \
|
||
sll tmp1, 29, tmp1; \
|
||
bis tmp0, tmp1, tmp0; \
|
||
lda tmp1, (val)(zero); \
|
||
sll tmp1, 8*(port & 3), tmp1; \
|
||
stl_p tmp1, 0x00(tmp0); \
|
||
mb
|
||
|
||
#define InPortByte(port,tmp0,tmp1) \
|
||
LDLI (tmp0, port); \
|
||
sll tmp0, BYTE_ENABLE_SHIFT, tmp0; \
|
||
lda tmp1, PCI_MEM(zero); \
|
||
sll tmp1, 29, tmp1; \
|
||
bis tmp0, tmp1, tmp0; \
|
||
ldl_p tmp0, 0x00(tmp0); \
|
||
srl tmp0, (8 * (port & 3)), tmp0; \
|
||
zap tmp0, 0xfe, tmp0
|
||
#endif
|
||
|
||
#define r0 $0
|
||
#define r1 $1
|
||
#define r2 $2
|
||
#define r3 $3
|
||
#define r4 $4
|
||
#define r5 $5
|
||
#define r6 $6
|
||
#define r7 $7
|
||
#define r8 $8
|
||
#define r9 $9
|
||
#define r10 $10
|
||
#define r11 $11
|
||
#define r12 $12
|
||
#define r13 $13
|
||
#define r14 $14
|
||
#define r15 $15
|
||
#define r16 $16
|
||
#define r17 $17
|
||
#define r18 $18
|
||
#define r19 $19
|
||
#define r20 $20
|
||
#define r21 $21
|
||
#define r22 $22
|
||
#define r23 $23
|
||
#define r24 $24
|
||
#define r25 $25
|
||
#define r26 $26
|
||
#define r27 $27
|
||
#define r28 $28
|
||
#define r29 $29
|
||
#define r30 $30
|
||
#define r31 $31
|
||
|
||
#ifdef SIMOS
|
||
#define DEBUGSTORE(c)
|
||
#define DEBUG_EXC_ADDR()
|
||
#else
|
||
#define DEBUGSTORE(c) \
|
||
lda r13, c(zero) ; \
|
||
bsr r25, debugstore
|
||
|
||
#define DEBUG_EXC_ADDR() \
|
||
bsr r25, put_exc_addr; \
|
||
DEBUGSTORE(13) ; \
|
||
DEBUGSTORE(10)
|
||
|
||
#endif /* SIMOS */
|
||
|
||
#define ALIGN_BLOCK \
|
||
.align 5
|
||
|
||
#define ALIGN_BRANCH \
|
||
.align 3
|
||
|
||
// This module is for all the OSF system specific code.
|
||
// This version is for the EV5 behavioral model.
|
||
// .sbttl "Edit History"
|
||
//+
|
||
// Who Rev When What
|
||
// ------------ --- ----------- --------------------------------
|
||
//
|
||
// [ deleted several pages of checking comments to make the file smaller - lance ]
|
||
//
|
||
// PALcode merge done here .... JRH ....8/30/94
|
||
// JM 1.00 1-aug-1994 Add support for pass2 to sys_perfmon code
|
||
// JM 1.01 2-aug-1994 Initialize cns_bc_config in reset
|
||
// JM 1.02 5-aug-1994 Add ARITH_AND_MCHK routine.
|
||
// Fix typo in bc_config init in rax reset flow.
|
||
// JM 1.03 19-aug-1994 BUG: sys_perfmon not generating mux control mask properly, overwriting counters 0 & 1;
|
||
// mode select masks messed up too.
|
||
//
|
||
// JH 1.03A 26-Oct-1994 Log PCI error2 register ...needed for CIA Pass 2 support
|
||
//
|
||
// JM 1.04 16-sep-1994 Moved perfmon code to ev5_osf_pal.m64
|
||
// JM 1.05 9-jan-1995 Fix to EI_STAT entry in MCHK logout frame -- OR in lower 28 bits (previously wiped out)
|
||
// JM 1.06 2-feb-1995 Change "HW_REI" to "HW_REI_SPE" everywhere that we may be changing to kernel mode from user
|
||
// (part of super-page bug fix).
|
||
// Initialize DC_TEST_CTL in reset flow.
|
||
//
|
||
// PALcode merge done here .... TLC ....02/06/95
|
||
//
|
||
// JM 1.07 3-mar-1995 Add init of dc_test_ctl; fix pvc_jsr statement in ret from set_sc_bc_ctl
|
||
// ES 1.08 17-mar-1995 Add osf_chm_fix to disable dcache in reset
|
||
//
|
||
// PALcode merge done here .... TLC ....03/21/95
|
||
//
|
||
//
|
||
// Entry points
|
||
// SYS_CFLUSH - Cache flush
|
||
// SYS_CSERVE - Console service
|
||
// SYS_WRIPIR - interprocessor interrupts
|
||
// SYS_HALT_INTERRUPT - Halt interrupt
|
||
// SYS_PASSIVE_RELEASE - Interrupt, passive release
|
||
// SYS_INTERRUPT - Interrupt
|
||
// SYS_RESET - Reset
|
||
// SYS_ENTER_CONSOLE
|
||
// SYS_PERFMON - Performance monitoring setup
|
||
//
|
||
//------------------------------------------------------------------------------
|
||
//
|
||
// EB164 specific library files ....
|
||
//
|
||
//------------------------------------------------------------------------------
|
||
#if eb164 != 0
|
||
|
||
|
||
// .sbttl "EB164 firmware required definition files"
|
||
_pal_def // console definition file
|
||
_cserve_def // cserve definition file
|
||
|
||
#define hlt_c_callback 33
|
||
|
||
//
|
||
// rtc based constants
|
||
//
|
||
#define rtc_base 0xe00 // RTC device is at offset 70 << 5
|
||
#define rtc_ptr 0x0 // RTC index register (offset 0 from rtc base)
|
||
#define rtc_data 0x20 // RTC data register (offset 1 from rtc base)
|
||
#define rtc_idx_csrc 0x0c // point to CSR C in the TOY chip
|
||
|
||
//
|
||
// interrupt vectors
|
||
//
|
||
#define vec_eisa_base 0x800 // base for pci vectors
|
||
#endif
|
||
|
||
ALIGN_BLOCK
|
||
.globl sys_wripir
|
||
sys_wripir: // R16 has the processor number.
|
||
// The XXM has no interprocessor interrupts
|
||
hw_rei
|
||
|
||
// .sbttl "CFLUSH- PALcode for CFLUSH instruction"
|
||
//+
|
||
// SYS_CFLUSH
|
||
// Entry:
|
||
//
|
||
// R16 - contains the PFN of the page to be flushed
|
||
//
|
||
// Function:
|
||
// Flush all Dstream caches of 1 entire page
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
.globl sys_cflush
|
||
sys_cflush:
|
||
// convert pfn to addr, and clean off <63:20>
|
||
sll r16, ((page_offset_size_bits)+(63-20)), r12
|
||
|
||
lda r13, 0x10(r31) // assume 16Mbytes of cache
|
||
sll r13, 20, r13 // convert to bytes
|
||
|
||
srl r12, 63-20, r12 // shift back to normal position
|
||
xor r12, r13, r12 // xor addr bit that aligns with cache size
|
||
|
||
or r31, 8192/(32*8), r13 // get count of loads
|
||
nop
|
||
|
||
CFLUSH_LOOP:
|
||
subq r13, 1, r13 // decr counter
|
||
mfpr r25, ev5__intid // Fetch level of interruptor
|
||
|
||
ldqp r31, 32*0(r12) // do a load
|
||
ldqp r31, 32*1(r12) // do next load
|
||
|
||
ldqp r31, 32*2(r12) // do next load
|
||
ldqp r31, 32*3(r12) // do next load
|
||
|
||
ldqp r31, 32*4(r12) // do next load
|
||
ldqp r31, 32*5(r12) // do next load
|
||
|
||
ldqp r31, 32*6(r12) // do next load
|
||
ldqp r31, 32*7(r12) // do next load
|
||
|
||
mfpr r14, ev5__ipl // Fetch current level
|
||
lda r12, (32*8)(r12) // skip to next cache block addr
|
||
|
||
cmple r25, r14, r25 // R25 = 1 if intid .less than or eql ipl
|
||
beq r25, CFLUSH_LOOP_10_ // if any int's pending, re-queue CFLUSH
|
||
|
||
bne r13, CFLUSH_LOOP // loop till done
|
||
hw_rei // back to user
|
||
|
||
ALIGN_BRANCH
|
||
CFLUSH_LOOP_10_: // Here if interrupted
|
||
mfpr r12, exc_addr
|
||
subq r12, 4, r12 // Backup PC to point to CFLUSH
|
||
|
||
mtpr r12, exc_addr
|
||
nop
|
||
|
||
mfpr r31, pt0 // Pad exc_addr write
|
||
hw_rei
|
||
|
||
|
||
// .sbttl "CSERVE- PALcode for CSERVE instruction"
|
||
//+
|
||
// SYS_CSERVE
|
||
//
|
||
// Function:
|
||
// Various functions for private use of console software
|
||
//
|
||
// option selector in r0
|
||
// arguments in r16....
|
||
//
|
||
//
|
||
// r0 = 0 unknown
|
||
//
|
||
// r0 = 1 ldqp
|
||
// r0 = 2 stqp
|
||
// args, are as for normal STQP/LDQP in VMS PAL
|
||
//
|
||
// r0 = 3 dump_tb's
|
||
// r16 = detination PA to dump tb's to.
|
||
//
|
||
// r0<0> = 1, success
|
||
// r0<0> = 0, failure, or option not supported
|
||
// r0<63:1> = (generally 0, but may be function dependent)
|
||
// r0 - load data on ldqp
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
.globl sys_cserve
|
||
sys_cserve:
|
||
cmpeq r18, CSERVE_K_RD_IMPURE, r0
|
||
bne r0, Sys_Cserve_Rd_Impure
|
||
|
||
cmpeq r18, CSERVE_K_JTOPAL, r0
|
||
bne r0, Sys_Cserve_Jtopal
|
||
|
||
// For now the XXM doesn't support any console callbacks
|
||
DEBUGSTORE(0x40)
|
||
bis r18, zero, r0
|
||
bsr r25, put_hex
|
||
DEBUGSTORE(13)
|
||
DEBUGSTORE(10)
|
||
or r31, r31, r0
|
||
hw_rei // and back we go
|
||
|
||
Sys_Cserve_Rd_Impure:
|
||
mfpr r0, pt_impure // Get base of impure scratch area.
|
||
hw_rei
|
||
|
||
// .sbttl "SYS_INTERRUPT - Interrupt processing code"
|
||
//+
|
||
// SYS_INTERRUPT
|
||
//
|
||
// Current state:
|
||
// Stack is pushed
|
||
// ps, sp and gp are updated
|
||
// r12, r14 - available
|
||
// r13 - INTID (new EV5 IPL)
|
||
// r14 - exc_addr
|
||
// r25 - ISR
|
||
// r16, r17, r18 - available
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
.globl sys_interrupt
|
||
sys_interrupt:
|
||
extbl r12, r14, r14 // Translate new OSFIPL->EV5IPL
|
||
mfpr r29, pt_kgp // update gp
|
||
|
||
mtpr r14, ev5__ipl // load the new IPL into Ibox
|
||
cmpeq r13, 31, r12
|
||
bne r12, sys_int_mchk_or_crd // Check for level 31 interrupt (machine check or crd)
|
||
|
||
cmpeq r13, 30, r12
|
||
bne r12, sys_int_powerfail // Check for level 30 interrupt (powerfail)
|
||
|
||
cmpeq r13, 29, r12
|
||
bne r12, sys_int_perf_cnt // Check for level 29 interrupt (performance counters)
|
||
|
||
cmpeq r13, 23, r12
|
||
bne r12, sys_int_23 // Check for level 23 interrupt
|
||
|
||
cmpeq r13, 22, r12
|
||
bne r12, sys_int_22 // Check for level 22 interrupt (clock)
|
||
|
||
cmpeq r13, 21, r12
|
||
bne r12, sys_int_21 // Check for level 21 interrupt
|
||
|
||
cmpeq r13, 20, r12
|
||
bne r12, sys_int_20 // Check for level 20 interrupt (I/O)
|
||
|
||
mfpr r14, exc_addr // ooops, something is wrong
|
||
br r31, pal_pal_bug_check_from_int
|
||
|
||
//+
|
||
//sys_int_2*
|
||
// Routines to handle device interrupts at IPL 23-20.
|
||
// System specific method to ack/clear the interrupt, detect passive release,
|
||
// detect interprocessor (22), interval clock (22), corrected
|
||
// system error (20)
|
||
//
|
||
// Current state:
|
||
// Stack is pushed
|
||
// ps, sp and gp are updated
|
||
// r12, r14 - available
|
||
// r13 - INTID (new EV5 IPL)
|
||
// r25 - ISR
|
||
//
|
||
// On exit:
|
||
// Interrupt has been ack'd/cleared
|
||
// a0/r16 - signals IO device interrupt
|
||
// a1/r17 - contains interrupt vector
|
||
// exit to ent_int address
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
sys_int_23:
|
||
// INT23 is unused on the XXM
|
||
nop
|
||
DEBUGSTORE(0x21)
|
||
DEBUGSTORE(0x32)
|
||
DEBUGSTORE(0x33)
|
||
DEBUGSTORE(13)
|
||
DEBUGSTORE(10)
|
||
lda r14, 0xffff(zero)
|
||
br r31, sys_int_mchk // log as a machine check
|
||
|
||
// INT22 is the Real Time Clock
|
||
//
|
||
// Dismiss the interrupt in the TOY
|
||
// Dispatch to kernel
|
||
//
|
||
ALIGN_BLOCK
|
||
sys_int_22:
|
||
OutPortByte(RTCADD,0x0C,r12,r14)// Set up RTCADD to index register C.
|
||
InPortByte(RTCDAT,r12,r14) // Read to clear interrupt.
|
||
mfpr r12, pt_entInt
|
||
lda r17, 0x600(r31) // r17 = interrupt vector for interval timer
|
||
mtpr r12, exc_addr
|
||
// DEBUGSTORE(0x2a)
|
||
// DEBUG_EXC_ADDR()
|
||
lda r16, 0x1(r31) // r16 = interrupt type for interval timer
|
||
STALL
|
||
hw_rei
|
||
|
||
ALIGN_BLOCK
|
||
sys_int_21:
|
||
// Not connected on the XXM
|
||
nop
|
||
DEBUGSTORE(0x21)
|
||
DEBUGSTORE(0x32)
|
||
DEBUGSTORE(0x31)
|
||
DEBUGSTORE(13)
|
||
DEBUGSTORE(10)
|
||
lda r14, 0xffff(zero)
|
||
br r31, sys_int_mchk // go log the interrupt as a machine check
|
||
|
||
// INT20 are device interrupts
|
||
// Dispatch to kernel
|
||
//
|
||
ALIGN_BLOCK
|
||
sys_int_20:
|
||
mfpr r12, pt_entInt // Get pointer to kernel handler.
|
||
lda r17, 0x800(zero) // Hardcode device interrupt for now
|
||
mtpr r12, exc_addr // Load kernel entry address
|
||
bis zero, 0x3, r16 // Signal I/O device interrupt
|
||
STALL
|
||
hw_rei
|
||
|
||
|
||
//+
|
||
// sys_passive_release
|
||
// Just pretend the interrupt never occurred.
|
||
//
|
||
// make sure we restore the old PS before calling this ....
|
||
//-
|
||
ALIGN_BRANCH
|
||
.globl sys_passive_release
|
||
sys_passive_release:
|
||
mtpr r11, ev5__dtb_cm // Restore Mbox current mode for ps
|
||
nop
|
||
|
||
mfpr r31, pt0 // Pad write to dtb_cm
|
||
|
||
hw_rei_spe
|
||
|
||
//+
|
||
//sys_int_powerfail
|
||
// The XXM doesn't generate these, right?
|
||
|
||
ALIGN_BLOCK
|
||
sys_int_powerfail:
|
||
nop
|
||
lda r14, 0xffff(zero)
|
||
br r31, sys_int_mchk // go log the interrupt as a machine check
|
||
|
||
//+
|
||
// sys_halt_interrupt
|
||
// A halt interrupt has been detected. Pass control to the console.
|
||
//
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
.globl sys_halt_interrupt
|
||
sys_halt_interrupt:
|
||
// wait for halt to go away
|
||
SYS_HALT_PIN: // REPEAT
|
||
mfpr r25, ev5__isr // : Fetch interrupt summary register
|
||
srl r25, isr_v_hlt, r25 // : Get HLT bit
|
||
blbs r25, SYS_HALT_PIN // UNTIL interrupt goes away
|
||
LDLI (r25, 25000000) // Loop 100msec on an XXM
|
||
SYS_HALT_KEY_DEBOUNCE:
|
||
subq r25, 1, r25
|
||
bne r25, SYS_HALT_KEY_DEBOUNCE
|
||
mfpr r25, ev5__isr
|
||
srl r25, isr_v_hlt, r25
|
||
blbs r25, SYS_HALT_PIN
|
||
|
||
mtpr r11, dtb_cm // Restore Mbox current mode
|
||
mtpr r0, pt0
|
||
// pvc_jsr updpcb, bsr=1
|
||
// bsr r0, pal_update_pcb // update the pcb
|
||
|
||
// lda r0, hlt_c_hw_halt(r31) // set halt code to hw halt
|
||
br r31, sys_enter_console // enter the console
|
||
|
||
|
||
//+
|
||
// sys_int_mchk_or_crd
|
||
//
|
||
// Current state:
|
||
// Stack is pushed
|
||
// ps, sp and gp are updated
|
||
// r12
|
||
// r13 - INTID (new EV5 IPL)
|
||
// r14 - exc_addr
|
||
// r25 - ISR
|
||
// r16, r17, r18 - available
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
|
||
sys_int_mchk_or_crd:
|
||
srl r25, isr_v_mck, r12
|
||
lda r14, 7(zero)
|
||
blbs r12, sys_int_mchk
|
||
bsr r12, sys_int_mchk // on the XXM it's always a mchk
|
||
|
||
|
||
|
||
// .sbttl "SYS_INT_MCHK - MCHK Interrupt code"
|
||
//+
|
||
// Machine check interrupt from the system. Setup and join the
|
||
// regular machine check flow.
|
||
// On exit:
|
||
// pt0 - saved r0
|
||
// pt1 - saved r1
|
||
// pt4 - saved r4
|
||
// pt5 - saved r5
|
||
// pt6 - saved r6
|
||
// pt10 - saved exc_addr
|
||
// pt_misc<47:32> - mchk code
|
||
// pt_misc<31:16> - scb vector
|
||
// r14 - base of Cbox IPRs in IO space
|
||
// MCES<mchk> is set
|
||
//-
|
||
ALIGN_BLOCK
|
||
sys_int_mchk:
|
||
//
|
||
// Common code to setup machine so we can join with
|
||
// the code to log processor detected machine checks
|
||
//
|
||
// Input Registers:
|
||
//
|
||
// r14 - machine check code
|
||
//
|
||
mfpr r12, exc_addr
|
||
|
||
mtpr r6, pt6
|
||
mtpr r12, pt10 // Stash exc_addr
|
||
|
||
bis r14, r31, r6 // save machine check code
|
||
sll r14, 32, r14 // Move mchk code to position
|
||
|
||
mfpr r12, pt_misc // Get MCES and scratch
|
||
mtpr r0, pt0 // Stash for scratch
|
||
|
||
zap r12, 0x3c, r12 // Clear scratch
|
||
blbs r12, sys_double_machine_check // MCHK halt if double machine check
|
||
|
||
or r12, r14, r12 // Combine mchk code
|
||
lda r14, scb_v_sysmchk(r31) // Get SCB vector
|
||
|
||
sll r14, 16, r14 // Move SCBv to position
|
||
or r12, r14, r14 // Combine SCBv
|
||
|
||
bis r14, 1<<mces_v_mchk, r14 // Set MCES<MCHK> bit
|
||
mtpr r14, pt_misc // Save mchk code!scbv!whami!mces
|
||
|
||
ldah r14, 0xfff0(r31)
|
||
mtpr r1, pt1 // Stash for scratch
|
||
|
||
zap r14, 0xE0, r14 // Get Cbox IPR base
|
||
mtpr r4, pt4
|
||
|
||
mtpr r5, pt5
|
||
|
||
// Start to collect the IPRs. Common entry point for mchk flows.
|
||
//
|
||
// Current state:
|
||
// pt0 - saved r0
|
||
// pt1 - saved r1
|
||
// pt4 - saved r4
|
||
// pt5 - saved r5
|
||
// pt6 - saved r6
|
||
// pt10 - saved exc_addr
|
||
// pt_misc<47:32> - mchk code
|
||
// pt_misc<31:16> - scb vector
|
||
// r6 - saved machine check code
|
||
// r0, r1, r4, r5, r12, r13, r25 - available
|
||
// r8, r9, r10 - available as all loads are physical
|
||
// MCES<mchk> is set and machine check code is saved
|
||
|
||
ldah r14, 0xfff0(r31)
|
||
mtpr r1, pt1 // Stash for scratch - 30 instructions
|
||
|
||
zap r14, 0xE0, r14 // Get Cbox IPR base
|
||
|
||
mb // MB before reading Scache IPRs
|
||
mfpr r1, icperr_stat
|
||
|
||
mfpr r8, dcperr_stat
|
||
mtpr r31, dc_flush // Flush the Dcache
|
||
|
||
mfpr r31, pt0 // Pad Mbox instructions from dc_flush
|
||
mfpr r31, pt0
|
||
nop
|
||
nop
|
||
|
||
ldqp r9, sc_addr(r14)// SC_ADDR IPR
|
||
bis r9, r31, r31 // Touch ld to make sure it completes before
|
||
// read of SC_STAT
|
||
ldqp r10, sc_stat(r14) // SC_STAT, also unlocks SC_ADDR
|
||
|
||
ldqp r12, ei_addr(r14)// EI_ADDR IPR
|
||
ldqp r13, bc_tag_addr(r14) // BC_TAG_ADDR IPR
|
||
ldqp r0, fill_syn(r14) // FILL_SYN IPR
|
||
// Touch lds to make sure they complete before reading EI_STAT
|
||
bis r12, r13, r31
|
||
bis r0, r0, r31
|
||
ldqp r25, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
|
||
ldqp r31, ei_stat(r14) // Read again to insure it is unlocked
|
||
br r31, sys_mchk_write_logout_frame // Join common machine check flow
|
||
|
||
|
||
// .sbttl "SYS_INT_PERF_CNT - Performance counter interrupt code"
|
||
//+
|
||
//sys_int_perf_cnt
|
||
//
|
||
// A performance counter interrupt has been detected. The stack has been pushed.
|
||
// IPL and PS are updated as well.
|
||
//
|
||
// on exit to interrupt entry point ENTINT::
|
||
// a0 = osfint_c_perf
|
||
// a1 = scb_v_perfmon (650)
|
||
// a2 = 0 if performance counter 0 fired
|
||
// a2 = 1 if performance counter 1 fired
|
||
// a2 = 2 if performance counter 2 fired
|
||
// (if more than one counter overflowed, an interrupt will be
|
||
// generated for each counter that overflows)
|
||
//
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
sys_int_perf_cnt: // Performance counter interrupt
|
||
lda r17, scb_v_perfmon(r31) // a1 to interrupt vector
|
||
mfpr r25, pt_entInt
|
||
|
||
lda r16, osfint_c_perf(r31) // a0 to perf counter code
|
||
mtpr r25, exc_addr
|
||
|
||
//isolate which perf ctr fired, load code in a2, and ack
|
||
mfpr r25, isr
|
||
or r31, r31, r18 // assume interrupt was pc0
|
||
|
||
srl r25, isr_v_pc1, r25 // isolate
|
||
cmovlbs r25, 1, r18 // if pc1 set, load 1 into r14
|
||
|
||
srl r25, 1, r25 // get pc2
|
||
cmovlbs r25, 2, r18 // if pc2 set, load 2 into r14
|
||
|
||
lda r25, 1(r31) // get a one
|
||
sll r25, r18, r25
|
||
|
||
sll r25, hwint_clr_v_pc0c, r25 // ack only the perf counter that generated the interrupt
|
||
mtpr r25, hwint_clr
|
||
|
||
hw_rei_spe
|
||
|
||
|
||
|
||
// .sbttl "System specific RESET code"
|
||
//+
|
||
// RESET code
|
||
// On entry:
|
||
// r1 = pal_base +8
|
||
//
|
||
// Entry state on trap:
|
||
// r0 = whami
|
||
// r2 = base of scratch area
|
||
// r3 = halt code
|
||
// and the following 3 if init_cbox is enabled:
|
||
// r5 = sc_ctl
|
||
// r6 = bc_ctl
|
||
// r7 = bc_cnfg
|
||
//
|
||
// Entry state on switch:
|
||
// r17 - new PC
|
||
// r18 - new PCBB
|
||
// r19 - new VPTB
|
||
//
|
||
//-
|
||
ALIGN_BLOCK
|
||
.globl sys_reset
|
||
sys_reset:
|
||
bis r1, r31, r22
|
||
bis r2, r31, r23
|
||
bis r3, r31, r24
|
||
|
||
lda r0, 0(zero) // The XXM has only one CPU
|
||
lda r2, 0x2000(zero) // KLUDGE the impure area address
|
||
lda r3, 0(zero) // Machine restart
|
||
mtpr r31, pt_misc // Zero out whami & swppal flag
|
||
mtpr r31, pt0 // halt code of "reset"
|
||
mtpr r31, pt1 // whami is always 0 on XXM
|
||
|
||
/* Check to see if the transfer from the POST (Power-on-Self Test) code
|
||
** is following a standard protocol and that the other input parameter
|
||
** values may be trusted. Register a3 (r19) will contain a signature if so.
|
||
**
|
||
** Register values:
|
||
**
|
||
** t0 (r1) bcCtl value, saved into pt4
|
||
** t1 (r2) bcCfg value
|
||
** t2 (r3) bcCfgOff value (values for bcache off)
|
||
**
|
||
** s6 (r15) encoded srom.s RCS revision
|
||
** a0 (r16) processor identification (a la SRM)
|
||
** a1 (r17) size of contiguous, good memory in bytes
|
||
** a2 (r18) cycle count in picoseconds
|
||
** a3 (r19) signature (0xDECB) in <31:16> and system revision ID in <15:0>
|
||
** a4 (r20) active processor mask
|
||
** a5 (r21) system context value
|
||
*/
|
||
lda r4, CNS_Q_IPR(r2) // Point to base of IPR area.
|
||
lda r4, pal_impure_common_size(r4) // Bias by PAL common size
|
||
SAVE_SHADOW(r22,CNS_Q_BC_CTL,r4) // Save shadow of bcCtl.
|
||
SAVE_SHADOW(r23,CNS_Q_BC_CFG,r4) // Save shadow of bcCfg.
|
||
#ifdef undef
|
||
SAVE_SHADOW(r24,CNS_Q_BC_CFG_OFF,r4) // Save shadow of bcCfg.
|
||
#endif
|
||
SAVE_SHADOW(r15,CNS_Q_SROM_REV,r4) // Save srom revision.
|
||
SAVE_SHADOW(r16,CNS_Q_PROC_ID,r4) // Save processor id.
|
||
SAVE_SHADOW(r17,CNS_Q_MEM_SIZE,r4) // Save memory size.
|
||
SAVE_SHADOW(r18,CNS_Q_CYCLE_CNT,r4) // Save cycle count.
|
||
SAVE_SHADOW(r19,CNS_Q_SIGNATURE,r4) // Save signature and sys rev.
|
||
SAVE_SHADOW(r20,CNS_Q_PROC_MASK,r4) // Save processor mask.
|
||
SAVE_SHADOW(r21,CNS_Q_SYSCTX,r4) // Save system context.
|
||
|
||
//;;;;;; mtpr r31, ic_flush_ctl; do not flush the icache - done by hardware before SROM load
|
||
|
||
/*
|
||
* Initialize the serial ports
|
||
*
|
||
* Baud rate: 9600 baud
|
||
* Word length: 8 bit characters
|
||
* Stop bits: 1 stop bit
|
||
* Parity: No parity
|
||
* Modem control: DTR, RTS active, OUT1 lov, UART interrupts enabled
|
||
*/
|
||
|
||
/* Initialize COM1*/
|
||
OutPortByte(COM1_LCR,LCR_M_DLAB,r12,r14)// Access clock divisor latch.
|
||
OutPortByte(COM1_DLL,DLA_K_BRG,r12,r14) // Set the baud rate.
|
||
OutPortByte(COM1_DLH,0,r12,r14)
|
||
OutPortByte(COM1_LCR,LCR_K_INIT,r12,r14)// Set line control register.
|
||
OutPortByte(COM1_MCR,MCR_K_INIT,r12,r14)// Set modem control register.
|
||
OutPortByte(COM1_IER,0x0f,r12,r14) // Turn on interrupts.
|
||
|
||
/* Flush COM1's receive buffer*/
|
||
#ifndef SIMOS
|
||
Sys_ResetFlushCom1:
|
||
InPortByte(COM1_LSR,r12,r14) // Read the line status.
|
||
blbc t0, Sys_ResetCom1Done // Are we done yet?
|
||
InPortByte(COM1_RBR,r12,r14) // Read receive buffer reg.
|
||
br zero, Sys_ResetFlushCom1 // Loop till done.
|
||
|
||
Sys_ResetCom1Done:
|
||
#endif
|
||
mb
|
||
|
||
mtpr r31, itb_ia // clear the ITB
|
||
mtpr r31, dtb_ia // clear the DTB
|
||
|
||
//;;;;;; lda r1, 0x1FFF(R31)
|
||
//;;;;;; mtpr r1, dc_test_ctl ; initialize tag index to all 1's.
|
||
|
||
/* Hardwire the base address of the PALcode */
|
||
lda r1, 0x4000(r31) // point to start of code
|
||
mtpr r1, pal_base // initialize PAL_BASE
|
||
|
||
// Interrupts
|
||
mtpr r31, astrr // stop ASTs
|
||
mtpr r31, aster // stop ASTs
|
||
mtpr r31, sirr // clear software interrupts
|
||
|
||
// enable shadow registers, floating point, kseg addressing
|
||
ldah r1, ((1<<(icsr_v_sde-16)) | (1<<(icsr_v_fpe-16)) | (2<<(icsr_v_spe-16)))(r31)
|
||
mtpr r1, icsr
|
||
|
||
// Mbox/Dcache init
|
||
lda r1, (1<<(mcsr_v_sp1))(r31)
|
||
mtpr r1, mcsr // MCSR - Super page enabled
|
||
lda r1, 1<<dc_mode_v_dc_ena(r31)
|
||
bsr r31, 1f
|
||
|
||
ALIGN_BRANCH
|
||
1: mtpr r1, dc_mode // turn Dcache on
|
||
nop
|
||
STALL // No Mbox instr in 1,2,3,4
|
||
STALL
|
||
STALL
|
||
STALL
|
||
mtpr r31, dc_flush // flush Dcache
|
||
|
||
// build PS (IPL=7,CM=K,VMM=0,SW=0)
|
||
lda r11, 0x7(r31) // Shadow copy of PS - kern mode, IPL=7
|
||
lda r1, 0x1e(r31)
|
||
|
||
mtpr r1, ev5__ipl // set internal <ipl>
|
||
mtpr r31, ips // set new ps<cm>=0, Ibox copy
|
||
mtpr r31, dtb_cm // set new ps<cm>=0, Mbox copy
|
||
|
||
// Create the PALtemp pt_intmask -
|
||
// MAP:
|
||
// OSF IPL EV5 internal IPL(hex) note
|
||
// 0 0
|
||
// 1 1
|
||
// 2 2
|
||
// 3 14 device
|
||
// 4 15 device
|
||
// 5 16 device
|
||
// 6 1e device
|
||
// 7 1e make sure we can take mchks at ipl 31
|
||
|
||
ldah r1, 0x1e1e(r31) // Create upper lw of int_mask
|
||
lda r1, 0x1615(r1)
|
||
|
||
sll r1, 32, r1
|
||
ldah r1, 0x1402(r1) // Create lower lw of int_mask
|
||
|
||
lda r1, 0x0100(r1)
|
||
mtpr r1, pt_intmask // Stash in PALtemp
|
||
|
||
// Unlock a bunch of chip internal IPRs
|
||
mtpr r31, exc_sum // clear exeception summary and exc_mask
|
||
mfpr r31, va // unlock va, mmstat
|
||
lda r8, ((1<<icperr_stat_v_dpe) | (1<<icperr_stat_v_tpe) | (1<<icperr_stat_v_tmr))(r31)
|
||
mtpr r8, icperr_stat // Clear Icache parity error & timeout
|
||
lda r8, ((1<<dcperr_stat_v_lock) | (1<<dcperr_stat_v_seo))(r31)
|
||
mtpr r8, dcperr_stat // Clear Dcache parity error status
|
||
|
||
rc r0 // clear intr_flag
|
||
mtpr r31, pt_trap
|
||
|
||
mfpr r0, pt_misc
|
||
srl r0, pt_misc_v_switch, r1
|
||
blbs r1, sys_reset_switch // see if we got here from swppal
|
||
|
||
// Rest of the "real" reset flow
|
||
// ASN
|
||
mtpr r31, dtb_asn
|
||
mtpr r31, itb_asn
|
||
|
||
lda r1, 0x1FFF(r31)
|
||
mtpr r1, dc_test_ctl // initialize tag index to all 1's.
|
||
|
||
lda r1, 0x67(r31)
|
||
sll r1, hwint_clr_v_pc0c, r1
|
||
mtpr r1, hwint_clr // Clear hardware interrupt requests
|
||
|
||
lda r1, 1<<mces_v_dpc(r31) // 1 in disable processor correctable error
|
||
mfpr r0, pt1 // get whami
|
||
insbl r0, 1, r0 // isolate whami in correct pt_misc position
|
||
or r0, r1, r1 // combine whami and mces
|
||
mtpr r1, pt_misc // store whami and mces, swap bit clear
|
||
|
||
// CPU specific impure pointer
|
||
extbl r0, 1, r0 //get whami again
|
||
#if eb164 != 0
|
||
// compile error .....
|
||
//
|
||
// mulq r0, ((pal_impure_specific_size+mchk_size+mchk_crd_size)/8), r0 ; whami * per_node size/8
|
||
lda r1, ((pal_impure_specific_size+mchk_size+mchk_crd_size)/8)(r31)
|
||
mulq r0, r1, r0 //
|
||
#endif
|
||
|
||
addq r0, pal_impure_common_size/8, r0// add common area
|
||
sll r0, 3, r0 // * 8
|
||
addq r2, r0, r2 // addr our impure area offset
|
||
mtpr r2, pt_impure
|
||
|
||
zapnot r3, 1, r0 // isolate halt code
|
||
mtpr r0, pt0 // save entry type
|
||
|
||
// Cycle counter
|
||
or r31, 1, r9 // get a one
|
||
sll r9, 32, r9 // shift to <32>
|
||
mtpr r31, cc // clear Cycle Counter
|
||
mtpr r9, cc_ctl // clear and enable the Cycle Counter
|
||
mtpr r31, pt_scc // clear System Cycle Counter
|
||
|
||
|
||
// Misc PALtemps
|
||
mtpr r31, maf_mode // no mbox instructions for 3 cycles
|
||
or r31, 1, r1 // get bogus scbb value
|
||
mtpr r1, pt_scbb // load scbb
|
||
mtpr r31, pt_prbr // clear out prbr
|
||
mfpr r1, pal_base
|
||
lda r1, (kludge_initial_pcbb-0x4000)(r1) // get address for temp pcbb
|
||
|
||
mtpr r1, pt_pcbb // load pcbb
|
||
lda r1, 2(r31) // get a two
|
||
sll r1, 32, r1 // gen up upper bits
|
||
mtpr r1, mvptbr
|
||
mtpr r1, ivptbr
|
||
mtpr r31, pt_ptbr
|
||
// Performance counters
|
||
mtpr r31, pmctr
|
||
|
||
// Clear pmctr_ctl in impure area
|
||
mfpr r1, pt_impure
|
||
stqp r31, CNS_Q_PM_CTL(r1)
|
||
|
||
ldah r14, 0xfff0(r31)
|
||
zap r14, 0xE0, r14 // Get Cbox IPR base
|
||
|
||
#ifndef SIMOS
|
||
ldqp r31, sc_stat(r14) // Clear sc_stat and sc_addr
|
||
ldqp r31, ei_stat(r14)
|
||
ldqp r31, ei_stat(r14) // Clear ei_stat, ei_addr, bc_tag_addr, fill_syn
|
||
#endif
|
||
mfpr r13, pt_impure
|
||
stqpc r31, 0(r13) // Clear lock_flag
|
||
|
||
lda r0, 0(zero)
|
||
mfpr r1, pt_impure
|
||
bsr r3, pal_save_state
|
||
|
||
mfpr r0, pt0 // get entry type
|
||
br r31, sys_enter_console // enter the cosole
|
||
|
||
|
||
// swppal entry
|
||
// r0 - pt_misc
|
||
// r17 - new PC
|
||
// r18 - new PCBB
|
||
// r19 - new VPTB
|
||
sys_reset_switch:
|
||
or r31, 1, r9
|
||
sll r9, pt_misc_v_switch, r9
|
||
bic r0, r9, r0 // clear switch bit
|
||
mtpr r0, pt_misc
|
||
|
||
rpcc r1 // get cyccounter
|
||
|
||
ldqp r22, osfpcb_q_fen(r18) // get new fen/pme
|
||
ldlp r23, osfpcb_l_cc(r18) // get cycle counter
|
||
ldlp r24, osfpcb_l_asn(r18) // get new asn
|
||
|
||
ldqp r25, osfpcb_q_Mmptr(r18)// get new mmptr
|
||
sll r25, page_offset_size_bits, r25 // convert pfn to pa
|
||
mtpr r25, pt_ptbr // load the new mmptr
|
||
mtpr r18, pt_pcbb // set new pcbb
|
||
|
||
bic r17, 3, r17 // clean use pc
|
||
mtpr r17, exc_addr // set new pc
|
||
mtpr r19, mvptbr
|
||
mtpr r19, ivptbr
|
||
|
||
ldqp r30, osfpcb_q_Usp(r18) // get new usp
|
||
mtpr r30, pt_usp // save usp
|
||
|
||
sll r24, dtb_asn_v_asn, r8
|
||
mtpr r8, dtb_asn
|
||
sll r24, itb_asn_v_asn, r24
|
||
mtpr r24, itb_asn
|
||
|
||
mfpr r25, icsr // get current icsr
|
||
lda r24, 1(r31)
|
||
sll r24, icsr_v_fpe, r24 // 1 in icsr<fpe> position
|
||
bic r25, r24, r25 // clean out old fpe
|
||
and r22, 1, r22 // isolate new fen bit
|
||
sll r22, icsr_v_fpe, r22
|
||
or r22, r25, r25 // or in new fpe
|
||
mtpr r25, icsr // update ibox ipr
|
||
|
||
subl r23, r1, r1 // gen new cc offset
|
||
insll r1, 4, r1 // << 32
|
||
mtpr r1, cc // set new offset
|
||
|
||
or r31, r31, r0 // set success
|
||
ldqp r30, osfpcb_q_Ksp(r18) // get new ksp
|
||
mfpr r31, pt0 // stall
|
||
hw_rei_stall
|
||
|
||
// .sbttl "SYS_MACHINE_CHECK - Machine check PAL"
|
||
ALIGN_BLOCK
|
||
//+
|
||
//sys_machine_check
|
||
// A machine_check trap has occurred. The Icache has been flushed.
|
||
//
|
||
//-
|
||
.globl sys_machine_check
|
||
sys_machine_check:
|
||
DEBUGSTORE(052)
|
||
DEBUGSTORE(052)
|
||
DEBUGSTORE(052)
|
||
// Need to fill up the refill buffer (32 instructions) and
|
||
// then flush the Icache again.
|
||
// Also, due to possible 2nd Cbox register file write for
|
||
// uncorrectable errors, no register file read or write for 7 cycles.
|
||
|
||
nop
|
||
mtpr r0, pt0 // Stash for scratch -- OK if Cbox overwrites r0 later
|
||
|
||
nop
|
||
nop
|
||
|
||
nop
|
||
nop
|
||
|
||
nop
|
||
nop
|
||
|
||
nop
|
||
nop
|
||
// 10 instructions; 5 cycles
|
||
|
||
nop
|
||
nop
|
||
|
||
nop
|
||
nop
|
||
|
||
// Register file can now be written
|
||
lda r0, scb_v_procmchk(r31) // SCB vector
|
||
mfpr r13, pt_mces // Get MCES
|
||
sll r0, 16, r0 // Move SCBv to correct position
|
||
bis r13, 1<<mces_v_mchk, r14 // Set MCES<MCHK> bit
|
||
|
||
zap r14, 0x3C, r14 // Clear mchk_code word and SCBv word
|
||
mtpr r14, pt_mces // 20 instructions
|
||
|
||
nop
|
||
or r14, r0, r14 // Insert new SCB vector
|
||
lda r0, mchk_c_proc_hrd_error(r31) // MCHK code
|
||
mfpr r12, exc_addr
|
||
|
||
sll r0, 32, r0 // Move MCHK code to correct position
|
||
mtpr r4, pt4
|
||
or r14, r0, r14 // Insert new MCHK code
|
||
mtpr r14, pt_misc // Store updated MCES, MCHK code, and SCBv
|
||
|
||
ldah r14, 0xfff0(r31)
|
||
mtpr r1, pt1 // Stash for scratch - 30 instructions
|
||
|
||
zap r14, 0xE0, r14 // Get Cbox IPR base
|
||
mtpr r12, pt10 // Stash exc_addr
|
||
|
||
mtpr r31, ic_flush_ctl // Second Icache flush, now it is really flushed.
|
||
// blbs r13, sys_double_machine_check ; MCHK halt if double machine check
|
||
blbs r12, sys_machine_check_while_in_pal // MCHK halt if machine check in pal
|
||
|
||
mtpr r6, pt6
|
||
mtpr r5, pt5
|
||
|
||
|
||
//+
|
||
// Start to collect the IPRs. Common entry point for mchk flows.
|
||
//
|
||
// Current state:
|
||
// pt0 - saved r0
|
||
// pt1 - saved r1
|
||
// pt4 - saved r4
|
||
// pt5 - saved r5
|
||
// pt6 - saved r6
|
||
// pt10 - saved exc_addr
|
||
// pt_misc<47:32> - mchk code
|
||
// pt_misc<31:16> - scb vector
|
||
// r14 - base of Cbox IPRs in IO space
|
||
// r0, r1, r4, r5, r6, r12, r13, r25 - available
|
||
// r8, r9, r10 - available as all loads are physical
|
||
// MCES<mchk> is set and machine check code is saved
|
||
//
|
||
//-
|
||
|
||
ALIGN_BRANCH
|
||
.globl sys_mchk_collect_iprs
|
||
sys_mchk_collect_iprs:
|
||
|
||
|
||
mb // MB before reading Scache IPRs
|
||
mfpr r1, icperr_stat
|
||
|
||
mfpr r8, dcperr_stat
|
||
mtpr r31, dc_flush // Flush the Dcache
|
||
|
||
mfpr r31, pt0 // Pad Mbox instructions from dc_flush
|
||
mfpr r31, pt0
|
||
nop
|
||
nop
|
||
|
||
ldqp r9, sc_addr(r14) // SC_ADDR IPR
|
||
bis r9, r31, r31 // Touch ld to make sure it completes before
|
||
// read of SC_STAT
|
||
ldqp r10, sc_stat(r14) // SC_STAT, also unlocks SC_ADDR
|
||
|
||
ldqp r12, ei_addr(r14) // EI_ADDR IPR
|
||
ldqp r13, bc_tag_addr(r14) // BC_TAG_ADDR IPR
|
||
ldqp r0, fill_syn(r14) // FILL_SYN IPR
|
||
// Touch lds to make sure they complete before reading EI_STAT
|
||
bis r12, r13, r31
|
||
// wait for r0 ldqp to complete
|
||
bis r0, r0, r31
|
||
ldqp r25, ei_stat(r14) // EI_STAT, unlock EI_ADDR, BC_TAG_ADDR, FILL_SYN
|
||
ldqp r31, ei_stat(r14) // Read again to insure it is unlocked
|
||
mfpr r6, pt_misc
|
||
extwl r6, 4, r6 // Fetch mchk code
|
||
br r31, sys_mchk_write_logout_frame //
|
||
|
||
|
||
|
||
//+
|
||
// Write the logout frame
|
||
//
|
||
// Current state:
|
||
// r0 - fill_syn
|
||
// r1 - icperr_stat
|
||
// r4 - available
|
||
// r5<0> - retry flag
|
||
// r6 - mchk code
|
||
// r8 - dcperr_stat
|
||
// r9 - sc_addr
|
||
// r10 - sc_stat
|
||
// r12 - ei_addr
|
||
// r13 - bc_tag_addr
|
||
// r14 - available
|
||
// r25 - ei_stat (shifted)
|
||
// pt0 - saved r0
|
||
// pt1 - saved r1
|
||
// pt4 - saved r4
|
||
// pt5 - saved r5
|
||
// pt6 - saved r6
|
||
// pt10 - saved exc_addr
|
||
//
|
||
//-
|
||
ALIGN_BRANCH
|
||
sys_mchk_write_logout_frame:
|
||
//------------------------------------------------------------------------------------
|
||
// EB164 specific code ....
|
||
//
|
||
// R14 - uncorrectable error logout frame address = 6000h + size of CRD frame
|
||
//
|
||
//------------------------------------------------------------------------------------
|
||
#if eb164 != 0
|
||
|
||
|
||
lda r14,PAL_LOGOUT_BASE(r31) // get the start of logout frame location
|
||
lda r14,mchk_mchk_base(r14) // add in the size of the CRD frame
|
||
#endif
|
||
|
||
// Write the first 2 quadwords of the logout area:
|
||
|
||
sll r5, 63, r5 // Move retry flag to bit 63
|
||
lda r4, mchk_size(r5) // Combine retry flag and frame size
|
||
stqp r4, mchk_flag(r14) // store flag/frame size
|
||
lda r4, mchk_sys_base(r31) // sys offset
|
||
sll r4, 32, r4
|
||
lda r4, mchk_cpu_base(r4) // cpu offset
|
||
stqp r4, mchk_offsets(r14) // store sys offset/cpu offset into logout frame
|
||
|
||
//+
|
||
// Write the mchk code to the logout area
|
||
// Write error IPRs already fetched to the logout area
|
||
// Restore some GPRs from PALtemps
|
||
//-
|
||
|
||
mfpr r5, pt5
|
||
stqp r6, mchk_mchk_code(r14)
|
||
mfpr r4, pt4
|
||
stqp r1, mchk_ic_perr_stat(r14)
|
||
mfpr r6, pt6
|
||
stqp r8, mchk_dc_perr_stat(r14)
|
||
mfpr r1, pt1
|
||
stqp r9, mchk_sc_addr(r14)
|
||
stqp r10, mchk_sc_stat(r14)
|
||
stqp r12, mchk_ei_addr(r14)
|
||
stqp r13, mchk_bc_tag_addr(r14)
|
||
stqp r0, mchk_fill_syn(r14)
|
||
mfpr r0, pt0
|
||
#define ei_stat_v_bc_tperr 28
|
||
sll r25, ei_stat_v_bc_tperr, r25 // Move EI_STAT status bits back to expected position
|
||
//
|
||
// Steve Shirron ei_stat.chip_id bits fix
|
||
//
|
||
// r25 has the ei_stat<35:28> bits aligned to bit 0.
|
||
// Because this alignment trashed the ei_stat.chip_id<27:24> bits,
|
||
// Steve's fix re-reads the ei_stat to recover the chip_id bits before
|
||
// writing the ei_stat to the log.
|
||
//
|
||
ldah r13, 0xfff0(r31) // r13 <- pointer to cbox
|
||
zapnot r13, 0x1f, r13 // :
|
||
ldqp r13, ei_stat(r13) // r13 <- contents of ei_stat register
|
||
sll r13, 64-ei_stat_v_bc_tperr, r13 // clear bits <63:36>
|
||
srl r13, 64-ei_stat_v_bc_tperr, r13 // put ei_stat bits back
|
||
or r25, r13, r25 // or-in the stat bits from the original read
|
||
stqp r25, mchk_ei_stat(r14) // write to the log
|
||
|
||
mfpr r25, pt10
|
||
stqp r25, mchk_exc_addr(r14)
|
||
|
||
// complete the CPU-specific part of the logout frame
|
||
|
||
#define mchk_logout(regName, regOff) \
|
||
mfpr r25, regName ; \
|
||
stqp r25, CNS_Q_/**/regOff(r14)
|
||
|
||
// mchk_logout(mm_stat, MM_STAT)
|
||
// mchk_logout(va, VA) // Unlocks VA and MM_STAT
|
||
// mchk_logout(isr, ISR)
|
||
// mchk_logout(icsr, ICSR)
|
||
// mchk_logout(pal_base, PAL_BASE)
|
||
// mchk_logout(exc_mask, EXC_MASK)
|
||
// mchk_logout(exc_sum, EXC_SUM)
|
||
|
||
mfpr r25, mm_stat
|
||
stqp r25, CNS_Q_MM_STAT(r14)
|
||
mfpr r25, va
|
||
stqp r25, CNS_Q_VA(r14)
|
||
mfpr r25, isr
|
||
stqp r25, CNS_Q_ISR(r14)
|
||
mfpr r25, icsr
|
||
stqp r25, CNS_Q_ICSR(r14)
|
||
mfpr r25, pal_base
|
||
stqp r25, CNS_Q_PAL_BASE(r14)
|
||
mfpr r25, exc_mask
|
||
stqp r25, CNS_Q_EXC_MASK(r14)
|
||
mfpr r25, exc_sum
|
||
stqp r25, CNS_Q_EXC_SUM(r14)
|
||
|
||
|
||
|
||
|
||
|
||
ldah r13, 0xfff0(r31)
|
||
zap r13, 0xE0, r13 // Get Cbox IPR base
|
||
ldqp r13, ld_lock(r13) // Get ld_lock IPR
|
||
stqp r13, mchk_ld_lock(r14) // and stash it in the frame
|
||
|
||
//+
|
||
// complete the PAL-specific part of the logout frame
|
||
//-
|
||
#define svpt(n)\
|
||
mfpr r25, pt/**/n ;\
|
||
stqp r25, CNS_Q_PT+(8*n)(r14)
|
||
|
||
mfpr r25, pt0
|
||
stqp r25, CNS_Q_PT+(8*0)(r14)
|
||
mfpr r25, pt1
|
||
stqp r25, CNS_Q_PT+(8*1)(r14)
|
||
mfpr r25, pt2
|
||
stqp r25, CNS_Q_PT+(8*2)(r14)
|
||
mfpr r25, pt3
|
||
stqp r25, CNS_Q_PT+(8*3)(r14)
|
||
mfpr r25, pt4
|
||
stqp r25, CNS_Q_PT+(8*4)(r14)
|
||
mfpr r25, pt5
|
||
stqp r25, CNS_Q_PT+(8*5)(r14)
|
||
mfpr r25, pt6
|
||
stqp r25, CNS_Q_PT+(8*6)(r14)
|
||
mfpr r25, pt7
|
||
stqp r25, CNS_Q_PT+(8*7)(r14)
|
||
mfpr r25, pt8
|
||
stqp r25, CNS_Q_PT+(8*8)(r14)
|
||
mfpr r25, pt9
|
||
stqp r25, CNS_Q_PT+(8*9)(r14)
|
||
mfpr r25, pt10
|
||
stqp r25, CNS_Q_PT+(8*10)(r14)
|
||
mfpr r25, pt11
|
||
stqp r25, CNS_Q_PT+(8*11)(r14)
|
||
mfpr r25, pt12
|
||
stqp r25, CNS_Q_PT+(8*12)(r14)
|
||
mfpr r25, pt13
|
||
stqp r25, CNS_Q_PT+(8*13)(r14)
|
||
mfpr r25, pt14
|
||
stqp r25, CNS_Q_PT+(8*14)(r14)
|
||
mfpr r25, pt15
|
||
stqp r25, CNS_Q_PT+(8*15)(r14)
|
||
mfpr r25, pt16
|
||
stqp r25, CNS_Q_PT+(8*16)(r14)
|
||
mfpr r25, pt17
|
||
stqp r25, CNS_Q_PT+(8*17)(r14)
|
||
mfpr r25, pt18
|
||
stqp r25, CNS_Q_PT+(8*18)(r14)
|
||
mfpr r25, pt19
|
||
stqp r25, CNS_Q_PT+(8*19)(r14)
|
||
mfpr r25, pt20
|
||
stqp r25, CNS_Q_PT+(8*20)(r14)
|
||
mfpr r25, pt21
|
||
stqp r25, CNS_Q_PT+(8*21)(r14)
|
||
mfpr r25, pt22
|
||
stqp r25, CNS_Q_PT+(8*22)(r14)
|
||
mfpr r25, pt23
|
||
stqp r25, CNS_Q_PT+(8*23)(r14)
|
||
|
||
|
||
// svpt(0)
|
||
// svpt(1)
|
||
// svpt(2)
|
||
// svpt(3)
|
||
// svpt(4)
|
||
// svpt(5)
|
||
// svpt(6)
|
||
// svpt(7)
|
||
// svpt(8)
|
||
// svpt(9)
|
||
// svpt(10)
|
||
// svpt(11)
|
||
// svpt(12)
|
||
// svpt(13)
|
||
// svpt(14)
|
||
// svpt(15)
|
||
// svpt(16)
|
||
// svpt(17)
|
||
// svpt(18)
|
||
// svpt(19)
|
||
// svpt(20)
|
||
// svpt(21)
|
||
// svpt(22)
|
||
// svpt(23)
|
||
//
|
||
//+
|
||
// Log system specific info here
|
||
//-
|
||
|
||
// Unlock IPRs
|
||
lda r8, ((1<<dcperr_stat_v_lock) | (1<<dcperr_stat_v_seo))(r31)
|
||
mtpr r8, dcperr_stat // Clear Dcache parity error status
|
||
|
||
lda r8, ((1<<icperr_stat_v_dpe) | (1<<icperr_stat_v_tpe) | (1<<icperr_stat_v_tmr))(r31)
|
||
mtpr r8, icperr_stat // Clear Icache parity error & timeout status
|
||
|
||
// pvc_jsr armc, bsr=1
|
||
bsr r12, sys_arith_and_mchk // go check for and deal with arith trap
|
||
|
||
mtpr r31, exc_sum // Clear Exception Summary
|
||
|
||
mfpr r25, pt10 // write exc_addr after arith_and_mchk to pickup new pc
|
||
stqp r25, mchk_exc_addr(r14)
|
||
|
||
//+
|
||
// Set up the km trap
|
||
//-
|
||
|
||
sys_post_mchk_trap:
|
||
mfpr r25, pt_misc // Check for flag from mchk interrupt
|
||
extwl r25, 4, r25
|
||
blbs r25, sys_mchk_stack_done // Stack from already pushed if from interrupt flow
|
||
|
||
bis r14, r31, r12 // stash pointer to logout area
|
||
mfpr r14, pt10 // get exc_addr
|
||
|
||
sll r11, 63-3, r25 // get mode to msb
|
||
bge r25, sys_post_mchk_trap_30_
|
||
|
||
mtpr r31, dtb_cm
|
||
mtpr r31, ips
|
||
|
||
mtpr r30, pt_usp // save user stack
|
||
mfpr r30, pt_ksp
|
||
|
||
sys_post_mchk_trap_30_:
|
||
lda sp, 0-osfsf_c_size(sp) // allocate stack space
|
||
nop
|
||
|
||
stq r18, osfsf_a2(sp) // a2
|
||
stq r11, osfsf_ps(sp) // save ps
|
||
|
||
stq r14, osfsf_pc(sp) // save pc
|
||
mfpr r25, pt_entInt // get the VA of the interrupt routine
|
||
|
||
stq r16, osfsf_a0(sp) // a0
|
||
lda r16, osfint_c_mchk(r31) // flag as mchk in a0
|
||
|
||
stq r17, osfsf_a1(sp) // a1
|
||
mfpr r17, pt_misc // get vector
|
||
|
||
stq r29, osfsf_gp(sp) // old gp
|
||
mtpr r25, exc_addr //
|
||
|
||
or r31, 7, r11 // get new ps (km, high ipl)
|
||
subq r31, 1, r18 // get a -1
|
||
|
||
extwl r17, 2, r17 // a1 <- interrupt vector
|
||
bis r31, ipl_machine_check, r25
|
||
|
||
mtpr r25, ev5__ipl // Set internal ipl
|
||
srl r18, 42, r18 // shift off low bits of kseg addr
|
||
|
||
sll r18, 42, r18 // shift back into position
|
||
mfpr r29, pt_kgp // get the kern r29
|
||
|
||
or r12, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address
|
||
|
||
hw_rei_spe // out to interrupt dispatch routine
|
||
|
||
|
||
//+
|
||
// The stack is pushed. Load up a0,a1,a2 and vector via entInt
|
||
//
|
||
//-
|
||
ALIGN_BRANCH
|
||
sys_mchk_stack_done:
|
||
lda r16, osfint_c_mchk(r31) // flag as mchk/crd in a0
|
||
lda r17, scb_v_sysmchk(r31) // a1 <- interrupt vector
|
||
|
||
subq r31, 1, r18 // get a -1
|
||
mfpr r25, pt_entInt
|
||
|
||
srl r18, 42, r18 // shift off low bits of kseg addr
|
||
mtpr r25, exc_addr // load interrupt vector
|
||
|
||
sll r18, 42, r18 // shift back into position
|
||
or r14, r18, r18 // EV4 algorithm - pass pointer to mchk frame as kseg address
|
||
|
||
hw_rei_spe // done
|
||
|
||
|
||
|
||
|
||
//sys_double_machine_check - a machine check was started, but MCES<MCHK> was
|
||
// already set. We will now double machine check halt.
|
||
//
|
||
// pt0 - old R0
|
||
//
|
||
ALIGN_BLOCK
|
||
.globl sys_double_machine_check
|
||
sys_double_machine_check:
|
||
|
||
// pvc_jsr updpcb, bsr=1
|
||
// bsr r0, pal_update_pcb // update the pcb
|
||
lda r0, hlt_c_dbl_mchk(r31)
|
||
br r31, sys_enter_console
|
||
|
||
//sys_machine_check_while_in_pal - a machine check was started, exc_addr points to
|
||
// a PAL PC. We will now machine check halt.
|
||
//
|
||
// pt0 - old R0
|
||
//
|
||
sys_machine_check_while_in_pal:
|
||
|
||
// pvc_jsr updpcb, bsr=1
|
||
// bsr r0, pal_update_pcb // update the pcb
|
||
lda r0, hlt_c_mchk_from_pal(r31)
|
||
br r31, sys_enter_console
|
||
|
||
//ARITH and MCHK
|
||
// Check for arithmetic errors and build trap frame,
|
||
// but don't post the trap.
|
||
// on entry:
|
||
// pt10 - exc_addr
|
||
// r12 - return address
|
||
// r14 - logout frame pointer
|
||
// r13 - available
|
||
// r8,r9,r10 - available except across stq's
|
||
// pt0,1,6 - available
|
||
//
|
||
// on exit:
|
||
// pt10 - new exc_addr
|
||
// r17 = exc_mask
|
||
// r16 = exc_sum
|
||
// r14 - logout frame pointer
|
||
//
|
||
ALIGN_BRANCH
|
||
sys_arith_and_mchk:
|
||
mfpr r13, ev5__exc_sum
|
||
srl r13, exc_sum_v_swc, r13
|
||
bne r13, handle_arith_and_mchk
|
||
|
||
// pvc_jsr armc, bsr=1, dest=1
|
||
ret r31, (r12) // return if no outstanding arithmetic error
|
||
|
||
handle_arith_and_mchk:
|
||
mtpr r31, ev5__dtb_cm // Set Mbox current mode to kernel -
|
||
// no virt ref for next 2 cycles
|
||
mtpr r14, pt0
|
||
|
||
mtpr r1, pt1 // get a scratch reg
|
||
and r11, osfps_m_mode, r1 // get mode bit
|
||
|
||
bis r11, r31, r25 // save ps
|
||
beq r1, handle_arith_and_mchk_10_ // if zero we are in kern now
|
||
|
||
bis r31, r31, r25 // set the new ps
|
||
mtpr r30, pt_usp // save user stack
|
||
|
||
mfpr r30, pt_ksp // get kern stack
|
||
handle_arith_and_mchk_10_:
|
||
mfpr r14, exc_addr // get pc into r14 in case stack writes fault
|
||
|
||
lda sp, 0-osfsf_c_size(sp) // allocate stack space
|
||
mtpr r31, ev5__ps // Set Ibox current mode to kernel
|
||
|
||
mfpr r1, pt_entArith
|
||
stq r14, osfsf_pc(sp) // save pc
|
||
|
||
stq r17, osfsf_a1(sp)
|
||
mfpr r17, ev5__exc_mask // Get exception register mask IPR - no mtpr exc_sum in next cycle
|
||
|
||
stq r29, osfsf_gp(sp)
|
||
stq r16, osfsf_a0(sp) // save regs
|
||
|
||
bis r13, r31, r16 // move exc_sum to r16
|
||
stq r18, osfsf_a2(sp)
|
||
|
||
stq r11, osfsf_ps(sp) // save ps
|
||
mfpr r29, pt_kgp // get the kern gp
|
||
|
||
mfpr r14, pt0 // restore logout frame pointer from pt0
|
||
bis r25, r31, r11 // set new ps
|
||
|
||
mtpr r1, pt10 // Set new PC
|
||
mfpr r1, pt1
|
||
|
||
// pvc_jsr armc, bsr=1, dest=1
|
||
ret r31, (r12) // return if no outstanding arithmetic error
|
||
|
||
|
||
|
||
|
||
|
||
// .sbttl "SYS_ENTER_CONSOLE - Common PALcode for ENTERING console"
|
||
|
||
// SYS_enter_console
|
||
//
|
||
// Entry:
|
||
// Entered when PAL wants to enter the console.
|
||
// usually as the result of a HALT instruction or button,
|
||
// or catastrophic error.
|
||
//
|
||
// Regs on entry...
|
||
//
|
||
// R0 = halt code
|
||
// pt0 <- r0
|
||
//
|
||
// Function:
|
||
//
|
||
// Save all readable machine state, and "call" the console
|
||
//
|
||
// Returns:
|
||
//
|
||
//
|
||
// Notes:
|
||
//
|
||
// In these routines, once the save state routine has been executed,
|
||
// the remainder of the registers become scratchable, as the only
|
||
// "valid" copy of them is the "saved" copy.
|
||
//
|
||
// Any registers or PTs that are modified before calling the save
|
||
// routine will have there data lost. The code below will save all
|
||
// state, but will loose pt 0,4,5.
|
||
//
|
||
//-
|
||
#define KSEG 0xfffffc0000000000
|
||
ALIGN_BLOCK
|
||
.globl sys_enter_console
|
||
sys_enter_console:
|
||
|
||
DEBUGSTORE(0x7a)
|
||
DEBUG_EXC_ADDR()
|
||
DEBUGSTORE(13)
|
||
DEBUGSTORE(10)
|
||
mtpr r1, pt4
|
||
mtpr r3, pt5
|
||
STALL
|
||
STALL
|
||
mfpr r1, pt_impure
|
||
bsr r3, pal_save_state
|
||
|
||
// build PS (IPL=7,CM=K,VMM=0,SW=0)
|
||
lda r11, 0x7(r31) // Shadow copy of PS - kern mode, IPL=7
|
||
lda r1, 0x1e(r31)
|
||
mtpr r1, ev5__ipl // set internal <ipl>
|
||
|
||
/* kernel sp: KSEG + 0xffe000 */
|
||
subq r31, 1, sp
|
||
sll sp, 42, sp
|
||
lda r3, 0xffe(zero)
|
||
sll r3, 12, r3
|
||
addq r3, sp, sp
|
||
mtpr sp, ptKsp // Update the saved KSP value.
|
||
mtpr zero, ips // Set mode to kernel, IPL = 0.
|
||
mtpr zero, dtb_ia // Flush the DTB
|
||
mtpr zero, itb_ia // Flush the ITB
|
||
mtpr zero, astrr // Clear all ASTs ...
|
||
mtpr zero, aster
|
||
mtpr zero, sirr // Clear all software interrupts.
|
||
// lda r3, pal_enter_console_ptr(r31) //find stored vector
|
||
// ldqp r1, 0(r3)
|
||
/* put the KSEG address in the top, then add 0x10000 to it */
|
||
subq r31, 1, r1
|
||
sll r1, 42, r1
|
||
|
||
ldah r1, 1(r1)
|
||
mtpr r1, exc_addr
|
||
mfpr r1, pt4
|
||
mfpr r3, pt5
|
||
STALL
|
||
STALL
|
||
hw_rei_stall
|
||
|
||
.align 7
|
||
kludge_initial_pcbb: // PCB is 128 bytes long
|
||
.quad 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||
|
||
.globl debugstore
|
||
debugstore:
|
||
stq_p r16,0(zero)
|
||
stq_p r17,8(zero)
|
||
lda r16, 0x400(zero)
|
||
sll r16, 29, r16
|
||
ldah r16, 0x280(r16)
|
||
9: lda r17, 0x140(r16)
|
||
ldl_p r17, 0(r17)
|
||
srl r17, 16, r17
|
||
and r17, 0x20, r17
|
||
beq r17, 9b
|
||
stl_p r13, 0(r16)
|
||
mb
|
||
ldq_p r17, 8(zero)
|
||
ldq_p r16, 0(zero)
|
||
jmp r31, (r25)
|
||
|
||
//
|
||
.globl put_exc_addr
|
||
put_exc_addr:
|
||
stq_p r16,0(zero)
|
||
stq_p r17,8(zero)
|
||
stq_p r18,16(zero)
|
||
stq_p r19,24(zero)
|
||
|
||
mfpr r16, exc_addr
|
||
bis r31, 64-4, r17 // shift count for quadword
|
||
|
||
1: lda r18, 0x400(zero) // Wait for UART ready
|
||
sll r18, 29, r18
|
||
ldah r18, 0x280(r18)
|
||
9: lda r19, 0x140(r18)
|
||
ldl_p r19, 0(r19)
|
||
srl r19, 16, r19
|
||
and r19, 0x20, r19
|
||
beq r19, 9b
|
||
|
||
srl r16, r17, r19 // grab a nibble
|
||
and r19, 0x0f, r19
|
||
addq r19, 0x30, r19 // make ascii
|
||
cmple r19, 0x39, r18
|
||
bne r18, 0f
|
||
addq r19, 0x27, r19 // 0x07 gets A-F
|
||
|
||
0: lda r18, 0x400(zero) // Wait for UART ready
|
||
sll r18, 29, r18
|
||
ldah r18, 0x280(r18)
|
||
|
||
stl_p r19, 0(r18)
|
||
mb
|
||
|
||
subq r17, 4, r17 // do all nibbles
|
||
bge r17, 1b
|
||
|
||
ldq_p r16,0(zero)
|
||
ldq_p r17,8(zero)
|
||
ldq_p r18,16(zero)
|
||
ldq_p r19,24(zero)
|
||
|
||
ret r31, (r25)
|
||
|
||
// print out r13
|
||
.globl put_hex
|
||
put_hex:
|
||
stq_p r16,0(zero)
|
||
stq_p r17,8(zero)
|
||
stq_p r18,16(zero)
|
||
stq_p r19,24(zero)
|
||
|
||
bis r13, zero, r16
|
||
bis r31, 64-4, r17 // shift count for quadword
|
||
|
||
1: lda r18, 0x400(zero) // Wait for UART ready
|
||
sll r18, 29, r18
|
||
ldah r18, 0x280(r18)
|
||
9: lda r19, 0x140(r18)
|
||
ldl_p r19, 0(r19)
|
||
srl r19, 16, r19
|
||
and r19, 0x20, r19
|
||
beq r19, 9b
|
||
|
||
srl r16, r17, r19 // grab a nibble
|
||
and r19, 0x0f, r19
|
||
addq r19, 0x30, r19 // make ascii
|
||
cmple r19, 0x39, r18
|
||
bne r18, 0f
|
||
addq r19, 0x27, r19 // 0x07 gets A-F
|
||
|
||
0: lda r18, 0x400(zero) // Wait for UART ready
|
||
sll r18, 29, r18
|
||
ldah r18, 0x280(r18)
|
||
|
||
stl_p r19, 0(r18)
|
||
mb
|
||
|
||
subq r17, 4, r17 // do all nibbles
|
||
bge r17, 1b
|
||
|
||
ldq_p r16,0(zero)
|
||
ldq_p r17,8(zero)
|
||
ldq_p r18,16(zero)
|
||
ldq_p r19,24(zero)
|
||
|
||
ret r31, (r25)
|
||
|
||
|
||
/*
|
||
**
|
||
** FUNCTIONAL DESCRIPTION:
|
||
**
|
||
** Transfer control to the specified address, passed in
|
||
** register a0, in PAL mode.
|
||
**
|
||
** INPUT PARAMETERS:
|
||
**
|
||
** a0 (r16) - Transfer address
|
||
**
|
||
** OUTPUT PARAMETERS:
|
||
**
|
||
** DECchip 21064 specific parameters:
|
||
**
|
||
** t0 (r1) - bcCtl
|
||
** t1 (r2) - bcCfg
|
||
**
|
||
** Firmware specific parameters:
|
||
**
|
||
** s6 (r15) - Encoded srom.s RCS revision
|
||
** a0 (r16) - Processor identification (a la SRM)
|
||
** a1 (r17) - Size of good memory in bytes
|
||
** a2 (r18) - Cycle count in picoseconds
|
||
** a3 (r19) - Protocol signature and system revision
|
||
** a4 (r20) - Active processor mask
|
||
** a5 (r21) - System Context value
|
||
**
|
||
** SIDE EFFECTS:
|
||
**
|
||
*/
|
||
ALIGN_BRANCH
|
||
|
||
Sys_Cserve_Jtopal:
|
||
bic a0, 3, t8 // Clear out low 2 bits of address
|
||
bis t8, 1, t8 // Or in PAL mode bit
|
||
|
||
mfpr t9, ptImpure // Get base of impure scratch area.
|
||
lda t9, CNS_Q_IPR(t9) // Point to start of IPR area.
|
||
|
||
RESTORE_SHADOW(a3,CNS_Q_SIGNATURE,t9) // Get signature.
|
||
srl a3, 16, t0 // Shift signature into lower word.
|
||
|
||
LDLI(t10,0xDECB) // Load the expected valid signature.
|
||
|
||
cmpeq t0, t10, t0 // Check if saved signature was valid.
|
||
blbc t0, 1f // If invalid, pass nothing.
|
||
/*
|
||
** Load the processor specific parameters ...
|
||
*/
|
||
RESTORE_SHADOW(t0,CNS_Q_BC_CTL,t9) // Get bcCtl.
|
||
RESTORE_SHADOW(t1,CNS_Q_BC_CFG,t9) // Get bcCfg.
|
||
/* RESTORE_SHADOW(t2,CNS_Q_BC_CFG_OFF,t9) // Get bcCfg.*/
|
||
/*
|
||
** Load the firmware specific parameters ...
|
||
*/
|
||
RESTORE_SHADOW(s6,CNS_Q_SROM_REV,t9) // Get srom revision.
|
||
RESTORE_SHADOW(a0,CNS_Q_PROC_ID,t9) // Get processor id.
|
||
RESTORE_SHADOW(a1,CNS_Q_MEM_SIZE,t9) // Get memory size.
|
||
RESTORE_SHADOW(a2,CNS_Q_CYCLE_CNT,t9) // Get cycle count.
|
||
RESTORE_SHADOW(a4,CNS_Q_PROC_MASK,t9) // Get processor mask.
|
||
RESTORE_SHADOW(a5,CNS_Q_SYSCTX,t9) // Get system context.
|
||
|
||
STALL
|
||
STALL
|
||
|
||
1: mtpr zero, ptWhami // Clear WHAMI and swap flag.
|
||
mtpr t8, excAddr // Load the dispatch address.
|
||
br zero, 2f
|
||
|
||
ALIGN_BLOCK
|
||
|
||
2: NOP
|
||
mtpr zero, icFlush // Flush the icache.
|
||
NOP
|
||
NOP
|
||
|
||
NOP // Required NOPs ... 1-10
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
NOP // Required NOPs ... 11-20
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
NOP // Required NOPs ... 21-30
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
NOP // Required NOPs ... 31-40
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
|
||
|
||
NOP // Required NOPs ... 41-44
|
||
NOP
|
||
NOP
|
||
NOP
|
||
|
||
hw_rei // Dispatch in PAL mode ...
|