1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS -
3   File:     os_spinLock.c
4 
5   Copyright 2003-2009 Nintendo. All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain
8   proprietary information of Nintendo of America Inc. and/or Nintendo
9   Company Ltd., and are protected by Federal copyright law. They may
10   not be disclosed to third parties or copied or duplicated in any form,
11   in whole or in part, without the prior written consent of Nintendo.
12 
13   $Date:: 2009-06-19#$
14   $Rev: 10786 $
15   $Author: okajima_manabu $
16  *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18 
19 
20 void    _ISDbgLib_Initialize(void);
21 void    _ISDbgLib_AllocateEmualtor(void);
22 void    _ISDbgLib_FreeEmulator(void);
23 void    _ISTDbgLib_Initialize(void);
24 void    _ISTDbgLib_AllocateEmualtor(void);
25 void    _ISTDbgLib_FreeEmulator(void);
26 
27 s32     OS_LockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void));
28 s32     OS_UnlockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void));
29 s32     OS_TryLockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*crtlFuncp) (void));
30 
31 static s32 OSi_DoLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
32                             BOOL disableFiq);
33 static s32 OSi_DoUnlockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
34                               BOOL disableFIQ);
35 static s32 OSi_DoTryLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
36                                BOOL disableFIQ);
37 
38 static void OSi_AllocateCartridgeBus(void);
39 static void OSi_FreeCartridgeBus(void);
40 
41 static void OSi_AllocateCardBus(void);
42 static void OSi_FreeCardBus(void);
43 
44 static void OSi_WaitByLoop(void);
45 
46 
47 #ifdef  SDK_ARM9
48 #define OSi_ASSERT_ID( id )       SDK_TASSERTMSG( id >= OS_MAINP_LOCK_ID_START && id <= OS_MAINP_SYSTEM_LOCK_ID, \
49                              "lock ID %d is out of bounds", id )
50 #else
51 #define OSi_ASSERT_ID( id )       SDK_TASSERTMSG( id >= OS_SUBP_LOCK_ID_START && id <= OS_SUBP_SYSTEM_LOCK_ID, \
52                              "lock ID %d is out of bounds", id )
53 #endif
54 
55 
56 #define OSi_LOCKID_INITIAL_FLAG_0     0xffffffff
57 #define OSi_LOCKID_INITIAL_FLAG_1     0xffff0000
58 
59 
60 #ifdef SDK_ARM9
61 #define OSi_ANYP_LOCK_ID_FLAG  HW_LOCK_ID_FLAG_MAIN
62 #define OSi_ANYP_LOCK_ID_START OS_MAINP_LOCK_ID_START
63 #else
64 #define OSi_ANYP_LOCK_ID_FLAG  HW_LOCK_ID_FLAG_SUB
65 #define OSi_ANYP_LOCK_ID_START OS_SUBP_LOCK_ID_START
66 #endif
67 
68 //======================================================================
69 //                      SYNC
70 //======================================================================
71 #ifdef SDK_TWL
72 /*---------------------------------------------------------------------------*
73   Name:         OSi_SyncWithOtherProc
74 
75   Description:  Syncs with other processor.
76 
77   Arguments:    type: OSi_SYNCTYPE_SENDER/RECVER
78                 syncBuf: Work area. Use 4 bytes
79 
80   Returns:      None.
81  *---------------------------------------------------------------------------*/
OSi_SyncWithOtherProc(int type,void * syncBuf)82 void OSi_SyncWithOtherProc( int type, void* syncBuf )
83 {
84     vu8* ptr1     = (vu8*)syncBuf;
85     vu8* ptr2     = (vu8*)syncBuf +1;
86     vu8* pfinish  = (vu8*)syncBuf +2;
87     vu8* pconf    = (vu8*)syncBuf +3;
88 
89     if ( type == OSi_SYNCTYPE_SENDER )
90     {
91         int n=0;
92         *pfinish = FALSE;
93         do
94         {
95             *ptr1 = (u8)( 0x80 | (n&0xf) );
96             while ( *ptr1 != *ptr2 && *pfinish == FALSE )
97             {
98                 OSi_WaitByLoop();
99             }
100             n ++;
101         } while( *pfinish == FALSE );
102         *pconf = TRUE;
103     }
104     else
105     {
106         int sum = 0;
107         *ptr2 = 0;
108         while( sum < 0x300 )
109         {
110             if ( *ptr2 != *ptr1 )
111             {
112                 *ptr2 = *ptr1;
113                 sum += *ptr2;
114             }
115             else
116             {
117                 OSi_WaitByLoop();
118             }
119         }
120         *pconf   = FALSE;
121         *pfinish = TRUE;
122         while( *pconf == FALSE )
123         {
124             OSi_WaitByLoop();
125         }
126     }
127 }
128 #endif
129 
130 //======================================================================
131 //                      DUMMY LOOP
132 //======================================================================
133 /*---------------------------------------------------------------------------*
134   Name:         OSi_WaitByLoop
135 
136   Description:  Waits by a for() loop.
137 
138   Arguments:    None.
139 
140   Returns:      None.
141  *---------------------------------------------------------------------------*/
OSi_WaitByLoop(void)142 static inline void OSi_WaitByLoop(void)
143 {
144     SVC_WaitByLoop(0x1000 / 4);
145 }
146 
147 //======================================================================
148 //                      INITIALIZE
149 //======================================================================
150 /*---------------------------------------------------------------------------*
151   Name:         OS_InitLock
152 
153   Description:  Initializes access rights to system lock variables and shared resources.
154 
155 
156                 The region used for cartridge mutexes will be cleared.
157                 (because that region is used by the debugger)
158 
159   Arguments:    None.
160 
161   Returns:      None.
162  *---------------------------------------------------------------------------*/
OS_InitLock(void)163 void OS_InitLock(void)
164 {
165     static BOOL isInitialized = FALSE;
166 #ifdef SDK_NITRO
167     OSLockWord *lockp;
168 #endif
169 
170     if (isInitialized)
171     {
172         return;                        // Do it only once
173     }
174     isInitialized = TRUE;
175 
176 //---------------- NITRO
177 #ifdef SDK_NITRO
178     lockp = (OSLockWord *)HW_INIT_LOCK_BUF;
179 
180 #ifdef  SDK_ARM9
181     {
182         //
183         // Code for MAIN PROCESSOR
184         //
185 
186         lockp->lockFlag = 0;
187         (void)OS_LockByWord(OS_MAINP_SYSTEM_LOCK_ID - 1, lockp, NULL);
188 
189         // Checks by the subprocessor for unused shared resources
190         while (lockp->extension != 0)
191         {
192             OSi_WaitByLoop();
193         }
194 
195         // Flag initialization for the lock ID counter
196         ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[0] = OSi_LOCKID_INITIAL_FLAG_0;
197         ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[1] = OSi_LOCKID_INITIAL_FLAG_1;
198 
199         // Clear the lock buffer (except for the cartridge region)
200         MI_CpuClear32((void *)HW_SHARED_LOCK_BUF, HW_CTRDG_LOCK_BUF - HW_SHARED_LOCK_BUF);
201 
202         // NITRO Card access rights -> subprocessor
203         MIi_SetCardProcessor(MI_PROCESSOR_ARM7);
204 
205         // Cartridge access rights -> subprocessor
206         MIi_SetCartridgeProcessor(MI_PROCESSOR_ARM7);
207 
208 #ifndef SDK_FINALROM
209 		{
210 			u32 type = OS_GetConsoleType();
211 			if ( type & OS_CONSOLE_TWLDEBUGGER )
212 			{
213                 _ISTDbgLib_Initialize();
214             }
215             else if ( type & (OS_CONSOLE_ISDEBUGGER | OS_CONSOLE_NITRO) )
216             {
217                 _ISDbgLib_Initialize();
218             }
219         }
220 #endif
221 
222         (void)OS_UnlockByWord(OS_MAINP_SYSTEM_LOCK_ID - 1, lockp, NULL);
223         (void)OS_LockByWord(OS_MAINP_SYSTEM_LOCK_ID, lockp, NULL);
224     }
225 
226 #else  // SDK_ARM7
227     {
228         //
229         // Code for SUBPROCESSOR
230         //
231 
232         lockp->extension = 0;
233         while (lockp->ownerID != OS_MAINP_SYSTEM_LOCK_ID)
234         {
235             OSi_WaitByLoop();
236         }
237 
238 #ifndef SDK_FINALROM
239         // [TODO]
240         // If a component leaks, it is necessary to create a component that calls the _ISTDbgLib_Initialize function
241         //
242 		{
243 			u32 type = OSi_DetectDebugger();
244 			if ( type & OS_CONSOLE_TWLDEBUGGER )
245 			{
246 				_ISTDbgLib_Initialize();
247 			}
248 			else if ( type & OS_CONSOLE_ISDEBUGGER )
249 			{
250 				_ISDbgLib_Initialize();
251 			}
252         }
253 #endif
254 
255         // Flag initialization for the lock ID counter
256         ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[0] = OSi_LOCKID_INITIAL_FLAG_0;
257         ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[1] = OSi_LOCKID_INITIAL_FLAG_1;
258 
259         // Synchronize the end of initialization with the main processor
260         lockp->extension = OS_SUBP_SYSTEM_LOCK_ID;
261     }
262 #endif
263 
264 //---------------- TWL
265 #else
266 #ifdef SDK_ARM9
267     // Flag initialization for the lock ID counter
268     ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[0] = OSi_LOCKID_INITIAL_FLAG_0;
269     ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[1] = OSi_LOCKID_INITIAL_FLAG_1;
270 
271     // Clear the lock buffer (except for the cartridge region)
272     MI_CpuClear32((void *)HW_SHARED_LOCK_BUF, HW_CTRDG_LOCK_BUF - HW_SHARED_LOCK_BUF);
273 
274     // NITRO Card access rights -> subprocessor
275     MIi_SetCardProcessor(MI_PROCESSOR_ARM7);
276 
277     // Cartridge access rights -> subprocessor
278     MIi_SetCartridgeProcessor(MI_PROCESSOR_ARM7);
279 
280     //---- Synchronize with ARM7
281     OSi_SyncWithOtherProc( OSi_SYNCTYPE_SENDER, (void*)HW_INIT_LOCK_BUF );
282     OSi_SyncWithOtherProc( OSi_SYNCTYPE_RECVER, (void*)HW_INIT_LOCK_BUF );
283 
284 #ifndef SDK_FINALROM
285 	{
286 		u32 type = OSi_DetectDebugger();
287 		if ( type & OS_CONSOLE_TWLDEBUGGER )
288 		{
289 			_ISTDbgLib_Initialize();
290 		}
291 		else if ( type & OS_CONSOLE_ISDEBUGGER )
292 		{
293 			_ISDbgLib_Initialize();
294 		}
295 	}
296 #endif
297 
298     //lockp->lockFlag = 0;
299     //(void)OS_LockByWord(OS_MAINP_SYSTEM_LOCK_ID, lockp, NULL);
300 
301 #else  // SDK_ARM7
302     // Flag initialization for the lock ID counter
303     ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[0] = OSi_LOCKID_INITIAL_FLAG_0;
304     ((u32 *)OSi_ANYP_LOCK_ID_FLAG)[1] = OSi_LOCKID_INITIAL_FLAG_1;
305 
306     //---- Synchronize with ARM9
307     OSi_SyncWithOtherProc( OSi_SYNCTYPE_RECVER, (void*)HW_INIT_LOCK_BUF );
308     OSi_SyncWithOtherProc( OSi_SYNCTYPE_SENDER, (void*)HW_INIT_LOCK_BUF );
309 
310 #ifndef SDK_FINALROM
311 	{
312 		u32 type = OSi_DetectDebugger();
313 		if ( type & OS_CONSOLE_TWLDEBUGGER )
314 		{
315 			_ISTDbgLib_Initialize();
316 		}
317 		else if ( type & OS_CONSOLE_ISDEBUGGER )
318 		{
319 			_ISDbgLib_Initialize();
320 		}
321 	}
322 #endif
323 
324 #endif // SDK_ARM7
325 
326 #endif // SDK_TWL
327 }
328 
329 //======================================================================
330 //                      LOCK
331 //======================================================================
332 /*---------------------------------------------------------------------------*
333   Name:         OSi_DoLockByWord
334 
335   Description:  Does spinlock. Keeps trying until success.
336 
337   Arguments:    lockID: Lock ID
338                 lockp: Pointer to lock variable
339                 ctrlFuncp: Function
340                 disableFiq: Whether to disable fiq
341 
342   Returns:      OS_LOCK_SUCCESS: Lock success.
343  *---------------------------------------------------------------------------*/
OSi_DoLockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void),BOOL disableFiq)344 static s32 OSi_DoLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
345                             BOOL disableFiq)
346 {
347     s32     lastLockFlag;
348 
349     while ((lastLockFlag =
350             OSi_DoTryLockByWord(lockID, lockp, ctrlFuncp, disableFiq)) > OS_LOCK_SUCCESS)
351     {
352         OSi_WaitByLoop();
353     }
354 
355     return lastLockFlag;
356 }
357 
358 /*---------------------------------------------------------------------------*
359   Name:         OS_LockByWord
360 
361   Description:  Does spinlock. Keeps trying until success.
362 
363   Arguments:    lockID: Lock ID
364                 lockp: Pointer to lock variable
365                 ctrlFuncp: Function
366 
367   Returns:      OS_LOCK_SUCCESS: Lock success.
368  *---------------------------------------------------------------------------*/
OS_LockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))369 s32 OS_LockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
370 {
371     return OSi_DoLockByWord(lockID, lockp, ctrlFuncp, FALSE);
372 }
373 
374 /*---------------------------------------------------------------------------*
375   Name:         OS_LockByWord_IrqAndFiq
376 
377   Description:  Does spinlock. Keeps trying until success.
378                 Disable irq and fiq.
379 
380   Arguments:    lockID: Lock ID
381                 lockp: Pointer to lock variable
382                 ctrlFuncp: Function
383 
384   Returns:      OS_LOCK_SUCCESS: Lock success.
385  *---------------------------------------------------------------------------*/
OS_LockByWord_IrqAndFiq(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))386 s32 OS_LockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
387 {
388     return OSi_DoLockByWord(lockID, lockp, ctrlFuncp, TRUE);
389 }
390 
391 
392 //======================================================================
393 //                      UNLOCK
394 //======================================================================
395 /*---------------------------------------------------------------------------*
396   Name:         OSi_DoUnlockByWord
397 
398   Description:  Unlocks.
399 
400   Arguments:    lockID: Lock ID
401                 lockp: Pointer to unlock variable
402                 ctrlFuncp: Function
403                 disableFiq: Whether to disable fiq
404 
405   Returns:      OS_UNLOCK_SUCCESS: Success.
406                 OS_UNLOCK_ERROR: Error while unlocking.
407  *---------------------------------------------------------------------------*/
OSi_DoUnlockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void),BOOL disableFIQ)408 static s32 OSi_DoUnlockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
409                               BOOL disableFIQ)
410 {
411     OSIntrMode lastInterrupts;
412 
413     OSi_ASSERT_ID(lockID);
414 
415     if (lockID != lockp->ownerID)
416     {
417         return OS_UNLOCK_ERROR;
418     }
419 
420     //---- Disable irq/fiq or irq
421     lastInterrupts = (disableFIQ) ? OS_DisableInterrupts_IrqAndFiq() : OS_DisableInterrupts();
422 
423     lockp->ownerID = 0;
424     if (ctrlFuncp)
425     {
426         ctrlFuncp();
427     }
428     lockp->lockFlag = 0;
429 
430     //---- Restore irq/fiq or irq
431     if (disableFIQ)
432     {
433         (void)OS_RestoreInterrupts_IrqAndFiq(lastInterrupts);
434     }
435     else
436     {
437         (void)OS_RestoreInterrupts(lastInterrupts);
438     }
439 
440     return OS_UNLOCK_SUCCESS;
441 }
442 
443 /*---------------------------------------------------------------------------*
444   Name:         OS_UnlockByWord
445 
446   Description:  Unlocks.
447                 Disable irq and fiq.
448 
449   Arguments:    lockID: Lock ID
450                 lockp: Pointer to unlock variable
451                 ctrlFuncp: Function
452 
453   Returns:      OS_UNLOCK_SUCCESS: Success.
454                 OS_UNLOCK_ERROR: Error while unlocking.
455  *---------------------------------------------------------------------------*/
OS_UnlockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))456 s32 OS_UnlockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
457 {
458     return OSi_DoUnlockByWord(lockID, lockp, ctrlFuncp, FALSE);
459 }
460 
461 //---- For compatibility to old name ('UnLock' <-> 'Unlock')
OS_UnLockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))462 s32 OS_UnLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
463 {
464     return OSi_DoUnlockByWord(lockID, lockp, ctrlFuncp, FALSE);
465 }
466 
467 /*---------------------------------------------------------------------------*
468   Name:         OS_UnlockByWord_IrqAndFiq
469 
470   Description:  Unlocks.
471 
472   Arguments:    lockID: Lock ID
473                 lockp: Pointer to unlock variable
474                 ctrlFuncp: Function
475 
476   Returns:      OS_UNLOCK_SUCCESS: Success.
477                 OS_UNLOCK_ERROR: Error while unlocking.
478  *---------------------------------------------------------------------------*/
OS_UnlockByWord_IrqAndFiq(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))479 s32 OS_UnlockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
480 {
481     return OSi_DoUnlockByWord(lockID, lockp, ctrlFuncp, TRUE);
482 }
483 
484 
485 //======================================================================
486 //                      TRY LOCK
487 //======================================================================
488 /*---------------------------------------------------------------------------*
489   Name:         OSi_DoTryLockByWord
490 
491   Description:  Tries to lock. Only does spinlock once.
492 
493   Arguments:    lockID: Lock ID
494                 lockp: Pointer to trying to lock variable
495                 ctrlFuncp: Function
496                 disableFiq: Whether to disable fiq
497 
498   Returns:      >0 value: Previous locked ID.
499                 OS_LOCK_SUCCESS: Lock success.
500  *---------------------------------------------------------------------------*/
OSi_DoTryLockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void),BOOL disableFIQ)501 static s32 OSi_DoTryLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void),
502                                BOOL disableFIQ)
503 {
504     s32     lastLockFlag;
505     OSIntrMode lastInterrupts;
506 
507     OSi_ASSERT_ID(lockID);
508 
509     //---- Disable irq/fiq or irq
510     lastInterrupts = (disableFIQ) ? OS_DisableInterrupts_IrqAndFiq() : OS_DisableInterrupts();
511 
512     lastLockFlag = (s32)MI_SwapWord(lockID, &lockp->lockFlag);
513 
514     if (lastLockFlag == OS_LOCK_SUCCESS)
515     {
516         if (ctrlFuncp)
517         {
518             ctrlFuncp();
519         }
520         lockp->ownerID = lockID;
521     }
522 
523     //---- Restore irq/fiq or irq
524     if (disableFIQ)
525     {
526         (void)OS_RestoreInterrupts_IrqAndFiq(lastInterrupts);
527     }
528     else
529     {
530         (void)OS_RestoreInterrupts(lastInterrupts);
531     }
532 
533     return lastLockFlag;
534 }
535 
536 /*---------------------------------------------------------------------------*
537   Name:         OS_TryLockByWord
538 
539   Description:  Tries to lock. Only does spinlock once.
540 
541   Arguments:    lockID: Lock ID
542                 lockp: Pointer to trying to lock variable
543                 ctrlFuncp: Function
544 
545   Returns:      >0 value: Previous locked ID.
546                 OS_LOCK_SUCCESS: Lock success.
547  *---------------------------------------------------------------------------*/
OS_TryLockByWord(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))548 s32 OS_TryLockByWord(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
549 {
550     return OSi_DoTryLockByWord(lockID, lockp, ctrlFuncp, FALSE);
551 }
552 
553 /*---------------------------------------------------------------------------*
554   Name:         OS_TryLockByWord_IrqAndFiq
555 
556   Description:  Tries to lock. Only does spinlock once.
557 
558   Arguments:    lockID: Lock ID
559                 lockp: Pointer to trying to lock variable
560                 ctrlFuncp: Function
561 
562   Returns:      >0 value: Previous locked ID.
563                 OS_LOCK_SUCCESS: Lock success.
564  *---------------------------------------------------------------------------*/
OS_TryLockByWord_IrqAndFiq(u16 lockID,OSLockWord * lockp,void (* ctrlFuncp)(void))565 s32 OS_TryLockByWord_IrqAndFiq(u16 lockID, OSLockWord *lockp, void (*ctrlFuncp) (void))
566 {
567     return OSi_DoTryLockByWord(lockID, lockp, ctrlFuncp, TRUE);
568 }
569 
570 
571 //======================================================================
572 //                      CARTRIDGE
573 //======================================================================
574 /*---------------------------------------------------------------------------*
575   Name:         OS_LockCartridge
576 
577   Description:  Locks cartridge.
578 
579   Arguments:    lockID: Lock ID
580 
581   Returns:      OS_LOCK_SUCCESS: Lock success.
582  *---------------------------------------------------------------------------*/
OS_LockCartridge(u16 lockID)583 s32 OS_LockCartridge(u16 lockID)
584 {
585     s32     lastLockFlag;
586 
587     OSi_ASSERT_ID(lockID);
588 
589     lastLockFlag =
590         OSi_DoLockByWord(lockID, (OSLockWord *)HW_CTRDG_LOCK_BUF, OSi_AllocateCartridgeBus, TRUE);
591 
592 #ifndef SDK_FINALROM
593 	{
594 		u32 type = OSi_DetectDebugger();
595 		if ( type & OS_CONSOLE_TWLDEBUGGER )
596 		{
597 			_ISTDbgLib_AllocateEmualtor();
598 		}
599 		else if ( type & OS_CONSOLE_ISDEBUGGER )
600 		{
601 			_ISDbgLib_AllocateEmualtor();
602 		}
603     }
604 #endif
605 
606     return lastLockFlag;
607 }
608 
609 /*---------------------------------------------------------------------------*
610   Name:         OS_UnlockCartridge
611 
612   Description:  Unlocks cartridge.
613 
614   Arguments:    lockID: Lock ID
615 
616   Returns:      OS_UNLOCK_SUCCESS: Success.
617                 OS_UNLOCK_ERROR: Error while unlocking.
618  *---------------------------------------------------------------------------*/
OS_UnlockCartridge(u16 lockID)619 s32 OS_UnlockCartridge(u16 lockID)
620 {
621     s32     lastLockFlag;
622 
623     OSi_ASSERT_ID(lockID);
624 
625 #ifndef SDK_FINALROM
626 	{
627 		u32 type = OSi_DetectDebugger();
628 		if ( type & OS_CONSOLE_TWLDEBUGGER )
629 		{
630 			_ISTDbgLib_FreeEmulator();
631 		}
632 		else if ( type & OS_CONSOLE_ISDEBUGGER )
633 		{
634 			_ISDbgLib_FreeEmulator();
635 		}
636 	}
637 #endif
638 
639     lastLockFlag =
640         OSi_DoUnlockByWord(lockID, (OSLockWord *)HW_CTRDG_LOCK_BUF, OSi_FreeCartridgeBus, TRUE);
641 
642     return lastLockFlag;
643 }
644 
645 //---- For compatibility to old name ('UnLock' <-> 'Unlock')
OS_UnLockCartridge(u16 lockID)646 asm s32 OS_UnLockCartridge( u16 lockID )
647 {
648   ldr  r1, =OS_UnlockCartridge
649   bx   r1
650 }
651 
652 /*---------------------------------------------------------------------------*
653   Name:         OS_TryLockCartridge
654 
655   Description:  Tries to lock cartridge.
656 
657   Arguments:    lockID: Lock ID
658 
659   Returns:      >0 value: Previous locked ID.
660                 OS_LOCK_SUCCESS: Lock success.
661  *---------------------------------------------------------------------------*/
OS_TryLockCartridge(u16 lockID)662 s32 OS_TryLockCartridge(u16 lockID)
663 {
664     s32     lastLockFlag;
665 
666     lastLockFlag =
667         OSi_DoTryLockByWord(lockID, (OSLockWord *)HW_CTRDG_LOCK_BUF, OSi_AllocateCartridgeBus,
668                             TRUE);
669 
670 #ifndef SDK_FINALROM
671 	if ( lastLockFlag == OS_LOCK_SUCCESS )
672 	{
673 		u32 type = OSi_DetectDebugger();
674 		if ( type & OS_CONSOLE_TWLDEBUGGER )
675 		{
676 			_ISTDbgLib_AllocateEmualtor();
677 		}
678 		else if ( type & OS_CONSOLE_ISDEBUGGER )
679 		{
680 			_ISDbgLib_AllocateEmualtor();
681 		}
682     }
683 #endif
684 
685     return lastLockFlag;
686 }
687 
688 //----------------
OSi_AllocateCartridgeBus(void)689 static void OSi_AllocateCartridgeBus(void)
690 {
691 #ifdef  SDK_ARM9
692     MIi_SetCartridgeProcessor(MI_PROCESSOR_ARM9);       // Cartridge for MAIN
693 #endif
694 }
695 
696 //----------------
OSi_FreeCartridgeBus(void)697 static void OSi_FreeCartridgeBus(void)
698 {
699 #ifdef  SDK_ARM9
700     MIi_SetCartridgeProcessor(MI_PROCESSOR_ARM7);       // Cartridge for SUB
701 #endif
702 }
703 
704 //======================================================================
705 //                      CARD
706 //======================================================================
707 /*---------------------------------------------------------------------------*
708   Name:         OS_LockCard
709 
710   Description:  Locks card.
711 
712   Arguments:    lockID: Lock ID
713 
714   Returns:      OS_LOCK_SUCCESS: Lock success.
715  *---------------------------------------------------------------------------*/
OS_LockCard(u16 lockID)716 s32 OS_LockCard(u16 lockID)
717 {
718     OSi_ASSERT_ID(lockID);
719 
720     return OS_LockByWord(lockID, (OSLockWord *)HW_CARD_LOCK_BUF, OSi_AllocateCardBus);
721 }
722 
723 /*---------------------------------------------------------------------------*
724   Name:         OS_UnlockCard
725 
726   Description:  Unlocks card.
727 
728   Arguments:    lockID: Lock ID
729 
730   Returns:      OS_UNLOCK_SUCCESS: Success.
731                 OS_UNLOCK_ERROR: Error while unlocking.
732  *---------------------------------------------------------------------------*/
OS_UnlockCard(u16 lockID)733 s32 OS_UnlockCard(u16 lockID)
734 {
735     OSi_ASSERT_ID(lockID);
736 
737     return OS_UnlockByWord(lockID, (OSLockWord *)HW_CARD_LOCK_BUF, OSi_FreeCardBus);
738 }
739 
740 //---- For compatibility to old name ('UnLock' <-> 'Unlock')
OS_UnLockCard(u16 lockID)741 asm s32 OS_UnLockCard( u16 lockID )
742 {
743   ldr  r1, =OS_UnlockCard
744   bx   r1
745 }
746 
747 /*---------------------------------------------------------------------------*
748   Name:         OS_TryLockCard
749 
750   Description:  Tries to lock card.
751 
752   Arguments:    lockID: Lock ID
753 
754   Returns:      >0 value: Previous locked ID.
755                 OS_LOCK_SUCCESS: Lock success.
756  *---------------------------------------------------------------------------*/
OS_TryLockCard(u16 lockID)757 s32 OS_TryLockCard(u16 lockID)
758 {
759     return OS_TryLockByWord(lockID, (OSLockWord *)HW_CARD_LOCK_BUF, OSi_AllocateCardBus);
760 }
761 
762 //----------------
OSi_AllocateCardBus(void)763 static void OSi_AllocateCardBus(void)
764 {
765 #ifdef  SDK_ARM9
766 #ifdef  SDK_TWL
767     // Preset reset flag with status of disable interrupts in OSi_DoTryLockByWord
768     if ( ((reg_MI_MC & REG_MI_MC_SL1_MODE_MASK) >> REG_MI_MC_SL1_MODE_SHIFT) == 0x2 )
769     {
770         reg_MI_MCCNT1 |= REG_MI_MCCNT1_RESB_MASK;
771     }
772 #endif
773     MIi_SetCardProcessor(MI_PROCESSOR_ARM9);    // Card for MAIN
774 #endif
775 }
776 
777 //----------------
OSi_FreeCardBus(void)778 static void OSi_FreeCardBus(void)
779 {
780 #ifdef  SDK_ARM9
781     MIi_SetCardProcessor(MI_PROCESSOR_ARM7);    // Card for SUB
782 #endif
783 }
784 
785 
786 //======================================================================
787 //                      READ OWNER
788 //======================================================================
789 /*---------------------------------------------------------------------------*
790   Name:         OS_ReadOwnerOfLockWord
791 
792   Description:  Reads the owner ID of a lock.
793 
794        - You can check which processor has ownership now if the module ID is nonzero.
795 
796        - For a shared resource, prohibiting interrupts can maintain only the main processor's ownership rights.
797 
798          In other states, it might be changed by subprocessors.
799        - The lock variable may not necessarily be unlocked even if owner module ID is 0.
800 
801   Arguments:    lockp: Pointer to lock
802 
803   Returns:      Owner ID.
804  *---------------------------------------------------------------------------*/
OS_ReadOwnerOfLockWord(OSLockWord * lockp)805 u16 OS_ReadOwnerOfLockWord(OSLockWord *lockp)
806 {
807     return lockp->ownerID;
808 }
809 
810 //======================================================================
811 //                     LOCK ID
812 //======================================================================
813 /*---------------------------------------------------------------------------*
814   Name:         OS_GetLockID
815 
816   Description:  Gets the lock ID.
817 
818   Arguments:    None.
819 
820   Returns:      OS_LOCK_ID_ERROR, if failed to get ID.
821 
822                 if ARM9
823                    0x40-0x6f: lockID
824                 else if ARM7
825                    0x80-0xaf: lockID
826                 endif
827 
828                 Only up to 48 kinds of IDs can be assigned.
829                 When managing multiple lock variables in a module, use a single ID whenever possible.
830 
831  *---------------------------------------------------------------------------*/
832 #include <nitro/code32.h>
OS_GetLockID(void)833 asm s32 OS_GetLockID( void )
834 {
835     //---- Is a flag set (a free ID) in the first 32 flag bits?
836     ldr    r3, =OSi_ANYP_LOCK_ID_FLAG
837     ldr    r1, [r3, #0]
838 
839 #ifdef SDK_ARM9
840     clz    r2, r1
841 #else
842     mov    r2, #0
843     mov    r0, #0x80000000
844 _lp1:
845     tst    r1, r0
846     bne    _ex1
847     add    r2, r2, #1
848     cmp    r2, #32
849     beq    _ex1
850 
851     mov    r0, r0, lsr #1
852     b      _lp1
853  _ex1:
854 #endif
855     cmp    r2, #32
856 
857     //---- When there is a free ID
858     movne  r0, #OSi_ANYP_LOCK_ID_START
859     bne    _1
860 
861     //---- Is there a flag that is set (a free ID) in the rear 323 bits?
862     add    r3, r3, #4
863     ldr    r1, [r3, #0]
864 #ifdef SDK_ARM9
865     clz    r2, r1
866 #else
867     mov    r2, #0
868     mov    r0, #0x80000000
869 _lp2:
870     tst    r1, r0
871     bne    _ex2
872     add    r2, r2, #1
873     cmp    r2, #32
874     beq    _ex2
875 
876     mov    r0, r0, lsr #1
877     b      _lp2
878  _ex2:
879 #endif
880     cmp    r2, #32
881 
882     //---- When there are no free IDs
883     ldr    r0, =OS_LOCK_ID_ERROR
884     bxeq   lr
885 
886     //---- When there is a free ID
887     mov    r0, #OSi_ANYP_LOCK_ID_START+32
888 
889 _1:
890     add    r0, r0, r2
891     mov    r1, #0x80000000
892     mov    r1, r1, lsr r2
893 
894     ldr    r2, [r3, #0]
895     bic    r2, r2, r1
896     str    r2, [r3, #0]
897 
898     bx     lr
899 }
900 
901 /*---------------------------------------------------------------------------*
902   Name:         OS_ReleaseLockID
903 
904   Description:  Releases lock ID.
905 
906   Arguments:    ID to tend to release
907 
908   Returns:      None.
909  *---------------------------------------------------------------------------*/
OS_ReleaseLockID(register u16 lockID)910 asm void OS_ReleaseLockID( register u16 lockID )
911 {
912 #pragma unused( lockID )
913 
914     ldr    r3, =OSi_ANYP_LOCK_ID_FLAG
915 
916     cmp    r0, #OSi_ANYP_LOCK_ID_START+32
917     addpl  r3, r3, #4
918 
919     subpl  r0, r0, #OSi_ANYP_LOCK_ID_START+32
920     submi  r0, r0, #OSi_ANYP_LOCK_ID_START
921 
922     mov r1, #0x80000000
923     mov r1, r1, lsr r0
924 
925     ldr    r2, [r3, #0]
926     orr    r2, r2, r1
927     str    r2, [r3, #0]
928 
929     bx     lr
930 }
931 #include <nitro/codereset.h>
932