/*---------------------------------------------------------------------------* Project: TwlSDK - OS - include File: spinLock.h 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:: 2008-09-17#$ $Rev: 8556 $ $Author: okubata_ryoma $ *---------------------------------------------------------------------------*/ #ifndef NITRO_OS_SPINLOCK_H_ #define NITRO_OS_SPINLOCK_H_ #ifdef __cplusplus extern "C" { #endif #include #ifdef SDK_NITRO #ifdef SDK_ARM9 #include #else //SDK_ARM7 #include #endif #else // SDK_TWL #include #ifdef SDK_ARM9 #include #else //SDK_ARM7 #include #endif #endif //SDK_NITRO //====================================================================== // Lock Functions // //Use these functions to exclusively control dedicated resources, such as the inter-CPU transfer FIFO, and common resources between CPUs, such as internal work RAM and VRAM-C/D shared by Game Cards, Game Paks, and CPUs. // // //====================================================================== // Lock ID #define OS_UNLOCK_ID 0 // ID when lock variable is not locked #define OS_MAINP_LOCKED_FLAG 0x40 // Main processor lock verification flag #define OS_MAINP_LOCK_ID_START 0x40 // Starting number of lock ID assignments, for main processor use #define OS_MAINP_LOCK_ID_END 0x6f // Assignment completion number #define OS_MAINP_DBG_LOCK_ID 0x70 // Debugger reservation number #define OS_MAINP_SYSTEM_LOCK_ID 0x7f // System reservation number #define OS_SUBP_LOCKED_FLAG 0x80 // Lock verification flag by sub processor #define OS_SUBP_LOCK_ID_START 0x80 // Starting number of lock ID assignments, for sub processor use #define OS_SUBP_LOCK_ID_END 0xaf // Assignment completion number #define OS_SUBP_DBG_LOCK_ID 0xb0 // Debugger reservation number #define OS_SUBP_SYSTEM_LOCK_ID 0xbf // System reservation number #define OS_LOCK_SUCCESS 0 // Lock success #define OS_LOCK_ERROR (-1) // Lock error #define OS_UNLOCK_SUCCESS 0 // Unlock success #define OS_UNLOCK_ERROR (-2) // Unlock error #define OS_LOCK_FREE 0 // Unlocking #define OS_LOCK_ID_ERROR (-3) // Lock ID error //---- Structure of Lock Variable typedef volatile struct OSLockWord { u32 lockFlag; u16 ownerID; u16 extension; } OSLockWord; /*---------------------------------------------------------------------------* Name: OS_InitLock Description: Initialize system lock variable and privilege to access shared resources. * cartridge exclusive control area is not cleared because debugger uses. Arguments: None. Returns: None. *---------------------------------------------------------------------------*/ void OS_InitLock(void); //---------------------------------------------------------------------- // Spinlock // //- This conducts spinlock of the lock variables for exclusive control of resources shared between processors and between modules. // //- Trials continue until lock succeeds. //- Be sure to lock resources shared between processors before using them. //If the timing of resources exclusively used by one processor can be adjusted, it is okay not to lock them. // // It's also possible to lock exclusive-use resources just for debugging. // //Arguments: // lockID: Lock ID // lockp: Lock variable's pointer // //Return values: // OS_LOCK_SUCCESS: Lock success //---------------------------------------------------------------------- s32 OS_LockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void)); s32 OS_LockCartridge(u16 lockID); s32 OS_LockCard(u16 lockID); //---------------------------------------------------------------------- // Unlock // //- This unlocks and passes access rights of shared resources to the subprocessor. //- In the case of running a module that is not locked, it will not be unlocked, and OS_UNLOCK_ERROR will be returned. // // //Arguments: // lockID: Lock ID // lockp: Lock variable's pointer // //Return values: // OS_UNLOCK_SUCCESS: Unlock success // OS_UNLOCK_ERROR: Unlock error //---------------------------------------------------------------------- s32 OS_UnlockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void)); s32 OS_UnlockCartridge(u16 lockID); s32 OS_UnlockCard(u16 lockID); //---- for compatibility with old name ('UnLock' <-> 'Unlock') // Because isd lib calls OS_UnLock*, these cannot be inlined. s32 OS_UnLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void)); s32 OS_UnLockCartridge(u16 lockID); s32 OS_UnLockCard(u16 lockID); //---------------------------------------------------------------------- // Lock trials // //- Try spinlock once only. //- Be sure to lock resources shared between processors before using them. //If the timing of resources exclusively used by one processor can be adjusted, it is okay not to lock them. // // It's also possible to lock exclusive-use resources just for debugging. // //Arguments: // lockID: Lock ID // lockp: Lock variable's pointer // CtrlFuncp: Resource control functions pointer // //Return values: // TRUE: Locked (the previously stored ID) // OS_LOCK_SUCCESS: Lock success //---------------------------------------------------------------------- s32 OS_TryLockByWord(u16 lockID, OSLockWord *lockp, void (*crtlFuncp) (void)); s32 OS_TryLockCartridge(u16 lockID); s32 OS_TryLockCard(u16 lockID); //---------------------------------------------------------------------- // Read the lock variable's owner module ID // //- This reads the lock variable's owner module ID. //- You can check which processor has ownership rights if the module ID is non-zero. // //In the case of a shared resource, only the state of the main processor side having ownership rights can be maintained by disabling interrupts. // // In other states, it might be changed by the sub processor. //- The lock variable may not necessarily be unlocked even if owner module ID is 0. // //Arguments: // lockp: Lock variable's pointer // //Return values: Owner module ID // //*Note: Be aware that byte access cannot be performed to the main memory unless it is through a cache. // // Thus, as a basic rule, you should use OS_ReadOwnerOfLockWord() for main memory. //---------------------------------------------------------------------- u16 OS_ReadOwnerOfLockWord(OSLockWord *lockp); #define OS_ReadOwnerOfLockCartridge() OS_ReadOwnerOfLockWord( (OSLockWord *)HW_CTRDG_LOCK_BUF ) #define OS_ReadOwnerOfLockCard() OS_ReadOwnerOfLockWord( (OSLockWord *)HW_CARD_LOCK_BUF ) /*---------------------------------------------------------------------------* Name: OS_GetLockID Description: Get lock ID. Arguments: None. Returns: OS_LOCK_ID_ERROR, if fail to get ID if ARM9 0x40-0x6f: lockID else if ARM7 0x80-0xaf: lockID endif *Notice: ID is allocated only 48 pattern at a highest. *---------------------------------------------------------------------------*/ s32 OS_GetLockID(void); /*---------------------------------------------------------------------------* Name: OS_ReleaseLockID Description: Release lock ID. Arguments: lockID: id to tend to release. Returns: None. *---------------------------------------------------------------------------*/ void OS_ReleaseLockID(u16 lockID); #ifdef SDK_TWL //================================================================ // Private Functions // These functions are for internal use. Never call them from the application. #define OSi_SYNCTYPE_SENDER 0 #define OSi_SYNCTYPE_RECVER 1 #define OSi_SYNCVAL_NOT_READY 0 #define OSi_SYNCVAL_READY 1 void OSi_SyncWithOtherProc( int type, void* syncBuf ); static inline void OSi_SetSyncValue( u8 n ) { *(vu8*)(HW_INIT_LOCK_BUF+4) = n; } static inline u8 OSi_GetSyncValue( void ) { return *(vu8*)(HW_INIT_LOCK_BUF+4); } #endif //-------------------------------------------------------------------------------- #ifdef __cplusplus } /* extern "C" */ #endif /* NITRO_OS_SPINLOCK_H_ */ #endif