1 /*-------------------------------------------------------------
3 system.c -- OS functions and initialization
6 Michael Wiedenbauer (shagkur)
7 Dave Murphy (WinterMute)
9 This software is provided 'as-is', without any express or implied
10 warranty. In no event will the authors be held liable for any
11 damages arising from the use of this software.
13 Permission is granted to anyone to use this software for any
14 purpose, including commercial applications, and to alter it and
15 redistribute it freely, subject to the following restrictions:
17 1. The origin of this software must not be misrepresented; you
18 must not claim that you wrote the original software. If you use
19 this software in a product, an acknowledgment in the product
20 documentation would be appreciated but is not required.
22 2. Altered source versions must be plainly marked as such, and
23 must not be misrepresented as being the original software.
25 3. This notice may not be removed or altered from any source
28 -------------------------------------------------------------*/
30 //#define DEBUG_SYSTEM
36 #include <sys/iosupport.h>
47 #include "wiilaunch.h"
52 #include "sys_state.h"
53 #include "lwp_threads.h"
54 #include "lwp_priority.h"
55 #include "lwp_watchdog.h"
56 #include "lwp_wkspace.h"
57 #include "lwp_objmgr.h"
58 #include "lwp_config.h"
59 #include "libversion.h"
61 #define SYSMEM1_SIZE 0x01800000
63 #define SYSMEM2_SIZE 0x04000000
65 #define KERNEL_HEAP (1*1024*1024)
68 #define DSPCR_DSPRESET 0x0800 // Reset DSP
69 #define DSPCR_DSPDMA 0x0200 // ARAM dma in progress, if set
70 #define DSPCR_DSPINTMSK 0x0100 // * interrupt mask (RW)
71 #define DSPCR_DSPINT 0x0080 // * interrupt active (RWC)
72 #define DSPCR_ARINTMSK 0x0040
73 #define DSPCR_ARINT 0x0020
74 #define DSPCR_AIINTMSK 0x0010
75 #define DSPCR_AIINT 0x0008
76 #define DSPCR_HALT 0x0004 // halt DSP
77 #define DSPCR_PIINT 0x0002 // assert DSP PI interrupt
78 #define DSPCR_RES 0x0001 // reset DSP
80 #define FONT_SIZE_ANSI (288 + 131072)
81 #define FONT_SIZE_SJIS (3840 + 1179648)
83 #define LWP_OBJTYPE_SYSWD 7
85 #define LWP_CHECK_SYSWD(hndl) \
87 if(((hndl)==SYS_WD_NULL) || (LWP_OBJTYPE(hndl)!=LWP_OBJTYPE_SYSWD)) \
91 #define _SHIFTL(v, s, w) \
92 ((u32) (((u32)(v) & ((0x01 << (w)) - 1)) << (s)))
93 #define _SHIFTR(v, s, w) \
94 ((u32)(((u32)(v) >> (s)) & ((0x01 << (w)) - 1)))
102 } sramcntrl
ATTRIBUTE_ALIGN(32);
104 typedef struct _alarm_st
111 alarmcallback alarmhandler
;
115 typedef struct _yay0header
{
116 unsigned int id ATTRIBUTE_PACKED
;
117 unsigned int dec_size ATTRIBUTE_PACKED
;
118 unsigned int links_offset ATTRIBUTE_PACKED
;
119 unsigned int chunks_offset ATTRIBUTE_PACKED
;
122 static u16 sys_fontenc
= 0xffff;
123 static u32 sys_fontcharsinsheet
= 0;
124 static u8
*sys_fontwidthtab
= NULL
;
125 static u8
*sys_fontimage
= NULL
;
126 static void *sys_fontarea
= NULL
;
127 static sys_fontheader
*sys_fontdata
= NULL
;
129 static lwp_queue sys_reset_func_queue
;
130 static u32 system_initialized
= 0;
131 static lwp_objinfo sys_alarm_objects
;
133 static void *__sysarena1lo
= NULL
;
134 static void *__sysarena1hi
= NULL
;
137 static void *__sysarena2lo
= NULL
;
138 static void *__sysarena2hi
= NULL
;
139 static void *__ipcbufferlo
= NULL
;
140 static void *__ipcbufferhi
= NULL
;
143 static void __RSWDefaultHandler();
144 static resetcallback __RSWCallback
= NULL
;
146 static void __POWDefaultHandler();
147 static powercallback __POWCallback
= NULL
;
149 static u32 __sys_resetdown
= 0;
152 static vu16
* const _viReg
= (u16
*)0xCC002000;
153 static vu32
* const _piReg
= (u32
*)0xCC003000;
154 static vu16
* const _memReg
= (u16
*)0xCC004000;
155 static vu16
* const _dspReg
= (u16
*)0xCC005000;
157 void __SYS_ReadROM(void *buf
,u32 len
,u32 offset
);
158 void* SYS_AllocArena1MemLo(u32 size
,u32 align
);
160 static s32
__sram_sync(void);
161 static s32
__sram_writecallback(s32 chn
,s32 dev
);
162 static s32
__mem_onreset(s32 final
);
164 extern void __lwp_thread_coreinit(void);
165 extern void __lwp_sysinit(void);
166 extern void __heap_init(void);
167 extern void __exception_init(void);
168 extern void __exception_closeall(void);
169 extern void __systemcall_init(void);
170 extern void __decrementer_init(void);
171 extern void __lwp_mutex_init(void);
172 extern void __lwp_cond_init(void);
173 extern void __lwp_mqbox_init(void);
174 extern void __lwp_sema_init(void);
175 extern void __exi_init(void);
176 extern void __si_init(void);
177 extern void __irq_init(void);
178 extern void __lwp_start_multitasking(void);
179 extern void __timesystem_init(void);
180 extern void __memlock_init(void);
181 extern void __libc_init(int);
183 extern void __libogc_malloc_lock( struct _reent
*ptr
);
184 extern void __libogc_malloc_unlock( struct _reent
*ptr
);
186 extern void __exception_console(void);
187 extern void __exception_printf(const char *str
, ...);
189 extern void __realmode(void*);
190 extern void __configMEM1_24Mb(void);
191 extern void __configMEM1_48Mb(void);
192 extern void __configMEM2_64Mb(void);
193 extern void __configMEM2_128Mb(void);
194 extern void __reset(u32 reset_code
);
196 extern u32
__IPC_ClntInit(void);
197 extern u32
__PADDisableRecalibration(s32 disable
);
199 extern void __console_init_ex(void *conbuffer
,int tgt_xstart
,int tgt_ystart
,int tgt_stride
,int con_xres
,int con_yres
,int con_stride
);
201 extern int clock_gettime(struct timespec
*tp
);
202 extern void timespec_substract(const struct timespec
*tp_start
,const struct timespec
*tp_end
,struct timespec
*result
);
205 extern int __libogc_lock_init(int *lock
,int recursive
);
206 extern int __libogc_lock_close(int *lock
);
207 extern int __libogc_lock_release(int *lock
);
208 extern int __libogc_lock_acquire(int *lock
);
209 extern void __libogc_exit(int status
);
210 extern void * __libogc_sbrk_r(struct _reent
*ptr
, ptrdiff_t incr
);
211 extern int __libogc_gettod_r(struct _reent
*ptr
, struct timeval
*tp
, struct timezone
*tz
);
213 extern u8 __gxregs
[];
214 extern u8 __text_start
[];
216 extern u8 __Arena1Lo
[], __Arena1Hi
[];
218 extern u8 __Arena2Lo
[], __Arena2Hi
[];
219 extern u8 __ipcbufferLo
[], __ipcbufferHi
[];
222 u8
*__argvArena1Lo
= (u8
*)0xdeadbeef;
224 static u32 __sys_inIPL
= (u32
)__isIPL
;
226 static u32 _dsp_initcode
[] =
228 0x029F0010,0x029F0033,0x029F0034,0x029F0035,
229 0x029F0036,0x029F0037,0x029F0038,0x029F0039,
230 0x12061203,0x12041205,0x00808000,0x0088FFFF,
231 0x00841000,0x0064001D,0x02180000,0x81001C1E,
232 0x00441B1E,0x00840800,0x00640027,0x191E0000,
233 0x00DEFFFC,0x02A08000,0x029C0028,0x16FC0054,
234 0x16FD4348,0x002102FF,0x02FF02FF,0x02FF02FF,
235 0x02FF02FF,0x00000000,0x00000000,0x00000000
238 static sys_resetinfo mem_resetinfo
= {
244 static const char *__sys_versiondate
;
245 static const char *__sys_versionbuild
;
247 static __inline__ alarm_st
* __lwp_syswd_open(syswd_t wd
)
250 return (alarm_st
*)__lwp_objmgr_get(&sys_alarm_objects
,LWP_OBJMASKID(wd
));
253 static __inline__
void __lwp_syswd_free(alarm_st
*alarm
)
255 __lwp_objmgr_close(&sys_alarm_objects
,&alarm
->object
);
256 __lwp_objmgr_free(&sys_alarm_objects
,&alarm
->object
);
261 void (*reload
)() = (void(*)())0x80001800;
262 u64 sig
= ((u64
)(*(u32
*)0x80001804) << 32) + *(u32
*)0x80001808;
263 if ( sig
== 0x5354554248415858ULL
) { // 'STUBHAXX'
267 SYS_ResetSystem(SYS_RETURNTOMENU
, 0, 0);
269 # define SOFTRESET_ADR *((vu32*)0xCC003024)
274 void __libogc_exit(int status
)
276 SYS_ResetSystem(SYS_SHUTDOWN
,0,0);
277 __lwp_thread_stopmultitasking(__reload
);
280 static void __init_syscall_array() {
281 __syscalls
.sbrk_r
= __libogc_sbrk_r
;
282 __syscalls
.lock_init
= __libogc_lock_init
;
283 __syscalls
.lock_close
= __libogc_lock_close
;
284 __syscalls
.lock_release
= __libogc_lock_release
;
285 __syscalls
.lock_acquire
= __libogc_lock_acquire
;
286 __syscalls
.malloc_lock
= __libogc_malloc_lock
;
287 __syscalls
.malloc_unlock
= __libogc_malloc_unlock
;
288 __syscalls
.exit
= __libogc_exit
;
289 __syscalls
.gettod_r
= __libogc_gettod_r
;
293 static alarm_st
* __lwp_syswd_allocate()
297 __lwp_thread_dispatchdisable();
298 alarm
= (alarm_st
*)__lwp_objmgr_allocate(&sys_alarm_objects
);
300 __lwp_objmgr_open(&sys_alarm_objects
,&alarm
->object
);
303 __lwp_thread_dispatchenable();
307 static s32
__mem_onreset(s32 final
)
311 __UnmaskIrq(IM_MEM0
|IM_MEM1
|IM_MEM2
|IM_MEM3
);
316 static void __sys_alarmhandler(void *arg
)
319 syswd_t thealarm
= (syswd_t
)arg
;
321 if(thealarm
==SYS_WD_NULL
|| LWP_OBJTYPE(thealarm
)!=LWP_OBJTYPE_SYSWD
) return;
323 __lwp_thread_dispatchdisable();
324 alarm
= (alarm_st
*)__lwp_objmgr_getnoprotection(&sys_alarm_objects
,LWP_OBJMASKID(thealarm
));
326 if(alarm
->alarmhandler
) alarm
->alarmhandler(thealarm
,alarm
->cb_arg
);
327 if(alarm
->periodic
) __lwp_wd_insert_ticks(&alarm
->alarm
,alarm
->periodic
);
329 __lwp_thread_dispatchunnest();
333 static void __dohotreset(u32 resetcode
)
337 _CPU_ISR_Disable(level
);
340 __reset(resetcode
<<3);
344 static s32
__call_resetfuncs(s32 final
)
348 lwp_queue
*header
= &sys_reset_func_queue
;
351 info
= (sys_resetinfo
*)header
->first
;
352 while(info
!=(sys_resetinfo
*)__lwp_queue_tail(header
)) {
353 if(info
->func
&& info
->func(final
)==0) ret
|= (ret
<<1);
354 info
= (sys_resetinfo
*)info
->node
.next
;
356 if(__sram_sync()==0) ret
|= (ret
<<1);
358 if(ret
&~0x01) return 0;
363 static void __doreboot(u32 resetcode
,s32 force_menu
)
367 _CPU_ISR_Disable(level
);
369 *((u32
*)0x817ffffc) = 0;
370 *((u32
*)0x817ffff8) = 0;
371 *((u32
*)0x800030e2) = 1;
375 static void __MEMInterruptHandler()
380 static void __RSWDefaultHandler()
386 static void __POWDefaultHandler()
392 static void __RSWHandler()
396 static u32 last_state
= 0;
397 static s64 hold_down
= 0;
399 hold_down
= gettime();
402 if(diff_usec(hold_down
,now
)>=100) break;
403 } while(!(_piReg
[0]&0x10000));
405 if(_piReg
[0]&0x10000) {
408 __MaskIrq(IRQMASK(IRQ_PI_RSW
));
420 static void __STMEventHandler(u32 event
)
425 if(event
==STM_EVENT_RESET
) {
426 ret
= SYS_ResetButtonDown();
428 _CPU_ISR_Disable(level
);
431 _CPU_ISR_Restore(level
);
435 if(event
==STM_EVENT_POWER
) {
436 _CPU_ISR_Disable(level
);
438 _CPU_ISR_Restore(level
);
443 static void __lowmem_init()
445 u32
*_gx
= (u32
*)__gxregs
;
448 void *ram_start
= (void*)0x80000000;
449 void *ram_end
= (void*)(0x80000000|SYSMEM1_SIZE
);
450 void *arena_start
= (void*)0x80003000;
451 #elif defined(HW_RVL)
452 void *arena_start
= (void*)0x80003F00;
456 memset(arena_start
,0,0x100);
457 if ( __argvArena1Lo
== (u8
*)0xdeadbeef ) __argvArena1Lo
= __Arena1Lo
;
459 memset(ram_start
,0,0x100);
460 *((u32
*)(ram_start
+0x20)) = 0x0d15ea5e; // magic word "disease"
461 *((u32
*)(ram_start
+0x24)) = 1; // version
462 *((u32
*)(ram_start
+0x28)) = SYSMEM1_SIZE
; // physical memory size
463 *((u32
*)(ram_start
+0x2C)) = 1 + ((*(u32
*)0xCC00302c)>>28);
465 *((u32
*)(ram_start
+0x30)) = (u32
)__argvArena1Lo
;
466 *((u32
*)(ram_start
+0x34)) = (u32
)__Arena1Hi
;
468 *((u32
*)(ram_start
+0xEC)) = (u32
)ram_end
; // ram_end (??)
469 *((u32
*)(ram_start
+0xF0)) = SYSMEM1_SIZE
; // simulated memory size
470 *((u32
*)(ram_start
+0xF8)) = TB_BUS_CLOCK
; // bus speed: 162 MHz
471 *((u32
*)(ram_start
+0xFC)) = TB_CORE_CLOCK
; // cpu speed: 486 Mhz
473 *((u16
*)(arena_start
+0xE0)) = 6; // production pads
474 *((u32
*)(arena_start
+0xE4)) = 0xC0008000;
476 DCFlushRangeNoSync(ram_start
, 0x100);
479 DCFlushRangeNoSync(arena_start
, 0x100);
480 DCFlushRangeNoSync(_gx
, 2048);
483 SYS_SetArenaLo((void*)__argvArena1Lo
);
484 SYS_SetArenaHi((void*)__Arena1Hi
);
486 SYS_SetArena2Lo((void*)__Arena2Lo
);
487 SYS_SetArena2Hi((void*)__Arena2Hi
);
492 static void __ipcbuffer_init()
494 __ipcbufferlo
= (void*)__ipcbufferLo
;
495 __ipcbufferhi
= (void*)__ipcbufferHi
;
499 static void __bat_config()
501 u32 realmem1
= SYSMEM1_SIZE
;
502 u32 simmem1
= SYSMEM1_SIZE
;
504 u32 simmem2
= SYSMEM2_SIZE
;
507 if(simmem1
<realmem1
&& !(simmem1
-0x1800000)) {
508 DCInvalidateRange((void*)0x81800000,0x01800000);
512 if(simmem1
<=0x01800000) __realmode(__configMEM1_24Mb
);
513 else if(simmem1
<=0x03000000) __realmode(__configMEM1_48Mb
);
516 if(simmem2
<=0x04000000) __realmode(__configMEM2_64Mb
);
517 else if(simmem2
<=0x08000000) __realmode(__configMEM2_128Mb
);
521 static void __memprotect_init()
525 _CPU_ISR_Disable(level
);
527 __MaskIrq((IM_MEM0
|IM_MEM1
|IM_MEM2
|IM_MEM3
));
532 IRQ_Request(IRQ_MEM0
,__MEMInterruptHandler
,NULL
);
533 IRQ_Request(IRQ_MEM1
,__MEMInterruptHandler
,NULL
);
534 IRQ_Request(IRQ_MEM2
,__MEMInterruptHandler
,NULL
);
535 IRQ_Request(IRQ_MEM3
,__MEMInterruptHandler
,NULL
);
536 IRQ_Request(IRQ_MEMADDRESS
,__MEMInterruptHandler
,NULL
);
538 SYS_RegisterResetFunc(&mem_resetinfo
);
540 __UnmaskIrq(IM_MEMADDRESS
); //only enable memaddress irq atm
542 _CPU_ISR_Restore(level
);
545 static __inline__ u32
__get_fontsize(void *buffer
)
547 u8
*ptr
= (u8
*)buffer
;
549 if(ptr
[0]=='Y' && ptr
[1]=='a' && ptr
[2]=='y') return (((u32
*)ptr
)[1]);
553 static u32
__read_rom(void *buf
,u32 len
,u32 offset
)
558 DCInvalidateRange(buf
,len
);
560 if(EXI_Lock(EXI_CHANNEL_0
,EXI_DEVICE_1
,NULL
)==0) return 0;
561 if(EXI_Select(EXI_CHANNEL_0
,EXI_DEVICE_1
,EXI_SPEED8MHZ
)==0) {
562 EXI_Unlock(EXI_CHANNEL_0
);
568 if(EXI_Imm(EXI_CHANNEL_0
,&loff
,4,EXI_WRITE
,NULL
)==0) ret
|= 0x0001;
569 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x0002;
570 if(EXI_Dma(EXI_CHANNEL_0
,buf
,len
,EXI_READ
,NULL
)==0) ret
|= 0x0004;
571 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x0008;
572 if(EXI_Deselect(EXI_CHANNEL_0
)==0) ret
|= 0x0010;
573 if(EXI_Unlock(EXI_CHANNEL_0
)==0) ret
|= 0x00020;
579 static u32
__getrtc(u32
*gctime
)
585 if(EXI_Lock(EXI_CHANNEL_0
,EXI_DEVICE_1
,NULL
)==0) return 0;
586 if(EXI_Select(EXI_CHANNEL_0
,EXI_DEVICE_1
,EXI_SPEED8MHZ
)==0) {
587 EXI_Unlock(EXI_CHANNEL_0
);
594 if(EXI_Imm(EXI_CHANNEL_0
,&cmd
,4,EXI_WRITE
,NULL
)==0) ret
|= 0x01;
595 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x02;
596 if(EXI_Imm(EXI_CHANNEL_0
,&time
,4,EXI_READ
,NULL
)==0) ret
|= 0x04;
597 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x08;
598 if(EXI_Deselect(EXI_CHANNEL_0
)==0) ret
|= 0x10;
600 EXI_Unlock(EXI_CHANNEL_0
);
607 static u32
__sram_read(void *buffer
)
611 DCInvalidateRange(buffer
,64);
613 if(EXI_Lock(EXI_CHANNEL_0
,EXI_DEVICE_1
,NULL
)==0) return 0;
614 if(EXI_Select(EXI_CHANNEL_0
,EXI_DEVICE_1
,EXI_SPEED8MHZ
)==0) {
615 EXI_Unlock(EXI_CHANNEL_0
);
620 command
= 0x20000100;
621 if(EXI_Imm(EXI_CHANNEL_0
,&command
,4,EXI_WRITE
,NULL
)==0) ret
|= 0x01;
622 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x02;
623 if(EXI_Dma(EXI_CHANNEL_0
,buffer
,64,EXI_READ
,NULL
)==0) ret
|= 0x04;
624 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x08;
625 if(EXI_Deselect(EXI_CHANNEL_0
)==0) ret
|= 0x10;
626 if(EXI_Unlock(EXI_CHANNEL_0
)==0) ret
|= 0x20;
632 static u32
__sram_write(void *buffer
,u32 loc
,u32 len
)
636 if(EXI_Lock(EXI_CHANNEL_0
,EXI_DEVICE_1
,__sram_writecallback
)==0) return 0;
637 if(EXI_Select(EXI_CHANNEL_0
,EXI_DEVICE_1
,EXI_SPEED8MHZ
)==0) {
638 EXI_Unlock(EXI_CHANNEL_0
);
643 cmd
= 0xa0000100+(loc
<<6);
644 if(EXI_Imm(EXI_CHANNEL_0
,&cmd
,4,EXI_WRITE
,NULL
)==0) ret
|= 0x01;
645 if(EXI_Sync(EXI_CHANNEL_0
)==0) ret
|= 0x02;
646 if(EXI_ImmEx(EXI_CHANNEL_0
,buffer
,len
,EXI_WRITE
)==0) ret
|= 0x04;
647 if(EXI_Deselect(EXI_CHANNEL_0
)==0) ret
|= 0x08;
648 if(EXI_Unlock(EXI_CHANNEL_0
)==0) ret
|= 0x10;
654 static s32
__sram_writecallback(s32 chn
,s32 dev
)
656 sramcntrl
.sync
= __sram_write(sramcntrl
.srambuf
+sramcntrl
.offset
,sramcntrl
.offset
,(64-sramcntrl
.offset
));
657 if(sramcntrl
.sync
) sramcntrl
.offset
= 64;
662 static s32
__sram_sync()
664 return sramcntrl
.sync
;
669 sramcntrl
.enabled
= 0;
670 sramcntrl
.locked
= 0;
671 sramcntrl
.sync
= __sram_read(sramcntrl
.srambuf
);
673 sramcntrl
.offset
= 64;
676 static void DisableWriteGatherPipe()
678 mtspr(920,(mfspr(920)&~0x40000000));
681 static void __buildchecksum(u16
*buffer
,u16
*c1
,u16
*c2
)
689 *c2
+= buffer
[6+i
]^-1;
693 static void* __locksram(u32 loc
)
697 _CPU_ISR_Disable(level
);
698 if(!sramcntrl
.locked
) {
699 sramcntrl
.enabled
= level
;
700 sramcntrl
.locked
= 1;
701 return (void*)((u32
)sramcntrl
.srambuf
+loc
);
703 _CPU_ISR_Restore(level
);
707 static u32
__unlocksram(u32 write
,u32 loc
)
709 syssram
*sram
= (syssram
*)sramcntrl
.srambuf
;
713 if((sram
->flags
&0x03)>0x02) sram
->flags
= (sram
->flags
&~0x03);
714 __buildchecksum((u16
*)sramcntrl
.srambuf
,&sram
->checksum
,&sram
->checksum_inv
);
716 if(loc
<sramcntrl
.offset
) sramcntrl
.offset
= loc
;
718 sramcntrl
.sync
= __sram_write(sramcntrl
.srambuf
+sramcntrl
.offset
,sramcntrl
.offset
,(64-sramcntrl
.offset
));
719 if(sramcntrl
.sync
) sramcntrl
.offset
= 64;
721 sramcntrl
.locked
= 0;
722 _CPU_ISR_Restore(sramcntrl
.enabled
);
723 return sramcntrl
.sync
;
726 //returns the size of font
727 static u32
__read_font(void *buffer
)
729 if(SYS_GetFontEncoding()==1) __SYS_ReadROM(buffer
,315392,1769216);
730 else __SYS_ReadROM(buffer
,12288,2084608);
731 return __get_fontsize(buffer
);
734 static void __expand_font(const u8
*src
,u8
*dest
)
739 u8
*data
= (u8
*)sys_fontdata
+44;
741 if(sys_fontdata
->sheet_format
==0x0000) {
742 cnt
= (sys_fontdata
->sheet_fullsize
/2)-1;
745 idx
= _SHIFTR(src
[cnt
],6,2);
748 idx
= _SHIFTR(src
[cnt
],4,2);
751 dest
[(cnt
<<1)+0] =((val1
&0xf0)|(val2
&0x0f));
753 idx
= _SHIFTR(src
[cnt
],2,2);
756 idx
= _SHIFTR(src
[cnt
],0,2);
759 dest
[(cnt
<<1)+1] =((val1
&0xf0)|(val2
&0x0f));
764 DCStoreRange(dest
,sys_fontdata
->sheet_fullsize
);
767 static void __dsp_bootstrap()
772 memcpy(SYS_GetArenaHi()-128,(void*)0x81000000,128);
773 memcpy((void*)0x81000000,_dsp_initcode
,128);
774 DCFlushRange((void*)0x81000000,128);
777 _dspReg
[5] = (DSPCR_DSPRESET
|DSPCR_DSPINT
|DSPCR_ARINT
|DSPCR_AIINT
|DSPCR_HALT
);
778 _dspReg
[5] |= DSPCR_RES
;
779 while(_dspReg
[5]&DSPCR_RES
);
782 while((_SHIFTL(_dspReg
[2],16,16)|(_dspReg
[3]&0xffff))&0x80000000);
784 ((u32
*)_dspReg
)[8] = 0x01000000;
785 ((u32
*)_dspReg
)[9] = 0;
786 ((u32
*)_dspReg
)[10] = 32;
789 while(!(status
&DSPCR_ARINT
)) status
= _dspReg
[5];
793 while((gettick()-tick
)<2194);
795 ((u32
*)_dspReg
)[8] = 0x01000000;
796 ((u32
*)_dspReg
)[9] = 0;
797 ((u32
*)_dspReg
)[10] = 32;
800 while(!(status
&DSPCR_ARINT
)) status
= _dspReg
[5];
803 _dspReg
[5] &= ~DSPCR_DSPRESET
;
804 while(_dspReg
[5]&0x400);
806 _dspReg
[5] &= ~DSPCR_HALT
;
807 while(!(_dspReg
[2]&0x8000));
810 _dspReg
[5] |= DSPCR_HALT
;
811 _dspReg
[5] = (DSPCR_DSPRESET
|DSPCR_DSPINT
|DSPCR_ARINT
|DSPCR_AIINT
|DSPCR_HALT
);
812 _dspReg
[5] |= DSPCR_RES
;
813 while(_dspReg
[5]&DSPCR_RES
);
815 memcpy((void*)0x81000000,SYS_GetArenaHi()-128,128);
817 printf("__audiosystem_init(finish)\n");
821 static void __dsp_shutdown()
825 _dspReg
[5] = (DSPCR_DSPRESET
|DSPCR_HALT
);
826 _dspReg
[27] &= ~0x8000;
827 while(_dspReg
[5]&0x400);
828 while(_dspReg
[5]&0x200);
830 _dspReg
[5] = (DSPCR_DSPRESET
|DSPCR_DSPINT
|DSPCR_ARINT
|DSPCR_AIINT
|DSPCR_HALT
);
832 while((_SHIFTL(_dspReg
[2],16,16)|(_dspReg
[3]&0xffff))&0x80000000);
835 while((gettick()-tick
)<44);
837 _dspReg
[5] |= DSPCR_RES
;
838 while(_dspReg
[5]&DSPCR_RES
);
841 static void decode_szp(void *src
,void *dest
)
846 u32 size
,cnt
,cmask
,bcnt
;
850 header
= (yay0header
*)src
;
851 size
= header
->dec_size
;
852 loff
= header
->links_offset
;
853 coff
= header
->chunks_offset
;
855 roff
= sizeof(yay0header
);
862 cmask
= *(u32
*)(src
+roff
);
867 if(cmask
&0x80000000) {
868 dest8
[cnt
++] = *(u8
*)(src
+coff
);
871 link
= *(u16
*)(src
+loff
);
874 tmp
= dest8
+(cnt
-(link
&0x0fff)-1);
877 k
= (*(u8
*)(src
+coff
))+18;
882 dest8
[cnt
++] = tmp
[i
];
890 syssram
* __SYS_LockSram()
892 return (syssram
*)__locksram(0);
895 syssramex
* __SYS_LockSramEx()
897 return (syssramex
*)__locksram(sizeof(syssram
));
900 u32
__SYS_UnlockSram(u32 write
)
902 return __unlocksram(write
,0);
905 u32
__SYS_UnlockSramEx(u32 write
)
907 return __unlocksram(write
,sizeof(syssram
));
912 return __sram_sync();
915 void __SYS_ReadROM(void *buf
,u32 len
,u32 offset
)
920 cpy_cnt
= (len
>256)?256:len
;
921 while(__read_rom(buf
,cpy_cnt
,offset
)==0);
928 u32
__SYS_GetRTC(u32
*gctime
)
936 if(__getrtc(&time1
)==0) ret
|= 0x01;
937 if(__getrtc(&time2
)==0) ret
|= 0x02;
948 void __SYS_SetTime(s64 time
)
952 s64
*pBootTime
= (s64
*)0x800030d8;
954 _CPU_ISR_Disable(level
);
961 _CPU_ISR_Restore(level
);
964 s64
__SYS_GetSystemTime()
968 s64
*pBootTime
= (s64
*)0x800030d8;
970 _CPU_ISR_Disable(level
);
973 _CPU_ISR_Restore(level
);
977 void __SYS_SetBootTime()
982 sram
= __SYS_LockSram();
983 __SYS_GetRTC(&gctime
);
984 __SYS_SetTime(secs_to_ticks(gctime
));
988 u32
__SYS_LoadFont(void *src
,void *dest
)
990 if(__read_font(src
)==0) return 0;
992 decode_szp(src
,dest
);
994 sys_fontdata
= (sys_fontheader
*)dest
;
995 sys_fontwidthtab
= (u8
*)dest
+sys_fontdata
->width_table
;
996 sys_fontcharsinsheet
= sys_fontdata
->sheet_column
*sys_fontdata
->sheet_row
;
998 /* TODO: implement SJIS handling */
1003 void* __SYS_GetIPCBufferLo()
1005 return __ipcbufferlo
;
1008 void* __SYS_GetIPCBufferHi()
1010 return __ipcbufferhi
;
1015 void _V_EXPORTNAME(void)
1016 { __sys_versionbuild
= _V_STRING
; __sys_versiondate
= _V_DATE_
; }
1019 void __SYS_DoPowerCB(void)
1022 powercallback powcb
;
1024 _CPU_ISR_Disable(level
);
1025 powcb
= __POWCallback
;
1026 __POWCallback
= __POWDefaultHandler
;
1028 _CPU_ISR_Restore(level
);
1032 void __SYS_InitCallbacks()
1035 __POWCallback
= __POWDefaultHandler
;
1036 __sys_resetdown
= 0;
1038 __RSWCallback
= __RSWDefaultHandler
;
1045 _CPU_ISR_Disable(level
);
1047 if(system_initialized
) return;
1048 system_initialized
= 1;
1052 __init_syscall_array();
1057 __lwp_wkspace_init(KERNEL_HEAP
);
1058 __lwp_queue_init_empty(&sys_reset_func_queue
);
1059 __lwp_objmgr_initinfo(&sys_alarm_objects
,LWP_MAX_WATCHDOGS
,sizeof(alarm_st
));
1061 __lwp_priority_init();
1062 __lwp_watchdog_init();
1064 __systemcall_init();
1065 __decrementer_init();
1070 __lwp_thread_coreinit();
1077 __timesystem_init();
1081 __memprotect_init();
1084 __SYS_SetBootTime();
1086 DisableWriteGatherPipe();
1087 __SYS_InitCallbacks();
1090 #elif defined(HW_DOL)
1091 IRQ_Request(IRQ_PI_RSW
,__RSWHandler
,NULL
);
1092 __MaskIrq(IRQMASK(IRQ_PI_RSW
));
1095 __lwp_thread_startmultitasking();
1096 _CPU_ISR_Restore(level
);
1099 // This function gets called inside the main thread, prior to the application's main() function
1103 __IOS_LoadStartupIOS();
1104 __IOS_InitializeSubsystems();
1105 STM_RegisterEventHandler(__STMEventHandler
);
1111 u32
SYS_ResetButtonDown()
1113 return (!(_piReg
[0]&0x00010000));
1117 void SYS_ResetSystem(s32 reset
,u32 reset_code
,s32 force_menu
)
1124 if(reset
==SYS_SHUTDOWN
) {
1125 ret
= __PADDisableRecalibration(TRUE
);
1128 while(__call_resetfuncs(FALSE
)==0);
1130 if(reset
==SYS_HOTRESET
&& force_menu
==TRUE
) {
1131 sram
= __SYS_LockSram();
1132 sram
->flags
|= 0x40;
1133 __SYS_UnlockSram(TRUE
);
1134 while(!__SYS_SyncSram());
1137 _CPU_ISR_Disable(level
);
1138 __call_resetfuncs(TRUE
);
1142 __lwp_thread_dispatchdisable();
1143 if(reset
==SYS_HOTRESET
) {
1144 __dohotreset(reset_code
);
1145 } else if(reset
==SYS_RESTART
) {
1146 __lwp_thread_closeall();
1147 __lwp_thread_dispatchunnest();
1148 __doreboot(reset_code
,force_menu
);
1151 __lwp_thread_closeall();
1153 memset((void*)0x80000040,0,140);
1154 memset((void*)0x800000D4,0,20);
1155 memset((void*)0x800000F4,0,4);
1156 memset((void*)0x80003000,0,192);
1157 memset((void*)0x800030C8,0,12);
1158 memset((void*)0x800030E2,0,1);
1160 __PADDisableRecalibration(ret
);
1166 void SYS_ResetSystem(s32 reset
,u32 reset_code
,s32 force_menu
)
1172 if(reset
==SYS_SHUTDOWN
) {
1173 ret
= __PADDisableRecalibration(TRUE
);
1176 while(__call_resetfuncs(FALSE
)==0);
1183 if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE
) {
1184 ret
= CONF_GetIdleLedMode();
1185 if(ret
<= 2) STM_SetLedMode(ret
);
1186 STM_ShutdownToIdle();
1188 STM_ShutdownToStandby();
1191 case SYS_POWEROFF_STANDBY
:
1192 STM_ShutdownToStandby();
1194 case SYS_POWEROFF_IDLE
:
1195 ret
= CONF_GetIdleLedMode();
1196 if(ret
>= 0 && ret
<= 2) STM_SetLedMode(ret
);
1197 STM_ShutdownToIdle();
1199 case SYS_RETURNTOMENU
:
1204 //TODO: implement SYS_HOTRESET
1205 // either restart failed or this is SYS_SHUTDOWN
1207 __IOS_ShutdownSubsystems();
1209 _CPU_ISR_Disable(level
);
1210 __call_resetfuncs(TRUE
);
1214 __lwp_thread_dispatchdisable();
1215 __lwp_thread_closeall();
1217 memset((void*)0x80000040,0,140);
1218 memset((void*)0x800000D4,0,20);
1219 memset((void*)0x800000F4,0,4);
1220 memset((void*)0x80003000,0,192);
1221 memset((void*)0x800030C8,0,12);
1222 memset((void*)0x800030E2,0,1);
1224 __PADDisableRecalibration(ret
);
1228 void SYS_RegisterResetFunc(sys_resetinfo
*info
)
1231 sys_resetinfo
*after
;
1232 lwp_queue
*header
= &sys_reset_func_queue
;
1234 _CPU_ISR_Disable(level
);
1235 for(after
=(sys_resetinfo
*)header
->first
;after
->node
.next
!=NULL
&& info
->prio
>=after
->prio
;after
=(sys_resetinfo
*)after
->node
.next
);
1236 __lwp_queue_insertI(after
->node
.prev
,&info
->node
);
1237 _CPU_ISR_Restore(level
);
1240 void SYS_UnregisterResetFunc(sys_resetinfo
*info
) {
1244 _CPU_ISR_Disable(level
);
1245 for (n
= sys_reset_func_queue
.first
; n
->next
; n
= n
->next
) {
1246 if (n
== &info
->node
) {
1247 __lwp_queue_extractI(n
);
1251 _CPU_ISR_Restore(level
);
1254 void SYS_SetArena1Lo(void *newLo
)
1258 _CPU_ISR_Disable(level
);
1259 __sysarena1lo
= newLo
;
1260 _CPU_ISR_Restore(level
);
1263 void* SYS_GetArena1Lo()
1268 _CPU_ISR_Disable(level
);
1269 arenalo
= __sysarena1lo
;
1270 _CPU_ISR_Restore(level
);
1275 void SYS_SetArena1Hi(void *newHi
)
1279 _CPU_ISR_Disable(level
);
1280 __sysarena1hi
= newHi
;
1281 _CPU_ISR_Restore(level
);
1284 void* SYS_GetArena1Hi()
1289 _CPU_ISR_Disable(level
);
1290 arenahi
= __sysarena1hi
;
1291 _CPU_ISR_Restore(level
);
1296 u32
SYS_GetArena1Size()
1300 _CPU_ISR_Disable(level
);
1301 size
= ((u32
)__sysarena1hi
- (u32
)__sysarena1lo
);
1302 _CPU_ISR_Restore(level
);
1307 void* SYS_AllocArena1MemLo(u32 size
,u32 align
)
1312 mem1lo
= (u32
)SYS_GetArena1Lo();
1313 ptr
= (void*)((mem1lo
+(align
-1))&~(align
-1));
1314 mem1lo
= ((((u32
)ptr
+size
+align
)-1)&~(align
-1));
1315 SYS_SetArena1Lo((void*)mem1lo
);
1321 void SYS_SetArena2Lo(void *newLo
)
1325 _CPU_ISR_Disable(level
);
1326 __sysarena2lo
= newLo
;
1327 _CPU_ISR_Restore(level
);
1330 void* SYS_GetArena2Lo()
1335 _CPU_ISR_Disable(level
);
1336 arenalo
= __sysarena2lo
;
1337 _CPU_ISR_Restore(level
);
1342 void SYS_SetArena2Hi(void *newHi
)
1346 _CPU_ISR_Disable(level
);
1347 __sysarena2hi
= newHi
;
1348 _CPU_ISR_Restore(level
);
1351 void* SYS_GetArena2Hi()
1356 _CPU_ISR_Disable(level
);
1357 arenahi
= __sysarena2hi
;
1358 _CPU_ISR_Restore(level
);
1363 u32
SYS_GetArena2Size()
1367 _CPU_ISR_Disable(level
);
1368 size
= ((u32
)__sysarena2hi
- (u32
)__sysarena2lo
);
1369 _CPU_ISR_Restore(level
);
1374 void* SYS_AllocArena2MemLo(u32 size
,u32 align
)
1379 mem2lo
= (u32
)SYS_GetArena2Lo();
1380 ptr
= (void*)((mem2lo
+(align
-1))&~(align
-1));
1381 mem2lo
= ((((u32
)ptr
+size
+align
)-1)&~(align
-1));
1382 SYS_SetArena2Lo((void*)mem2lo
);
1388 void SYS_ProtectRange(u32 chan
,void *addr
,u32 bytes
,u32 cntrl
)
1391 u32 pstart
,pend
,level
;
1393 if(chan
<SYS_PROTECTCHANMAX
) {
1394 pstart
= ((u32
)addr
)&~0x3ff;
1395 pend
= ((((u32
)addr
)+bytes
)+1023)&~0x3ff;
1396 DCFlushRange((void*)pstart
,(pend
-pstart
));
1398 _CPU_ISR_Disable(level
);
1400 __UnmaskIrq(IRQMASK(chan
));
1401 _memReg
[chan
<<2] = _SHIFTR(pstart
,10,16);
1402 _memReg
[(chan
<<2)+1] = _SHIFTR(pend
,10,16);
1404 rcntrl
= _memReg
[8];
1405 rcntrl
= (rcntrl
&~(_SHIFTL(3,(chan
<<1),2)))|(_SHIFTL(cntrl
,(chan
<<1),2));
1406 _memReg
[8] = rcntrl
;
1408 if(cntrl
==SYS_PROTECTRDWR
)
1409 __MaskIrq(IRQMASK(chan
));
1412 _CPU_ISR_Restore(level
);
1416 void* SYS_AllocateFramebuffer(GXRModeObj
*rmode
)
1418 return memalign(32, VIDEO_GetFrameBufferSize(rmode
));
1421 u32
SYS_GetFontEncoding()
1425 if(sys_fontenc
<=0x0001) return sys_fontenc
;
1428 tv_mode
= VIDEO_GetCurrentTvMode();
1429 if(tv_mode
==VI_NTSC
&& _viReg
[55]&0x0002) ret
= 1;
1434 u32
SYS_InitFont(sys_fontheader
**font_header
)
1436 void *packed_data
= NULL
;
1438 if(!font_header
) return 0;
1440 *font_header
= NULL
;
1441 if(SYS_GetFontEncoding()==1) {
1442 sys_fontarea
= memalign(32,FONT_SIZE_SJIS
);
1443 memset(sys_fontarea
,0,FONT_SIZE_SJIS
);
1444 packed_data
= (void*)((u32
)sys_fontarea
+868096);
1446 sys_fontarea
= memalign(32,FONT_SIZE_ANSI
);
1447 memset(sys_fontarea
,0,FONT_SIZE_ANSI
);
1448 packed_data
= (void*)((u32
)sys_fontarea
+119072);
1451 if(__SYS_LoadFont(packed_data
,sys_fontarea
)==1) {
1452 sys_fontimage
= (u8
*)((((u32
)sys_fontarea
+sys_fontdata
->sheet_image
)+31)&~31);
1453 __expand_font((u8
*)sys_fontarea
+sys_fontdata
->sheet_image
,sys_fontimage
);
1454 *font_header
= sys_fontdata
;
1461 void SYS_GetFontTexture(s32 c
,void **image
,s32
*xpos
,s32
*ypos
,s32
*width
)
1468 if(!sys_fontwidthtab
|| ! sys_fontimage
) return;
1470 if(c
>0x20 && c
<0xff) c
-= 0x20;
1473 sheets
= c
/sys_fontcharsinsheet
;
1474 rem
= c
%sys_fontcharsinsheet
;
1475 *image
= sys_fontimage
+(sys_fontdata
->sheet_size
*sheets
);
1476 *xpos
= (rem
%sys_fontdata
->sheet_column
)*sys_fontdata
->cell_width
;
1477 *ypos
= (rem
/sys_fontdata
->sheet_column
)*sys_fontdata
->cell_height
;
1478 *width
= sys_fontwidthtab
[c
];
1481 void SYS_GetFontTexel(s32 c
,void *image
,s32 pos
,s32 stride
,s32
*width
)
1489 if(!sys_fontwidthtab
|| ! sys_fontimage
) return;
1491 if(c
<sys_fontdata
->first_char
|| c
>sys_fontdata
->last_char
) c
= sys_fontdata
->inval_char
;
1492 else c
-= sys_fontdata
->first_char
;
1494 sheets
= c
/sys_fontcharsinsheet
;
1495 rem
= c
%sys_fontcharsinsheet
;
1496 xoff
= (rem
%sys_fontdata
->sheet_column
)*sys_fontdata
->cell_width
;
1497 yoff
= (rem
/sys_fontdata
->sheet_column
)*sys_fontdata
->cell_height
;
1498 img_start
= sys_fontimage
+(sys_fontdata
->sheet_size
*sheets
);
1501 while(ypos
<sys_fontdata
->cell_height
) {
1503 while(xpos
<sys_fontdata
->cell_width
) {
1504 ptr1
= img_start
+(((sys_fontdata
->sheet_width
/8)<<5)*((ypos
+yoff
)/8));
1505 ptr1
= ptr1
+(((xpos
+xoff
)/8)<<5);
1506 ptr1
= ptr1
+(((ypos
+yoff
)%8)<<2);
1507 ptr1
= ptr1
+(((xpos
+xoff
)%8)/2);
1509 ptr2
= image
+((ypos
/8)*(((stride
<<1)/8)<<5));
1510 ptr2
= ptr2
+(((xpos
+pos
)/8)<<5);
1511 ptr2
= ptr2
+(((xpos
+pos
)%8)/2);
1512 ptr2
= ptr2
+((ypos
%8)<<2);
1520 *width
= sys_fontwidthtab
[c
];
1523 s32
SYS_CreateAlarm(syswd_t
*thealarm
)
1527 alarm
= __lwp_syswd_allocate();
1528 if(!alarm
) return -1;
1530 alarm
->alarmhandler
= NULL
;
1532 alarm
->start_per
= 0;
1533 alarm
->periodic
= 0;
1535 *thealarm
= (LWP_OBJMASKTYPE(LWP_OBJTYPE_SYSWD
)|LWP_OBJMASKID(alarm
->object
.id
));
1536 __lwp_thread_dispatchenable();
1540 s32
SYS_SetAlarm(syswd_t thealarm
,const struct timespec
*tp
,alarmcallback cb
,void *cbarg
)
1544 alarm
= __lwp_syswd_open(thealarm
);
1545 if(!alarm
) return -1;
1547 alarm
->cb_arg
= cbarg
;
1548 alarm
->alarmhandler
= cb
;
1549 alarm
->ticks
= __lwp_wd_calc_ticks(tp
);
1551 alarm
->periodic
= 0;
1552 alarm
->start_per
= 0;
1554 __lwp_wd_initialize(&alarm
->alarm
,__sys_alarmhandler
,alarm
->object
.id
,(void*)thealarm
);
1555 __lwp_wd_insert_ticks(&alarm
->alarm
,alarm
->ticks
);
1556 __lwp_thread_dispatchenable();
1560 s32
SYS_SetPeriodicAlarm(syswd_t thealarm
,const struct timespec
*tp_start
,const struct timespec
*tp_period
,alarmcallback cb
,void *cbarg
)
1564 alarm
= __lwp_syswd_open(thealarm
);
1565 if(!alarm
) return -1;
1567 alarm
->start_per
= __lwp_wd_calc_ticks(tp_start
);
1568 alarm
->periodic
= __lwp_wd_calc_ticks(tp_period
);
1569 alarm
->alarmhandler
= cb
;
1570 alarm
->cb_arg
= cbarg
;
1574 __lwp_wd_initialize(&alarm
->alarm
,__sys_alarmhandler
,alarm
->object
.id
,(void*)thealarm
);
1575 __lwp_wd_insert_ticks(&alarm
->alarm
,alarm
->start_per
);
1576 __lwp_thread_dispatchenable();
1580 s32
SYS_RemoveAlarm(syswd_t thealarm
)
1584 alarm
= __lwp_syswd_open(thealarm
);
1585 if(!alarm
) return -1;
1587 alarm
->alarmhandler
= NULL
;
1589 alarm
->periodic
= 0;
1590 alarm
->start_per
= 0;
1592 __lwp_wd_remove_ticks(&alarm
->alarm
);
1593 __lwp_syswd_free(alarm
);
1594 __lwp_thread_dispatchenable();
1598 s32
SYS_CancelAlarm(syswd_t thealarm
)
1602 alarm
= __lwp_syswd_open(thealarm
);
1603 if(!alarm
) return -1;
1605 alarm
->alarmhandler
= NULL
;
1607 alarm
->periodic
= 0;
1608 alarm
->start_per
= 0;
1610 __lwp_wd_remove_ticks(&alarm
->alarm
);
1611 __lwp_thread_dispatchenable();
1615 resetcallback
SYS_SetResetCallback(resetcallback cb
)
1620 _CPU_ISR_Disable(level
);
1621 old
= __RSWCallback
;
1626 __UnmaskIrq(IRQMASK(IRQ_PI_RSW
));
1628 __MaskIrq(IRQMASK(IRQ_PI_RSW
));
1630 _CPU_ISR_Restore(level
);
1635 powercallback
SYS_SetPowerCallback(powercallback cb
)
1640 _CPU_ISR_Disable(level
);
1641 old
= __POWCallback
;
1643 _CPU_ISR_Restore(level
);
1648 void SYS_StartPMC(u32 mcr0val
,u32 mcr1val
)
1670 printf("<%d load/stores / %d miss cycles / %d cycles / %d instructions>\n",mfpmc1(),mfpmc2(),mfpmc3(),mfpmc4());
1673 void SYS_SetWirelessID(u32 chan
,u32 id
)
1679 sram
= __SYS_LockSramEx();
1680 if(sram
->wirelessPad_id
[chan
]!=(u16
)id
) {
1681 sram
->wirelessPad_id
[chan
] = (u16
)id
;
1684 __SYS_UnlockSramEx(write
);
1687 u32
SYS_GetWirelessID(u32 chan
)
1693 sram
= __SYS_LockSramEx();
1694 id
= sram
->wirelessPad_id
[chan
];
1695 __SYS_UnlockSramEx(0);
1700 u32
SYS_GetHollywoodRevision()
1703 DCInvalidateRange((void*)0x80003138,8);
1704 rev
= *((u32
*)0x80003138);