SMB directory recursion works now, fixed an ugly bug in smb_recv
[libogc.git] / libogc / system.c
blob03255177cd2790d9b54db41c21502690c617d8e0
1 /*-------------------------------------------------------------
3 system.c -- OS functions and initialization
5 Copyright (C) 2004
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
26 distribution.
28 -------------------------------------------------------------*/
30 //#define DEBUG_SYSTEM
32 #include <stdlib.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <malloc.h>
36 #include <sys/iosupport.h>
38 #include "asm.h"
39 #include "irq.h"
40 #include "exi.h"
41 #if defined(HW_RVL)
42 #include "ipc.h"
43 #include "ios.h"
44 #include "stm.h"
45 #include "es.h"
46 #include "conf.h"
47 #include "wiilaunch.h"
48 #endif
49 #include "cache.h"
50 #include "video.h"
51 #include "system.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
62 #if defined(HW_RVL)
63 #define SYSMEM2_SIZE 0x04000000
64 #endif
65 #define KERNEL_HEAP (1*1024*1024)
67 // DSPCR bits
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) \
86 { \
87 if(((hndl)==SYS_WD_NULL) || (LWP_OBJTYPE(hndl)!=LWP_OBJTYPE_SYSWD)) \
88 return NULL; \
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)))
96 struct _sramcntrl {
97 u8 srambuf[64];
98 u32 offset;
99 s32 enabled;
100 s32 locked;
101 s32 sync;
102 } sramcntrl ATTRIBUTE_ALIGN(32);
104 typedef struct _alarm_st
106 lwp_obj object;
107 wd_cntrl alarm;
108 u64 ticks;
109 u64 periodic;
110 u64 start_per;
111 alarmcallback alarmhandler;
112 void *cb_arg;
113 } alarm_st;
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;
120 } yay0header;
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;
136 #if defined(HW_RVL)
137 static void *__sysarena2lo = NULL;
138 static void *__sysarena2hi = NULL;
139 static void *__ipcbufferlo = NULL;
140 static void *__ipcbufferhi = NULL;
141 #endif
143 static void __RSWDefaultHandler();
144 static resetcallback __RSWCallback = NULL;
145 #if defined(HW_RVL)
146 static void __POWDefaultHandler();
147 static powercallback __POWCallback = NULL;
149 static u32 __sys_resetdown = 0;
150 #endif
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[];
215 extern u8 __isIPL[];
216 extern u8 __Arena1Lo[], __Arena1Hi[];
217 #if defined(HW_RVL)
218 extern u8 __Arena2Lo[], __Arena2Hi[];
219 extern u8 __ipcbufferLo[], __ipcbufferHi[];
220 #endif
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 = {
240 __mem_onreset,
244 static const char *__sys_versiondate;
245 static const char *__sys_versionbuild;
247 static __inline__ alarm_st* __lwp_syswd_open(syswd_t wd)
249 LWP_CHECK_SYSWD(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);
259 void __reload()
261 void (*reload)() = (void(*)())0x80001800;
262 u64 sig = ((u64)(*(u32*)0x80001804) << 32) + *(u32*)0x80001808;
263 if ( sig == 0x5354554248415858ULL) { // 'STUBHAXX'
264 reload();
266 #ifdef HW_RVL
267 SYS_ResetSystem(SYS_RETURNTOMENU, 0, 0);
268 #else
269 # define SOFTRESET_ADR *((vu32*)0xCC003024)
270 SOFTRESET_ADR=0;
271 #endif
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()
295 alarm_st *alarm;
297 __lwp_thread_dispatchdisable();
298 alarm = (alarm_st*)__lwp_objmgr_allocate(&sys_alarm_objects);
299 if(alarm) {
300 __lwp_objmgr_open(&sys_alarm_objects,&alarm->object);
301 return alarm;
303 __lwp_thread_dispatchenable();
304 return NULL;
307 static s32 __mem_onreset(s32 final)
309 if(final==TRUE) {
310 _memReg[8] = 255;
311 __UnmaskIrq(IM_MEM0|IM_MEM1|IM_MEM2|IM_MEM3);
313 return 1;
316 static void __sys_alarmhandler(void *arg)
318 alarm_st *alarm;
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));
325 if(alarm) {
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();
332 #if defined(HW_DOL)
333 static void __dohotreset(u32 resetcode)
335 u32 level;
337 _CPU_ISR_Disable(level);
338 _viReg[1] = 0;
339 ICFlashInvalidate();
340 __reset(resetcode<<3);
342 #endif
344 static s32 __call_resetfuncs(s32 final)
346 s32 ret;
347 sys_resetinfo *info;
348 lwp_queue *header = &sys_reset_func_queue;
350 ret = 1;
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;
359 return 1;
362 #if defined(HW_DOL)
363 static void __doreboot(u32 resetcode,s32 force_menu)
365 u32 level;
367 _CPU_ISR_Disable(level);
369 *((u32*)0x817ffffc) = 0;
370 *((u32*)0x817ffff8) = 0;
371 *((u32*)0x800030e2) = 1;
373 #endif
375 static void __MEMInterruptHandler()
377 _memReg[16] = 0;
380 static void __RSWDefaultHandler()
385 #if defined(HW_RVL)
386 static void __POWDefaultHandler()
389 #endif
391 #if defined(HW_DOL)
392 static void __RSWHandler()
394 s64 now;
395 static u32 down = 0;
396 static u32 last_state = 0;
397 static s64 hold_down = 0;
399 hold_down = gettime();
400 do {
401 now = gettime();
402 if(diff_usec(hold_down,now)>=100) break;
403 } while(!(_piReg[0]&0x10000));
405 if(_piReg[0]&0x10000) {
406 down = 0;
407 last_state = 1;
408 __MaskIrq(IRQMASK(IRQ_PI_RSW));
411 if(__RSWCallback) {
412 __RSWCallback();
415 _piReg[0] = 2;
417 #endif
419 #if defined(HW_RVL)
420 static void __STMEventHandler(u32 event)
422 s32 ret;
423 u32 level;
425 if(event==STM_EVENT_RESET) {
426 ret = SYS_ResetButtonDown();
427 if(ret) {
428 _CPU_ISR_Disable(level);
429 __sys_resetdown = 1;
430 __RSWCallback();
431 _CPU_ISR_Restore(level);
435 if(event==STM_EVENT_POWER) {
436 _CPU_ISR_Disable(level);
437 __POWCallback();
438 _CPU_ISR_Restore(level);
441 #endif
443 static void __lowmem_init()
445 u32 *_gx = (u32*)__gxregs;
447 #if defined(HW_DOL)
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;
453 #endif
455 memset(_gx,0,2048);
456 memset(arena_start,0,0x100);
457 if ( __argvArena1Lo == (u8*)0xdeadbeef ) __argvArena1Lo = __Arena1Lo;
458 #if defined(HW_DOL)
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);
477 #endif
479 DCFlushRangeNoSync(arena_start, 0x100);
480 DCFlushRangeNoSync(_gx, 2048);
481 _sync();
483 SYS_SetArenaLo((void*)__argvArena1Lo);
484 SYS_SetArenaHi((void*)__Arena1Hi);
485 #if defined(HW_RVL)
486 SYS_SetArena2Lo((void*)__Arena2Lo);
487 SYS_SetArena2Hi((void*)__Arena2Hi);
488 #endif
491 #if defined(HW_RVL)
492 static void __ipcbuffer_init()
494 __ipcbufferlo = (void*)__ipcbufferLo;
495 __ipcbufferhi = (void*)__ipcbufferHi;
497 #endif
499 static void __bat_config()
501 u32 realmem1 = SYSMEM1_SIZE;
502 u32 simmem1 = SYSMEM1_SIZE;
503 #if defined(HW_RVL)
504 u32 simmem2 = SYSMEM2_SIZE;
505 #endif
507 if(simmem1<realmem1 && !(simmem1-0x1800000)) {
508 DCInvalidateRange((void*)0x81800000,0x01800000);
509 _memReg[20] = 2;
512 if(simmem1<=0x01800000) __realmode(__configMEM1_24Mb);
513 else if(simmem1<=0x03000000) __realmode(__configMEM1_48Mb);
515 #if defined(HW_RVL)
516 if(simmem2<=0x04000000) __realmode(__configMEM2_64Mb);
517 else if(simmem2<=0x08000000) __realmode(__configMEM2_128Mb);
518 #endif
521 static void __memprotect_init()
523 u32 level;
525 _CPU_ISR_Disable(level);
527 __MaskIrq((IM_MEM0|IM_MEM1|IM_MEM2|IM_MEM3));
529 _memReg[16] = 0;
530 _memReg[8] = 255;
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);
539 __bat_config();
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]);
550 else return 0;
553 static u32 __read_rom(void *buf,u32 len,u32 offset)
555 u32 ret;
556 u32 loff;
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);
563 return 0;
566 ret = 0;
567 loff = offset<<6;
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;
575 if(ret) return 0;
576 return 1;
579 static u32 __getrtc(u32 *gctime)
581 u32 ret;
582 u32 cmd;
583 u32 time;
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);
588 return 0;
591 ret = 0;
592 time = 0;
593 cmd = 0x20000000;
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);
601 *gctime = time;
602 if(ret) return 0;
604 return 1;
607 static u32 __sram_read(void *buffer)
609 u32 command,ret;
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);
616 return 0;
619 ret = 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;
628 if(ret) return 0;
629 return 1;
632 static u32 __sram_write(void *buffer,u32 loc,u32 len)
634 u32 cmd,ret;
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);
639 return 0;
642 ret = 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;
650 if(ret) return 0;
651 return 1;
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;
659 return 1;
662 static s32 __sram_sync()
664 return sramcntrl.sync;
667 void __sram_init()
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)
683 u32 i;
685 *c1 = 0;
686 *c2 = 0;
687 for(i=0;i<4;i++) {
688 *c1 += buffer[6+i];
689 *c2 += buffer[6+i]^-1;
693 static void* __locksram(u32 loc)
695 u32 level;
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);
704 return NULL;
707 static u32 __unlocksram(u32 write,u32 loc)
709 syssram *sram = (syssram*)sramcntrl.srambuf;
711 if(write) {
712 if(!loc) {
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)
736 s32 cnt;
737 u32 idx;
738 u8 val1,val2;
739 u8 *data = (u8*)sys_fontdata+44;
741 if(sys_fontdata->sheet_format==0x0000) {
742 cnt = (sys_fontdata->sheet_fullsize/2)-1;
744 while(cnt>=0) {
745 idx = _SHIFTR(src[cnt],6,2);
746 val1 = data[idx];
748 idx = _SHIFTR(src[cnt],4,2);
749 val2 = data[idx];
751 dest[(cnt<<1)+0] =((val1&0xf0)|(val2&0x0f));
753 idx = _SHIFTR(src[cnt],2,2);
754 val1 = data[idx];
756 idx = _SHIFTR(src[cnt],0,2);
757 val2 = data[idx];
759 dest[(cnt<<1)+1] =((val1&0xf0)|(val2&0x0f));
761 cnt--;
764 DCStoreRange(dest,sys_fontdata->sheet_fullsize);
767 static void __dsp_bootstrap()
769 u16 status;
770 u32 tick;
772 memcpy(SYS_GetArenaHi()-128,(void*)0x81000000,128);
773 memcpy((void*)0x81000000,_dsp_initcode,128);
774 DCFlushRange((void*)0x81000000,128);
776 _dspReg[9] = 67;
777 _dspReg[5] = (DSPCR_DSPRESET|DSPCR_DSPINT|DSPCR_ARINT|DSPCR_AIINT|DSPCR_HALT);
778 _dspReg[5] |= DSPCR_RES;
779 while(_dspReg[5]&DSPCR_RES);
781 _dspReg[0] = 0;
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;
788 status = _dspReg[5];
789 while(!(status&DSPCR_ARINT)) status = _dspReg[5];
790 _dspReg[5] = status;
792 tick = gettick();
793 while((gettick()-tick)<2194);
795 ((u32*)_dspReg)[8] = 0x01000000;
796 ((u32*)_dspReg)[9] = 0;
797 ((u32*)_dspReg)[10] = 32;
799 status = _dspReg[5];
800 while(!(status&DSPCR_ARINT)) status = _dspReg[5];
801 _dspReg[5] = status;
803 _dspReg[5] &= ~DSPCR_DSPRESET;
804 while(_dspReg[5]&0x400);
806 _dspReg[5] &= ~DSPCR_HALT;
807 while(!(_dspReg[2]&0x8000));
808 status = _dspReg[3];
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);
816 #ifdef _SYS_DEBUG
817 printf("__audiosystem_init(finish)\n");
818 #endif
821 static void __dsp_shutdown()
823 u32 tick;
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);
831 _dspReg[0] = 0;
832 while((_SHIFTL(_dspReg[2],16,16)|(_dspReg[3]&0xffff))&0x80000000);
834 tick = gettick();
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)
843 u32 i,k,link;
844 u8 *dest8,*tmp;
845 u32 loff,coff,roff;
846 u32 size,cnt,cmask,bcnt;
847 yay0header *header;
849 dest8 = (u8*)dest;
850 header = (yay0header*)src;
851 size = header->dec_size;
852 loff = header->links_offset;
853 coff = header->chunks_offset;
855 roff = sizeof(yay0header);
856 cmask = 0;
857 cnt = 0;
858 bcnt = 0;
860 do {
861 if(!bcnt) {
862 cmask = *(u32*)(src+roff);
863 roff += 4;
864 bcnt = 32;
867 if(cmask&0x80000000) {
868 dest8[cnt++] = *(u8*)(src+coff);
869 coff++;
870 } else {
871 link = *(u16*)(src+loff);
872 loff += 2;
874 tmp = dest8+(cnt-(link&0x0fff)-1);
875 k = link>>12;
876 if(k==0) {
877 k = (*(u8*)(src+coff))+18;
878 coff++;
879 } else k += 2;
881 for(i=0;i<k;i++) {
882 dest8[cnt++] = tmp[i];
885 cmask <<= 1;
886 bcnt--;
887 } while(cnt<size);
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));
910 u32 __SYS_SyncSram()
912 return __sram_sync();
915 void __SYS_ReadROM(void *buf,u32 len,u32 offset)
917 u32 cpy_cnt;
919 while(len>0) {
920 cpy_cnt = (len>256)?256:len;
921 while(__read_rom(buf,cpy_cnt,offset)==0);
922 offset += cpy_cnt;
923 buf += cpy_cnt;
924 len -= cpy_cnt;
928 u32 __SYS_GetRTC(u32 *gctime)
930 u32 cnt,ret;
931 u32 time1,time2;
933 cnt = 0;
934 ret = 0;
935 while(cnt<16) {
936 if(__getrtc(&time1)==0) ret |= 0x01;
937 if(__getrtc(&time2)==0) ret |= 0x02;
938 if(ret) return 0;
939 if(time1==time2) {
940 *gctime = time1;
941 return 1;
943 cnt++;
945 return 0;
948 void __SYS_SetTime(s64 time)
950 u32 level;
951 s64 now;
952 s64 *pBootTime = (s64*)0x800030d8;
954 _CPU_ISR_Disable(level);
955 now = gettime();
956 now -= time;
957 now += *pBootTime;
958 *pBootTime = now;
959 settime(now);
960 EXI_ProbeReset();
961 _CPU_ISR_Restore(level);
964 s64 __SYS_GetSystemTime()
966 u32 level;
967 s64 now;
968 s64 *pBootTime = (s64*)0x800030d8;
970 _CPU_ISR_Disable(level);
971 now = gettime();
972 now += *pBootTime;
973 _CPU_ISR_Restore(level);
974 return now;
977 void __SYS_SetBootTime()
979 syssram *sram;
980 u32 gctime;
982 sram = __SYS_LockSram();
983 __SYS_GetRTC(&gctime);
984 __SYS_SetTime(secs_to_ticks(gctime));
985 __SYS_UnlockSram(0);
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 */
999 return 1;
1002 #if defined(HW_RVL)
1003 void* __SYS_GetIPCBufferLo()
1005 return __ipcbufferlo;
1008 void* __SYS_GetIPCBufferHi()
1010 return __ipcbufferhi;
1013 #endif
1015 void _V_EXPORTNAME(void)
1016 { __sys_versionbuild = _V_STRING; __sys_versiondate = _V_DATE_; }
1018 #if defined(HW_RVL)
1019 void __SYS_DoPowerCB(void)
1021 u32 level;
1022 powercallback powcb;
1024 _CPU_ISR_Disable(level);
1025 powcb = __POWCallback;
1026 __POWCallback = __POWDefaultHandler;
1027 powcb();
1028 _CPU_ISR_Restore(level);
1030 #endif
1032 void __SYS_InitCallbacks()
1034 #if defined(HW_RVL)
1035 __POWCallback = __POWDefaultHandler;
1036 __sys_resetdown = 0;
1037 #endif
1038 __RSWCallback = __RSWDefaultHandler;
1041 void SYS_Init()
1043 u32 level;
1045 _CPU_ISR_Disable(level);
1047 if(system_initialized) return;
1048 system_initialized = 1;
1050 _V_EXPORTNAME();
1052 __init_syscall_array();
1053 __lowmem_init();
1054 #if defined(HW_RVL)
1055 __ipcbuffer_init();
1056 #endif
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));
1060 __sys_state_init();
1061 __lwp_priority_init();
1062 __lwp_watchdog_init();
1063 __exception_init();
1064 __systemcall_init();
1065 __decrementer_init();
1066 __irq_init();
1067 __exi_init();
1068 __sram_init();
1069 __si_init();
1070 __lwp_thread_coreinit();
1071 __lwp_sysinit();
1072 __memlock_init();
1073 __lwp_mqbox_init();
1074 __lwp_sema_init();
1075 __lwp_mutex_init();
1076 __lwp_cond_init();
1077 __timesystem_init();
1078 __dsp_bootstrap();
1080 if(!__sys_inIPL)
1081 __memprotect_init();
1083 #ifdef SDLOADER_FIX
1084 __SYS_SetBootTime();
1085 #endif
1086 DisableWriteGatherPipe();
1087 __SYS_InitCallbacks();
1088 #if defined(HW_RVL)
1089 __IPC_ClntInit();
1090 #elif defined(HW_DOL)
1091 IRQ_Request(IRQ_PI_RSW,__RSWHandler,NULL);
1092 __MaskIrq(IRQMASK(IRQ_PI_RSW));
1093 #endif
1094 __libc_init(1);
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
1100 void SYS_PreMain()
1102 #if defined(HW_RVL)
1103 __IOS_LoadStartupIOS();
1104 __IOS_InitializeSubsystems();
1105 STM_RegisterEventHandler(__STMEventHandler);
1106 CONF_Init();
1107 WII_Initialize();
1108 #endif
1111 u32 SYS_ResetButtonDown()
1113 return (!(_piReg[0]&0x00010000));
1116 #if defined(HW_DOL)
1117 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1119 u32 level,ret = 0;
1120 syssram *sram;
1122 __dsp_shutdown();
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);
1140 LCDisable();
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);
1162 #endif
1164 #if defined(HW_RVL)
1166 void SYS_ResetSystem(s32 reset,u32 reset_code,s32 force_menu)
1168 u32 level,ret = 0;
1170 __dsp_shutdown();
1172 if(reset==SYS_SHUTDOWN) {
1173 ret = __PADDisableRecalibration(TRUE);
1176 while(__call_resetfuncs(FALSE)==0);
1178 switch(reset) {
1179 case SYS_RESTART:
1180 STM_RebootSystem();
1181 break;
1182 case SYS_POWEROFF:
1183 if(CONF_GetShutdownMode() == CONF_SHUTDOWN_IDLE) {
1184 ret = CONF_GetIdleLedMode();
1185 if(ret <= 2) STM_SetLedMode(ret);
1186 STM_ShutdownToIdle();
1187 } else {
1188 STM_ShutdownToStandby();
1190 break;
1191 case SYS_POWEROFF_STANDBY:
1192 STM_ShutdownToStandby();
1193 break;
1194 case SYS_POWEROFF_IDLE:
1195 ret = CONF_GetIdleLedMode();
1196 if(ret >= 0 && ret <= 2) STM_SetLedMode(ret);
1197 STM_ShutdownToIdle();
1198 break;
1199 case SYS_RETURNTOMENU:
1200 WII_ReturnToMenu();
1201 break;
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);
1212 LCDisable();
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);
1226 #endif
1228 void SYS_RegisterResetFunc(sys_resetinfo *info)
1230 u32 level;
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) {
1241 u32 level;
1242 lwp_node *n;
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);
1248 break;
1251 _CPU_ISR_Restore(level);
1254 void SYS_SetArena1Lo(void *newLo)
1256 u32 level;
1258 _CPU_ISR_Disable(level);
1259 __sysarena1lo = newLo;
1260 _CPU_ISR_Restore(level);
1263 void* SYS_GetArena1Lo()
1265 u32 level;
1266 void *arenalo;
1268 _CPU_ISR_Disable(level);
1269 arenalo = __sysarena1lo;
1270 _CPU_ISR_Restore(level);
1272 return arenalo;
1275 void SYS_SetArena1Hi(void *newHi)
1277 u32 level;
1279 _CPU_ISR_Disable(level);
1280 __sysarena1hi = newHi;
1281 _CPU_ISR_Restore(level);
1284 void* SYS_GetArena1Hi()
1286 u32 level;
1287 void *arenahi;
1289 _CPU_ISR_Disable(level);
1290 arenahi = __sysarena1hi;
1291 _CPU_ISR_Restore(level);
1293 return arenahi;
1296 u32 SYS_GetArena1Size()
1298 u32 level,size;
1300 _CPU_ISR_Disable(level);
1301 size = ((u32)__sysarena1hi - (u32)__sysarena1lo);
1302 _CPU_ISR_Restore(level);
1304 return size;
1307 void* SYS_AllocArena1MemLo(u32 size,u32 align)
1309 u32 mem1lo;
1310 void *ptr = NULL;
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);
1317 return ptr;
1320 #if defined(HW_RVL)
1321 void SYS_SetArena2Lo(void *newLo)
1323 u32 level;
1325 _CPU_ISR_Disable(level);
1326 __sysarena2lo = newLo;
1327 _CPU_ISR_Restore(level);
1330 void* SYS_GetArena2Lo()
1332 u32 level;
1333 void *arenalo;
1335 _CPU_ISR_Disable(level);
1336 arenalo = __sysarena2lo;
1337 _CPU_ISR_Restore(level);
1339 return arenalo;
1342 void SYS_SetArena2Hi(void *newHi)
1344 u32 level;
1346 _CPU_ISR_Disable(level);
1347 __sysarena2hi = newHi;
1348 _CPU_ISR_Restore(level);
1351 void* SYS_GetArena2Hi()
1353 u32 level;
1354 void *arenahi;
1356 _CPU_ISR_Disable(level);
1357 arenahi = __sysarena2hi;
1358 _CPU_ISR_Restore(level);
1360 return arenahi;
1363 u32 SYS_GetArena2Size()
1365 u32 level,size;
1367 _CPU_ISR_Disable(level);
1368 size = ((u32)__sysarena2hi - (u32)__sysarena2lo);
1369 _CPU_ISR_Restore(level);
1371 return size;
1374 void* SYS_AllocArena2MemLo(u32 size,u32 align)
1376 u32 mem2lo;
1377 void *ptr = NULL;
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);
1384 return ptr;
1386 #endif
1388 void SYS_ProtectRange(u32 chan,void *addr,u32 bytes,u32 cntrl)
1390 u16 rcntrl;
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()
1423 u32 ret,tv_mode;
1425 if(sys_fontenc<=0x0001) return sys_fontenc;
1427 ret = 0;
1428 tv_mode = VIDEO_GetCurrentTvMode();
1429 if(tv_mode==VI_NTSC && _viReg[55]&0x0002) ret = 1;
1430 sys_fontenc = ret;
1431 return ret;
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);
1445 } else {
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;
1455 return 1;
1458 return 0;
1461 void SYS_GetFontTexture(s32 c,void **image,s32 *xpos,s32 *ypos,s32 *width)
1463 u32 sheets,rem;
1465 *xpos = 0;
1466 *ypos = 0;
1467 *image = NULL;
1468 if(!sys_fontwidthtab || ! sys_fontimage) return;
1470 if(c>0x20 && c<0xff) c -= 0x20;
1471 else c = 0;
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)
1483 u32 sheets,rem;
1484 u32 xoff,yoff;
1485 u32 xpos,ypos;
1486 u8 *img_start;
1487 u8 *ptr1,*ptr2;
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);
1500 ypos = 0;
1501 while(ypos<sys_fontdata->cell_height) {
1502 xpos = 0;
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);
1514 *ptr2 = *ptr1;
1516 xpos += 2;
1518 ypos++;
1520 *width = sys_fontwidthtab[c];
1523 s32 SYS_CreateAlarm(syswd_t *thealarm)
1525 alarm_st *alarm;
1527 alarm = __lwp_syswd_allocate();
1528 if(!alarm) return -1;
1530 alarm->alarmhandler = NULL;
1531 alarm->ticks = 0;
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();
1537 return 0;
1540 s32 SYS_SetAlarm(syswd_t thealarm,const struct timespec *tp,alarmcallback cb,void *cbarg)
1542 alarm_st *alarm;
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();
1557 return 0;
1560 s32 SYS_SetPeriodicAlarm(syswd_t thealarm,const struct timespec *tp_start,const struct timespec *tp_period,alarmcallback cb,void *cbarg)
1562 alarm_st *alarm;
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;
1572 alarm->ticks = 0;
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();
1577 return 0;
1580 s32 SYS_RemoveAlarm(syswd_t thealarm)
1582 alarm_st *alarm;
1584 alarm = __lwp_syswd_open(thealarm);
1585 if(!alarm) return -1;
1587 alarm->alarmhandler = NULL;
1588 alarm->ticks = 0;
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();
1595 return 0;
1598 s32 SYS_CancelAlarm(syswd_t thealarm)
1600 alarm_st *alarm;
1602 alarm = __lwp_syswd_open(thealarm);
1603 if(!alarm) return -1;
1605 alarm->alarmhandler = NULL;
1606 alarm->ticks = 0;
1607 alarm->periodic = 0;
1608 alarm->start_per = 0;
1610 __lwp_wd_remove_ticks(&alarm->alarm);
1611 __lwp_thread_dispatchenable();
1612 return 0;
1615 resetcallback SYS_SetResetCallback(resetcallback cb)
1617 u32 level;
1618 resetcallback old;
1620 _CPU_ISR_Disable(level);
1621 old = __RSWCallback;
1622 __RSWCallback = cb;
1623 #if defined(HW_DOL)
1624 if(__RSWCallback) {
1625 _piReg[0] = 2;
1626 __UnmaskIrq(IRQMASK(IRQ_PI_RSW));
1627 } else
1628 __MaskIrq(IRQMASK(IRQ_PI_RSW));
1629 #endif
1630 _CPU_ISR_Restore(level);
1631 return old;
1634 #if defined(HW_RVL)
1635 powercallback SYS_SetPowerCallback(powercallback cb)
1637 u32 level;
1638 powercallback old;
1640 _CPU_ISR_Disable(level);
1641 old = __POWCallback;
1642 __POWCallback = cb;
1643 _CPU_ISR_Restore(level);
1644 return old;
1646 #endif
1648 void SYS_StartPMC(u32 mcr0val,u32 mcr1val)
1650 mtmmcr0(mcr0val);
1651 mtmmcr1(mcr1val);
1654 void SYS_StopPMC()
1656 mtmmcr0(0);
1657 mtmmcr1(0);
1660 void SYS_ResetPMC()
1662 mtpmc1(0);
1663 mtpmc2(0);
1664 mtpmc3(0);
1665 mtpmc4(0);
1668 void SYS_DumpPMC()
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)
1675 u32 write;
1676 syssramex *sram;
1678 write = 0;
1679 sram = __SYS_LockSramEx();
1680 if(sram->wirelessPad_id[chan]!=(u16)id) {
1681 sram->wirelessPad_id[chan] = (u16)id;
1682 write = 1;
1684 __SYS_UnlockSramEx(write);
1687 u32 SYS_GetWirelessID(u32 chan)
1689 u16 id;
1690 syssramex *sram;
1692 id = 0;
1693 sram = __SYS_LockSramEx();
1694 id = sram->wirelessPad_id[chan];
1695 __SYS_UnlockSramEx(0);
1696 return id;
1699 #if defined(HW_RVL)
1700 u32 SYS_GetHollywoodRevision()
1702 u32 rev;
1703 DCInvalidateRange((void*)0x80003138,8);
1704 rev = *((u32*)0x80003138);
1705 return rev;
1707 #endif