diff options
Diffstat (limited to 'private/ntos/fw/mips/j4start.s')
-rw-r--r-- | private/ntos/fw/mips/j4start.s | 756 |
1 files changed, 756 insertions, 0 deletions
diff --git a/private/ntos/fw/mips/j4start.s b/private/ntos/fw/mips/j4start.s new file mode 100644 index 000000000..e2057fde3 --- /dev/null +++ b/private/ntos/fw/mips/j4start.s @@ -0,0 +1,756 @@ +#if defined(JAZZ) && defined(R4000) + +// TITLE("NT System Boot Startup") +//++ +// +// Copyright (c) 1991 Microsoft Corporation +// +// Module Name: +// +// j4start.s +// +// Abstract: +// +// This module gains control after the ROM selftest has executed. +// Its function is to initialize the hardware for the ARC firmware. +// +// Author: +// +// David N. Cutler (davec) 22-Apr-1991 +// +// Environment: +// +// Kernel mode only. +// +// Revision History: +// +//-- + +#include "ksmips.h" + +#ifndef DUO +#include "jazzprom.h" +#else +#include "duoprom.h" +#endif + +#include "dmaregs.h" + +#define PROM_BASE (EEPROM_VIRTUAL_BASE) +#define PROM_ENTRY(x) (PROM_BASE + ((x) * 8)) + + +//TEMPTEMP +#define SECONDARY_CACHE_SIZE (1 << 20) + +// +// This definitions must match the restart block in arc.h +// + +#define RstBlkSavedState 0x28 // Offset to saved state area +#define RstBlkRestartAdr 0x10 +#define RstBlkBootStatus 0x1C + +#define RstBlkFltF0 RstBlkSavedState+0x000 +#define RstBlkFltF1 RstBlkSavedState+0x004 +#define RstBlkFltF2 RstBlkSavedState+0x008 +#define RstBlkFltF3 RstBlkSavedState+0x00C +#define RstBlkFltF4 RstBlkSavedState+0x010 +#define RstBlkFltF5 RstBlkSavedState+0x014 +#define RstBlkFltF6 RstBlkSavedState+0x018 +#define RstBlkFltF7 RstBlkSavedState+0x01C +#define RstBlkFltF8 RstBlkSavedState+0x020 +#define RstBlkFltF9 RstBlkSavedState+0x024 +#define RstBlkFltF10 RstBlkSavedState+0x028 +#define RstBlkFltF11 RstBlkSavedState+0x02C +#define RstBlkFltF12 RstBlkSavedState+0x030 +#define RstBlkFltF13 RstBlkSavedState+0x034 +#define RstBlkFltF14 RstBlkSavedState+0x038 +#define RstBlkFltF15 RstBlkSavedState+0x03C +#define RstBlkFltF16 RstBlkSavedState+0x040 +#define RstBlkFltF17 RstBlkSavedState+0x044 +#define RstBlkFltF18 RstBlkSavedState+0x048 +#define RstBlkFltF19 RstBlkSavedState+0x04C +#define RstBlkFltF20 RstBlkSavedState+0x050 +#define RstBlkFltF21 RstBlkSavedState+0x054 +#define RstBlkFltF22 RstBlkSavedState+0x058 +#define RstBlkFltF23 RstBlkSavedState+0x05C +#define RstBlkFltF24 RstBlkSavedState+0x060 +#define RstBlkFltF25 RstBlkSavedState+0x064 +#define RstBlkFltF26 RstBlkSavedState+0x068 +#define RstBlkFltF27 RstBlkSavedState+0x06C +#define RstBlkFltF28 RstBlkSavedState+0x070 +#define RstBlkFltF29 RstBlkSavedState+0x074 +#define RstBlkFltF30 RstBlkSavedState+0x078 +#define RstBlkFltF31 RstBlkSavedState+0x07C +#define RstBlkFsr RstBlkSavedState+0x080 +#define RstBlkIntAt RstBlkSavedState+0x084 +#define RstBlkIntV0 RstBlkSavedState+0x088 +#define RstBlkIntV1 RstBlkSavedState+0x08C +#define RstBlkIntA0 RstBlkSavedState+0x090 +#define RstBlkIntA1 RstBlkSavedState+0x094 +#define RstBlkIntA2 RstBlkSavedState+0x098 +#define RstBlkIntA3 RstBlkSavedState+0x09C +#define RstBlkIntT0 RstBlkSavedState+0x0A0 +#define RstBlkIntT1 RstBlkSavedState+0x0A4 +#define RstBlkIntT2 RstBlkSavedState+0x0A8 +#define RstBlkIntT3 RstBlkSavedState+0x0AC +#define RstBlkIntT4 RstBlkSavedState+0x0B0 +#define RstBlkIntT5 RstBlkSavedState+0x0B4 +#define RstBlkIntT6 RstBlkSavedState+0x0B8 +#define RstBlkIntT7 RstBlkSavedState+0x0BC +#define RstBlkIntS0 RstBlkSavedState+0x0C0 +#define RstBlkIntS1 RstBlkSavedState+0x0C4 +#define RstBlkIntS2 RstBlkSavedState+0x0C8 +#define RstBlkIntS3 RstBlkSavedState+0x0CC +#define RstBlkIntS4 RstBlkSavedState+0x0D0 +#define RstBlkIntS5 RstBlkSavedState+0x0D4 +#define RstBlkIntS6 RstBlkSavedState+0x0D8 +#define RstBlkIntS7 RstBlkSavedState+0x0DC +#define RstBlkIntT8 RstBlkSavedState+0x0E0 +#define RstBlkIntT9 RstBlkSavedState+0x0E4 +#define RstBlkIntK0 RstBlkSavedState+0x0E8 +#define RstBlkIntK1 RstBlkSavedState+0x0EC +#define RstBlkIntGp RstBlkSavedState+0x0F0 +#define RstBlkIntSp RstBlkSavedState+0x0F4 +#define RstBlkIntS8 RstBlkSavedState+0x0F8 +#define RstBlkIntRa RstBlkSavedState+0x0FC +#define RstBlkIntLo RstBlkSavedState+0x100 +#define RstBlkIntHi RstBlkSavedState+0x104 +#define RstBlkPsr RstBlkSavedState+0x108 +#define RstBlkFir RstBlkSavedState+0x10C + +// +// Define Boot status bits. +// +#define BootStarted (1 << 0) +#define BootFinished (1 << 1) +#define RestartStarted (1 << 2) +#define RestartFinished (1 << 3) +#define PowerFailStarted (1 << 4) +#define PowerFailFinished (1 << 5) +#define ProcessorReady (1 << 6) +#define ProcessorRunning (1 << 7) +#define ProcessorStart (1 << 8) + + +.extern TimerTicks 4 + + + SBTTL("Map PCR Routine") +//++ +// +// Routine Description: +// +// This routine is executed by processor B. It moves the current mapping +// for the PCR (set to processor A's PCR) to be two pages below it. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + LEAF_ENTRY(ReMapPCR) + .set noreorder + .set noat + + li t0,((PCR_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2) + mtc0 t0,entryhi + nop // 3 cycle hazard + nop // + nop // + tlbp // probe tlb. + nop // 2 cycle hazard + nop // + mfc0 t1,index // get result of probe + nop // 1 cycle hazard + bltz t1,30f // branch if entry not in the tlb + move v0,zero // set return value to false + tlbr // read entry from the tb + nop // 3 cycle hazard + nop // + nop // + mfc0 t1,entrylo1 // get entry lo 1 + nop + srl t2,t1,ENTRYLO_PFN // extract PFN + subu t2,t2,2 // substract two pages + sll t2,t2,ENTRYLO_PFN // shift back up + andi t1,t1,0x3F // keep page color + or t1,t2,t1 // merge with new PFN + mtc0 t1,entrylo1 // + nop // 1 cycle hazard + tlbwi // write updated entry in the tlb. + li v0,1 // set return value to true +30: + j ra // return false + nop + + .set reorder + .set at + + .end ReMapPCR + + + SBTTL("Initialize PCR Routine") +//++ +// +// Routine Description: +// +// This routine initializes the PCR needed by the Hal funcions. +// +// Arguments: +// +// None. +// +// Return Value: +// +// None. +// +//-- + + NESTED_ENTRY(InitializePCR, 0x30, zero) + + subu sp,sp,0x30 // allocate stack frame + sw ra,0x14(sp) // save return address + sw s0,0x18(sp) // save integer registers s0 - s4 + sw s1,0x1C(sp) // + sw s2,0x20(sp) // + sw s3,0x24(sp) // + sw s4,0x28(sp) // +#ifdef DUO +// +// Change the PCR mapping if processor B +// + li t0,DMA_VIRTUAL_BASE // load DMA base + lw t0,DmaWhoAmI(t0) // read Who am I register + beq t0,zero,10f // branch if A + bal ReMapPCR // Processor B Changes the mapping + +10: +#endif + +// +// Compute the size of the primary data cache, the primary data cache line +// size, the primary instruction cache, and the primary instruction cache +// line size. +// + .set noreorder + .set noat + mfc0 s4,config // get configuration data + mtc0 zero,pagemask // initialize the page mask register + mtc0 zero,watchlo // initialize the watch address register + mtc0 zero,watchhi // + mtc0 zero,wired // initialize the wired register + mtc0 zero,count // initialize the count register + mtc0 zero,compare // initialize the compare register + ctc1 zero,fsr // clear floating status + .set at + .set reorder + + srl t0,s4,CONFIG_IC // compute instruction cache size + and t0,t0,0x7 // + addu t0,t0,12 // + li s0,1 // + sll s0,s0,t0 // + srl t0,s4,CONFIG_IB // compute instruction cache line size + and t0,t0,1 // + li s1,16 // + sll s1,s1,t0 // + srl t0,s4,CONFIG_DC // compute data cache size + and t0,t0,0x7 // + addu t0,t0,12 // + li s2,1 // + sll s2,s2,t0 // + srl t0,s4,CONFIG_DB // compute data cache line size + and t0,t0,1 // + li s3,16 // + sll s3,s3,t0 // + +// +// Initialize the low memory transfer vector and next free TB index value. +// + + li t0,TRANSFER_VECTOR // get address of transfer vector + la t1,KiGeneralException // get address of trap handler + sw t1,0(t0) // set address of trap handler + // next free TB entry set in j4reset.s +10: +// +// Zero the PCR page because it is read before it is written. +// + + li a0,PCR_VIRTUAL_BASE // set address of PCR + li a1,PAGE_SIZE // set size of area to zero + jal RtlZeroMemory // zero PCR + +// +// Set the primary instruction size, the primary instruction cache line size, +// the primary data cache size, and the primary data cache line size. +// + + li t1,KiPcr // get PCR address + sw s0,PcFirstLevelIcacheSize(t1) // set size of instruction cache + sw s1,PcFirstLevelIcacheFillSize(t1) // set line size of instruction cache + sw s2,PcFirstLevelDcacheSize(t1) // set size of data cache + sw s3,PcFirstLevelDcacheFillSize(t1) // set line size of data cache + + +// +// Compute the size of the secondary data cache, the secondary data cache line +// size, the secondary instruction cache, and the secondary instruction cache +// line size. +// + + li s0,0 // compute instruction cache size + li s1,0 // compute instruction cache line size + li s2,0 // data cache size if no secondary + li s3,0 // data cache line size if no secondary + li t1,(1 << CONFIG_SC) + and t0,s4,t1 + bne t0,zero,10f // if non-zero no secondary cache + li s2,SECONDARY_CACHE_SIZE // compute data cache size + srl t0,s4,CONFIG_SB // compute data cache line size + and t0,t0,3 // + li s3,16 // + sll s3,s3,t0 // +10: + +// +// Set the secondary instruction size, the secondary instruction cache line size, +// the secondary data cache size, and the secondary data cache line size. +// + + li t1,KiPcr // get PCR address + sw s0,PcSecondLevelIcacheSize(t1) // set size of instruction cache + sw s1,PcSecondLevelIcacheFillSize(t1) // set line size of instruction cache + sw s2,PcSecondLevelDcacheSize(t1) // set size of data cache + sw s3,PcSecondLevelDcacheFillSize(t1) // set line size of data cache + +// +// Set the data cache fill size and alignment values. +// + + lw t2,PcSecondLevelDcacheSize(t1) // get second level dcache size + + .set noreorder + .set noat + bnel zero,t2,5f // if ne, second level cache present + lw t2,PcSecondLevelDcacheFillSize(t1) // get second level fill size + lw t2,PcFirstLevelDcacheFillSize(t1) // get first level fill size + .set at + .set reorder + +5: subu t3,t2,1 // compute dcache alignment value + sw t2,PcDcacheFillSize(t1) // set dcache fill size + sw t3,PcDcacheAlignment(t1) // set dcache alignment value + + lw ra,0x14(sp) // restore registers + lw s0,0x18(sp) // + lw s1,0x1C(sp) // + lw s2,0x20(sp) // + lw s3,0x24(sp) // + lw s4,0x28(sp) // + addu sp,sp,0x30 // deallocate stack frame + j ra // return + .end InitializePCR + + +#ifndef DUO + SBTTL("Read Floppy Data From Fifo") +//++ +// +// Routine Description: +// +// This routine is called to read data from the floppy fifo. +// +// Arguments: +// +// Buffer (a0) - Supplies a pointer to the buffer that receives the data +// read. +// +// Return Value: +// +// The number of bytes read is returned as the function value. +// +//-- + + LEAF_ENTRY(ReadFloppyFifo) + + move v0,zero // clear number of bytes read + li t0,FLOPPY_VIRTUAL_BASE // set base address of floppy registers + li t1,0xc0 // set constant for dio and rqm bits + +// +// Read data from floppy fifo. +// + + .set noreorder + .set noat +10: lbu t2,4(t0) // read MSR register + nop // + and t3,t2,t1 // clear all but dio and rqm bits + bne t1,t3,10b // if ne, rqm and dio not both set + and t3,t2,0x20 // test nonDMA bit + beq zero,t3,20f // if eq, end of transfer + addu a0,a0,1 // increment the buffer address + addu v0,v0,1 // increment number of bytes read + lbu t2,5(t0) // read floppy fifo + b 10b // + sb t2,-1(a0) // store byte in buffer + .set at + .set reorder + +20: j ra // return + + .end ReadFloppyFifo + + SBTTL("Write Data to Floppy Fifo") +//++ +// +// Routine Description: +// +// This routine is called to write data to the floppy fifo. +// +// Arguments: +// +// Buffer (a0) - Supplies a pointer to the buffer that contains the data +// to be written. +// +// Length (a1) - Supplies the number of bytes to be written to the fifo. +// +// Return Value: +// +// The number of bytes written is returned as the function value. +// +//-- + + LEAF_ENTRY(WriteFloppyFifo) + + move v0,zero // clear number of bytes writen + li t0,FLOPPY_VIRTUAL_BASE // set base address of floppy registers + li t1,0x80 // set constant for dio and rqm bits +// +// Write data to floppy fifo. +// + + .set noreorder + .set noat + addu a1,a0,a1 // address of last byte to transfer. + lbu t5,0(a0) // read first byte to write to fifo +10: lbu t2,4(t0) // read MSR register + nop // + andi t3,t2,0xc0 // clear all but dio and rqm bits + bne t1,t3,10b // if ne, rqm not set or dio set set + nop + addu a0,a0,1 // increment the buffer address + sb t5,5(t0) // write floppy fifo. + bne a0,a1,10b // if not last byte, send next + lbu t5,0(a0) // read next byte from buffer + +// +// All bytes written to fifo. Wait until floppy controller empties it. +// + +20: lbu t2,4(t0) // read MSR register + nop + andi t3,t2,0x20 // test nonDMA bit + bne t3,zero,20b // if neq, transfer not finished. + nop + .set at + .set reorder + + j ra // return + + .end WriteFloppyFifo + +#endif + +#ifdef DUO + + SBTTL("Test for IP interrupt") +//++ +// +// Routine Desription: +// +// This routine reads the cause register and returns True +// if the IP interrupt bit is set False otherwise +// +// Arguments: +// +// None. +// +// Return Value: +//// +// +// +//-- + + LEAF_ENTRY(IsIpInterruptSet) + .set noreorder + .set noat + + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + and t0,t1 // and them + beq t0,zero,20f // branch if not set + move v0,zero // set return value to False if no IP int + li t0,DMA_VIRTUAL_BASE // load DMA base + lw t0,DmaIpInterruptAcknowledge(t0)// read IP Ack register to clear it +10: + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + and t0,t1 // and them + bne t0,zero,10b // Keep looping if still set + li v0,1 // set return value to True +20: + j ra // return to caller. + nop + .set reorder + .set at + + .end IsIpInterruptSet + + SBTTL("Wait for IP interrupt") +//++ +// +// Routine Desription: +// +// This routine waits for an IP interrupt by polling the cause register +// When the IP interrupt occurs, it clears it and returns to the caller. +// +// Arguments: +// +// a0 Supplies a timeout period in milliseconds to wait for. +// +// The Loop takes about 12 internal cycles. +// For an internal clock of 100MHz this is about 8192 loops +// per millisecond. +// +// +// +// Return Value: +// +// zero if the Ip interrupt was not received in the specified timeout +// period. One otherwise. +// +// +//-- + + LEAF_ENTRY(WaitForIpInterrupt) + .set noreorder + .set noat + + bne a0,zero,10f // if timeout specified count loops + sll a0,a0,13 // multiply millisecons by 8192 = Loop count + +5: + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + // TMPTMP need symbolic definition + and t0,t1 // and them + beq t0,zero,5b // Keep looping if not set + nop + b 20f // go to clear interrupt + nop + +10: + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + addiu a0,a0,-1 // decrement loop counter + beq a0,zero,40f // branch out of loop if Timeout + move v0,zero // set return value to zero + nop + and t0,t1 // and them + beq t0,zero,10b // Keep looping if not set + nop + +20: + li t0,DMA_VIRTUAL_BASE // load DMA base + lw t0,DmaIpInterruptAcknowledge(t0)// read IP Ack register to clear it +30: + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + and t0,t1 // and them + bne t0,zero,30b // Keep looping if still set + addiu v0,zero,1 // set return value to 1 + +40: + j ra // return to the caller. + nop + + .set reorder + .set at + .end WaitForIpInterrupt + + + + SBTTL("Boot RestartProcessor") +//++ +// +// Routine Desription: +// +// This routine loads the Saved State Area of the RestartBlock +// supplied by a0 into the processor and transfers execution to +// the restart address. +// This routine assumes that the supplied restart block is valid. +// +// Arguments: +// +// a0 PRESTART_BLOCK. +// +// Return Value: +// +// This routine does not return. +// +//-- + + + LEAF_ENTRY(FwBootRestartProcessor) + .set noreorder + .set noat +// +// Cache is flushed by the caller. +// +// move s0,a0 +// la k0,HalSweepDcache +// jal k0 +// nop +// move a0,s0 + +10: + lw t0,RstBlkBootStatus(a0) // read boot status + li t1,ProcessorStart // get boot start bit mask + and t0,t0,t1 // and them + bne t0,zero,30f // if set go to load restart block + nop + +// +// Check if another IP interrupt was send to notify us to give up booting. +// + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + and t0,t1 // and them + beq t0,zero,Wait // branch if not set + li t0,DMA_VIRTUAL_BASE // load DMA base + lw t0,DmaIpInterruptAcknowledge(t0)// read IP Ack register to clear it +15: + mfc0 t0,cause // get cause register + li t1,1<<14 // mask to test IP interrupt + and t0,t1 // and them + bne t0,zero,15b // Keep looping if still set + nop // return to the caller. + j ra // + +Wait: + li t0,0x10000 // load delay value +20: // + bne t0,zero,20b // wait + addiu t0,t0,-1 + b 10b + nop + +30: + move k0,a0 // put address of restart block in k0 + lwc1 f0,RstBlkFltF0(k0) // Load floating registers + lwc1 f1,RstBlkFltF1(k0) // don't use double loads since + lwc1 f2,RstBlkFltF2(k0) // the alignment is not known. + lwc1 f3,RstBlkFltF3(k0) // + lwc1 f4,RstBlkFltF4(k0) + lwc1 f5,RstBlkFltF5(k0) + lwc1 f6,RstBlkFltF6(k0) + lwc1 f7,RstBlkFltF7(k0) + lwc1 f8,RstBlkFltF8(k0) + lwc1 f9,RstBlkFltF9(k0) + lwc1 f10,RstBlkFltF10(k0) + lwc1 f11,RstBlkFltF11(k0) + lwc1 f12,RstBlkFltF12(k0) + lwc1 f13,RstBlkFltF13(k0) + lwc1 f14,RstBlkFltF14(k0) + lwc1 f15,RstBlkFltF15(k0) + lwc1 f16,RstBlkFltF16(k0) + lwc1 f17,RstBlkFltF17(k0) + lwc1 f18,RstBlkFltF18(k0) + lwc1 f19,RstBlkFltF19(k0) + lwc1 f20,RstBlkFltF20(k0) + lwc1 f21,RstBlkFltF21(k0) + lwc1 f22,RstBlkFltF22(k0) + lwc1 f23,RstBlkFltF23(k0) + lwc1 f24,RstBlkFltF24(k0) + lwc1 f25,RstBlkFltF25(k0) + lwc1 f26,RstBlkFltF26(k0) + lwc1 f27,RstBlkFltF27(k0) + lwc1 f28,RstBlkFltF28(k0) + lwc1 f29,RstBlkFltF29(k0) + lwc1 f30,RstBlkFltF30(k0) + lwc1 f31,RstBlkFltF31(k0) + + lw k1,RstBlkFsr(k0) // load fsr + ctc1 k1,fsr // transfer to coprocessor + + lw AT,RstBlkIntAt(k0) // load integer registers + lw v0,RstBlkIntV0(k0) + lw v1,RstBlkIntV1(k0) + lw a0,RstBlkIntA0(k0) + lw a1,RstBlkIntA1(k0) + lw a2,RstBlkIntA2(k0) + lw a3,RstBlkIntA3(k0) + lw t0,RstBlkIntT0(k0) + lw t1,RstBlkIntT1(k0) + lw t2,RstBlkIntT2(k0) + lw t3,RstBlkIntT3(k0) + lw t4,RstBlkIntT4(k0) + lw t5,RstBlkIntT5(k0) + lw t6,RstBlkIntT6(k0) + lw t7,RstBlkIntT7(k0) + lw s0,RstBlkIntS0(k0) + lw s1,RstBlkIntS1(k0) + lw s2,RstBlkIntS2(k0) + lw s3,RstBlkIntS3(k0) + lw s4,RstBlkIntS4(k0) + lw s5,RstBlkIntS5(k0) + lw s6,RstBlkIntS6(k0) + lw s7,RstBlkIntS7(k0) + lw t8,RstBlkIntT8(k0) + lw t9,RstBlkIntT9(k0) + // Skip k0, k1 + lw gp,RstBlkIntGp(k0) + lw sp,RstBlkIntSp(k0) + lw s8,RstBlkIntS8(k0) + lw ra,RstBlkIntRa(k0) + lw k1,RstBlkIntLo(k0) // load IntLo + mtlo k1 // move value to register + lw k1,RstBlkIntHi(k0) // load IntHi + mthi k1 // move value to register + lw k1,RstBlkPsr(k0) // load psr + mtc0 k1,psr // move to cop0 + nop // fill for psr write 3 cycles hazard + lw k1,RstBlkFir(k0) // load epc + mtc0 k1,epc // move to cop0 + + lw k1,RstBlkIntK0(k0) // load k0 into k1 + mtc0 k1,lladdr // save k0 in cop0 register + + lw k1,RstBlkBootStatus(k0) // read boot status + ori k1,ProcessorRunning | BootStarted // Or in status bits. + sw k1,RstBlkBootStatus(k0) // write updated boot status + + lw k1,RstBlkIntK1(k0) // load k1 + lw k0,RstBlkFir(k0) // load restart address + j k0 // go to restart address + mfc0 k0,lladdr // restore k0 in delay slot. + +ALTERNATE_ENTRY(FwBootRestartProcessorEnd) + nop + .set reorder + .set at + + .end RestartProcessor + +#endif // DUO + +#endif |