1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CARD - libraries
3   File:     card_common.c
4 
5   Copyright 2007-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:: 2009-01-13#$
14   $Rev: 9813 $
15   $Author: yosizaki $
16 
17  *---------------------------------------------------------------------------*/
18 
19 
20 #include "../include/card_common.h"
21 #include "../include/card_event.h"
22 #include "../include/card_spi.h"
23 #include <nitro/card/rom.h>
24 
25 
26 /*---------------------------------------------------------------------------*/
27 /* Variables */
28 
29 CARDiCommon cardi_common ATTRIBUTE_ALIGN(32);
30 static CARDiCommandArg cardi_arg ATTRIBUTE_ALIGN(32);
31 
32 
33 /*---------------------------------------------------------------------------*/
34 /* Functions */
35 
36 /*---------------------------------------------------------------------------*
37   Name:         CARDi_LockResource
38 
39   Description:  Exclusively locks resources.
40 
41   Arguments:    owner: Lock-ID indicating the owner of the lock
42                 target: Resource target on the card bus to be locked
43 
44   Returns:      None.
45  *---------------------------------------------------------------------------*/
CARDi_LockResource(CARDiOwner owner,CARDTargetMode target)46 void CARDi_LockResource(CARDiOwner owner, CARDTargetMode target)
47 {
48     CARDiCommon *const p = &cardi_common;
49     OSIntrMode bak_psr = OS_DisableInterrupts();
50     if (p->lock_owner == owner)
51     {
52         if (p->lock_target != target)
53         {
54             OS_TPanic("card-lock : can not reuse same ID for locking without unlocking!");
55         }
56     }
57     else
58     {
59         while (p->lock_owner != OS_LOCK_ID_ERROR)
60         {
61             OS_SleepThread(p->lock_queue);
62         }
63         p->lock_owner = owner;
64         p->lock_target = target;
65     }
66     ++p->lock_ref;
67     (void)OS_RestoreInterrupts(bak_psr);
68 }
69 
70 /*---------------------------------------------------------------------------*
71   Name:         CARDi_UnlockResource
72 
73   Description:  Exclusively unlocks resources.
74 
75   Arguments:    owner: Lock-ID indicating the owner of the lock
76                 target: Resource target on the card bus to be unlocked
77 
78   Returns:      None.
79  *---------------------------------------------------------------------------*/
CARDi_UnlockResource(CARDiOwner owner,CARDTargetMode target)80 void CARDi_UnlockResource(CARDiOwner owner, CARDTargetMode target)
81 {
82     CARDiCommon *p = &cardi_common;
83     OSIntrMode bak_psr = OS_DisableInterrupts();
84     if ((p->lock_owner != owner) || !p->lock_ref)
85     {
86         OS_TPanic("card-unlock : specified ID for unlocking is not locking one!");
87     }
88     else
89     {
90         if (p->lock_target != target)
91         {
92             OS_TPanic("card-unlock : locking target and unlocking one are different!");
93         }
94         if (!--p->lock_ref)
95         {
96             p->lock_owner = OS_LOCK_ID_ERROR;
97             p->lock_target = CARD_TARGET_NONE;
98             OS_WakeupThread(p->lock_queue);
99         }
100     }
101     (void)OS_RestoreInterrupts(bak_psr);
102 }
103 
104 /*---------------------------------------------------------------------------*
105   Name:         CARDi_GetAccessLevel
106 
107   Description:  Gets the allowed ROM access level.
108 
109   Arguments:    None.
110 
111   Returns:      Allowed ROM access level.
112  *---------------------------------------------------------------------------*/
CARDi_GetAccessLevel(void)113 CARDAccessLevel CARDi_GetAccessLevel(void)
114 {
115     CARDAccessLevel level = CARD_ACCESS_LEVEL_NONE;
116     if (OS_GetBootType() == OS_BOOTTYPE_ROM)
117     {
118         level = CARD_ACCESS_LEVEL_FULL;
119     }
120     else if (!OS_IsRunOnTwl())
121     {
122         level = CARD_ACCESS_LEVEL_BACKUP;
123     }
124 #ifdef SDK_TWL
125     else
126     {
127         const CARDRomHeaderTWL *header = CARD_GetOwnRomHeaderTWL();
128         if (header->access_control.game_card_nitro_mode)
129         {
130             level = CARD_ACCESS_LEVEL_FULL;
131         }
132         else if (header->access_control.game_card_on)
133         {
134             level = CARD_ACCESS_LEVEL_BACKUP;
135         }
136     }
137 #endif
138     return level;
139 }
140 
141 /*---------------------------------------------------------------------------*
142   Name:         CARDi_WaitAsync
143 
144   Description:  Waits for an asynchronous process to complete.
145 
146   Arguments:    None.
147 
148   Returns:      If the latest processing result is CARD_RESULT_SUCCESS, returns TRUE.
149  *---------------------------------------------------------------------------*/
CARDi_WaitAsync(void)150 BOOL CARDi_WaitAsync(void)
151 {
152     SDK_ASSERT(CARD_IsAvailable());
153     return CARDi_WaitForTask(&cardi_common, FALSE, NULL, NULL);
154 }
155 
156 /*---------------------------------------------------------------------------*
157   Name:         CARDi_TryWaitAsync
158 
159   Description:  Tries to wait for an asynchronous process to complete and returns control immediately regardless of success or failure.
160 
161   Arguments:    None.
162 
163   Returns:      If the most recent asynchronous processing is complete, TRUE.
164  *---------------------------------------------------------------------------*/
CARDi_TryWaitAsync(void)165 BOOL CARDi_TryWaitAsync(void)
166 {
167     CARDiCommon *const p = &cardi_common;
168     SDK_ASSERT(CARD_IsAvailable());
169 
170     return !(p->flag & CARD_STAT_BUSY);
171 }
172 
CARDi_InitResourceLock(void)173 void CARDi_InitResourceLock(void)
174 {
175     CARDiCommon *p = &cardi_common;
176     p->lock_owner = OS_LOCK_ID_ERROR;
177     p->lock_ref = 0;
178     p->lock_target = CARD_TARGET_NONE;
179     OS_InitThreadQueue(p->lock_queue);
180 }
181 
182 
183 
184 
185 
186 
CARDi_InitCommand(void)187 void CARDi_InitCommand(void)
188 {
189     CARDiCommon *p = &cardi_common;
190 
191 #if defined(SDK_ARM9)
192     p->cmd = &cardi_arg;
193     MI_CpuFillFast(&cardi_arg, 0x00, sizeof(cardi_arg));
194     DC_FlushRange(&cardi_arg, sizeof(cardi_arg));
195 #else
196     p->cmd = CARD_UNSYNCHRONIZED_BUFFER;
197 #endif
198 
199     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_FS, CARDi_OnFifoRecv);
200 }
201