#if defined(JAZZ) && defined(R3000) /*++ Copyright (c) 1990 Microsoft Corporation Module Name: j3reset.s Abstract: This module is the start of the boot code. This code will be the first run upon reset. It contains the self-test and initialization. Author: Lluis Abello (lluis) 8-Jan-91 Environment: Executes in kernal mode. Notes: ***** IMPORTANT ***** This module must be linked such that it resides in the first page of the rom. Revision History: Some code is stolen from johncoop's "reset.s" --*/ // // include header file // #include "ksmips.h" #include #include "selfmap.h" #include "led.h" #include "jzconfig.h" #include "dmaregs.h" #include "ioaccess.h" #define PROM_BASE (KSEG1_BASE | 0x1fc00000) #define PROM_ENTRY(x) (PROM_BASE + ((x) * 8)) // // redifne bal to be a relative branch and link instead of jal as it's // defined in kxmips.h // The cpp will issue a redefinition warning message. // #define bal bgezal zero, #define DMA_CHANNEL_GAP 0x20 // distance beetwen DMA channels // // create a small sdata section. // .sdata .space 4 .text .set noreorder .set noat .globl ResetVector ResetVector: /*++ Routine Description: This routine will provide the jump vectors located at the targets of the processor exception vectors. This routine must be located at the start of ROM which is the location of the reset vector. Arguments: None. Return Value: None. --*/ // // this instruction must be loaded at location 0 in the // rom. This will appear as BFC00000 to the processor // b ResetException nop // // This is the jump table for rom routines that other // programs can call. They are placed here so that they // will be unlikely to move. // // // This becomes PROM_ENTRY(2) as defined in ntmips.h // .align 4 li k0,MONITOR_LINK_ADDRESS // la k0,MonitorReInit li k1,GLOBAL_DATA_BASE j k0 sw $31,0x7C(k1) // save return address // // This becomes PROM_ENTRYS(12,13) // .align 6 nop // entry 8 nop nop // entry 9 nop b TlbInit // entry 10 nop nop // entry 11 nop GetCharJumpInstruction: b GetCharJumpInstruction // entry 12 nop PutCharJumpInstruction: b PutCharJumpInstruction // entry 13 nop b PutLedDisplay // entry 14 nop GetLineJumpInstruction: b GetLineJumpInstruction // entry 15 nop PutLineJumpInstruction: b PutLineJumpInstruction // entry 16 nop // .word BitMapPointers-LINK_ADDRESS+KSEG0_BASE // entry 17 address of BitmapPointers nop_opcode: nop // nop opcode to test the icache j ra // return opcode // // these next vectors should be loaded at BFC00100,BFC00180, // They are for the TLBmiss, and // common exceptions respectively. // .align 8 UserTlbMiss: // // checks if exception occurred in the tlbtest // mfc0 k1,epc // we enter this routine a la k0,TlbTestBegin // load the start address of the // TlbTest code likely to fail slt k0,k1,k0 // check if exception happend bne k0,zero,NormalException // on a smaller address la k0,TlbTestEnd // load the end address of the // TlbTest code likely to fail slt k0,k0,k1 // and check if exception happend bne k0,zero,NormalException // on a bigger address nop lui a1,LED_BLINK // bal PutLedDisplay // or a0,a1,a0 // NormalException: la k0,ExceptionDispatch // mfc0 k1,cause // read cause register j k0 // go to Dispatcher andi k1,k1,0xFF // just execcode field from cause reg. .align 7 mfc0 k1,cause // get cause li k0,KSEG1_BASE // sw k1,0(k0) // write cause reg to phys address zero la k0,ExceptionDispatch // get address of Dispatcher j k0 // go to dispatcher andi k1,k1,0xFF // just execcode field from cause reg. .align 4 ALTERNATE_ENTRY(MemoryRoutines) // The test code is copied from here to EndMemoryRoutines // into memory to run it cached. /*++ VOID WriteAddressTest( StartAddress Size Xor pattern ) Routine Description: This routine will store the address of each location xored with the Pattern into each location. Arguments: a0 - supplies start of memory area to test a1 - supplies length of memory area in bytes a2 - supplies the pattern to Xor with. Note: the values of the arguments are preserved. Return Value: This routine returns no value. --*/ ALTERNATE_ENTRY(MemoryTest) // The monitor calls this LEAF_ENTRY(WriteAddressTest) add t1,a0,a1 // t1 = last address. xor t0,a0,a2 // t0 value to write move t2,a0 // t2=current address writeaddress: sw t0,0(t2) // store addiu t2,t2,4 // compute next address xor t0,t2,a2 // next pattern sw t0,0(t2) addiu t2,t2,4 // compute next address xor t0,t2,a2 // next pattern sw t0,0(t2) addiu t2,t2,4 // compute next address xor t0,t2,a2 // next pattern sw t0,0(t2) addiu t2,t2,4 // compute next address bne t2,t1, writeaddress // check for end condition xor t0,t2,a2 // value to write j ra nop .end WriteAddressTest /*++ VOID WriteNoXorAddressTest( StartAddress Size ) Routine Description: This routine will store the address of each location into each location. Arguments: a0 - supplies start of memory area to test a1 - supplies length of memory area in bytes Note: the values of the arguments are preserved. Return Value: This routine returns no value. --*/ LEAF_ENTRY(WriteNoXorAddressTest) add t1,a0,a1 // t1 = last address. addiu t1,t1,-4 move t2,a0 // t2=current address writenoXoraddress: sw t2,0(t2) // store first address addiu t2,t2,4 // compute next address sw t2,0(t2) // store first address addiu t2,t2,4 // compute next address sw t2,0(t2) // store first address addiu t2,t2,4 // compute next address sw t2,0(t2) // store bne t2,t1, writenoXoraddress // check for end condition addiu t2,t2,4 // compute next address j ra nop .end WriteNoXorAddressTest /*++ VOID CheckAddressTest( StartAddress Size Xor pattern LedDisplayValue ) Routine Description: This routine will check that each location contains it's address xored with the Pattern as written by WriteAddressTest. Note: the values of the arguments are preserved. Arguments: This routine will check that each location contains it's address xored with the Pattern as written by WriteAddressTest. The memory is read cached or non cached according to the address specified by a0. Write address test writes allways KSEG1_ADR=KSEG1_ADR ^ KSEG1_XOR if a0 is in KSEG0 to read the data cached, then the XOR_PATTERN Must be such that: KSEG0_ADR ^ KSEG0_XOR = KSEG1_ADR ^ KSEG1_XOR Examples: If XorPattern with which WriteAddressTest was called is KSEG1_PAT and the XorPattern this routine needs is KSEG0_PAT: KSEG1_XOR Written KSEG0_XOR So that 0x00000000 0xA0 0x20000000 0x80 ^ 0x20 = 0xA0 0xFFFFFFFF 0x5F 0xDFFFFFFF 0x80 ^ 0xDF = 0x5F 0x01010101 0xA1 0x21010101 0x80 ^ 0x21 = 0xA1 Note: the values of the arguments are preserved. a0 - supplies start of memory area to test a1 - supplies length of memory area in bytes a2 - supplies the pattern to Xor with. a3 - suplies the value to display in the led in case of failure Return Value: This routine returns no value. It will hang displaying the test number if it finds an error and not configured in loop on error. --*/ LEAF_ENTRY(CheckAddressTest) move t3,a0 // t3 first address. add t2,t3,a1 // last address. checkaddress: lw t1,0(t3) // load from first location xor t0,t3,a2 // first expected value bne t1,t0,PatternFail addiu t3,t3,4 // compute next address lw t1,0(t3) // load from first location xor t0,t3,a2 // first expected value bne t1,t0,PatternFail addiu t3,t3,4 // compute next address lw t1,0(t3) // load from first location xor t0,t3,a2 // first expected value bne t1,t0,PatternFail addiu t3,t3,4 // compute next address lw t1,0(t3) // load from first location xor t0,t3,a2 // first expected value bne t1,t0,PatternFail // check last one. addiu t3,t3,4 // compute next address bne t3,t2, checkaddress // check for end condition move v0,zero // set return value to zero. j ra // return a zero to the caller PatternFail: // // check if we are in loop on error // li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register lb t0,0(t0) // read register value. li t1,LOOP_ON_ERROR_MASK // get value to compare andi t0,DIAGNOSTIC_MASK // mask diagnostic bits. li v0,PROM_ENTRY(14) // load address of PutLedDisplay beq t1,t0,10f // brnach if loop on error. move s8,a0 // save register a0 lui t0,LED_BLINK // get LED blink code jal v0 // Blink LED and hang. or a0,a3,t0 // pass a3 as argument in a0 10: lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code jal v0 // Set LOOP ON ERROR on LED or a0,a3,t0 // pass a3 as argument in a0 b CheckAddressTest // Loop back to test again. move a0,s8 // restoring arguments. .end CheckAddressTest /*++ VOID CheckNoXorAddressTest( StartAddress Size LedDisplayValue ) Routine Description: This routine will check that each location contains it's address xored with the Pattern as written by WriteAddressTest. Arguments: Note: the values of the arguments are preserved. a0 - supplies start of memory area to test a1 - supplies length of memory area in bytes a2 - supplies the pattern to Xor with. a3 - suplies the value to display in the led in case of failure Return Value: This routine returns no value. It will hang displaying the test number if it finds an error. --*/ LEAF_ENTRY(CheckNoXorAddressTest) addiu t3,a0,-4 // t3 first address-4 add t2,a0,a1 // last address. addiu t2,t2,-8 // adjust move t1,t3 // get copy of t3 just for first check checkaddressNX: bne t1,t3,PatternFailNX lw t1,4(t3) // load from first location addiu t3,t3,4 // compute next address bne t1,t3,PatternFailNX lw t1,4(t3) // load from next location addiu t3,t3,4 // compute next address bne t1,t3,PatternFailNX lw t1,4(t3) // load from next location addiu t3,t3,4 // compute next address bne t1,t3,PatternFailNX // check lw t1,4(t3) // load from next location bne t3,t2, checkaddressNX // check for end condition addiu t3,t3,4 // compute next address bne t1,t3,PatternFailNX // check last nop j ra // return a zero to the caller move v0,zero // PatternFailNX: // // check if we are in loop on error // li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register lb t0,0(t0) // read register value. li t1,LOOP_ON_ERROR_MASK // get value to compare andi t0,DIAGNOSTIC_MASK // mask diagnostic bits. li v0,PROM_ENTRY(14) // load address of PutLedDisplay beq t1,t0,10f // brnach if loop on error. move s8,a0 // save register a0 lui t0,LED_BLINK // get LED blink code jal v0 // Blink LED and hang. or a0,a3,t0 // pass a3 as argument in a0 10: lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code jal v0 // Set LOOP ON ERROR on LED or a0,a3,t0 // pass a3 as argument in a0 b CheckNoXorAddressTest // Loop back to test again. move a0,s8 // restoring arguments. .end CheckNoXorAddressTest .globl ResetException ResetException: .globl _start _start: /*++ Routine Description: This is the handler for the reset exception. It first checks the cause of the exception. If it is an NMI, then control is passed to the exception dispatch routine. Otherwise the machine is initialized. 1. Invalidate TLB, and clear coprocessor 0 cause register 2. Map the diagnostic LED, and MCT_ADR control register, zero remaining TLB 3. Test the processor 4. Test the reset state of address chip and then initialize values. 5. Map all of rom, and begin executing code in virtual address space. 6. Perform checksum of ROM 7. Test a small portion of memory. (Test code run from ROM) 8. Test the TLB 9. Copy memory test routines to memory so they can execute faster there. 10. flush and initialize dcache. 11. Test a larger section of memory. (Test code run uncached from memory) 12. Flush and initialize icache. 13. Initialize TlbMiss handler routine. 14. Test Video Memory 15. Copy Selftest image from rom to memory, and call. 16. Copy monitor image from rom to memory, and jump. Note: This routine must be loaded into the first page of rom. Any routines that are called before jumping to virtual addresses must also be loaded into the first page of rom. Arguments: None. Return Value: None. --*/ // // Initialize cause and status registers. // li t0,(1 << PSR_BEV) mtc0 t0,psr mtc0 zero,cause // // Map the 7 segment display // MapDisplay: li t0,LED_LO li t1,LED_HI mtc0 t0,entrylo mtc0 t1,entryhi mtc0 zero,index nop tlbwi // // Map also the MCTADR // li t0,(1< v1 bgtz s0,ProcessorError // if s0 > zero error or t4,AT,v0 // t4=X bltz s0,ProcessorError // if s0 < zero error nor t5,v0,AT // t5=~X and t6,t4,t5 // t6=0 bltzal t6,ProcessorError // if t6 < 0 error. Load ra in any case nop RaAddress: la t7,RaAddress- LINK_ADDRESS + RESET_VECTOR // get expected address in ra bne ra,t7,ProcessorError // error if don't mach ori s1,zero,0x100 // load constant mult s1,t3 // 0x100*0xFF mfhi s3 // s3=0 mflo s2 // s2=0xFF00 blez s3,10f // branch if correct sll s4,t3,zero // move t3 into s4 addiu s4,100 // change value in s4 to produce an error 10: divu s5,s2,s4 // divide 0xFF00/0xFF nop nop mfhi s6 // remainder s6=0 bne s5,s1,ProcessorError nop blez s6,10f // branch if no error nop j ProcessorError 10: sub s7,s5,s4 // s7=1 mthi s7 mtlo AT xori gp,s5,0x2566 // gp=0x2466 move s0,sp // save sp for now srl sp,gp,s7 // sp=0x1233 mflo s8 // s8=0x12344321 mfhi k0 // k0=1 ori k1,zero,16 // k1=16 sra k1,s8,k1 // k1=0x1234 add AT,sp,k0 // AT=0x1234 bne k1,AT,ProcessorError // branch on error nop // // Processor test passed if code gets this far // Continuue with test of address chip. // b MctadrTest // // processor error routine // ProcessorError: lui a0,LED_BLINK // blink also means that bal PutLedDisplay // the routine hangs. ori a0,LED_PROCESSOR_TEST // displaying this value. /*++ VOID PutLedDisplay( a0 - display value. ) Routine Description: This routine will display in the LED the value specified as argument a0. This routine must reside in the first page of ROM because it is called before mapping the rom. Arguments: a0 value to display. Return Value: None. --*/ LEAF_ENTRY(PutLedDisplay) li t0,DIAGNOSTIC_VIRTUAL_BASE // load address of display LedBlinkLoop: srl t1,a0,16 // get upper bits of a0 in t1 srl t3,a0,4 // get test number li t4,LED_LOOP_ERROR // bne t1,t4, DisplayTestID andi t3,t3,0xF // clear other bits. ori t3,t3,LED_DECIMAL_POINT // Set decimal point DisplayTestID: li t4,LED_BLINK // check if need to hung beq t1,t4, ShowSubtestID sb t3,0(t0) // write test ID to led. j ra // return to caller. nop ShowSubtestID: li t2,LED_DELAY_LOOP // get delay value. TestWait: bne t2,zero,TestWait // loop until zero addiu t2,t2,-1 // decrrement counter li t3,LED_DECIMAL_POINT+LED_BLANK // sb t3,0(t0) // write decimal point li t2,LED_DELAY_LOOP/2 // get delay value. DecPointWait: bne t2,zero,DecPointWait // loop until zero addiu t2,t2,-1 // decrement counter andi t3,a0,0xF // get subtest number sb t3,0(t0) // write subtest in LED li t2,LED_DELAY_LOOP // get delay value. SubTestWait: bne t2,zero,SubTestWait // loop until zero addiu t2,t2,-1 // decrrement counter b LedBlinkLoop // go to it again nop .end PutLedDisplay /*++ VOID ZeroMemory( ULONG StartAddress ULONG Size ); Routine Description: This routine will zero a range of memory. Arguments: a0 - supplies start of memory a1 - supplies length of memory in bytes Return Value: None. --*/ LEAF_ENTRY(ZeroMemory) add a1,a1,a0 // Compute End address addiu a1,a1,-4 // ZeroMemoryLoop: sw zero,0(a0) // zero memory. bne a0,a1,ZeroMemoryLoop // loop until done. addiu a0,a0,4 j ra // return nop ALTERNATE_ENTRY(ZeroMemoryEnd) nop .end ZeroMemory LEAF_ENTRY(R3000CacheInit) /*++ Routine Description: This routine will flush the R3000 caches. This is done by setting the isolate cache bit in the status register and then doing partial stores to the cache. This routine should be called with the swapcache bit set to flush the icache. This entire routine should run uncached. Arguments: None. Return Value: None. --*/ // // save status register and then // set isolation bit. This means that operations will // not actually go to memory. // mfc0 t1,psr // get psr li t0,(1 << PSR_ISC) // set isolate cache bit or t0,t1,t0 // or them together mtc0 t0,psr // disable interrupts, isolate cache. nop // wait for data cache isolation nop nop nop nop nop nop nop // // by writing partials the caches are invalidated. // these writes don't actually go to memory because // cache is isolated. // write to all cache lines. // li t0,KSEG0_BASE // physical address for flushing li t4,DATA_CACHE_SIZE // load size of cache. add t4,t0,t4 // value for end of loop condition flushcacheloop: sb zero,0(t0) // flush cache block sb zero,4(t0) sb zero,8(t0) sb zero,12(t0) sb zero,16(t0) sb zero,20(t0) sb zero,24(t0) addu t0,t0,32 // advance flush pointer sltu t1,t0,t4 // check if end of cache. bne zero,t1,flushcacheloop // if ne, more to flush sb zero,-4(t0) nop // wait for store oper. to clear pipe nop nop nop li t0,(1 << PSR_BEV) nop mtc0 t0,psr // unisolate and swap caches back nop // wait for caches to swap back nop nop j ra // return. nop .end R3000CacheInit LEAF_ENTRY(R3000ICacheTest) /*++ Routine Description: This routine will write the Icache with nops plus a return opcode and execute them. This entire routine should run uncached. Arguments: a0 - nop opcode a1 - j ra opcode Return Value: None. --*/ // // Copy nops to memory plus a return opcode, and jump to execute them in cached // space. // li t0,KSEG1_BASE+MEMTEST_SIZE // start of tested memory li t1,INSTRUCTION_CACHE_SIZE-4 // size filled with nop opcodes add t1,t1,t0 // last address. WriteNop: sw a0,0(t0) // write nop opcode bne t0,t1,WriteNop // check if last addiu t0,t0,4 li t1,KSEG0_BASE+MEMTEST_SIZE // address of wirtten nops in cached space j t1 // go to execute cached sw a1,-8(t0) // store return opcode the return // opcode will return to the caller // leave a nop in the delay slot .end R3000ICacheTest /*++ VOID DataCopy( ULONG SourceAddress ULONG DestinationAddress ULONG Length ); Routine Description: This routine will copy data from one location to another Source, destination, and length must be word aligned. Arguments: a0 - supplies source of data a1 - supplies destination of data a2 - supplies length of data in bytes Return Value: None. --*/ LEAF_ENTRY(DataCopy) add a2,a2,a0 // get last address CopyLoop: lw t5,0(a0) // get source of data addiu a0,a0,4 // increment source pointer sw t5,0(a1) // put to dest. bne a0,a2,CopyLoop // loop until address=last address addiu a1,a1,4 // increment destination pointer j ra // return nop ALTERNATE_ENTRY(EndMemoryRoutines) nop .end DataCopy //++ // // VOID // FlushWriteBuffer ( // VOID // ) // // Routine Description: // // This function flushes the write buffer on the current processor. // this routine does the same that NtFlushWriteBuffer except that it // doesn't return any value. It's intended to be called just // from this module. // // It must reside in the first page of the ROM. // // Arguments: // // None. // // Return Value: // // None. // //-- LEAF_ENTRY(FlushWriteBuffer) .set noreorder .set noat nop // four nop's are required nop // nop // nop // 10: // bc0f 10b // if false, write buffer not empty nop // j ra // return nop .end FlushWritebuffer RomRemoteSpeedValues: // // This table contains the default values for the remote speed regs. // .byte REMSPEED1 // ethernet .byte REMSPEED2 // SCSI .byte REMSPEED3 // Floppy .byte REMSPEED4 // RTC .byte REMSPEED5 // Kbd/Mouse .byte REMSPEED6 // Serial port .byte 7 // New dev .byte REMSPEED8 // Parallel .byte REMSPEED9 // NVRAM .byte REMSPEED10 // Int src reg .byte REMSPEED11 // PROM .byte REMSPEED12 // Sound .byte 7 // New dev .byte REMSPEED14 // External Eisa latch .align 4 MctadrTest: // // Test the mctadr registers. // bal PutLedDisplay ori a0,zero,LED_MCTADR_RESET // // check chip reset values // MctadrReset: li t0,DEVICE_VIRTUAL_BASE // Get base address of MCTADR lw v0,DmaConfiguration(t0) // Check Config reset value li t1,CONFIG_RESET // bne v0,t1,MctadrResetError lw v0,DmaInvalidAddress(t0) lw v1,DmaTranslationBase(t0) bne v0,zero,MctadrResetError// Check LFAR reset value lw v0,DmaTranslationLimit(t0) bne v1,zero,MctadrResetError// Check Ttable base reset value lw v1,DmaRemoteFailedAddress(t0) bne v0,zero,MctadrResetError// Check TT limit reset value lw v0,DmaMemoryFailedAddress(t0) bne v1,zero,MctadrResetError// Check RFAR reset value lw v1,DmaByteMask(t0) bne v0,zero,MctadrResetError// Check MFAR reset value addiu t1,t0,DmaRemoteSpeed0 // address of REM_SPEED 0 bne v1,zero,MctadrResetError// Check TT_BMASK reset value addiu t2,t0,DmaRemoteSpeed15 // address of REM_SPEED 15 lw v0,0(t1) // read register li t3,REMSPEED_RESET // addiu t1,t1,8 // next register address. NextRemSpeed: bne v0,t3,MctadrResetError // Check Rem speed reg reset value lw v0,0(t1) // read next rem speed bne t1,t2,NextRemSpeed addiu t1,t1,8 // next register address. bne v0,t3,MctadrResetError // Check last Rem speed reg reset value addiu t1,t0,DmaChannel0Mode // address of CHAN0MODE register addiu t2,t0,DmaChannel7Address// address of DMA_CHAN7ADDR (last reg) lw v0,0(t1) // read register addiu t1,t1,8 // next register address. NextChannelReg: bne v0,zero,MctadrResetError// Check channel reg reset value lw v0,0(t1) // read next channel bne t1,t2,NextChannelReg addiu t1,t1,8 // next register address. bne v0,zero,MctadrResetError// Checklast channel reg reset value lw v0,DmaInterruptSource(t0) // read DMA Channel interrupt lw v1,DmaErrortype(t0) // read eisa/ethernet error reg bne v0,zero,MctadrResetError// check Intpend lw v0,DmaRefreshRate(t0) bne v1,zero,MctadrResetError// check Eisa error type reset value li t1,REFRRATE_RESET bne v0,t1,MctadrResetError // check Refresh rate reset value lw v0,DmaSystemSecurity(t0) li t1,SECURITY_RESET bne v0,t1,MctadrResetError // check Security reg reset value lw v0,DmaInterruptAcknowledge(t0) // read register but don't check // // now perform a register test // bal PutLedDisplay ori a0,zero,LED_MCTADR_REG // Next test Led value MctadrReg: // // Check the data path between R4K and Mctadr by writing to Byte mask reg. // li t0,DEVICE_VIRTUAL_BASE sw zero,DmaCacheMaintenance(t0) // select cache block zero. li t1,1 sw t1,DmaLogicalTag(t0) // Set LFN=zero, Offset=0 , Direction=READ from memory, Valid li t2,0x55555555 bal FlushWriteBuffer sw t2,DmaByteMask(t0) // write patten to Byte mask lw v0,DmaByteMask(t0) // read Byte mask sw t1,DmaPhysicalTag(t0) // PFN=0 and Valid bne v0,t2,MctadrRegError // addu t2,t2,t2 // t1=0xAAAAAAAA bal FlushWriteBuffer sw t2,DmaByteMask(t0) // write patten to Byte mask lw v0,DmaByteMask(t0) // read Byte mask li t2,0xFFFFFFFF // expected value bne v0,t2,MctadrRegError // Check byte mask li a0,0xA0000000 // get memory address zero. bal FlushWriteBuffer sw zero,0(a0) // write address zero -> flushes buffers lw v0,DmaByteMask(t0) // read Byte mask // //Initialize mem config to 64MB and Write to some registers // li t1,0x17F sw t1,DmaConfiguration(t0) // Init Global Config li t2,0x1555000 // sw t2,DmaTranslationBase(t0)// write to TT BASE li t4,MEMORY_REFRESH_RATE sw t4,DmaRefreshRate(t0) // Initialize REFRESH RATE li t3,0x5550 bal FlushWriteBuffer sw t3,DmaTranslationLimit(t0) // write to TT_limit lw v0,DmaConfiguration(t0) // READ GLOBAL CONFIG lw v1,DmaTranslationBase(t0) // read TT BASE bne v0,t1,MctadrRegError // check GLOBAL CONFIG lw v0,DmaTranslationLimit(t0) // read TT_limit bne v1,t2,MctadrRegError // check TT-BASE lw v1,DmaRefreshRate(t0) // Read REFRESH RATE bne v0,t3,MctadrRegError // check TT-LIMIT li t1,0x2AAA000 bne v1,t4,MctadrRegError // check REFRESH RATE li t2,0xAAA0 sw t1,DmaTranslationBase(t0) // write to TT BASE bal FlushWriteBuffer sw t2,DmaTranslationLimit(t0) // write to TT_limit lw v0,DmaTranslationBase(t0) // read TT BASE lw v1,DmaTranslationLimit(t0) // read TT_limit bne v0,t1,MctadrRegError // check TT-BASE li t1,TT_BASE_ADDRESS // Init translation table base address sw t1,DmaTranslationBase(t0) // Init TT BASE bne v1,t2,MctadrRegError // check TT-LIMIT sw zero,DmaTranslationLimit(t0) // clear TT-limit // // Initialize remote speed registers. // addiu t1,t0,DmaRemoteSpeed1 // address of REM_SPEED 1 la a1,RomRemoteSpeedValues - LINK_ADDRESS + RESET_VECTOR // addiu t2,a1,14 // addres of last value WriteNextRemSpeed: lbu v0,0(a1) // load init value for rem speed addiu a1,a1,1 // compute next address sw v0,0(t1) // write to rem speed reg bne a1,t2,WriteNextRemSpeed // check for end condition addiu t1,t1,8 // next register address bal FlushWriteBuffer addiu a1,t2,-14 // address of first value for rem speed register addiu t1,t0,DmaRemoteSpeed1 // address of REM_SPEED 1 lbu v1,0(a1) // read expected value CheckNextRemSpeed: lw v0,0(t1) // read register addiu a1,a1,1 // address of next value bne v0,v1,MctadrRegError // check register addiu t1,t1,8 // address of next register bne a1,t2,CheckNextRemSpeed // check for end condition lbu v1,0(a1) // read expected value // // Now test the DMA channel registers // addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs li a0,0x15 // Mode li a1,0x2 // enable li a2,0xAAAAA // byte count li a3,0x555555 // address WriteNextChannel: sw a0,0(t1) // write mode sw a1,0x8(t1) // write enable sw a2,0x10(t1) // write byte count sw a3,0x18(t1) // write address addiu t1,t1,DMA_CHANNEL_GAP // compute address of next channel addiu a2,a2,1 // change addres bne t1,t2,WriteNextChannel addiu a3,a3,-1 // change Byte count bal FlushWriteBuffer // flush // // Check channel regs. // addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs li a2,0xAAAAA // byte count li a3,0x555555 // address CheckNextChannel: lw t4,0x0(t1) // read mode lw t5,0x8(t1) // read enable bne t4,a0,MctadrRegError // check mode lw t4,0x10(t1) // read byte count bne t5,a1,MctadrRegError // check enable lw t5,0x18(t1) // read address bne t4,a2,MctadrRegError // check abyte count addiu a2,a2,1 // next expected byte count bne t5,a3,MctadrRegError // check address addiu t1,t1,DMA_CHANNEL_GAP // next channel address bne t1,t2,CheckNextChannel addiu a3,a3,-1 // // Now do a second test on DMA channel registers // addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs li a0,0x2A // Mode li a2,0x55555 // byte count li a3,0xAAAAAA // address WriteNextChannel2: sw a0,0(t1) // write mode sw a2,0x10(t1) // write byte count sw a3,0x18(t1) // write address addiu t1,t1,DMA_CHANNEL_GAP // compute address of next channel addiu a2,a2,1 // change addres bne t1,t2,WriteNextChannel2 addiu a3,a3,-1 // change Byte count bal FlushWriteBuffer // flush // // Check channel regs. // addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs li a2,0x55555 // byte count li a3,0xAAAAAA // address CheckNextChannel2: lw t4,0x0(t1) // read mode lw t5,0x10(t1) // read byte count bne t4,a0,MctadrRegError // check mode lw t4,0x18(t1) // read address bne t5,a2,MctadrRegError // check abyte count addiu a2,a2,1 // next expected byte count bne t4,a3,MctadrRegError // check address addiu t1,t1,DMA_CHANNEL_GAP // next channel address bne t1,t2,CheckNextChannel2 addiu a3,a3,-1 // // Now zero the channel registers // addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs ZeroChannelRegs: addiu t1,t1,8 bne t1,t2,ZeroChannelRegs sw zero,-8(t1) // clear reg bal FlushWriteBuffer // flush addiu t1,t0,DmaChannel0Mode // address of channel 0 addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs CheckZeroedChannelRegs: lw a0,0(t1) addiu t1,t1,8 // next channel bne a0,zero,MctadrRegError // check nop bne t1,t2,CheckZeroedChannelRegs nop // // Address chip test passed if code reaches this point // Skip over error case routines. // b MapROM // go for the ROM Checksum // // Address chip error routines. // MctadrRegError: li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register lb t0,0(t0) // read register value. li t1,LOOP_ON_ERROR_MASK // get value to compare andi t0,DIAGNOSTIC_MASK // mask diagnostic bits. li v0,PROM_ENTRY(14) // load address of PutLedDisplay beq t1,t0,10f // branch if loop on error. ori a0,zero,LED_MCTADR_REG // load LED display value. lui t0,LED_BLINK // get LED blink code jal v0 // Blink LED and hang. or a0,a0,t0 // pass argument in a0 10: lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code jal v0 // Set LOOP ON ERROR on LED or a0,a0,t0 // pass argument in a0 b MctadrReg nop MctadrResetError: li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register lb t0,0(t0) // read register value. li t1,LOOP_ON_ERROR_MASK // get value to compare andi t0,DIAGNOSTIC_MASK // mask diagnostic bits. li v0,PROM_ENTRY(14) // load address of PutLedDisplay beq t1,t0,10f // branch if loop on error. ori a0,zero,LED_MCTADR_RESET // load LED display value. lui t0,LED_BLINK // get LED blink code jal v0 // Blink LED and hang. or a0,a0,t0 // pass argument in a0 10: lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code jal v0 // Set LOOP ON ERROR on LED or a0,a0,t0 // pass argument in a0 b MctadrReset nop // // Map the rom into the TLB so can run from virtual address space. // MapROM: bal PutLedDisplay ori a0,zero,LED_ROM_CHECKSUM // // initialize the TLB to map the whole ROM. This takes 16 or 32 entries. // li t0,ROM_LO // entry lo li t1,ROM_HI // entry hi li t2,(1<> 12) << ENTRYHI_VPN) //entryhi li t4,(64 << INDEX_INDEX) // last entry zero_tlb: mtc0 t0,entrylo // store entry lo mtc0 t2,entryhi // store entry high mtc0 t5,index // store index addiu t0,t0,(1 << ENTRYLO_PFN) // increment for next page tlbwi // store tlb entry addiu t5,t5,(1<