1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - OS - libraries
3   File:     os_vramExclusive.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-09-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include        <nitro/os/ARM9/vramExclusive.h>
19 #include        <nitro/os/common/interrupt.h>
20 #include        <nitro/os/common/system.h>
21 
22 
23 /*---------------------------------------------------------------------------*
24     Internal Variable Definitions
25  *---------------------------------------------------------------------------*/
26 static u32 OSi_vramExclusive;
27 static u16 OSi_vramLockId[OS_VRAM_BANK_KINDS];
28 
29 
30 /*===========================================================================*/
31 
32 /*---------------------------------------------------------------------------*
33   Name:         OsCountZeroBits
34 
35   Description:  Counts and returns the number of sequential zeroes in the 32-bit value starting from the top.
36 
37   Arguments:    bitmap: The value to evaluate
38 
39   Returns:      u32: The number of 0 bits.
40                                                         0x80000000 = 0; 0x00000000 = 32.
41  *---------------------------------------------------------------------------*/
42 #include        <nitro/code32.h>
43 static asm u32
OsCountZeroBits(u32 bitmap)44 OsCountZeroBits( u32 bitmap )
45 {
46     clz         r0,             r0
47         bx              lr
48         }
49 #include        <nitro/codereset.h>
50 
51 
52 /*---------------------------------------------------------------------------*
53   Name:         OSi_InitVramExclusive
54 
55   Description:  Initializes VRAM exclusion processes.
56 
57   Arguments:    None.
58 
59   Returns:      None.
60  *---------------------------------------------------------------------------*/
61 void
OSi_InitVramExclusive(void)62 OSi_InitVramExclusive( void )
63 {
64     s32         i;
65 
66     OSi_vramExclusive = 0x0000;
67     for( i = 0 ; i < OS_VRAM_BANK_KINDS ; i ++ )
68     {
69         OSi_vramLockId[ i ] = 0;
70     }
71 }
72 
73 /*---------------------------------------------------------------------------*
74   Name:         OSi_TryLockVram
75 
76   Description:  Tries the VRAM exclusive lock.
77 
78   Arguments:    bank: ID bitmap of VRAM on which exclusive lock is being tried
79                 lockId: Any ID that can be used as key for locking
80 
81   Returns:      BOOL: Returns TRUE if the lock is successful.
82  *---------------------------------------------------------------------------*/
OSi_TryLockVram(u16 bank,u16 lockId)83 BOOL OSi_TryLockVram(u16 bank, u16 lockId)
84 {
85     u32     workMap;
86     s32     zeroBits;
87     OSIntrMode enabled = OS_DisableInterrupts();
88 
89     // Check whether exclusive lock already set with different ID
90     workMap = (u32)(bank & OSi_vramExclusive);
91     while (TRUE)
92     {
93         zeroBits = (s32)(31 - OsCountZeroBits(workMap));
94         if (zeroBits < 0)
95         {
96             break;
97         }
98         workMap &= ~(0x00000001 << zeroBits);
99         if (OSi_vramLockId[zeroBits] != lockId)
100         {
101             (void)OS_RestoreInterrupts(enabled);
102             return FALSE;
103         }
104     }
105 
106     // Lock all VRAM with specified ID
107     workMap = (u32)(bank & OS_VRAM_BANK_ID_ALL);
108     while (TRUE)
109     {
110         zeroBits = (s32)(31 - OsCountZeroBits(workMap));
111         if (zeroBits < 0)
112         {
113             break;
114         }
115         workMap &= ~(0x00000001 << zeroBits);
116         OSi_vramLockId[zeroBits] = lockId;
117         OSi_vramExclusive |= (0x00000001 << zeroBits);
118     }
119 
120     (void)OS_RestoreInterrupts(enabled);
121     return TRUE;
122 }
123 
124 /*---------------------------------------------------------------------------*
125   Name:         OSi_UnlockVram
126 
127   Description:  Releases VRAM exclusive lock.
128 
129   Arguments:    bank: ID bitmap of VRAM on which exclusive lock is being released
130                 lockId: Arbitrary ID specified when locked
131 
132   Returns:      None.
133  *---------------------------------------------------------------------------*/
OSi_UnlockVram(u16 bank,u16 lockId)134 void OSi_UnlockVram(u16 bank, u16 lockId)
135 {
136     u32     workMap;
137     s32     zeroBits;
138     OSIntrMode enabled = OS_DisableInterrupts();
139 
140     workMap = (u32)(bank & OSi_vramExclusive & OS_VRAM_BANK_ID_ALL);
141     while (TRUE)
142     {
143         zeroBits = (s32)(31 - OsCountZeroBits((u32)workMap));
144         if (zeroBits < 0)
145         {
146             break;
147         }
148         workMap &= ~(0x00000001 << zeroBits);
149         if (OSi_vramLockId[zeroBits] == lockId)
150         {
151             OSi_vramLockId[zeroBits] = 0;
152             OSi_vramExclusive &= ~(0x00000001 << zeroBits);
153         }
154     }
155 
156     (void)OS_RestoreInterrupts(enabled);
157 }
158 
159 /*---------------------------------------------------------------------------*
160     End of file
161  *---------------------------------------------------------------------------*/
162