tm_rdram_boot.s
9.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
/*
* tm_rdram_boot.s: Bootstrap file which loads tinymon_rdram into rdram memory
* from the standard gload point within ramrom. We also
* provide our own romheader file, where the first word
* (in ramrom) contains the size of the program to be loaded
* in bytes.
*/
#include "regdef.h"
#include "asm.h"
#include <R4300.h>
#include <rcp.h>
#define MANUFACTURE_NEC 0x00000500
#define MANUFACTURE_TOSHIBA 0x00000200
#define NEC_RELEASE_C2
#ifdef NEC_RELEASE_C2
/* NEC Rev C2 mode enable/disable */
#define RDRAM_ENABLE 0xc2800000
#define RDRAM_DISABLE 0xc0800000
#else
/* Non NEC Rev C2 mode enable/disable */
#define RDRAM_ENABLE 0xc6800000
#define RDRAM_DISABLE 0xc4800000
#endif
#define tinymon_rdram_dma_start 0xa0000000
#define tinymon_rdram_start 0xa0000200
#define tinymon_rdram_size 0x00000400
#define rd_rams 0xa0100400
#define ramrom_memsize 0xb0000030
/* 16K of instruction cache and 8K of data cache */
#define icache_size 0x4000
#define dcache_size 0x2000
#define icache_linesize (8*4)
#define dcache_linesize (4*4)
LEAF (tm_rdram_boot) # Address = 0xB0000400.
.set noreorder
/*
* XXX clear SR_BEV bit in tm_rdram
*/
li t1, SR_BEV|SR_CU0 # Initialize SR
mtc0 t1, C0_SR # Clear Status Register.
#***set sp
# Save room for the argument registers that passed by C program
li sp, PHYS_TO_K1(SP_IMEM_END - 15)
#ifdef RUN_CACHED
li t1, CONFIG_BE|CONFIG_UNCACHED # Run uncached.
mtc0 t1, C0_CONFIG # Enable Cache in KSeg0.
mtc0 zero,C0_CAUSE # initialize cause register
# Invalid I cache
.set reorder
la t0, 0x80000000
addu t1, t0, icache_size
.set noreorder
init_icache:
cache CACH_PI|C_IINV,0(t0) # use index invalidate
bltu t0,t1,init_icache # on entire cache
addu t0,icache_linesize
la t0, 0x80000000
addu t1, t0, dcache_size
init_dcache:
cache CACH_PD|C_IWBINV,0(t0) # use index invalidate
bltu t0,t1,init_dcache # on entire cache, so we can save
addu t0,dcache_linesize # some cache data for NMI case
#endif
# (Cribbed from PR/lib/BringupBoot/Boot.s; should work on rev1 or rev2)
# Need to initialize RD-RAM in cold reset case
la t0,PHYS_TO_K1(RI_BASE_REG)
lui t2, 0xa3f8
lui t3, 0xa3f0
la t4, PHYS_TO_K1(MI_BASE_REG)
ori t1, zero, 0x10
sw t1, 0x0004(t0) # Enable RAC auto-calibration control
# Delay 4096 RCP clock cycles.
li s1,6
wait_rac:
nop
addi s1, 0xffff # s1 = s1 - 1
bne s1,zero,wait_rac
nop
sw zero, 0x0008(t0) # Load current control regs.
ori t1, zero, 0x0014
sw t1, 0x000c(t0) # Set transmit and receive selects
sw zero,0(t0) # Reset all RDRAM devices
# Delay 100 RCP clock cycle
li s1,4
wait_rac1:
nop
addi s1, 0xffff # s1 = s1 - 1
bne s1,zero,wait_rac1
nop
ori t1, zero, 0x000e
sw t1,0(t0) # Enable RDRAM access
ori t1, zero, 0x010f
sw t1, 0x0000(t4) # Initialize the delay register
li t1, 0x18082838
sw t1, 0x0008(t2)
sw zero, 0x14(t2) # Initialize Refrow regs.
lui t1, 0x8000
sw t1, 4(t2) # move all RDRAMs to top of address
# Place all RDRAMs at 2 Mbyte boundaries and determine the size
# of each RDRAM
move t5,zero # next_device = 0;
move t6,zero # next_id = 0;
lui t7,0xa3f0 # next_reg = 0x03f00000;
move t8,zero # next_1_id = 0;
lui t9,0xa3f0 # next_1_reg = 0x03f00000;
lui a0,0xa000 # next_1_mem = 0;
move a1,zero # next_2_id = 0;
lui a2,0xa3f0 # next_2_reg = 0x03f00000;
lui a3,0xa000 # next_2_mem = 0;
addiu sp,sp,-72
move v0,sp # save sp location for next loop
lw s0,PHYS_TO_K1(MI_VERSION_REG)
/*
li s1,ramrom_memsize
sw s0,0x0(s1)
*/
la s1,0x01010101
bne s0,s1,rcp2
nop
li s0,0x200 # reg_step = 0x00000200;
ori s1,t3,0x4000 # reg_max = 0x03f04000
b loop1
nop
rcp2:
li s0,0x400 # reg_step = 0x00000400;
ori s1,t3,0x8000 # reg_max = 0x03f08000
loop1:
# move the next RDRAM to the next 2 MByte slot
sw t6,4(s1) # reg_max + 0x4 = next_id;
# enable the RDRAM
li t1,RDRAM_ENABLE
sw t1,0xc(t7) # next_reg + 0xc = RDRAM_ENABLE
# determine the RDRAM size
li t1,0x2000
sw t1,0(t4)
lw t3,0(t7)
lui t0,0xf0ff
and t3,t0
sw t3,0(sp) # device_type[next_device] =
# read_data & 0xf0ff0000;
addi sp,8
li t1,0x1000
sw t1,0(t4)
beqz t3,done_loop1
lui t0,0xb019
bne t3,t0,LM
nop
lui t0,0x0800
add t8,t0 # next_1_id = next_1_id + 0x08000000
add t9,s0
add t9,s0 # next_1_reg = next_1_reg + (reg_step*2)
lui t0,0x0020
add a0,t0
LM:
li t0,0x2000
sw t0,0(t4) # WriteWord(0x04300000, 0x00002000);
lw t1,0x24(t7)
li t0,0x1000
sw t0,0(t4) # WriteWord(0x04300000, 0x00001000);
andi t1,0xffff
li t0,MANUFACTURE_NEC
bne t1,t0,toshiba
nop
li t0,0x101c0a04
sw t0,0x18(t7) #WriteWord(next_reg + 0x18, 0x101c0a04)
b done_manufacture
toshiba:
li t0,0x080c1204
sw t0,0x18(t7) #WriteWord(next_reg + 0x18, 0x080c1204)
done_manufacture:
lui t0,0x0800
add t6,t0 # next_id = next_id + 0x08000000
add t7,s0
add t7,s0 # next_reg = next_reg + (reg_step * 2)
addiu t5,1
sltiu t0,t5,8
bne t0,zero,loop1
nop
done_loop1:
# Reinitialize all the RDRAMs
li t0,RDRAM_DISABLE
sw t0,0xc(t2) # WriteWord(0x03f8000c, RDRAM_DISABLE)
lui t0,0x8000
sw t0,0x4(t2) # WriteWord(0x03f80004, 0x80000000)
# Group the RDRAMs in 1 Mbyte and 2 Mbyte blocks
move sp,v0 # restore sp back
move v1,zero # i = 0
loop2:
lw t1,0(sp)
addi sp,8
lui t0,0xb009
bne t1,t0,HM
nop
# Move the RDRAM to the next 1 Mbyte slot
sw t8,0x4(s1) # WriteWord(reg_max + 0x4, next_1_id)
li t0,RDRAM_ENABLE
sw t0,0xc(t9) # WriteWord(next_1_reg+0xc,RDRAM_ENABLE)
# Tickle the RDRAM
lw t0,0(a0) #ReadWord(next_1_mem+0x00000,&read_data)
lui t0,0x8
add t0,a0
lw t1,0(t0) #ReadWord(next_1_mem+0x80000,&read_data)
lw t0,0(a0) #ReadWord(next_1_mem+0x00000,&read_data)
lui t0,0x8
add t0,a0
lw t1,0(t0) #ReadWord(next_1_mem+0x80000,&read_data)
lui t0,0x0400
add t6,t0 # next_1_id = next_1_id + 0x04000000
add t9,s0 # next_1_reg = next_1_reg + reg_step
lui t0,0x0010
add a0,t0
b done_loop2
HM:
# Move the RDRAM to the next 2 Mbyte slot
sw a1,0x4(s1) # WriteWord(reg_max + 0x4, next_2_id)
li t0,RDRAM_ENABLE
sw t0,0xc(a2) # WriteWord(next_2_reg+0xc,RDRAM_ENABLE)
# Tickle the RDRAM
lw t0,0(a3) #ReadWord(next_2_mem+0x00000,&read_data)
lui t0,0x08
add t0,a3
lw t1,0(t0)
lui t0,0x10
add t0,a3
lw t1,0(t0)
lui t0,0x18
add t0,a3
lw t1,0(t0)
lw t0,0(a3) #ReadWord(next_2_mem+0x00000,&read_data)
lui t0,0x08
add t0,a3
lw t1,0(t0)
lui t0,0x10
add t0,a3
lw t1,0(t0)
lui t0,0x18
add t0,a3
lw t1,0(t0)
lui t0,0x0800
add a1,t0 # next_2_id = next_2_id + 0x08000000
add a2,s0
add a2,s0 # next_2_reg = next_2_reg+(reg_step * 2)
lui t0,0x0020
add a3,t0
done_loop2:
addiu v1,1
slt t0,v1,t5
bne t0,zero,loop2
nop
# enable refresh
lui t2, 0xa470 # Enable refresh
li t1, 0x24040
sw t1, 0x0010(t2)
# save osMemSize to reserved area
/*
li t0,ramrom_memsize
li t1,0xfffffff
and a0,t1
sw a0,0x4(t0)
*/
.set reorder
load_ipl3:
# relocate the current running program to RD-RAM
la t0,block17s # the beginning of relocated program
la t3,pifipl3e # the end of relocated program
# Load the tinymon program from 0xB0000800 in ramrom to 0x00000000 in rdram.
# (We use 0xa0000000, since the K1 seg guarantees uncached access.
# tinymon_rdram will provide it''s own exception vectors.
la t1,K0_TO_K1(rd_rams) # load RD-RAM start address for IPL3
send2:
lw t5,0(t0) # load Boot from ROM
sw t5,0(t1) # store Boot to RD-RAM
addiu t0,4 # add Boot address
addiu t1,4 # add RD-RAM adress
bltu t0,t3,send2
#********<16 Jump to IPL3 in RD-RAM (cache enable)>
la t4,rd_rams
jr t4
#*******<17 Load game program to RD-RAM>
block17s:
# Send 1M byte game program from cartridge ROM
# ($19+game_offset ~ 19+game_offset+0xffffc) to RDRAM (0x80000400 ~ 0x801003fc)
# We need to reserve the first 1k for exception vector
lui t3,0xb000 #set source address of cartridge ROM
lw t0,0x8(t3) # get rom offset to the game
# (this is 0x2000 bytes into ramrom)
cart:
add t0,t3
li t2,0x1fffffff
and t0,t2
sw t0,PHYS_TO_K1(PI_CART_ADDR_REG)
la t1,K0_TO_PHYS(tinymon_rdram_dma_start) # game''s boot address
sw t1,PHYS_TO_K1(PI_DRAM_ADDR_REG)
la t2,tinymon_rdram_size # DMA size
sw t2,PHYS_TO_K1(PI_WR_LEN_REG) # start DMA
# wait for DMA to finish
waitdma:
.set noreorder
#ifdef __linux
.rept 0x1f
#else
.repeat 0x1f
#endif
nop
.endr
.set reorder
lw t3,PHYS_TO_K1(PI_STATUS_REG)
andi t3,PI_STATUS_DMA_BUSY
bnez t3,waitdma
# Make sure DMA works
#get checksum for RDRAM
li t2,tinymon_rdram_size
li t1,tinymon_rdram_dma_start
add t3,t2,t1
lui t4,0xb000 #set source address of cartridge ROM
lw t0,0x8(t4) # get rom address of the game
add t4,t0 # the address of rom image
check1:
lw t5,0(t1)
lw t6,0(t4)
# compare data
bne t5,t6,fail
addiu t1,4
addiu t4,4
bltu t1,t3,check1
#
# Jump to tinymon program in RD-RAM
#
la t1,tinymon_rdram_start
jr t1
.set noreorder
fail:
lui s0,0xb000
sw t5,0x20(s0)
nop
nop
sw t6,0x24(s0)
nop
nop
sw t1,0x28(s0)
nop
nop
sw t4,0x2c(s0)
nop
nop
loop:
b loop
.align 7 # Align to address 0x780
AllPurposeExceptionHandler:
b AllPurposeExceptionHandler
nop
pifipl3e:
nop
.set noreorder
#ifdef __linux__
.rept 9
#else
.repeat 9
#endif
nop
.endr
li k0,0x80102000
mfc0 k1,C0_CAUSE
sw k1,0(k0)
mfc0 k1,C0_SR
sw k1,4(k0)
mfc0 k1,C0_EPC
sw k1,4(k0)
sw ra,4(k0)
1:
b 1b
END (tm_rdram_boot)