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