1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS -
3   File:     os_spinLock.c
4 
5   Copyright 2003–2008 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:: 2008-11-12#$
14   $Rev: 9295 $
15   $Author: yada $
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_ASSERTMSG( 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_ASSERTMSG( 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:  Wait 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:  Initialize system lock variable
154                 and privilege to access shared resources.
155 
156                 * cartridge exclusive control area is not cleared
157                   because debugger uses.
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 sub processor 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 -> sub processor.
203         MIi_SetCardProcessor(MI_PROCESSOR_ARM7);
204 
205         // Cartridge access rights -> sub processor.
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 SUB PROCESSOR
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 -> sub processor.
275     MIi_SetCardProcessor(MI_PROCESSOR_ARM7);
276 
277     // Cartridge access rights -> sub processor.
278     MIi_SetCartridgeProcessor(MI_PROCESSOR_ARM7);
279 
280     //---- synchronism 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     //---- synchronism 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:  Do spinlock. Keep 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:  Do spinlock. Keep 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:  Do spinlock. Keep 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:  Unlock.
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:  Unlock.
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:  Unlock.
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:  Try to lock. Only 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:  Try to lock. Only 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:  Try to lock. Only 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:  Lock 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:  Unlock 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:  Try 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:  Lock 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:  Unlock 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:  Try 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:  Read the owner id of a lock.
793 
794        - You can check which processor has ownership rights at time when module ID is non-zero.
795 
796        - For common releases, it is possible to maintain by prohibiting interrupts only for states where the main processor has ownership.
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 fail to get ID
821 
822                 if ARM9
823                    0x40-0x6f:       lockID
824                 else if ARM7
825                    0x80-0xaf:       lockID
826                 endif
827 
828                 *Notice:  ID is allocated only 48 pattern at a highest.
829 
830                 Only up to 48 kinds of IDs can be assigned.
831                When controlling multiple lock variables in a module, use one ID as much as possible.
832 
833  *---------------------------------------------------------------------------*/
834 #include <nitro/code32.h>
OS_GetLockID(void)835 asm s32 OS_GetLockID( void )
836 {
837     //---- Is there a flag that is set (a free ID) in the first 32 flag bits?
838     ldr    r3, =OSi_ANYP_LOCK_ID_FLAG
839     ldr    r1, [r3, #0]
840 
841 #ifdef SDK_ARM9
842     clz    r2, r1
843 #else
844     mov    r2, #0
845     mov    r0, #0x80000000
846 _lp1:
847     tst    r1, r0
848     bne    _ex1
849     add    r2, r2, #1
850     cmp    r2, #32
851     beq    _ex1
852 
853     mov    r0, r0, lsr #1
854     b      _lp1
855  _ex1:
856 #endif
857     cmp    r2, #32
858 
859     //---- When there is a free ID.
860     movne  r0, #OSi_ANYP_LOCK_ID_START
861     bne    _1
862 
863     //---- Is there a flag that is set (a free ID) in the rear 323 bits?
864     add    r3, r3, #4
865     ldr    r1, [r3, #0]
866 #ifdef SDK_ARM9
867     clz    r2, r1
868 #else
869     mov    r2, #0
870     mov    r0, #0x80000000
871 _lp2:
872     tst    r1, r0
873     bne    _ex2
874     add    r2, r2, #1
875     cmp    r2, #32
876     beq    _ex2
877 
878     mov    r0, r0, lsr #1
879     b      _lp2
880  _ex2:
881 #endif
882     cmp    r2, #32
883 
884     //---- When there are no free IDs.
885     ldr    r0, =OS_LOCK_ID_ERROR
886     bxeq   lr
887 
888     //---- When there is a free ID.
889     mov    r0, #OSi_ANYP_LOCK_ID_START+32
890 
891 _1:
892     add    r0, r0, r2
893     mov    r1, #0x80000000
894     mov    r1, r1, lsr r2
895 
896     ldr    r2, [r3, #0]
897     bic    r2, r2, r1
898     str    r2, [r3, #0]
899 
900     bx     lr
901 }
902 
903 /*---------------------------------------------------------------------------*
904   Name:         OS_ReleaseLockID
905 
906   Description:  Releases the lock ID.
907 
908   Arguments:    id to tend to release.
909 
910   Returns:      None.
911  *---------------------------------------------------------------------------*/
OS_ReleaseLockID(register u16 lockID)912 asm void OS_ReleaseLockID( register u16 lockID )
913 {
914 #pragma unused( lockID )
915 
916     ldr    r3, =OSi_ANYP_LOCK_ID_FLAG
917 
918     cmp    r0, #OSi_ANYP_LOCK_ID_START+32
919     addpl  r3, r3, #4
920 
921     subpl  r0, r0, #OSi_ANYP_LOCK_ID_START+32
922     submi  r0, r0, #OSi_ANYP_LOCK_ID_START
923 
924     mov r1, #0x80000000
925     mov r1, r1, lsr r0
926 
927     ldr    r2, [r3, #0]
928     orr    r2, r2, r1
929     str    r2, [r3, #0]
930 
931     bx     lr
932 }
933 #include <nitro/codereset.h>
934