Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2598 lines
96 KiB

4 years ago
  1. #if defined(JAZZ) && defined(R4000) && !defined(DUO)
  2. /*++
  3. Copyright (c) 1991 Microsoft Corporation
  4. Module Name:
  5. j4reset.s
  6. Abstract:
  7. This module is the start of the prom code. This code will
  8. be the first run upon reset. It contains the self-test and
  9. initialization.
  10. Author:
  11. Lluis Abello (lluis) 8-Jan-91
  12. Environment:
  13. Executes in kernal mode.
  14. Notes:
  15. ***** IMPORTANT *****
  16. This module must be linked such that it resides in the
  17. first page of the rom.
  18. Revision History:
  19. Some code stolen from johncoop's "reset.s"
  20. --*/
  21. //
  22. // include header file
  23. //
  24. #include <ksmips.h>
  25. #include <jazzprom.h>
  26. #include "dmaregs.h"
  27. #include "selfmap.h"
  28. #include "led.h"
  29. #include "j4reset.h"
  30. //TEMPTEMP
  31. #define COPY_ENTRY 6
  32. .text
  33. .set noreorder
  34. .set noat
  35. ALTERNATE_ENTRY(ResetVector)
  36. /*++
  37. Routine Description:
  38. This routine will provide the jump vectors located
  39. at the targets of the processor exception vectors.
  40. N.B. This routine must be located at the start of ROM which
  41. is the location of the reset vector.
  42. Arguments:
  43. None.
  44. Return Value:
  45. None.
  46. --*/
  47. //
  48. // this instruction must be loaded at location 0 in the
  49. // rom. This will appear as BFC00000 to the processor
  50. //
  51. ori zero,zero,0xffff // this is a dummy instruction to
  52. // fix a bug where the first byte
  53. // fetched from the PROM is wrong
  54. b ResetException
  55. nop
  56. //
  57. // This is the jump table for rom routines that other
  58. // programs can call. They are placed here so that they
  59. // will be unlikely to move.
  60. //
  61. //
  62. // This becomes PROM_ENTRY(2) as defined in ntmips.h
  63. //
  64. .align 4
  65. nop
  66. //
  67. // Entries 4 to 7 are used for the ROM Version and they
  68. // must be zero in this file.
  69. //
  70. //
  71. // This becomes PROM_ENTRYS(8,9...)
  72. //
  73. .align 6
  74. nop // entry 8
  75. nop
  76. nop // entry 9
  77. nop
  78. b TlbInit // entry 10
  79. nop
  80. nop // entry 11
  81. nop
  82. nop // entry 12
  83. nop
  84. nop // entry 13
  85. nop
  86. b PutLedDisplay // entry 14
  87. nop
  88. nop // entry 15
  89. nop
  90. nop // entry 16
  91. nop
  92. RomRemoteSpeedValues:
  93. //
  94. // This table contains the default values for the remote speed regs.
  95. //
  96. .byte REMSPEED1 // ethernet
  97. .byte REMSPEED2 // SCSI
  98. .byte REMSPEED3 // Floppy
  99. .byte REMSPEED4 // RTC
  100. .byte REMSPEED5 // Kbd/Mouse
  101. .byte REMSPEED6 // Serial port 1
  102. .byte REMSPEED7 // Serial port 2
  103. .byte REMSPEED8 // Parallel
  104. .byte REMSPEED9 // NVRAM
  105. .byte REMSPEED10 // Int src reg
  106. .byte REMSPEED11 // PROM
  107. .byte REMSPEED12 // Sound
  108. .byte REMSPEED13 // New dev
  109. .byte REMSPEED14 // External Eisa latch
  110. .byte REMSPEED15 // LED
  111. .align 4
  112. //
  113. // New TLB Entries can be added to the following table
  114. // The format of the table is:
  115. // entryhi; entrylo0; entrylo1; pagemask
  116. //
  117. #define TLB_HI 0
  118. #define TLB_LO0 4
  119. #define TLB_LO1 8
  120. #define TLB_MASK 12
  121. TlbEntryTable:
  122. .word ((PROM_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  123. .word ((PROM_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  124. (1 << ENTRYLO_V) + (2 << ENTRYLO_C)
  125. #ifdef PROM256
  126. .word (1 << ENTRYLO_G) // set global bit even if page not used
  127. .word (PAGEMASK_256KB << PAGEMASK_PAGEMASK)
  128. #endif
  129. #ifdef PROM128
  130. .word (((PROM_PHYSICAL_BASE+0x10000) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  131. (1 << ENTRYLO_V) + (2 << ENTRYLO_C)
  132. .word (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
  133. #endif
  134. #ifdef PROM64
  135. .word (1 << ENTRYLO_G) // set global bit even if page not used
  136. .word (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
  137. #endif
  138. //
  139. // I/O Device space non-cached, valid, dirty
  140. //
  141. .word ((DEVICE_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  142. .word ((DEVICE_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  143. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  144. .word (1 << ENTRYLO_G) // set global bit even if page not used
  145. .word (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
  146. //
  147. // Interrupt source register space
  148. // non-cached - read/write
  149. //
  150. .word ((INTERRUPT_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  151. .word ((INTERRUPT_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  152. (1 << ENTRYLO_D) + (1 << ENTRYLO_V) + (2 << ENTRYLO_C)
  153. .word (1 << ENTRYLO_G) // set global bit even if page not used
  154. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  155. //
  156. // video control 2MB non-cached read/write.
  157. //
  158. .word ((VIDEO_CONTROL_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  159. .word ((VIDEO_CONTROL_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  160. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  161. .word (((VIDEO_CONTROL_PHYSICAL_BASE+0x100000) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  162. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  163. .word (PAGEMASK_1MB << PAGEMASK_PAGEMASK)
  164. //
  165. // extended video control 2MB non-cached read/write.
  166. //
  167. .word ((EXTENDED_VIDEO_CONTROL_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  168. .word ((EXTENDED_VIDEO_CONTROL_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  169. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  170. .word (((EXTENDED_VIDEO_CONTROL_PHYSICAL_BASE+0x100000) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  171. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  172. .word (PAGEMASK_1MB << PAGEMASK_PAGEMASK)
  173. //
  174. // video memory space 8Mb non-cached read/write
  175. //
  176. .word ((VIDEO_MEMORY_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  177. .word ((VIDEO_MEMORY_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  178. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  179. .word (((VIDEO_MEMORY_PHYSICAL_BASE+0x400000) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  180. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  181. .word (PAGEMASK_4MB << PAGEMASK_PAGEMASK)
  182. //
  183. // EISA I/O 16Mb non-cached read/write
  184. // EISA MEM 16Mb non-cached read/write
  185. //
  186. .word ((EISA_IO_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  187. .word ((EISA_IO_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  188. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  189. .word ((0x100000) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  190. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  191. .word (PAGEMASK_16MB << PAGEMASK_PAGEMASK)
  192. //
  193. // EISA I/O page 0 non-cached read/write
  194. // EISA I/O page 1 non-cached read/write
  195. //
  196. .word ((EISA_EXTERNAL_IO_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  197. .word ((0 >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  198. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  199. .word (((EISA_IO_PHYSICAL_BASE + 1 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  200. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  201. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  202. //
  203. // EISA I/O page 2 non-cached read/write
  204. // EISA I/O page 3 non-cached read/write
  205. //
  206. .word (((EISA_EXTERNAL_IO_VIRTUAL_BASE + 2 * PAGE_SIZE) >> 13) << ENTRYHI_VPN2)
  207. .word (((EISA_IO_PHYSICAL_BASE + 2 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  208. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  209. .word (((EISA_IO_PHYSICAL_BASE + 3 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  210. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  211. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  212. //
  213. // EISA I/O page 4 non-cached read/write
  214. // EISA I/O page 5 non-cached read/write
  215. //
  216. .word (((EISA_EXTERNAL_IO_VIRTUAL_BASE + 4 * PAGE_SIZE) >> 13) << ENTRYHI_VPN2)
  217. .word (((EISA_IO_PHYSICAL_BASE + 4 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  218. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  219. .word (((EISA_IO_PHYSICAL_BASE + 5 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  220. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  221. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  222. //
  223. // EISA I/O page 6 non-cached read/write
  224. // EISA I/O page 7 non-cached read/write
  225. //
  226. .word (((EISA_EXTERNAL_IO_VIRTUAL_BASE + 6 * PAGE_SIZE) >> 13) << ENTRYHI_VPN2)
  227. .word (((EISA_IO_PHYSICAL_BASE + 6 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  228. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  229. .word (((EISA_IO_PHYSICAL_BASE + 7 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  230. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  231. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  232. //
  233. // EISA I/O pages 8,9,a,b non-cached read/write
  234. // EISA I/O pages c,d,e,f non-cached read/write
  235. //
  236. .word (((EISA_EXTERNAL_IO_VIRTUAL_BASE + 8 * PAGE_SIZE) >> 13) << ENTRYHI_VPN2)
  237. .word (((EISA_IO_PHYSICAL_BASE + 8 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  238. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  239. .word (((EISA_IO_PHYSICAL_BASE + 12 * PAGE_SIZE) >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  240. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  241. .word (PAGEMASK_16KB << PAGEMASK_PAGEMASK)
  242. //
  243. // Map PCR for kernel debugger.
  244. //
  245. .word ((PCR_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  246. .word (1 << ENTRYLO_G) // set global bit even if page not used
  247. .word ((PCR_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  248. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (2 << ENTRYLO_C)
  249. .word (PAGEMASK_4KB << PAGEMASK_PAGEMASK)
  250. //
  251. // Map 64KB of memory for the video prom code&data cached.
  252. //
  253. .word ((VIDEO_PROM_CODE_VIRTUAL_BASE >> 13) << ENTRYHI_VPN2)
  254. .word ((VIDEO_PROM_CODE_PHYSICAL_BASE >> 12) << ENTRYLO_PFN) + (1 << ENTRYLO_G) + \
  255. (1 << ENTRYLO_V) + (1 << ENTRYLO_D) + (3 << ENTRYLO_C)
  256. .word (1 << ENTRYLO_G) // set global bit even if page not used
  257. .word (PAGEMASK_64KB << PAGEMASK_PAGEMASK)
  258. TlbEntryEnd:
  259. .byte 0
  260. //
  261. // these next vectors should be loaded at BFC00200,BFC00300,
  262. // and BFC00380. They are for the TLBmiss, cache_error, and
  263. // common exceptions respectively.
  264. //
  265. .align 9
  266. LEAF_ENTRY(UserTlbMiss200)
  267. UserTlbMiss:
  268. li k0,KSEG1_BASE
  269. lw k0,0x1018(k0) // Load address of UTBMiss handler
  270. nop
  271. jal k1,k0 // jump to handler saving return
  272. nop // address in k1
  273. mtc0 k0,epc // Handler returns return address in K0
  274. nop // 2 cycle Hazard
  275. nop
  276. eret // restore from exception
  277. .end UserTlbMiss200
  278. LEAF_ENTRY(TlbInit)
  279. /*++
  280. Routine Description:
  281. This routine will initialize the TLB for virtual addressing.
  282. It sets the TLB according to a table of TLB entries.
  283. Mapping:
  284. I/O device E0000000 - E00FFFFF
  285. Intr src reg E0100000 - E0100FFF
  286. video cntr E0200000 - E0203FFF
  287. video memory 40000000 - 40200000
  288. prom space E1000000 - E100FFFF
  289. eisa i/o space E2000000 - E2FFFFFF
  290. eisa mem space E3000000 - E3FFFFFF
  291. reserved E4000000 -
  292. All other unused TLB entries will be zeroed and therefore invalidated.
  293. N.B. This routine must be loaded in the first page of the rom and must
  294. be called using BFC00XXXX addresses.
  295. Arguments:
  296. None.
  297. Return Value:
  298. None.
  299. Revision History:
  300. --*/
  301. //
  302. // zero the whole TLB
  303. //
  304. mtc0 zero,entrylo0 // tag data to store
  305. mtc0 zero,entrylo1
  306. li t0,KSEG0_BASE // set entry hi
  307. mtc0 t0,entryhi
  308. mtc0 zero,pagemask
  309. move s0,zero // tlb entry index
  310. li t0, 48 // get last index (TB_SIZE)
  311. mtc0 s0,index // entry pointer
  312. tlbzeroloop:
  313. addiu s0,s0,1<<INDEX_INDEX // increment counter
  314. tlbwi // store it
  315. bne s0,t0,tlbzeroloop // loop if less than max entries
  316. mtc0 s0,index // entry pointer
  317. //
  318. // Get address and boundary of Table
  319. //
  320. la t1, TlbEntryTable - LINK_ADDRESS + RESET_VECTOR
  321. la t2, TlbEntryEnd - LINK_ADDRESS + RESET_VECTOR
  322. li s0, COPY_ENTRY+1 // tlb entry index
  323. 10:
  324. lw t3, TLB_HI(t1) // get entryhi
  325. lw t4, TLB_LO0(t1) // get entrylo0
  326. lw t5, TLB_LO1(t1) // get entrylo1
  327. lw t6, TLB_MASK(t1) // get pagemask
  328. mtc0 t3,entryhi // write entryhi
  329. mtc0 t4,entrylo0 // write entrylo0
  330. mtc0 t5,entrylo1 // write entrylo1
  331. mtc0 t6,pagemask // write pagemask
  332. mtc0 s0,index // write index
  333. addiu s0,s0,1 // compute index for next tlb entry
  334. tlbwi // write tlb entry
  335. addiu t1,t1,16 // set pointer to next entry
  336. bne t1,t2,10b // if not last go for next
  337. li t0,TRANSFER_VECTOR // get address of transfer vector
  338. sw s0,4(t0) // set next free TB entry index
  339. j ra
  340. nop
  341. .end TlbInit
  342. ParityError:
  343. //
  344. // Copy the firmware from PROM to memory.
  345. //
  346. //
  347. // Copy the firmware.
  348. //
  349. la s0,Decompress-LINK_ADDRESS+KSEG1_BASE
  350. // address of decompression routine in cached space
  351. la a0,end // end of this file is start of selftest
  352. li a1,RAM_TEST_DESTINATION_ADDRESS
  353. // destination is uncached link address.
  354. jal s0 // jump to decompress
  355. nop
  356. //
  357. // Initialize the stack to the low memory and Call Rom tests.
  358. //
  359. li t0,RAM_TEST_DESTINATION_ADDRESS // address of copied code
  360. li sp,RAM_TEST_STACK_ADDRESS | KSEG1_BASE // init stack non cached
  361. move a1,s5 // Pass cacheerr register as 2nd arg
  362. jal t0 // jump to self-test in memory
  363. li a0,3 // pass cause of exception as argument.
  364. //
  365. // This becomes the entry point of a Cache Error Exception.
  366. // It should be located at address BFC00300
  367. //
  368. .align 8
  369. /*++
  370. ParityHandler();
  371. Routine Description:
  372. This routine is called as a result of a Cache Error exception.
  373. Changes KSEG0 coherency to non cached in the config register.
  374. Reinitializes the TLB.
  375. Copies the firmware to memory and jumps to it.
  376. A message is printed.
  377. Arguments:
  378. This routine doesn't preserve state.
  379. Return Value:
  380. None.
  381. --*/
  382. LEAF_ENTRY(ParityHandler300)
  383. //
  384. // Should save state.
  385. //
  386. li k0,(1<<PSR_BEV) | (1 << PSR_CU1) | (1<<PSR_ERL)
  387. mtc0 k0,psr // Clear interrupt bit while ERL still set
  388. nop
  389. li k0,(1<<PSR_BEV) | (1 << PSR_CU1)
  390. nop
  391. mtc0 k0,psr // Clear ERL bit
  392. nop
  393. bal TlbInit // reinitialize the tlb
  394. mfc0 s5,cacheerr // Load cache error register
  395. bal PutLedDisplay
  396. ori a0,zero,LED_PARITY //
  397. mfc0 k0,config // get config register
  398. li k1,~(7 << CONFIG_K0) // mask to clear Kseg0 coherency bits
  399. and k0,k0,k1 // clear bits
  400. ori k0,(2 << CONFIG_K0) // make kseg0 non cached
  401. mtc0 k0,config //
  402. //
  403. // Copy the copy routines to memory
  404. //
  405. la a0,MemoryRoutines // source
  406. la a1,MemoryRoutines-LINK_ADDRESS+KSEG1_BASE // destination location
  407. la t2,EndMemoryRoutines // end
  408. bal DataCopy // copy code to memory
  409. subu a2,t2,a0 // length of code
  410. b ParityError
  411. nop
  412. .end ParityHandler300
  413. //
  414. // This becomes the entry point of a General Exception.
  415. // It should be located at address BFC00380
  416. //
  417. .align 7
  418. LEAF_ENTRY(GeneralException380)
  419. li k0,KSEG1_BASE
  420. lw k0,0x1014(k0) // Load address of GE handler
  421. nop
  422. jal k1,k0 // jump to handler saving return
  423. nop // address in k1
  424. mtc0 k0,epc // Handler returns return address in K0
  425. nop // 2 cycle Hazard
  426. nop
  427. eret // restore from exception
  428. nop
  429. .end GeneralException380
  430. ALTERNATE_ENTRY(ResetException)
  431. ALTERNATE_ENTRY(_start)
  432. /*++
  433. Routine Description:
  434. This is the handler for the reset exception. It first checks the cause
  435. of the exception. If it is an NMI, then control is passed to the
  436. exception dispatch routine. Otherwise the machine is initialized.
  437. The basic are:
  438. 1) Map the I/O devices.
  439. 2) Test the processor.
  440. 3) Test the MCTADR
  441. 4) Map ROM. Perform a ROM checksum.
  442. 5) Test a portion of Memory
  443. 6) Test TLB
  444. 7) Copy routines to memory
  445. 8) Initialize caches
  446. 9) Initialize stack for C language calls and other stack operations
  447. 10) Copy selftest and firmware code to memory and jump to it.
  448. N.B. This routine must be loaded into the first page of rom.
  449. Arguments:
  450. None.
  451. Return Value:
  452. None.
  453. --*/
  454. //
  455. // Initialize the TLB.
  456. //
  457. bal TlbInit // reinitialize the tlb
  458. nop
  459. //
  460. // Check cause of exception, if SR bit in PSR is set treat it as a soft reset
  461. // or an NMI, otherwise it's a cold reset.
  462. //
  463. mfc0 k0,psr // get cause register
  464. li k1,(1<<PSR_SR) // bit indicates soft reset.
  465. mtc0 zero,watchlo // initialize the watch
  466. mtc0 zero,watchhi // address registers
  467. and k1,k1,k0 // mask PSR with SR bit
  468. li k0,(1<<PSR_BEV) | (1 << PSR_CU1) | (1<<PSR_ERL)
  469. mtc0 k0,psr // Clear interrupt bit while ERL still set
  470. nop
  471. beq k1,zero,ResetCPU // go if cold reset
  472. li k0,(1<<PSR_BEV) | (1 << PSR_CU1)
  473. nop
  474. mtc0 k0,psr // Clear ERL bit
  475. li k0,DMA_VIRTUAL_BASE // load base address of MCT_ADR
  476. lw k1,DmaInterruptSource(k0) // Read the interrupt source register.
  477. nop
  478. andi k0,k1,(1<<11) // test for NMI
  479. bne k0,zero,20f // if bit set this is an NMI
  480. nop // otherwise is a softreset.
  481. b SoftReset // jump to soft reset
  482. ori s5,zero,1 // set s5 to tell that selftest can be skipped
  483. 20:
  484. //
  485. // Nmi Handler jump to firmware to print message.
  486. //
  487. bal PutLedDisplay // set a dash in the LED
  488. ori a0,zero,LED_NMI //
  489. //
  490. // Copy the copy routines to memory
  491. //
  492. la a0,MemoryRoutines // source
  493. la a1,MemoryRoutines-LINK_ADDRESS+KSEG1_BASE // destination location
  494. la t2,EndMemoryRoutines // end
  495. bal DataCopy // copy code to memory
  496. sub a2,t2,a0 // length of code
  497. la t2,InvalidateICache-LINK_ADDRESS+KSEG1_BASE // non-cached space
  498. jal t2 // Invalidate the instruction cache
  499. nop
  500. la k0,NMI // Join common code
  501. mfc0 s6,errorepc // get error epc
  502. j k0 // running at PROM Vaddress.
  503. li s5,2 // indicate exception is NMI.
  504. ResetCPU:
  505. move s5,zero // clear s5 to indicate cold reset
  506. SoftReset:
  507. //
  508. // Initialize PSR to BEV and COP1 enabled. It's important to clear ERL since
  509. // the ErrorEPC is undefined and further exceptions will set ERL or EXL
  510. // according to the nature of the exception.
  511. //
  512. li k0,(1<<PSR_BEV) | (1 << PSR_CU1)
  513. mtc0 k0,psr
  514. nop
  515. nop
  516. //
  517. // If there is no secondary cache or the secondary cache block size is greater
  518. // than 16 bytes, set the primary instruction cache block size to
  519. // 32 bytes, otherwise set to 16 bytes.
  520. //
  521. mfc0 t0,config
  522. li t1, (1 << CONFIG_IB) + (0 << CONFIG_DB) + (0 << CONFIG_CU) + \
  523. (3 << CONFIG_K0)
  524. srl t2,t0,CONFIG_SC // check for secondary cache
  525. and t2,t2,1 // isolate the bit
  526. bne t2,zero,10f // if none, block size stays 32 bytes
  527. srl t2,t0,CONFIG_SB // check secondary cache block size
  528. and t2,t2,3 // isolate the bit
  529. bne t2,zero,10f // if not 16 bytes, size stays 32 bytes
  530. nop
  531. li t1, (0 << CONFIG_IB) + (0 << CONFIG_DB) + (0 << CONFIG_CU) + \
  532. (3 << CONFIG_K0)
  533. 10:
  534. li t2, 0xFFFFFFC0
  535. and t0,t0,t2 // clear soft bits in config
  536. or t0,t0,t1 // set soft bits in config
  537. mtc0 t0,config
  538. nop
  539. nop
  540. bal PutLedDisplay // BLANK the LED
  541. ori a0,zero,LED_BLANK<<TEST_SHIFT
  542. //
  543. // now go to the virtual address instead of using the page
  544. // 1FC00000 that is mapped by the address chip.
  545. //
  546. la t0,Virtual
  547. j t0
  548. nop
  549. Virtual:
  550. beq s5,1,SkipProcessorTest // Skip processor test if softreset
  551. nop
  552. bal PutLedDisplay // Show processor test is staring
  553. ori a0,zero,LED_PROCESSOR_TEST
  554. bal ProcessorTest // Test the processor
  555. nop
  556. move s5,zero // clear s5 to indicate cold reset
  557. SkipProcessorTest:
  558. bal PutLedDisplay // Show MCT_ADR reset test is starting
  559. ori a0,zero,LED_MCTADR_RESET
  560. bal MctadrResetTest
  561. nop
  562. bal PutLedDisplay // Show MCT_ADR register test is starting
  563. ori a0,zero,LED_MCTADR_REG
  564. bal MctadrRegisterTest
  565. nop
  566. beq s5,1,SkipRomChecksum // Skip checksum if softreset
  567. nop
  568. //
  569. // Perform a ROM Checksum.
  570. //
  571. bal PutLedDisplay // Display in the LED that
  572. ori a0,zero,LED_ROM_CHECKSUM // ROM Checksum is being executed
  573. li a0,PROM_VIRTUAL_BASE // address of PROM
  574. li t0,ROM_SIZE
  575. add a1,a0,t0 // end of loop address
  576. move t0,zero // init sum register
  577. RomCheckSum:
  578. lw t1,0(a0) // fetch word
  579. lw t2,4(a0) // fetch second word
  580. addu t0,t0,t1 // calculate checksum add from ofs 0
  581. lw t1,8(a0)
  582. addu t0,t0,t2 // calculate checksum add from ofs 4
  583. lw t2,0xC(a0)
  584. addu t0,t0,t1 // calculate checksum add from ofs 8
  585. addiu a0,a0,16 // compute next address
  586. bne a0,a1,RomCheckSum // check end of loop condition
  587. addu t0,t0,t2 // calculate checksum add from ofs c
  588. //
  589. // if test passes, jump to next part of initialization code.
  590. //
  591. beq t0,zero,TestMemory // Branch if calculated checksum is correct
  592. move s5,zero // clear s5 this tells to run selftest
  593. lui a0,LED_BLINK // otherwise hang
  594. bal PutLedDisplay // by calling PutLedDisplay
  595. ori a0,a0,LED_ROM_CHECKSUM // blinking the test number
  596. SkipRomChecksum:
  597. TestMemory:
  598. bal PutLedDisplay // call PutLedDisplay to show that
  599. ori a0,zero,LED_MEMORY_TEST_1 // Mem test is starting
  600. //
  601. // Call memory test routine to test small portion of memory.
  602. // a0 is start of tested memory. a1 is length in bytes to test
  603. //
  604. //
  605. // Disable Parity exceptions for the first memory test. Otherwise
  606. // if something is wrong with the memory we jump to the moon.
  607. //
  608. li t0, (1<<PSR_DE) | (1 << PSR_CU1) | (1 << PSR_BEV)
  609. mtc0 t0,psr
  610. nop
  611. li a0,KSEG1_BASE // start of mem test
  612. ori a1,zero,MEMTEST_SIZE // length to test in bytes
  613. ctc1 zero,fsr // clear floating status
  614. nop
  615. bal WriteNoXorAddressTest
  616. move a2,zero // xor pattern zero
  617. bal CheckNoXorAddressTest
  618. ori a3,zero,LED_MEMORY_TEST_1 // set Test/Subtest ID
  619. //
  620. // Do the same flipping all bits
  621. //
  622. bal WriteAddressTest
  623. li a2,-1 // Xor pattern = FFFFFFFF
  624. bal CheckAddressTest
  625. nop
  626. //
  627. // Do the same flipping some bits to be sure parity bits are flipped in each byte
  628. //
  629. lui a2,0x0101
  630. bal WriteAddressTest
  631. ori a2,a2,0x0101 // Xor pattern = 01010101
  632. bal CheckAddressTest
  633. nop
  634. bal SizeMemory // start by sizing the memory.
  635. nop //
  636. //
  637. // The next step is to copy a number of routines to memory so they can
  638. // be executed more quickly. Calculate the arguments for DataCopy call:
  639. // a0 is source of data, a1 is dest, a2 is length in bytes
  640. //
  641. la a0,MemoryRoutines // source
  642. la a1,MemoryRoutines-LINK_ADDRESS+KSEG1_BASE // destination location
  643. la t2,EndMemoryRoutines // end
  644. bal DataCopy // copy code to memory
  645. sub a2,t2,a0 // length of code
  646. //
  647. // Call cache initialization routine in non-cached memory
  648. //
  649. bal PutLedDisplay // display that cache init
  650. ori a0,zero,LED_CACHE_INIT // is starting
  651. la s1,R4000CacheInit-LINK_ADDRESS+KSEG1_BASE // non-cached address
  652. jal s1 // initialize caches
  653. nop
  654. //
  655. // call routine now in cached memory to test bigger portion of memory
  656. //
  657. bal PutLedDisplay // display that memory test
  658. ori a0,zero,LED_WRITE_MEMORY_2 // is starting
  659. li a0,KSEG1_BASE+MEMTEST_SIZE // start of memory to write non cached
  660. li a1,FW_TOP_ADDRESS-MEMTEST_SIZE // test the memory needed to copy the code
  661. // to memory, the stack and the video prom.
  662. la s1,WriteNoXorAddressTest-LINK_ADDRESS+KSEG0_BASE // address of routine in memory cached
  663. jal s1 // Write and therefore init mem.
  664. move a2,zero // xor pattern
  665. la s2,CheckNoXorAddressTest-LINK_ADDRESS+KSEG0_BASE // address of routine in memory
  666. jal s2 // Check written memory
  667. ori a3,zero,LED_READ_MEMORY_2 // load LED value if memory test fails
  668. la s1,WriteAddressTest-LINK_ADDRESS+KSEG0_BASE // address of routine cached
  669. li a0,KSEG0_BASE+MEMTEST_SIZE // start of memory now cached
  670. li a2,0xDFFFFFFF // to flipp all bits
  671. jal s1 // Write second time now cached.
  672. la s2,CheckAddressTest-LINK_ADDRESS+KSEG0_BASE // address of routine in memory
  673. jal s2 // check also cached.
  674. nop
  675. lui a2,0x0101
  676. jal s1 // Write third time cached.
  677. ori a2,a2,0x0101 // flipping some bits
  678. jal s2 // check also cached.
  679. nop
  680. //
  681. // if we come back, the piece of memory is tested and therefore initialized.
  682. //
  683. //
  684. // If an NMI occurred. s5 contains the erorrepc.
  685. // the Tlb has already been initialized and the I cache flushed.
  686. // Copy the firmware to memory and display a message from there.
  687. //
  688. NMI:
  689. //
  690. // Invalidate the data caches so that the firmware can be copied to
  691. // noncached space without a conflict.
  692. //
  693. bal InvalidateDCache
  694. nop
  695. bal InvalidateSCache
  696. nop
  697. //
  698. // Copy the firmware.
  699. //
  700. la s0,Decompress-LINK_ADDRESS+KSEG0_BASE
  701. // address of decompression routine in cached space
  702. la a0,end // end of this file is start of selftest
  703. li a1,RAM_TEST_DESTINATION_ADDRESS
  704. // destination is uncached link address.
  705. jal s0 // jump to decompress
  706. nop
  707. bal InvalidateICache // Invalidate the instruction cache
  708. nop
  709. //
  710. // Zero the memory up to the firmware.
  711. //
  712. li t0,KSEG0_BASE // start of memory to zero
  713. li t1,RAM_TEST_LINK_ADDRESS // at the start of the firmware.
  714. mtc1 zero,f0 // zero f0
  715. mtc1 zero,f1 // zero f1
  716. ZeroFirst:
  717. addi t0,8 // increment by a doubleword
  718. bne t0,t1,ZeroFirst // branch if not done
  719. sdc1 f0,-8(t0) // write doubleword
  720. //
  721. // Flush the data cache
  722. //
  723. bal FlushDCache
  724. nop
  725. //
  726. // Initialize the stack to the low memory and Call Rom tests.
  727. //
  728. li t0,RAM_TEST_LINK_ADDRESS // address of copied code
  729. li sp,RAM_TEST_STACK_ADDRESS // init stack
  730. move a1,s6
  731. jal t0 // jump to self-test in memory
  732. move a0,s5 // pass cause of exception as argument.
  733. 99:
  734. b 99b // hang if we get here.
  735. nop //
  736. //
  737. // Routines between MemoryRoutines and EndMemoryRoutines are copied
  738. // into memory to run them cached.
  739. //
  740. .align 4 // Align it to 16 bytes boundary so that
  741. ALTERNATE_ENTRY(MemoryRoutines) // DataCopy doesn't need to check alignments
  742. /*++
  743. VOID
  744. PutLedDisplay(
  745. a0 - display value.
  746. )
  747. Routine Description:
  748. This routine will display in the LED the value specified as argument
  749. a0.
  750. bits [31:16] specify the mode.
  751. bits [7:4] specify the Test number.
  752. bits [3:0] specify the Subtest number.
  753. The mode can be:
  754. LED_NORMAL Display the Test number
  755. LED_BLINK Loop displaying Test - Dot - Subtest
  756. LED_LOOP_ERROR Display the Test number with the dot iluminated
  757. N.B. This routine must reside in the first page of ROM because it is
  758. called before mapping the rom!!
  759. Arguments:
  760. a0 value to display.
  761. Note: The value of the argument is preserved
  762. Return Value:
  763. If a0 set to LED_BLINK does not return.
  764. --*/
  765. LEAF_ENTRY(PutLedDisplay)
  766. li t0,DIAGNOSTIC_VIRTUAL_BASE // load address of display
  767. LedBlinkLoop:
  768. srl t1,a0,16 // get upper bits of a0 in t1
  769. srl t3,a0,4 // get test number
  770. li t4,LED_LOOP_ERROR //
  771. bne t1,t4, DisplayTestID
  772. andi t3,t3,0xF // clear other bits.
  773. ori t3,t3,LED_DECIMAL_POINT // Set decimal point
  774. DisplayTestID:
  775. li t4,LED_BLINK // check if need to hung
  776. sb t3,0(t0) // write test ID to led.
  777. beq t1,t4, ShowSubtestID
  778. nop
  779. j ra // return to caller.
  780. nop
  781. ShowSubtestID:
  782. li t2,LED_DELAY_LOOP // get delay value.
  783. TestWait:
  784. bne t2,zero,TestWait // loop until zero
  785. addiu t2,t2,-1 // decrement counter
  786. li t3,LED_DECIMAL_POINT+LED_BLANK
  787. sb t3,0(t0) // write decimal point
  788. li t2,LED_DELAY_LOOP/2 // get delay value.
  789. DecPointWait:
  790. bne t2,zero,DecPointWait // loop until zero
  791. addiu t2,t2,-1 // decrement counter
  792. andi t3,a0,0xF // get subtest number
  793. sb t3,0(t0) // write subtest in LED
  794. li t2,LED_DELAY_LOOP // get delay value.
  795. SubTestWait:
  796. bne t2,zero,SubTestWait // loop until zero
  797. addiu t2,t2,-1 // decrement counter
  798. b LedBlinkLoop // go to it again
  799. nop
  800. .end PutLedDisplay
  801. LEAF_ENTRY(InvalidateICache)
  802. /*++
  803. Routine Description:
  804. This routine invalidates the contents of the instruction cache.
  805. The instruction cache is invalidated by writing an invalid tag to
  806. each cache line, therefore nothing is written back to memory.
  807. Arguments:
  808. None.
  809. Return Value:
  810. None.
  811. --*/
  812. //
  813. // invalid state
  814. //
  815. mfc0 t5,config // read config register
  816. li t0,(PRIMARY_CACHE_INVALID << TAGLO_PSTATE)
  817. mtc0 t0,taglo // set tag registers to invalid
  818. mtc0 zero,taghi
  819. srl t0,t5,CONFIG_IC // compute instruction cache size
  820. and t0,t0,0x7 //
  821. addu t0,t0,12 //
  822. li t6,1 //
  823. sll t6,t6,t0 // t6 = I cache size
  824. srl t0,t5,CONFIG_IB // compute instruction cache line size
  825. and t0,t0,1 //
  826. li t7,16 //
  827. sll t7,t7,t0 // t7 = I cache line size
  828. //
  829. // store tag to all icache lines
  830. //
  831. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  832. addu t0,t1,t6 // get last index address
  833. subu t0,t0,t7
  834. WriteICacheTag:
  835. cache INDEX_STORE_TAG_I,0(t1) // store tag in Instruction cache
  836. bne t1,t0,WriteICacheTag // loop
  837. addu t1,t1,t7 // increment index
  838. j ra
  839. nop
  840. .end InvalidateICache
  841. LEAF_ENTRY(InvalidateDCache)
  842. /*++
  843. Routine Description:
  844. This routine invalidates the contents of the D cache.
  845. Data cache is invalidated by writing an invalid tag to each cache
  846. line, therefore nothing is written back to memory.
  847. Arguments:
  848. None.
  849. Return Value:
  850. None.
  851. --*/
  852. //
  853. // invalid state
  854. //
  855. mfc0 t5,config // read config register for cache size
  856. li t0, (PRIMARY_CACHE_INVALID << TAGLO_PSTATE)
  857. mtc0 t0,taglo // set tag to invalid
  858. mtc0 zero,taghi
  859. srl t0,t5,CONFIG_DC // compute data cache size
  860. and t0,t0,0x7 //
  861. addu t0,t0,12 //
  862. li t6,1 //
  863. sll t6,t6,t0 // t6 = data cache size
  864. srl t0,t5,CONFIG_DB // compute data cache line size
  865. and t0,t0,1 //
  866. li t7,16 //
  867. sll t7,t7,t0 // t7 = data cache line size
  868. //
  869. // store tag to all Dcache
  870. //
  871. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  872. addu t2,t1,t6 // add cache size
  873. subu t2,t2,t7 // adjust for cache line size.
  874. WriteDCacheTag:
  875. cache INDEX_STORE_TAG_D,0(t1) // store tag in Data cache
  876. bne t1,t2,WriteDCacheTag // loop
  877. addu t1,t1,t7 // increment index by cache line
  878. j ra
  879. nop
  880. .end InvalidateDCache
  881. LEAF_ENTRY(FlushDCache)
  882. /*++
  883. Routine Description:
  884. This routine flushes the whole contents of the Dcache
  885. Arguments:
  886. None.
  887. Return Value:
  888. None.
  889. --*/
  890. mfc0 t5,config // read config register
  891. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  892. srl t0,t5,CONFIG_DC // compute data cache size
  893. and t0,t0,0x7 //
  894. addu t0,t0,12 //
  895. li t6,1 //
  896. sll t6,t6,t0 // t6 = data cache size
  897. srl t0,t5,CONFIG_DB // compute data cache line size
  898. and t0,t0,1 //
  899. li t7,16 //
  900. sll t7,t7,t0 // t7 = data cache line size
  901. addu t0,t1,t6 // compute last index address
  902. subu t0,t0,t7
  903. FlushDCacheTag:
  904. cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) // Invalidate data cache
  905. bne t1,t0,FlushDCacheTag // loop
  906. addu t1,t1,t7 // increment index
  907. //
  908. // check for a secondary cache.
  909. //
  910. li t1,(1 << CONFIG_SC)
  911. and t0,t5,t1
  912. bne t0,zero,10f // if non-zero no secondary cache
  913. li t6,SECONDARY_CACHE_SIZE // t6 = secondary cache size
  914. srl t0,t5,CONFIG_SB // compute secondary cache line size
  915. and t0,t0,3 //
  916. li t7,16 //
  917. sll t7,t7,t0 // t7 = secondary cache line size
  918. //
  919. // invalidate all secondary lines
  920. //
  921. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  922. addu t0,t1,t6 // get last index address
  923. subu t0,t0,t7
  924. FlushSDCacheTag:
  925. cache INDEX_WRITEBACK_INVALIDATE_SD,0(t1) // invalidate secondary cache
  926. bne t1,t0,FlushSDCacheTag // loop
  927. addu t1,t1,t7 // increment index
  928. 10:
  929. j ra
  930. nop
  931. .end FlushDCache
  932. LEAF_ENTRY(InvalidateSCache)
  933. /*++
  934. Routine Description:
  935. This routine invalidates the contents of the secondary cache.
  936. The secondary cache is invalidated by writing an invalid tag to
  937. each cache line, therefore nothing is written back to memory.
  938. Arguments:
  939. None.
  940. Return Value:
  941. None.
  942. --*/
  943. mfc0 t5,config // read config register
  944. //
  945. // check for a secondary cache.
  946. //
  947. li t1,(1 << CONFIG_SC)
  948. and t0,t5,t1
  949. bne t0,zero,NoSecondaryCache // if non-zero no secondary cache
  950. li t0,(SECONDARY_CACHE_INVALID << TAGLO_SSTATE)
  951. mtc0 t0,taglo // set tag registers to invalid
  952. mtc0 zero,taghi
  953. li t6,SECONDARY_CACHE_SIZE // t6 = secondary cache size
  954. srl t0,t5,CONFIG_SB // compute secondary cache line size
  955. and t0,t0,3 //
  956. li t7,16 //
  957. sll t7,t7,t0 // t7 = secondary cache line size
  958. //
  959. // store tag to all secondary lines
  960. //
  961. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  962. addu t0,t1,t6 // get last index address
  963. subu t0,t0,t7
  964. WriteSICacheTag:
  965. cache INDEX_STORE_TAG_SD,0(t1) // store tag in secondary cache
  966. bne t1,t0,WriteSICacheTag // loop
  967. addu t1,t1,t7 // increment index
  968. NoSecondaryCache:
  969. j ra
  970. nop
  971. .end InvalidateSCache
  972. LEAF_ENTRY(InitDataCache)
  973. /*++
  974. Routine Description:
  975. This routine initializes the data fields of the primary and
  976. secondary data caches.
  977. Arguments:
  978. None.
  979. Return Value:
  980. None.
  981. --*/
  982. mfc0 t5,config // read config register
  983. //
  984. // check for a secondary cache.
  985. //
  986. li t1,(1 << CONFIG_SC)
  987. and t0,t5,t1
  988. bne t0,zero,NoSecondaryCache1 // if non-zero no secondary cache
  989. li t6,SECONDARY_CACHE_SIZE // t6 = secondary cache size
  990. srl t0,t5,CONFIG_SB // compute secondary cache line size
  991. and t0,t0,3 //
  992. li t7,16 //
  993. sll t7,t7,t0 // t7 = secondary cache line size
  994. //
  995. // store tag and data to all secondary lines
  996. //
  997. mtc1 zero,f0 // zero f0
  998. mtc1 zero,f1 // zero f1
  999. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  1000. addu t0,t1,t6 // get last index address
  1001. subu t0,t0,t7
  1002. andi t4,t7,16 // isolate secondary cache line size
  1003. WriteSCacheDe:
  1004. cache CREATE_DIRTY_EXCLUSIVE_SD,0(t1) // store tag in secondary cache
  1005. nop // MIPS does this
  1006. bne t4,zero,10f //
  1007. sdc1 f0,0(t1) // write
  1008. sdc1 f0,16(t1) // write
  1009. sdc1 f0,24(t1) // write
  1010. 10: sdc1 f0,8(t1) // write
  1011. bne t1,t0,WriteSCacheDe // loop
  1012. addu t1,t1,t7 // increment index
  1013. //
  1014. // Flush the primary data cache to the secondary cache
  1015. //
  1016. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  1017. srl t0,t5,CONFIG_DC // compute data cache size
  1018. and t0,t0,0x7 //
  1019. addu t0,t0,12 //
  1020. li t6,1 //
  1021. sll t6,t6,t0 // t6 = data cache size
  1022. srl t0,t5,CONFIG_DB // compute data cache line size
  1023. and t0,t0,1 //
  1024. li t7,16 //
  1025. sll t7,t7,t0 // t7 = data cache line size
  1026. addu t0,t1,t6 // compute last index address
  1027. subu t0,t0,t7
  1028. FlushPDCacheTag:
  1029. cache INDEX_WRITEBACK_INVALIDATE_D,0(t1) // Invalidate data cache
  1030. bne t1,t0,FlushPDCacheTag // loop
  1031. addu t1,t1,t7 // increment index
  1032. j ra // return
  1033. nop
  1034. NoSecondaryCache1:
  1035. srl t0,t5,CONFIG_DC // compute data cache size
  1036. and t0,t0,0x7 //
  1037. addu t0,t0,12 //
  1038. li t6,1 //
  1039. sll t6,t6,t0 // t6 = data cache size
  1040. srl t0,t5,CONFIG_DB // compute data cache line size
  1041. and t0,t0,1 //
  1042. li t7,16 //
  1043. sll t7,t7,t0 // t7 = data cache line size
  1044. //
  1045. // create dirty exclusive to all Dcache
  1046. //
  1047. mtc1 zero,f0 // zero f0
  1048. mtc1 zero,f1 // zero f1
  1049. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  1050. addu t2,t1,t6 // add cache size
  1051. subu t2,t2,t7 // adjust for cache line size.
  1052. WriteDCacheDe:
  1053. cache CREATE_DIRTY_EXCLUSIVE_D,0(t1) // store tag in Data cache
  1054. nop
  1055. sdc1 f0,0(t1) // write
  1056. sdc1 f0,8(t1) // write
  1057. bne t1,t2,WriteDCacheDe // loop
  1058. addu t1,t1,t7 // increment index by cache line
  1059. j ra // return
  1060. nop
  1061. .end InitDataCache
  1062. LEAF_ENTRY(R4000CacheInit)
  1063. /*++
  1064. Routine Description:
  1065. This routine will initialize the cache tags and data for the
  1066. primary data cache, primary instruction cache, and the secondary cache
  1067. (if present).
  1068. Subroutines are called to invalidate all of the tags in the
  1069. instruction and data caches.
  1070. Arguments:
  1071. None.
  1072. Return Value:
  1073. None.
  1074. --*/
  1075. move s0,ra // save ra.
  1076. //
  1077. // Disable Cache Error exceptions.
  1078. //
  1079. li t0, (1<<PSR_DE) | (1 << PSR_CU1) | (1 << PSR_BEV)
  1080. mtc0 t0,psr
  1081. //
  1082. // Invalidate the caches
  1083. //
  1084. bal InvalidateICache
  1085. nop
  1086. bal InvalidateDCache
  1087. nop
  1088. bal InvalidateSCache
  1089. nop
  1090. //
  1091. // Initialize the data cache(s)
  1092. //
  1093. bal InitDataCache
  1094. nop
  1095. //
  1096. // Fill the Icache, all icache lines
  1097. //
  1098. mfc0 t5,config // read config register
  1099. nop
  1100. srl t0,t5,CONFIG_IC // compute instruction cache size
  1101. and t0,t0,0x7 //
  1102. addu t0,t0,12 //
  1103. li s1,1 //
  1104. sll s1,s1,t0 // s1 = I cache size
  1105. srl t0,t5,CONFIG_IB // compute instruction cache line size
  1106. and t0,t0,1 //
  1107. li s2,16 //
  1108. sll s2,s2,t0 // s2 = I cache line size
  1109. ICacheStart:
  1110. li t1,KSEG0_BASE+(1<<20) // get virtual address to index cache
  1111. addu t0,t1,s1 // add I cache size
  1112. subu t0,t0,s2 // sub line size.
  1113. FillICache:
  1114. cache INDEX_FILL_I,0(t1) // Fill I cache from memory
  1115. bne t1,t0,FillICache // loop
  1116. addu t1,t1,s2 // increment index
  1117. //
  1118. // Invalidate the caches again
  1119. //
  1120. bal InvalidateICache
  1121. nop
  1122. bal InvalidateDCache
  1123. nop
  1124. bal InvalidateSCache
  1125. nop
  1126. //
  1127. // Enable cache error exception.
  1128. //
  1129. li t1, (1 << PSR_CU1) | (1 << PSR_BEV)
  1130. mtc0 t1,psr
  1131. nop
  1132. nop
  1133. nop
  1134. move ra,s0 // move return address back to ra
  1135. j ra // return from routine
  1136. nop
  1137. .end R4000CacheInit
  1138. /*++
  1139. VOID
  1140. WriteAddressTest(
  1141. StartAddress
  1142. Size
  1143. Xor pattern
  1144. )
  1145. Routine Description:
  1146. This routine will store the address of each location xored with
  1147. the Pattern into each location.
  1148. Arguments:
  1149. a0 - supplies start of memory area to test
  1150. a1 - supplies length of memory area in bytes
  1151. a2 - supplies the pattern to Xor with.
  1152. Note: the values of the arguments are preserved.
  1153. Return Value:
  1154. This routine returns no value.
  1155. --*/
  1156. LEAF_ENTRY(WriteAddressTest)
  1157. add t1,a0,a1 // t1 = last address.
  1158. xor t0,a0,a2 // t0 value to write
  1159. move t2,a0 // t2=current address
  1160. writeaddress:
  1161. sw t0,0(t2) // store
  1162. addiu t2,t2,4 // compute next address
  1163. xor t0,t2,a2 // next pattern
  1164. sw t0,0(t2)
  1165. addiu t2,t2,4 // compute next address
  1166. xor t0,t2,a2 // next pattern
  1167. sw t0,0(t2)
  1168. addiu t2,t2,4 // compute next address
  1169. xor t0,t2,a2 // next pattern
  1170. sw t0,0(t2)
  1171. addiu t2,t2,4 // compute next address
  1172. bne t2,t1, writeaddress // check for end condition
  1173. xor t0,t2,a2 // value to write
  1174. j ra
  1175. nop
  1176. .end WriteAddressTest
  1177. /*++
  1178. VOID
  1179. WriteNoXorAddressTest(
  1180. StartAddress
  1181. Size
  1182. )
  1183. Routine Description:
  1184. This routine will store the address of each location
  1185. into each location.
  1186. Arguments:
  1187. a0 - supplies start of memory area to test
  1188. a1 - supplies length of memory area in bytes
  1189. Note: the values of the arguments are preserved.
  1190. Return Value:
  1191. This routine returns no value.
  1192. --*/
  1193. LEAF_ENTRY(WriteNoXorAddressTest)
  1194. nop
  1195. nop
  1196. nop
  1197. nop
  1198. add t1,a0,a1 // t1 = last address.
  1199. addiu t1,t1,-4
  1200. move t2,a0 // t2=current address
  1201. writenoXoraddress:
  1202. sw t2,0(t2) // store first address
  1203. addiu t2,t2,4 // compute next address
  1204. sw t2,0(t2) // store first address
  1205. addiu t2,t2,4 // compute next address
  1206. sw t2,0(t2) // store first address
  1207. addiu t2,t2,4 // compute next address
  1208. sw t2,0(t2) // store
  1209. bne t2,t1, writenoXoraddress // check for end condition
  1210. addiu t2,t2,4 // compute next address
  1211. j ra
  1212. nop
  1213. .end WriteNoXorAddressTest
  1214. /*++
  1215. VOID
  1216. CheckAddressTest(
  1217. StartAddress
  1218. Size
  1219. Xor pattern
  1220. LedDisplayValue
  1221. )
  1222. Routine Description:
  1223. This routine will check that each location contains it's address
  1224. xored with the Pattern as written by WriteAddressTest. The memory
  1225. is read cached or non cached according to the address specified by a0.
  1226. if WriteAddressTest used a KSEG1_ADR to write the data and this
  1227. routine is called to read KSEG0_ADR in order to read the data cached,
  1228. then the XOR_PATTERN Must be such that:
  1229. KSEG0_ADR ^ KSEG0_XOR = KSEG1_ADR ^ KSEG1_XOR
  1230. Examples:
  1231. If XorPattern with which WriteAddressTest was called is KSEG1_XOR
  1232. then the XorPattern this routine needs is KSEG0_XOR:
  1233. KSEG1_XOR Written KSEG0_XOR So that
  1234. 0x00000000 0xA00000000 0x20000000 0x8000000 ^ 0x2000000 = 0xA0000000
  1235. 0xFFFFFFFF 0x5F0000000 0xDFFFFFFF 0x8000000 ^ 0xDF00000 = 0x5F000000
  1236. 0x01010101 0xA10000000 0x21010101 0x8000000 ^ 0x2100000 = 0xA1000000
  1237. This allows to write non cached to initialize memory and check the same
  1238. data trough cached addresses.
  1239. Arguments:
  1240. a0 - supplies start of memory area to test
  1241. a1 - supplies length of memory area in bytes
  1242. a2 - supplies the pattern to Xor with.
  1243. a3 - suplies the value to display in the led in case of failure
  1244. Note: the values of the arguments are preserved.
  1245. Return Value:
  1246. Returns a zero if no error is found.
  1247. If errors are found, this routine behaves different depending
  1248. on where the caller resides:
  1249. - If the caller is executing in KSEG0 or KSEG1 returns 1
  1250. - If the caller is executing im ROM_VIRT addresses the
  1251. routine hangs blinking the LED or looping if the loop on error
  1252. bit is set in the config register.
  1253. --*/
  1254. LEAF_ENTRY(CheckAddressTest)
  1255. move t3,a0 // t3 first address.
  1256. add t2,t3,a1 // last address.
  1257. checkaddress:
  1258. lw t1,0(t3) // load from first location
  1259. xor t0,t3,a2 // first expected value
  1260. bne t1,t0,PatternFail
  1261. addiu t3,t3,4 // compute next address
  1262. lw t1,0(t3) // load from first location
  1263. xor t0,t3,a2 // first expected value
  1264. bne t1,t0,PatternFail
  1265. addiu t3,t3,4 // compute next address
  1266. lw t1,0(t3) // load from first location
  1267. xor t0,t3,a2 // first expected value
  1268. bne t1,t0,PatternFail
  1269. addiu t3,t3,4 // compute next address
  1270. lw t1,0(t3) // load from first location
  1271. xor t0,t3,a2 // first expected value
  1272. bne t1,t0,PatternFail // check last one.
  1273. addiu t3,t3,4 // compute next address
  1274. bne t3,t2, checkaddress // check for end condition
  1275. move v0,zero // set return value to zero.
  1276. j ra // return a zero to the caller
  1277. PatternFail:
  1278. //
  1279. // check if we are in loop on error
  1280. //
  1281. li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register
  1282. lb t0,0(t0) // read register value.
  1283. li t1,LOOP_ON_ERROR_MASK // get value to compare
  1284. andi t0,DIAGNOSTIC_MASK // mask diagnostic bits.
  1285. li v0,PROM_ENTRY(14) // load address of PutLedDisplay
  1286. beq t1,t0,10f // brnach if loop on error.
  1287. move s8,a0 // save register a0
  1288. lui t0,LED_BLINK // get LED blink code
  1289. jal v0 // Blink LED and hang.
  1290. or a0,a3,t0 // pass a3 as argument in a0
  1291. 10:
  1292. lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code
  1293. jal v0 // Set LOOP ON ERROR on LED
  1294. or a0,a3,t0 // pass a3 as argument in a0
  1295. b CheckAddressTest // Loop back to test again.
  1296. move a0,s8 // restoring arguments.
  1297. .end CheckAddressTest
  1298. /*++
  1299. VOID
  1300. CheckNoXorAddressTest(
  1301. StartAddress
  1302. Size
  1303. not used
  1304. LedDisplayValue
  1305. )
  1306. Routine Description:
  1307. This routine will check that each location contains it's address.
  1308. as written by WriteNoXorAddressTest.
  1309. Arguments:
  1310. Note: the values of the arguments are preserved.
  1311. a0 - supplies start of memory area to test
  1312. a1 - supplies length of memory area in bytes
  1313. a2 - Not used
  1314. a3 - suplies the value to display in the led in case of failure
  1315. Return Value:
  1316. This routine returns no value.
  1317. The routine hangs blinking the LED or looping if the loop on error
  1318. bit is set in the config register.
  1319. --*/
  1320. LEAF_ENTRY(CheckNoXorAddressTest)
  1321. addiu t3,a0,-4 // t3 first address-4
  1322. add t2,a0,a1 // last address.
  1323. addiu t2,t2,-8 // adjust
  1324. move t1,t3 // get copy of t3 just for first check
  1325. checkaddressNX:
  1326. bne t1,t3,PatternFailNX
  1327. lw t1,4(t3) // load from first location
  1328. addiu t3,t3,4 // compute next address
  1329. bne t1,t3,PatternFailNX
  1330. lw t1,4(t3) // load from next location
  1331. addiu t3,t3,4 // compute next address
  1332. bne t1,t3,PatternFailNX
  1333. lw t1,4(t3) // load from next location
  1334. addiu t3,t3,4 // compute next address
  1335. bne t1,t3,PatternFailNX // check
  1336. lw t1,4(t3) // load from next location
  1337. bne t3,t2, checkaddressNX // check for end condition
  1338. addiu t3,t3,4 // compute next address
  1339. bne t1,t3,PatternFailNX // check last
  1340. nop
  1341. j ra // return a zero to the caller
  1342. move v0,zero //
  1343. PatternFailNX:
  1344. //
  1345. // check if we are in loop on error
  1346. //
  1347. li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register
  1348. lb t0,0(t0) // read register value.
  1349. li t1,LOOP_ON_ERROR_MASK // get value to compare
  1350. andi t0,DIAGNOSTIC_MASK // mask diagnostic bits.
  1351. li v0,PROM_ENTRY(14) // load address of PutLedDisplay
  1352. beq t1,t0,10f // brnach if loop on error.
  1353. move s8,a0 // save register a0
  1354. lui t0,LED_BLINK // get LED blink code
  1355. jal v0 // Blink LED and hang.
  1356. or a0,a3,t0 // pass a3 as argument in a0
  1357. 10:
  1358. lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code
  1359. jal v0 // Set LOOP ON ERROR on LED
  1360. or a0,a3,t0 // pass a3 as argument in a0
  1361. b CheckNoXorAddressTest // Loop back to test again.
  1362. move a0,s8 // restoring arguments.
  1363. .end CheckNoXorAddressTest
  1364. /*++
  1365. VOID
  1366. ZeroMemory(
  1367. ULONG StartAddress
  1368. ULONG Size
  1369. );
  1370. Routine Description:
  1371. This routine will zero a range of memory.
  1372. Arguments:
  1373. a0 - supplies start of memory
  1374. a1 - supplies length of memory in bytes
  1375. Return Value:
  1376. None.
  1377. --*/
  1378. LEAF_ENTRY(ZeroMemory)
  1379. add a1,a1,a0 // Compute End address
  1380. addiu a1,a1,-4 // adjust address
  1381. ZeroMemoryLoop:
  1382. sw zero,0(a0) // zero memory.
  1383. bne a0,a1,ZeroMemoryLoop // loop until done.
  1384. addiu a0,a0,4 // compute next address
  1385. j ra // return
  1386. nop
  1387. ALTERNATE_ENTRY(ZeroMemoryEnd)
  1388. nop
  1389. .end ZeroMemory
  1390. //++
  1391. //
  1392. //PULONG
  1393. //Decompress(
  1394. // IN PULONG InputImage,
  1395. // IN PULONG OutputImage
  1396. // )
  1397. //
  1398. //
  1399. //Routine Description:
  1400. //
  1401. // This routine decompresses the input image.
  1402. //
  1403. //Arguments:
  1404. //
  1405. // InputImage (a0) - byte pointer to the image to be decompressed.
  1406. // OutputImage (a1) - byte pointer to the area to write decompressed image.
  1407. //
  1408. // N.B. The first ULONG of the InputImage contains the decompressed length in bytes.
  1409. // See romcomp.c for a description of method.
  1410. //
  1411. //Return Value:
  1412. //
  1413. // None.
  1414. //
  1415. //--
  1416. .set reorder
  1417. LEAF_ENTRY(Decompress)
  1418. lw a2,(a0) // get the target size.
  1419. srl a2,a2,2 // get size of output in words/symbols.
  1420. addiu a0,a0,4 // address of next word
  1421. move a3,a1 // stash output image base
  1422. //
  1423. // Calculate the offset width from the size. Assume size > 2 ULONG.
  1424. //
  1425. #define SHORT_INDEX_WIDTH 10
  1426. li t8,1 // start at two
  1427. srl t0,a2,1 // offset must only span half the image.
  1428. 5:
  1429. addiu t8,t8,1 // next bit
  1430. srl t1,t0,t8 // shift off low bits
  1431. bgtz t1,5b // quit when we find the highest set bit.
  1432. //
  1433. // Set the symbol register bit count to zero so that on the first iteration of the loop we will
  1434. // get the first symbol longword. Add one to the symbol count to allow for first loop entry.
  1435. //
  1436. li t1,0 // number of valid bits
  1437. addiu a2,a2,1 // increment symbol count
  1438. //
  1439. // Loop, decompressing the data. There is always at least one bit in the register at this point.
  1440. //
  1441. 10:
  1442. //
  1443. // Decrement the symbol count and exit the loop when done.
  1444. //
  1445. addiu a2,a2,-1 // decrement symbol count
  1446. beq zero,a2,99f // return
  1447. //
  1448. // Load symbol register if it is empty.
  1449. //
  1450. bne zero,t1,12f // check for lack of bits
  1451. lw t0,(a0) // get the next word
  1452. addiu a0,a0,4 // address of next word
  1453. li t1,32 // number of valid bits
  1454. 12:
  1455. //
  1456. // Test first bit of symbol
  1457. //
  1458. andi t2,t0,0x1 // test the low bit
  1459. addiu t1,t1,-1 // decrement bit count
  1460. srl t0,t0,1 // shift symbol
  1461. bne zero,t1,20f // check for lack of bits
  1462. lw t0,(a0) // get the next word
  1463. addiu a0,a0,4 // address of next word
  1464. li t1,32 // number of valid bits
  1465. 20:
  1466. bne zero,t2,50f // if not zero then this is an index
  1467. 30:
  1468. //
  1469. // First bit of symbol is zero, this is the zero or unique case. Check the next bit.
  1470. //
  1471. andi t2,t0,0x1 // test the low bit
  1472. addiu t1,t1,-1 // decrement bit count
  1473. srl t0,t0,1 // shift symbol
  1474. bne zero,t2,40f // if not zero then this is a unique word symbol
  1475. //
  1476. // This is the zero case. 0b00
  1477. //
  1478. sw zero,(a1) // store the zero
  1479. addiu a1,a1,4 // increment the output image pointer
  1480. b 10b // go get the next symbol.
  1481. //
  1482. // The symbol is a unique word. 0b10. Get the next 32 bits and write them to the output.
  1483. //
  1484. // The symbol register contains 0 to 31 bits of the word to be written. Get the next
  1485. // word, shift and merge it with the existing symbol to produce a complete word. The remainder
  1486. // of the new word becomes the next symbol register contents.
  1487. //
  1488. // Note that since we read a new word we don't have to decrement the bit counter since it runs
  1489. // mod 32.
  1490. //
  1491. 40:
  1492. lw t3,(a0) // get next word
  1493. addiu a0,a0,4 // address of next word
  1494. sll t2,t3,t1 // shift it by the bit count
  1495. or t0,t0,t2 // put it in with the existing contents of the symbol register
  1496. sw t0,(a1) // store the word
  1497. addiu a1,a1,4 // increment the output image pointer
  1498. li t2,32 // get shift count for new word to make new symbol register
  1499. subu t2,t2,t1 //
  1500. srl t0,t3,t2 // new contents of symbol register. For bit count zero case
  1501. // this is a nop
  1502. b 10b // go get the next symbol.
  1503. //
  1504. // This is the index case. 0bX1. Now the next bit determines whether the offset is relative(1) or
  1505. // absolute(0). Stash the next bit for when we use the offset.
  1506. //
  1507. 50:
  1508. andi t4,t0,0x1 // get the relative/absolute bit
  1509. addiu t1,t1,-1 // decrement bit count
  1510. srl t0,t0,1 // shift symbol
  1511. bne zero,t1,55f // check for lack of bits
  1512. lw t0,(a0) // get the next word
  1513. addiu a0,a0,4 // address of next word
  1514. li t1,32 // number of valid bits
  1515. 55:
  1516. //
  1517. // Get the next bit. This tells us whether we have a long(0) or a short(1) index.
  1518. //
  1519. andi t2,t0,0x1 // test the low bit
  1520. addiu t1,t1,-1 // decrement bit count
  1521. srl t0,t0,1 // shift symbol
  1522. bne zero,t1,60f // check for lack of bits
  1523. lw t0,(a0) // get the next word
  1524. addiu a0,a0,4 // address of next word
  1525. li t1,32 // number of valid bits
  1526. 60:
  1527. li t5,SHORT_INDEX_WIDTH // preload with short index width
  1528. bne zero,t2,70f // if not zero then this is a short index.
  1529. move t5,t8 // use long index width
  1530. //
  1531. // Get the index based on the width. If the currently available bits are less than the
  1532. // number that we need then we must read another word.
  1533. //
  1534. 70:
  1535. li t7,0 // zero the remainder
  1536. sub t2,t5,t1 // get difference between what we need and what we have
  1537. blez t2,75f // if we got what we need
  1538. lw t6,(a0) // get next word
  1539. addiu a0,a0,4 // address of next word
  1540. sll t7,t6,t1 // shift new bits into position
  1541. or t0,t0,t7 // move new bits into symbol register
  1542. srl t7,t6,t2 // adjust remainder
  1543. addiu t1,t1,32 // pre-bias the bit count for later decrement.
  1544. 75:
  1545. li t3,1 // grab a one
  1546. sll t3,t3,t5 // shift it by number of bits we will extract
  1547. addiu t3,t3,-1 // make a mask
  1548. and t2,t0,t3 // grab the index
  1549. sll t2,t2,2 // make it a byte index
  1550. srl t0,t0,t5 // shift out bits we used.
  1551. or t0,t0,t7 // merge in remainder if any.
  1552. sub t1,t1,t5 // decrement the bit count, correct regardless
  1553. //
  1554. // Use index to write output based on the absolute(0)/relative(1) bit.
  1555. //
  1556. 80:
  1557. bne zero,t4,85f // test for the relative case.
  1558. addu t3,a3,t2 // address by absolute
  1559. b 87f // go move the word
  1560. 85:
  1561. subu t3,a1,t2 // address by relative
  1562. //
  1563. // Move the byte.
  1564. //
  1565. 87:
  1566. lw t2,(t3) // get the word
  1567. sw t2,(a1) // store the word
  1568. addiu a1,a1,4 // increment output pointer
  1569. b 10b // go do next symbol
  1570. //
  1571. // Return
  1572. //
  1573. 99:
  1574. j ra // return
  1575. .end Decompress
  1576. .set noreorder
  1577. /*++
  1578. VOID
  1579. DataCopy(
  1580. ULONG SourceAddress
  1581. ULONG DestinationAddress
  1582. ULONG Length
  1583. );
  1584. Routine Description:
  1585. This routine will copy data from one location to another
  1586. Source, destination, and length must be dword aligned.
  1587. Arguments:
  1588. a0 - supplies source of data
  1589. a1 - supplies destination of data
  1590. a2 - supplies length of data in bytes
  1591. Return Value:
  1592. None.
  1593. --*/
  1594. LEAF_ENTRY(DataCopy)
  1595. add a2,a2,a0 // get last address
  1596. CopyLoop:
  1597. ldc1 f0,0(a0) // load 1st double word
  1598. ldc1 f2,8(a0) // load 2nd double word
  1599. addiu a0,a0,16 // increment source pointer
  1600. sdc1 f0,0(a1) // store 1st double word
  1601. sdc1 f2,8(a1) // store 2nd double word
  1602. bne a0,a2,CopyLoop // loop until address=last address
  1603. addiu a1,a1,16 // increment destination pointer
  1604. j ra // return
  1605. nop
  1606. .align 4 // Align it to 16 bytes boundary so that
  1607. ALTERNATE_ENTRY(EndMemoryRoutines) // DataCopy doesn't need to check alignments
  1608. nop
  1609. .end DataCopy
  1610. /*++
  1611. VOID
  1612. ProcessorTest(
  1613. VOID
  1614. );
  1615. Routine Description:
  1616. This routine tests the processor. Test uses all registers and almost all
  1617. the instructions.
  1618. N.B. This routine destroys the values in all of the registers.
  1619. Arguments:
  1620. None.
  1621. Return Value:
  1622. None, but will hang flashing the led if an error occurs.
  1623. --*/
  1624. LEAF_ENTRY(ProcessorTest)
  1625. lui a0,0x1234 // a0=0x12340000
  1626. ori a1,a0,0x4321 // a1=0x12344321
  1627. add a2,zero,a0 // a2=0x12340000
  1628. addiu a3,zero,-0x4321 // a3=0xFFFFBCDF
  1629. subu AT,a2,a3 // AT=0x12344321
  1630. bne a1,AT,ProcessorError // branch if no match match
  1631. andi v0,a3,0xFFFF // v0=0x0000BCDF
  1632. ori v1,v0,0xFFFF // v1=0x0000FFFF
  1633. sll t0,v1,16 // t0=0xFFFF0000
  1634. xor t1,t0,v1 // t1=0xFFFFFFFF
  1635. sra t2,t0,16 // t2=0xFFFFFFFF
  1636. beq t1,t2,10f // if eq good
  1637. srl t3,t0,24 // t3=0x000000FF
  1638. j ProcessorError // if wasn't eq error.
  1639. 10: sltu s0,t0,v1 // S0=0 because t0 > v1
  1640. bgtz s0,ProcessorError // if s0 > zero error
  1641. or t4,AT,v0 // t4=X
  1642. bltz s0,ProcessorError // if s0 < zero error
  1643. nor t5,v0,AT // t5=~X
  1644. and t6,t4,t5 // t6=0
  1645. move s0,ra // save ra in s0
  1646. bltzal t6,ProcessorError // if t6 < 0 error, load ra in case
  1647. nop
  1648. RaAddress:
  1649. //la t7,RaAddress - LINK_ADDRESS + RESET_VECTOR // get expected address in ra
  1650. la t7,RaAddress // get expected address in ra
  1651. bne ra,t7,ProcessorError // error if don't match
  1652. move ra,s0 // put ra back
  1653. ori s1,zero,0x100 // load constant
  1654. mult s1,t3 // 0x100*0xFF
  1655. mfhi s3 // s3=0
  1656. mflo s2 // s2=0xFF00
  1657. blez s3,10f // branch if correct
  1658. sll s4,t3,zero // move t3 into s4
  1659. addiu s4,100 // change value in s4 to produce an error
  1660. 10: divu s5,s2,s4 // divide 0xFF00/0xFF
  1661. nop
  1662. nop
  1663. mfhi s6 // remainder s6=0
  1664. bne s5,s1,ProcessorError
  1665. nop
  1666. blez s6,10f // branch if no error
  1667. nop
  1668. j ProcessorError
  1669. 10: sub s7,s5,s4 // s7=1
  1670. mthi s7
  1671. mtlo AT
  1672. xori gp,s5,0x2566 // gp=0x2466
  1673. move s0,sp // save sp for now
  1674. srl sp,gp,s7 // sp=0x1233
  1675. mflo s8 // s8=0x12344321
  1676. mfhi k0 // k0=1
  1677. ori k1,zero,16 // k1=16
  1678. sra k1,s8,k1 // k1=0x1234
  1679. add AT,sp,k0 // AT=0x1234
  1680. bne k1,AT,ProcessorError // branch on error
  1681. nop
  1682. #ifdef R4001
  1683. //
  1684. // Some extra stuff added to verify that the R4000 bug is fixed
  1685. // If it hangs a minus sign will be displayed in the LED
  1686. //
  1687. li t0,DIAGNOSTIC_VIRTUAL_BASE
  1688. li t1,0xB // value to display '-' in the LED
  1689. sw t1,0(t0) // write to the LED should be sb
  1690. lw t2,8(t0) // do something
  1691. sll t5,t0,t1 // 2 cycle instruction
  1692. #endif
  1693. j ra // return
  1694. nop
  1695. ProcessorError:
  1696. lui a0,LED_BLINK // blink also means that
  1697. bal PutLedDisplay // the routine hangs.
  1698. ori a0,LED_PROCESSOR_TEST // displaying this value.
  1699. .end ProcessorTest
  1700. /*++
  1701. VOID
  1702. MctadrReset(
  1703. VOID
  1704. );
  1705. Routine Description:
  1706. This routine tests the reset values of the MCT_ADR asic.
  1707. Arguments:
  1708. None.
  1709. Return Value:
  1710. None, but will hang flashing the led if an error occurs.
  1711. --*/
  1712. LEAF_ENTRY(MctadrResetTest)
  1713. move s0,ra // save return address.
  1714. //
  1715. // Test the mctadr reset values.
  1716. //
  1717. MctadrReset:
  1718. li t0,DMA_VIRTUAL_BASE // Get base address of MCTADR
  1719. lw v0,DmaConfiguration(t0) // Check Config reset value
  1720. li t1,CONFIG_RESET_MCTADR_REV1 // Check for REV1 ASIC, i.e. JAZZ
  1721. beq v0,t1,10f
  1722. li t1,CONFIG_RESET_MCTADR_REV2 // Check for REV2 ASIC, i.e. FIS/USION
  1723. bne v0,t1,MctadrResetError
  1724. lw v0,DmaRevisionLevel(t0) // Get revision level register
  1725. slti t1,v0,3 // Check for REV3 ASIC
  1726. bnez t1,5f // If not REV3 or greater, enable interrupts
  1727. nop
  1728. mfc0 t1,config // Get R4000 config register
  1729. srl t2,t1,CONFIG_SC // check for secondary cache
  1730. and t2,t2,1 // isolate the bit
  1731. beq t2,zero,5f // if secondary cache, enable interrupts
  1732. nop
  1733. b 10f // Fision with REV3 or greater, don't
  1734. nop // enable interrups over the bus
  1735. 5:
  1736. addiu t1,t0,DmaRemoteSpeed15 // DmaRemoteSpeed15 is the interrupt
  1737. // enable register in REV2
  1738. li v0,0x3f // MCTADR interrupt enable mask
  1739. sw v0,0(t1) // Enable interrupts in MCTADR
  1740. 10:
  1741. lw v0,DmaInvalidAddress(t0)
  1742. lw v1,DmaTranslationBase(t0)
  1743. bne v0,zero,MctadrResetError // Check LFAR reset value
  1744. lw v0,DmaTranslationLimit(t0)
  1745. bne v1,zero,MctadrResetError // Check Ttable base reset value
  1746. lw v1,DmaRemoteFailedAddress(t0)
  1747. bne v0,zero,MctadrResetError // Check TT limit reset value
  1748. lw v0,DmaMemoryFailedAddress(t0)
  1749. bne v1,zero,MctadrResetError // Check RFAR reset value
  1750. lw v1,DmaByteMask(t0)
  1751. bne v0,zero,MctadrResetError // Check MFAR reset value
  1752. addiu t1,t0,DmaRemoteSpeed0 // address of REM_SPEED 0
  1753. bne v1,zero,MctadrResetError // Check TT_BMASK reset value
  1754. addiu t2,t0,DmaRemoteSpeed14 // address of REM_SPEED 14
  1755. // Don't check 15 because this is
  1756. // the interrupt enable for REV2
  1757. lw v0,0(t1) // read register
  1758. li t3,REMSPEED_RESET //
  1759. addiu t1,t1,8 // next register address.
  1760. NextRemSpeed:
  1761. bne v0,t3,MctadrResetError // Check Rem speed reg reset value
  1762. lw v0,0(t1) // read next rem speed
  1763. bne t1,t2,NextRemSpeed
  1764. addiu t1,t1,8 // next register address.
  1765. bne v0,t3,MctadrResetError // Check last Rem speed reg reset value
  1766. addiu t1,t0,DmaChannel0Mode // address of first channel register
  1767. addiu t2,t0,DmaChannel7Address // address of last channel register
  1768. lw v0,0(t1) // read register
  1769. addiu t1,t1,8 // next register address.
  1770. NextChannelReg:
  1771. bne v0,zero,MctadrResetError // Check channel reg reset value
  1772. lw v0,0(t1) // read next channel
  1773. bne t1,t2,NextChannelReg
  1774. addiu t1,t1,8 // next register address.
  1775. bne v0,zero,MctadrResetError // Checklast channel reg reset value
  1776. lw v0,DmaInterruptSource(t0)// read DMA Channel interrupt
  1777. lw v1,DmaErrortype(t0) // read eisa/ethernet error reg
  1778. bne v0,zero,MctadrResetError // check Intpend
  1779. lw v0,DmaRefreshRate(t0)
  1780. bne v1,zero,MctadrResetError // check Eisa error type reset value
  1781. li t1,REFRRATE_RESET
  1782. bne v0,t1,MctadrResetError // check Refresh rate reset value
  1783. lw v0,DmaSystemSecurity(t0)
  1784. li t1,SECURITY_RESET
  1785. bne v0,t1,MctadrResetError // check Security reg reset value
  1786. lw v0,DmaInterruptAcknowledge(t0) // read register but don't check
  1787. j s0 // return to caller
  1788. MctadrResetError:
  1789. li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register
  1790. lb t0,0(t0) // read register value.
  1791. li t1,LOOP_ON_ERROR_MASK // get value to compare
  1792. andi t0,DIAGNOSTIC_MASK // mask diagnostic bits.
  1793. beq t1,t0,10f // branch if loop on error.
  1794. ori a0,zero,LED_MCTADR_RESET// load LED display value.
  1795. lui t0,LED_BLINK // get LED blink code
  1796. bal PutLedDisplay // Blink LED and hang.
  1797. or a0,a0,t0 // pass argument in a0
  1798. 10:
  1799. lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code
  1800. bal PutLedDisplay // Set LOOP ON ERROR on LED
  1801. or a0,a0,t0 // pass argument in a0
  1802. b MctadrReset
  1803. nop
  1804. .end MctadrResetTest
  1805. /*++
  1806. VOID
  1807. MctadrRegisterTest(
  1808. VOID
  1809. );
  1810. Routine Description:
  1811. This routine tests the MCT_ADR registers.
  1812. Arguments:
  1813. None.
  1814. Return Value:
  1815. None, but will hang flashing the led if an error occurs.
  1816. --*/
  1817. LEAF_ENTRY(MctadrRegisterTest)
  1818. move s0,ra // save return address.
  1819. //
  1820. // Check the data path between R4K and Mctadr by writing to Byte mask reg.
  1821. //
  1822. MctadrReg:
  1823. li t0,DMA_VIRTUAL_BASE
  1824. lw v0,DmaConfiguration(t0) // Check Config reset value
  1825. li t1,CONFIG_RESET_MCTADR_REV1 // Check for REV1 ASIC, i.e. JAZZ
  1826. beq v0,t1,10f
  1827. li t1,0x17F // For Jazz, 2Mb Video, 64 Mb Main
  1828. li t1,0x5fa // For FIS/USION, 2MB Video, 256 MBytes Main
  1829. 10:
  1830. sw t1,DmaConfiguration(t0) // Init Global Config
  1831. lw v0,DmaConfiguration(t0) // Read Configuration
  1832. nop
  1833. bne v0,t1,MctadrRegError // check GLOBAL CONFIG
  1834. sw zero,DmaCacheMaintenance(t0)// select cache block zero.
  1835. li t1,1
  1836. sw t1,DmaLogicalTag(t0) // Set LFN=zero, Offset=0 , Direction=READ from memory, Valid
  1837. li t2,0x55555555
  1838. sw t2,DmaByteMask(t0) // write pattern to Byte mask
  1839. lw v0,DmaByteMask(t0) // read Byte mask
  1840. sw t1,DmaPhysicalTag(t0) // PFN=0 and Valid
  1841. bne v0,t2,MctadrRegError //
  1842. addu t2,t2,t2 // t1=0xAAAAAAAA
  1843. sw t2,DmaByteMask(t0) // write patten to Byte mask
  1844. lw v0,DmaByteMask(t0) // read Byte mask
  1845. li t2,0xFFFFFFFF // expected value
  1846. bne v0,t2,MctadrRegError // Check byte mask
  1847. li a0,0xA0000000 // get memory address zero.
  1848. sw zero,0(a0) // write address zero -> flushes buffers
  1849. lw v0,DmaByteMask(t0) // read Byte mask
  1850. nop
  1851. bne v0,zero,MctadrRegError // Check byte mask was cleared.
  1852. li t4,MEMORY_REFRESH_RATE //
  1853. sw t4,DmaRefreshRate(t0) //
  1854. li t2,0x1555000 //
  1855. sw t2,DmaTranslationBase(t0) // write base of Translation Table
  1856. li t3,0x5550
  1857. sw t3,DmaTranslationLimit(t0) // write to TT_limit
  1858. lw v1,DmaTranslationBase(t0) // read TT Base
  1859. lw v0,DmaTranslationLimit(t0) // read TT_limit
  1860. bne v1,t2,MctadrRegError // check TT-BASE
  1861. lw v1,DmaRefreshRate(t0)
  1862. bne v0,t3,MctadrRegError // check TT-LIMIT
  1863. li t2,0xAAA0
  1864. bne v1,t4,MctadrRegError // check REFRESH Rate
  1865. li t1,0x2AAA000
  1866. sw t1,DmaTranslationBase(t0) // write to Translation Base
  1867. sw t2,DmaTranslationLimit(t0) // write to Translation Limit
  1868. lw v0,DmaTranslationBase(t0) // read TT Base
  1869. lw v1,DmaTranslationLimit(t0) // read TT limit
  1870. bne v0,t1,MctadrRegError // check TT Base
  1871. li t1, TT_BASE_ADDRESS // Init translation table base address
  1872. sw t1, DmaTranslationBase(t0) // Initialize TT Base
  1873. bne v1,t2,MctadrRegError // check TT Limit
  1874. nop
  1875. sw zero,DmaTranslationLimit(t0) // clear TT Limit
  1876. //
  1877. // Initialize remote speed registers.
  1878. //
  1879. addiu t1,t0,DmaRemoteSpeed1 // address of REM_SPEED 1
  1880. la a1,RomRemoteSpeedValues - LINK_ADDRESS + RESET_VECTOR //
  1881. addiu t2,a1,14 // addres of last value
  1882. WriteNextRemSpeed:
  1883. lbu v0,0(a1) // load init value for rem speed
  1884. addiu a1,a1,1 // compute next address
  1885. sw v0,0(t1) // write to rem speed reg
  1886. bne a1,t2,WriteNextRemSpeed // check for end condition
  1887. addiu t1,t1,8 // next register address
  1888. addiu a1,t2,-14 // address of first value for rem speed register
  1889. addiu t1,t0,DmaRemoteSpeed1 // address of REM_SPEED 1
  1890. lbu v1,0(a1) // read expected value
  1891. CheckNextRemSpeed:
  1892. lw v0,0(t1) // read register
  1893. addiu a1,a1,1 // address of next value
  1894. bne v0,v1,MctadrRegError // check register
  1895. addiu t1,t1,8 // address of next register
  1896. bne a1,t2,CheckNextRemSpeed // check for end condition
  1897. lbu v1,0(a1) // read expected value
  1898. //
  1899. // Now test the DMA channel registers
  1900. //
  1901. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1902. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1903. li a0,0x15 // Mode
  1904. li a1,0x2 // enable
  1905. li a2,0xAAAAA // byte count
  1906. li a3,0x555555 // address
  1907. WriteNextChannel:
  1908. sw a0,0(t1) // write mode
  1909. sw a1,0x8(t1) // write enable
  1910. sw a2,0x10(t1) // write byte count
  1911. sw a3,0x18(t1) // write address
  1912. addiu t1,t1,DMA_CHANNEL_GAP // compute address of next channel
  1913. addiu a2,a2,1 // change addres
  1914. bne t1,t2,WriteNextChannel
  1915. addiu a3,a3,-1 // change Byte count
  1916. //
  1917. // Check channel regs.
  1918. //
  1919. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1920. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1921. li a2,0xAAAAA // byte count
  1922. li a3,0x555555 // address
  1923. CheckNextChannel:
  1924. lw t4,0x0(t1) // read mode
  1925. lw t5,0x8(t1) // read enable
  1926. bne t4,a0,MctadrRegError // check mode
  1927. lw t4,0x10(t1) // read byte count
  1928. bne t5,a1,MctadrRegError // check enable
  1929. lw t5,0x18(t1) // read address
  1930. bne t4,a2,MctadrRegError // check abyte count
  1931. addiu a2,a2,1 // next expected byte count
  1932. bne t5,a3,MctadrRegError // check address
  1933. addiu t1,t1,DMA_CHANNEL_GAP // next channel address
  1934. bne t1,t2,CheckNextChannel
  1935. addiu a3,a3,-1
  1936. //
  1937. // Now do a second test on DMA channel registers
  1938. //
  1939. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1940. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1941. li a0,0x2A // Mode
  1942. li a2,0x55555 // byte count
  1943. li a3,0xAAAAAA // address
  1944. WriteNextChannel2:
  1945. sw a0,0(t1) // write mode
  1946. sw a2,0x10(t1) // write byte count
  1947. sw a3,0x18(t1) // write address
  1948. addiu t1,t1,DMA_CHANNEL_GAP // compute address of next channel
  1949. addiu a2,a2,1 // change addres
  1950. bne t1,t2,WriteNextChannel2
  1951. addiu a3,a3,-1 // change Byte count
  1952. //
  1953. // Check channel regs.
  1954. //
  1955. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1956. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1957. li a2,0x55555 // byte count
  1958. li a3,0xAAAAAA // address
  1959. CheckNextChannel2:
  1960. lw t4,0x0(t1) // read mode
  1961. lw t5,0x10(t1) // read byte count
  1962. bne t4,a0,MctadrRegError // check mode
  1963. lw t4,0x18(t1) // read address
  1964. bne t5,a2,MctadrRegError // check abyte count
  1965. addiu a2,a2,1 // next expected byte count
  1966. bne t4,a3,MctadrRegError // check address
  1967. addiu t1,t1,DMA_CHANNEL_GAP // next channel address
  1968. bne t1,t2,CheckNextChannel2
  1969. addiu a3,a3,-1
  1970. //
  1971. // Now zero the channel registers
  1972. //
  1973. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1974. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1975. ZeroChannelRegs:
  1976. addiu t1,t1,8
  1977. sw zero,-8(t1) // clear reg
  1978. bne t1,t2,ZeroChannelRegs
  1979. nop //R4KFIX
  1980. addiu t1,t0,DmaChannel0Mode // address of channel 0
  1981. addiu t2,t1,8*DMA_CHANNEL_GAP // last address of channel regs
  1982. CheckZeroedChannelRegs:
  1983. lw a0,0(t1)
  1984. addiu t1,t1,8 // next channel
  1985. bne a0,zero,MctadrRegError // check
  1986. nop
  1987. bne t1,t2,CheckZeroedChannelRegs
  1988. nop
  1989. j s0 // return to caller.
  1990. MctadrRegError:
  1991. li t0,DIAGNOSTIC_VIRTUAL_BASE // get base address of diag register
  1992. lb t0,0(t0) // read register value.
  1993. li t1,LOOP_ON_ERROR_MASK // get value to compare
  1994. andi t0,DIAGNOSTIC_MASK // mask diagnostic bits.
  1995. beq t1,t0,10f // branch if loop on error.
  1996. ori a0,zero,LED_MCTADR_REG // load LED display value.
  1997. lui t0,LED_BLINK // get LED blink code
  1998. bal PutLedDisplay // Blink LED and hang.
  1999. or a0,a0,t0 // pass argument in a0
  2000. 10:
  2001. lui t0,LED_LOOP_ERROR // get LED LOOP_ERROR code
  2002. bal PutLedDisplay // Set LOOP ON ERROR on LED
  2003. or a0,a0,t0 // pass argument in a0
  2004. b MctadrReg
  2005. nop
  2006. .end MctadrRegisterTest
  2007. /*++
  2008. SizeMemory(
  2009. );
  2010. Routine Description:
  2011. This routine sizes the memory and writes the proper value into
  2012. the GLOBAL CONFIG register. The way memory is sized is the following:
  2013. For JAZZ:
  2014. The global config is ALREADY set to 64MB
  2015. for each bank base address i.e. 48,32,16,0 MB
  2016. ID0 is written to offset 0 from base of bank
  2017. ID4 is written to offset 4MB from base of bank
  2018. if ID4 is found at offset 0 the current bank has 1MB SIMMs.
  2019. if ID0 is found at offset 0 and ID4 is found at offset 4,
  2020. the current bank has 4MB SIMMs.
  2021. if data does not match or a parity exception is taken
  2022. then memory is not present in that bank.
  2023. For FIS/USION:
  2024. The global config is ALREADY set to 256MB
  2025. for each bank base address i.e. 192,128,64,0 MB
  2026. ID0 is written to offset 0 from base of bank
  2027. ID4 is written to offset 4MB from base of bank
  2028. ID20 is written to offset 20MB from base of bank
  2029. if ID20 is found at offset 0 the current bank has 1MB SIMMs.
  2030. if ID0 is found at offset 0 and ID20 is found at offset 4,
  2031. the current bank has 4MB SIMMs.
  2032. if ID0 is found at offset 0 and ID4 is found at offset 4
  2033. and ID20 is found at offset 20, the current bank has 16MB SIMMs.
  2034. if data does not match or a parity exception is taken
  2035. then memory is not present in that bank.
  2036. Arguments:
  2037. None.
  2038. Return Value:
  2039. If the installed memory is inconsistent, does not return
  2040. and the LED flashes A.E
  2041. --*/
  2042. #define MEM_ID0 0x0A0A0A0A
  2043. #define MEM_ID4 0xF5F5F5F5
  2044. #define MEM_ID20 0xA0A0A0A0
  2045. LEAF_ENTRY(SizeMemory)
  2046. .set noat
  2047. .set noreorder
  2048. li t0,DMA_VIRTUAL_BASE // Get base address of MCTADR
  2049. lw v0,DmaConfiguration(t0) // Check Config reset value
  2050. li t1,0x5fa // FIS/USION
  2051. beq v0,t1,Fission // Branch if 256 MByte config value found
  2052. li t0,0xA3000000 // get address 48MB
  2053. li t1,MEM_ID0 // get ID0
  2054. li t2,0xA3400000 // get address 52MB
  2055. li t3,MEM_ID4 // get ID4
  2056. li s0,3 // counts how many banks left to check
  2057. move t8,zero // t8 stores the present banks
  2058. move t9,zero // t9 stores the size of the banks
  2059. SizeBank:
  2060. move a1,zero // set current bank to 1 MB by default
  2061. sw t1,0x0(t0) // fill whole memory line at base of bank
  2062. sw t1,0x4(t0)
  2063. sw t1,0x8(t0)
  2064. sw t1,0xC(t0)
  2065. sw t3,0x0(t2) // fill whole memory line at base of bank + 4MB
  2066. sw t3,0x4(t2)
  2067. sw t3,0x8(t2)
  2068. sw t3,0xC(t2)
  2069. //
  2070. // Check written2data
  2071. //
  2072. lw t4,0x0(t0) // read whole memory line.
  2073. lw t5,0x4(t0) // the four words must be identical
  2074. lw t6,0x8(t0) //
  2075. lw t7,0xC(t0) //
  2076. move a0,zero // tells that bank not present
  2077. bne t4,t5,10f // check for consistency
  2078. nop
  2079. bne t4,t6,10f // check for consistency
  2080. nop //
  2081. bne t4,t7,10f // check for consistency
  2082. nop //
  2083. beq t4,t3,10f // If ID4 is found at PA 0
  2084. li a0,0x1 // bank is present and SIMMS are 1 MB
  2085. bne t4,t1,10f // if neither ID4 nor ID0 is found we are in trouble
  2086. move a0,zero // no memory in bank
  2087. li a0,0x1 // bank is present and SIMMS
  2088. // look like they are 4 MB
  2089. //
  2090. // ID written at Address 0 has been correctly checked
  2091. // Now check the ID written at address 4MB
  2092. //
  2093. lw t4,0x0(t2) // read whole memory line.
  2094. lw t5,0x4(t2) // the four words must be identical
  2095. bne t3,t4,10f // check for consistency
  2096. lw t6,0x8(t2) //
  2097. bne t3,t5,10f // check for consistency
  2098. lw t7,0xC(t2) //
  2099. bne t3,t6,10f // check for consistency
  2100. nop //
  2101. bne t3,t7,10f // check for consistency
  2102. nop
  2103. li a1,0x1 // If all matches SIMMs are 4MB
  2104. 10: //
  2105. // a0 has the value 0 if no memory in bank 1 if memory in bank
  2106. // a1 has the value 0 if 1MB SIMMS 1 if 4MB SIMMS
  2107. //
  2108. or t8,t8,a0 // accummulate present banks
  2109. or t9,t9,a1 // accummulate size of banks
  2110. //
  2111. // Check if last bank
  2112. //
  2113. beq s0,zero,Done
  2114. //
  2115. // Now set addresses to check next bank
  2116. //
  2117. li AT,0x01000000 // load 16MB
  2118. subu t0,t0,AT // subtract to base address
  2119. subu t2,t2,AT // subtract to base address + 4MB
  2120. sll t8,t8,1 // make room for next bank
  2121. sll t9,t9,1 // make room for next bank
  2122. b SizeBank // go to size next memory bank
  2123. addiu s0,s0,-1 // subtract one to the num of banks left
  2124. Done: //
  2125. // t8 has the present banks in bits 3-0 for banks 3-0
  2126. // t9 has the size of the banks in bits 3-2 and 1-0
  2127. //
  2128. // Check that memory is present in bank zero
  2129. //
  2130. andi t0,t8,1
  2131. beq t0,zero,WrongMemory
  2132. sll t8,t8,2 // shift bank enable bits to bits 5-2
  2133. andi t9,t9,0x3 // get rid of bits 2-3
  2134. or t8,t9,t8 // or size of banks with present banks
  2135. ori v0,t8,0x340 // Set Video RAM size and map PROM bits
  2136. li t0,DMA_VIRTUAL_BASE // Get base address of MCTADR
  2137. sw v0,DmaConfiguration(t0) // Store computed Config
  2138. j ra // return to caller.
  2139. nop
  2140. Fission:
  2141. li t0,0xAC000000 // get address 196MB
  2142. li t1,MEM_ID0 // get ID0
  2143. li t2,0xAC400000 // get address 200MB
  2144. li t3,MEM_ID4 // get ID4
  2145. li t4,0xAD400000 // get address 216MB
  2146. li t5,MEM_ID20 // get ID20
  2147. li s0,3 // counts how many banks left to check
  2148. move t8,zero // t8 stores the present banks
  2149. move t9,zero // t9 stores the size of the banks
  2150. FSizeBank:
  2151. move a1,zero // set current bank to 1 MB by default
  2152. sw t1,0x0(t0) // fill whole memory line at base of bank
  2153. sw t1,0x4(t0)
  2154. sw t1,0x8(t0)
  2155. sw t1,0xC(t0)
  2156. sw t3,0x0(t2) // fill whole memory line at base of bank + 4MB
  2157. sw t3,0x4(t2)
  2158. sw t3,0x8(t2)
  2159. sw t3,0xC(t2)
  2160. sw t5,0x0(t4) // fill whole memory line at base of bank + 20MB
  2161. sw t5,0x4(t4)
  2162. sw t5,0x8(t4)
  2163. sw t5,0xC(t4)
  2164. //
  2165. // Check written data
  2166. //
  2167. lw t6,0x0(t0) // read some of the memory line.
  2168. lw t7,0xC(t0) // the two words must be identical
  2169. move a0,zero // tells that bank not present
  2170. bne t6,t7,10f // check for consistency
  2171. nop
  2172. beq t6,t5,10f // If ID20 is found at 0MB
  2173. li a0,0x1 // bank is present and SIMMS are 1 MB
  2174. bne t6,t1,10f // if neither ID20 nor ID0 is found we are in trouble
  2175. move a0,zero // no memory in bank
  2176. li a0,0x1 // bank is present
  2177. //
  2178. // ID written at Address 0 has been correctly checked
  2179. // Now check the ID written at address 4MB
  2180. //
  2181. lw t6,0x0(t2) // read some of the memory line.
  2182. lw t7,0xC(t2) // the two words must be identical
  2183. nop
  2184. bne t6,t7,WrongMemory // check for consistency
  2185. nop
  2186. beq t6,t5,10f // If ID20 is found at 4MB
  2187. li a1,0x1 // bank is present and SIMMS are 4 MB
  2188. bne t6,t3,WrongMemory // if neither ID20 nor ID4 is found we are in trouble
  2189. nop
  2190. //
  2191. // ID written at Address 4MB has been correctly checked
  2192. // Now check the ID written at address 20MB
  2193. //
  2194. lw t6,0x0(t4) // read some of the memory line.
  2195. lw t7,0xC(t4) // the two words must be identical
  2196. nop
  2197. bne t6,t7,WrongMemory // check for consistency
  2198. nop
  2199. bne t6,t5,WrongMemory // if ID20 is not found we are in trouble
  2200. nop
  2201. li a1,0x2 // If all matches SIMMs are 16MB
  2202. 10: //
  2203. // a0 has the value 0 if no memory in bank, 1 if memory in bank
  2204. // a1 has the value 0 if 1MB SIMMS, 1 if 4MB SIMMS, 2 if 16MB SIMMS
  2205. //
  2206. or t8,t8,a0 // accummulate present banks
  2207. or t9,t9,a1 // accummulate size of banks
  2208. //
  2209. // Check if last bank
  2210. //
  2211. beq s0,zero,FDone
  2212. nop
  2213. //
  2214. // Now set addresses to check next bank
  2215. //
  2216. beq s0,2,Swizzle // swizzle banks
  2217. li AT,0x04000000 // load +64
  2218. li AT,-0x08000000 // load -128MB
  2219. Swizzle:
  2220. addu t0,t0,AT // add to base address
  2221. addu t2,t2,AT // add to base address + 4MB
  2222. addu t4,t4,AT // add to base address + 20MB
  2223. sll t8,t8,1 // make room for next bank
  2224. sll t9,t9,2 // make room for next bank
  2225. b FSizeBank // go to size next memory bank
  2226. addiu s0,s0,-1 // subtract one to the num of banks left
  2227. FDone: //
  2228. // t8 has the present banks in bits 3-0 for banks 3-0
  2229. // t9 has the size of the banks in bits 7:6, 5:4, 3:2, and 1:0
  2230. //
  2231. // Check that memory is present in bank zero
  2232. //
  2233. andi t0,t8,1
  2234. beq t0,zero,WrongMemory
  2235. sll t8,t8,4 // shift bank enable bits to bits 7-4
  2236. andi t9,t9,0xF // get rid of size bits 7-4
  2237. or t8,t9,t8 // or size of banks with present banks
  2238. ori v0,t8,0x500 // Set Video RAM size and map PROM bits
  2239. li t0,DMA_VIRTUAL_BASE // Get base address of MCTADR
  2240. ori v0,0x1000 // Enable timer interrupts for REV3 and
  2241. // greater ASICS
  2242. sw v0,DmaConfiguration(t0) // Store computed Config
  2243. j ra // return to caller.
  2244. nop
  2245. WrongMemory:
  2246. //
  2247. // Control reaches here if the memory can't be sized.
  2248. //
  2249. lui a0,LED_BLINK // Hang
  2250. bal PutLedDisplay // blinking the error code
  2251. ori a0,a0,LED_WRONG_MEMORY // in the LED
  2252. .end SizeMemory
  2253. #endif // JAZZ && R4000