/*---------------------------------------------------------------------------* Project: TwlSDK - OS File: os_arena.c Copyright 2003-2008 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. $Date:: 2009-06-19#$ $Rev: 10786 $ $Author: okajima_manabu $ *---------------------------------------------------------------------------*/ #include #define OSi_TRUNC(n, a) (((u32) (n)) & ~((a) - 1)) #define OSi_ROUND(n, a) (((u32) (n) + (a) - 1) & ~((a) - 1)) #define OS_ERR_GETARENAHI_INIT "OS_GetArenaHi: init in advance" #define OS_ERR_GETARENAHI_INVALID "OS_GetArenaHi: invalid arena (hi void OSi_InitArenaEx_ltdmain(void); void OSi_InitArenaEx_ltdmain(void) { u32 consoleType = OS_GetConsoleType(); u32 memSize = consoleType & OS_CONSOLE_SIZE_MASK; #ifdef SDK_FINALROM // Protect extra main memory area OS_SetProtectionRegionEx(3, HW_CTRDG_ROM, OS_PR_SIZE_64MB); #else if (OSi_MainExArenaEnabled && memSize == OS_CONSOLE_SIZE_32MB) { OSIntrMode enabled = OS_DisableInterrupts(); OS_SetProtectionRegionEx(3, HW_CTRDG_ROM, OS_PR_SIZE_128MB); //(void)OS_SetDPermissionsForProtectionRegion(OS_PR3_ACCESS_MASK, OS_PR3_ACCESS_RW); //OS_EnableICacheForProtectionRegion(1<<3); //OS_EnableDCacheForProtectionRegion(1<<3); //OS_EnableWriteBufferForProtectionRegion(1<<3); (void)OS_RestoreInterrupts(enabled); } else { // Protect extra main memory area OS_SetProtectionRegionEx(3, HW_CTRDG_ROM, OS_PR_SIZE_64MB); } #endif } #include #endif void OS_InitArenaEx(void) { u32 consoleType = OS_GetConsoleType(); u32 memSize = consoleType & OS_CONSOLE_SIZE_MASK; OS_InitArenaHiAndLo(OS_ARENA_MAINEX); #ifdef SDK_NITRO //---------------- Nitro #ifdef SDK_FINALROM OS_SetProtectionRegionEx(1, HW_MAIN_MEM_MAIN, OS_PR_SIZE_4MB); #else OSi_SetForMainPR( consoleType ); #endif #else //ifdef SDK_NITRO //---------------- Twl if (! OS_IsRunOnTwl()) { //---------------- Twl: nitro #ifdef SDK_FINALROM OS_SetProtectionRegionEx(1, HW_MAIN_MEM_MAIN, OS_PR_SIZE_4MB); #else OSi_SetForMainPR( consoleType ); #endif OS_SetProtectionRegionEx(2, HW_MAIN_MEM_IM_SHARED_END - HW_MAIN_MEM_IM_SHARED_SIZE, OS_PR_SIZE_4KB); } else { //---------------- Twl: twl OSi_InitArenaEx_ltdmain(); } #endif //ifdef SDK_NITRO } #endif // ifdef SDK_ARM9 //================================================================================ // GET ARENA INFO //================================================================================ /*---------------------------------------------------------------------------* Name: OS_GetArenaInfo Description: Get the pointer of Arena structure Arguments: None. Returns: the pointer of Arena structure *---------------------------------------------------------------------------*/ void *OS_GetArenaInfo(void) { return (void *)&OSi_GetArenaInfo(); } /*---------------------------------------------------------------------------* Name: OS_GetArenaHi Description: Get the high boundary of the arena Arguments: id : arena ID Returns: the high boundary of the arena *---------------------------------------------------------------------------*/ void *OS_GetArenaHi(OSArenaId id) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); SDK_TASSERTMSG((u32)OSi_GetArenaInfo().lo[id] != 0xffffffff, OS_ERR_GETARENALO_INIT); SDK_TASSERTMSG((u32)OSi_GetArenaInfo().lo[id] <= (u32)OSi_GetArenaInfo().hi[id], OS_ERR_GETARENALO_INVALID); return OSi_GetArenaInfo().hi[id]; } /*---------------------------------------------------------------------------* Name: OS_GetArenaLo Description: Get the low boundary of the arena Arguments: id : arena ID Returns: the low boundary of the arena *---------------------------------------------------------------------------*/ void *OS_GetArenaLo(OSArenaId id) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); SDK_TASSERTMSG((u32)OSi_GetArenaInfo().lo[id] != 0xffffffff, OS_ERR_GETARENALO_INIT); SDK_TASSERTMSG((u32)OSi_GetArenaInfo().lo[id] <= (u32)OSi_GetArenaInfo().hi[id], OS_ERR_GETARENALO_INVALID); return OSi_GetArenaInfo().lo[id]; } /*---------------------------------------------------------------------------* Name: OS_GetInitArenaHi Description: Get the initial high boundary of the arena Arguments: id : arena ID Returns: the initial high boundary of the arena *---------------------------------------------------------------------------*/ void *OS_GetInitArenaHi(OSArenaId id) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); switch (id) { #ifdef SDK_ARM9 case OS_ARENA_MAIN: #ifdef SDK_NITRO return (void *)OSi_MAIN_ARENA_HI_DEFAULT; #else return (OS_IsRunOnTwl())? (void *)OSi_MAIN_ARENA_HI_DEFAULT_forTWL: (void *)OSi_MAIN_ARENA_HI_DEFAULT_forNITRO; #endif case OS_ARENA_MAINEX: if ( ! OSi_MainExArenaEnabled ) { return 0; } else { u32 size = OS_GetConsoleType() & OS_CONSOLE_SIZE_MASK; #ifdef SDK_NITRO return (void*) ( (size == OS_CONSOLE_SIZE_4MB)? 0: OSi_MAINEX_ARENA_HI_DEFAULT ); #else return (OS_IsRunOnTwl())? (void*)( (size == OS_CONSOLE_SIZE_16MB)? 0: OSi_MAINEX_ARENA_HI_DEFAULT_forTWL ): (void*)( (size == OS_CONSOLE_SIZE_4MB)? 0: OSi_MAINEX_ARENA_HI_DEFAULT_forNITRO ); #endif } case OS_ARENA_ITCM: return (void *)HW_ITCM_ARENA_HI_DEFAULT; case OS_ARENA_DTCM: { u32 irqStackLo; u32 sysStackLo; irqStackLo = (u32)HW_DTCM_IRQ_STACK_END - OSi_IRQ_STACKSIZE; if (OSi_SYS_STACKSIZE == 0) // maximum SysStack in DTCM { sysStackLo = HW_DTCM; if (sysStackLo < OSi_DTCM_ARENA_LO_DEFAULT) { sysStackLo = OSi_DTCM_ARENA_LO_DEFAULT; } } else if (OSi_SYS_STACKSIZE < 0) { sysStackLo = OSi_DTCM_ARENA_LO_DEFAULT - OSi_SYS_STACKSIZE; } else { sysStackLo = irqStackLo - OSi_SYS_STACKSIZE; } SDK_ASSERT((u32)OSi_DTCM_ARENA_LO_DEFAULT <= sysStackLo && sysStackLo < irqStackLo); return (void *)sysStackLo; } case OS_ARENA_SHARED: return (void *)HW_SHARED_ARENA_HI_DEFAULT; case OS_ARENA_WRAM_MAIN: return (void *)OSi_WRAM_MAIN_ARENA_HI_DEFAULT; #else case OS_ARENA_MAIN_SUBPRIV: #ifdef SDK_NITRO return (void *)OSi_MAIN_SUBPRIV_ARENA_HI_DEFAULT; #else return (OS_IsRunOnTwl())? (void *)OSi_MAIN_SUBPRIV_ARENA_HI_DEFAULT_forTWL: (void *)OSi_MAIN_SUBPRIV_ARENA_HI_DEFAULT_forNITRO; #endif case OS_ARENA_WRAM_SUB: return (void *)OSi_WRAM_SUB_ARENA_HI_DEFAULT; case OS_ARENA_WRAM_SUBPRIV: { u32 irqStackLo; u32 sysStackLo; // ---- Sub-Processor private Work RAM // decide sysStackLo irqStackLo = (u32)HW_PRV_WRAM_IRQ_STACK_END - OSi_IRQ_STACKSIZE; sysStackLo = (u32)HW_PRV_WRAM; //---- if program area is larger than the size of common wram if ((u32)SDK_WRAM_ARENA_LO > (u32)HW_PRV_WRAM) { sysStackLo = (u32)SDK_WRAM_ARENA_LO; } if (OSi_SYS_STACKSIZE == 0) // maximum SysStack in SURPRIV-WRAM { // do nothing } else if (OSi_SYS_STACKSIZE < 0) { sysStackLo -= OSi_SYS_STACKSIZE; } else { sysStackLo = irqStackLo - OSi_SYS_STACKSIZE; } SDK_ASSERT((u32)HW_PRV_WRAM <= sysStackLo && sysStackLo < irqStackLo); return (void *)sysStackLo; } #endif default: SDK_WARNING(0, "Bad arena id"); } return NULL; } /*---------------------------------------------------------------------------* Name: OS_GetInitArenaLo Description: Get the initial low boundary of the arena Arguments: id : arena ID Returns: the initial low boundary of the arena *---------------------------------------------------------------------------*/ void *OS_GetInitArenaLo(OSArenaId id) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); switch (id) { #ifdef SDK_ARM9 case OS_ARENA_MAIN: #ifdef SDK_NITRO return (void *)OSi_MAIN_ARENA_LO_DEFAULT; #else return (OS_IsRunOnTwl())? (void *)OSi_MAIN_ARENA_LO_DEFAULT_forTWL: (void *)OSi_MAIN_ARENA_LO_DEFAULT_forNITRO; #endif case OS_ARENA_MAINEX: if ( ! OSi_MainExArenaEnabled ) { return (void*)0; } else { u32 size = OS_GetConsoleType() & OS_CONSOLE_SIZE_MASK; #ifdef SDK_NITRO return (void*)( (size == OS_CONSOLE_SIZE_4MB)? 0: OSi_MAINEX_ARENA_LO_DEFAULT ); #else return (OS_IsRunOnTwl())? (void*)( (size == OS_CONSOLE_SIZE_16MB)? 0: OSi_MAINEX_ARENA_LO_DEFAULT_forTWL ): (void*)( (size == OS_CONSOLE_SIZE_4MB)? 0: OSi_MAINEX_ARENA_LO_DEFAULT_forNITRO ); #endif } case OS_ARENA_ITCM: return (void *)OSi_ITCM_ARENA_LO_DEFAULT; case OS_ARENA_DTCM: return (void *)OSi_DTCM_ARENA_LO_DEFAULT; case OS_ARENA_SHARED: return (void *)HW_SHARED_ARENA_LO_DEFAULT; case OS_ARENA_WRAM_MAIN: return (void *)OSi_WRAM_MAIN_ARENA_LO_DEFAULT; #else case OS_ARENA_MAIN_SUBPRIV: #ifdef SDK_NITRO return (void *)OSi_MAIN_SUBPRIV_ARENA_LO_DEFAULT; #else return (OS_IsRunOnTwl())? (void *)OSi_MAIN_SUBPRIV_ARENA_LO_DEFAULT_forTWL: (void *)OSi_MAIN_SUBPRIV_ARENA_LO_DEFAULT_forNITRO; #endif case OS_ARENA_WRAM_SUB: { u32 wramSubLo = OSi_WRAM_SUB_ARENA_LO_DEFAULT; if ((u32)HW_WRAM_END < (u32)wramSubLo) { wramSubLo = (u32)HW_WRAM_END; } return (void *)wramSubLo; } case OS_ARENA_WRAM_SUBPRIV: { u32 privWramLo = OSi_WRAM_SUBPRIV_ARENA_LO_DEFAULT; if ((u32)SDK_WRAM_ARENA_LO > (u32)privWramLo) { privWramLo = (u32)SDK_WRAM_ARENA_LO; } return (void *)privWramLo; } #endif default: SDK_WARNING(0, "Bad arena id"); } return NULL; } //================================================================================ // SET ARENA INFO //================================================================================ /*---------------------------------------------------------------------------* Name: OS_SetArenaHi Description: Set the high boundary of the arena Arguments: id : arena ID newHi : New high boundary of the arena. Returns: None. *---------------------------------------------------------------------------*/ void OS_SetArenaHi(OSArenaId id, void *newHi) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); OSi_GetArenaInfo().hi[id] = newHi; } /*---------------------------------------------------------------------------* Name: OS_GetArenaLo Description: Set the low boundary of the arena Arguments: id : arena ID newLo : New low boundary of the arena. Returns: None. *---------------------------------------------------------------------------*/ void OS_SetArenaLo(OSArenaId id, void *newLo) { SDK_ASSERT(OSi_Initialized); SDK_ARENAID_ASSERT(id); OSi_GetArenaInfo().lo[id] = newLo; } //================================================================================ // ALLOC //================================================================================ /*---------------------------------------------------------------------------* Name: OS_AllocFromArenaLo Description: Allocates /size/ bytes from the low boundary of the arena. Some additional memory will also be consumed from arena for the alignment. Arguments: id : arena ID size : Size of object to be allocated align : Alignment of object and new arena boundary to be set (must be power of 2). Returns: a pointer to the allocated space aligned with /align/ bytes boundaries. The new low boundary of the arena is also aligned with /align/ bytes boundaries. NULL if cannot allocate. *---------------------------------------------------------------------------*/ void *OS_AllocFromArenaLo(OSArenaId id, u32 size, u32 align) { void *ptr; u8 *arenaLo; ptr = OS_GetArenaLo(id); if (!ptr) { return NULL; } arenaLo = ptr = (void *)OSi_ROUND(ptr, align); arenaLo += size; arenaLo = (u8 *)OSi_ROUND(arenaLo, align); if (arenaLo > OS_GetArenaHi(id)) { return NULL; } OS_SetArenaLo(id, arenaLo); return ptr; } /*---------------------------------------------------------------------------* Name: OS_AllocFromArenaHi Description: Allocates /size/ bytes from the high boundary of the arena. Some additional memory will also be consumed from arena for the alignment. Arguments: id : arena ID size : Size of object to be allocated align : Alignment of object and new arena boundary to be set (must be power of 2). Returns: a pointer to the allocated space aligned with /align/ bytes boundaries. The new high boundary of the arena is also aligned with /align/ bytes boundaries. NULL if cannot allocate. *---------------------------------------------------------------------------*/ void *OS_AllocFromArenaHi(OSArenaId id, u32 size, u32 align) { void *ptr; u8 *arenaHi; arenaHi = OS_GetArenaHi(id); if (!arenaHi) { return NULL; } arenaHi = (u8 *)OSi_TRUNC(arenaHi, align); arenaHi -= size; arenaHi = ptr = (void *)OSi_TRUNC(arenaHi, align); if (arenaHi < OS_GetArenaLo(id)) { return NULL; } OS_SetArenaHi(id, arenaHi); return ptr; } #ifdef SDK_ARM9 /*---------------------------------------------------------------------------* Name: OS_EnableMainExArena Description: Set extended main memory arena enable. This function should be called before OS_Init(). Arguments: None Returns: None *---------------------------------------------------------------------------*/ void OS_EnableMainExArena(void) { SDK_ASSERT(!OSi_Initialized); OSi_MainExArenaEnabled = TRUE; } /*---------------------------------------------------------------------------* Name: OS_DisableMainExArena Description: Set extended main memory arena disable. This function should be called before OS_Init(). Arguments: None Returns: None *---------------------------------------------------------------------------*/ void OS_DisableMainExArena(void) { SDK_ASSERT(!OSi_Initialized); OSi_MainExArenaEnabled = FALSE; } #endif #ifndef SDK_FINALROM //================================================================================ // DUMP ARENA INFO //================================================================================ /*---------------------------------------------------------------------------* Name: OS_DumpArenaInfo Description: display arena info Arguments: id : arena id isInfoLine : whether display explanation line or not. TRUE ... display FALSE ... not display. Returns: None *---------------------------------------------------------------------------*/ void OS_DumpArenaInfo( OSArenaId id, BOOL isInfoLine ) { static const char* arenaName[] = { "MainRAM-Main", "MainRAM-Sub ", "MainRAM-EX ", "ITCM ", "DTCM ", "SharedMemory", "WRAM-Main ", "WRAM-Sub ", "WRAM-Subpriv" }; SDK_ASSERT( 0<=id && id<=sizeof(arenaName)/sizeof(char*) ); if ( isInfoLine ) { OS_TPrintf(" NAME ID LO addr HI addr size\n" ); } OS_TPrintf("%12s %1d %8x %8x %8x\n", arenaName[(int)id], id, OS_GetArenaLo(id), OS_GetArenaHi(id), (u32)OS_GetArenaHi(id) - (u32)OS_GetArenaLo(id) ); } /*---------------------------------------------------------------------------* Name: OS_DumpAllArenaInfo Description: display each arena info Arguments: None Returns: None *---------------------------------------------------------------------------*/ void OS_DumpAllArenaInfo(void) { static const OSArenaId id[] = { OS_ARENA_MAIN, OS_ARENA_MAIN_SUBPRIV, OS_ARENA_MAINEX, OS_ARENA_ITCM, OS_ARENA_DTCM, OS_ARENA_SHARED, OS_ARENA_WRAM_MAIN, OS_ARENA_WRAM_SUB, OS_ARENA_WRAM_SUBPRIV }; int n; BOOL isInfoLine = TRUE; //---- display all arena info for( n=0; ninfo.lo[n] = OSi_GetArenaInfo().lo[n]; resource->info.hi[n] = OSi_GetArenaInfo().hi[n]; } (void)OS_RestoreInterrupts(enabled); return TRUE; }