// 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 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< 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 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< mtpr r31, ips // set new ps=0, Ibox copy mtpr r31, dtb_cm // set new ps=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< 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 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< 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 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< 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 /* 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 ...