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