1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CARD - libraries
3   File:     card_common.c
4 
5   Copyright 2007-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-26#$
14   $Rev: 10827 $
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         BOOL                    backupPowerOn = FALSE;
129         if (header->access_control.game_card_nitro_mode)
130         {
131             level |= CARD_ACCESS_LEVEL_ROM;
132             backupPowerOn = TRUE;
133         }
134         else if (header->access_control.game_card_on)
135         {
136             backupPowerOn = TRUE;
137         }
138         if (backupPowerOn)
139         {
140             if (header->access_control.backup_access_read)
141             {
142                 level |= CARD_ACCESS_LEVEL_BACKUP_R;
143             }
144             if (header->access_control.backup_access_write)
145             {
146                 level |= CARD_ACCESS_LEVEL_BACKUP_W;
147             }
148         }
149     }
150 #endif
151     return level;
152 }
153 
154 /*---------------------------------------------------------------------------*
155   Name:         CARDi_WaitAsync
156 
157   Description:  Waits for an asynchronous process to complete.
158 
159   Arguments:    None.
160 
161   Returns:      If the latest processing result is CARD_RESULT_SUCCESS, returns TRUE.
162  *---------------------------------------------------------------------------*/
CARDi_WaitAsync(void)163 BOOL CARDi_WaitAsync(void)
164 {
165     SDK_ASSERT(CARD_IsAvailable());
166     return CARDi_WaitForTask(&cardi_common, FALSE, NULL, NULL);
167 }
168 
169 /*---------------------------------------------------------------------------*
170   Name:         CARDi_TryWaitAsync
171 
172   Description:  Tries to wait for an asynchronous process to complete and returns control immediately regardless of success or failure.
173 
174   Arguments:    None.
175 
176   Returns:      If the most recent asynchronous processing is complete, TRUE.
177  *---------------------------------------------------------------------------*/
CARDi_TryWaitAsync(void)178 BOOL CARDi_TryWaitAsync(void)
179 {
180     CARDiCommon *const p = &cardi_common;
181     SDK_ASSERT(CARD_IsAvailable());
182 
183     return !(p->flag & CARD_STAT_BUSY);
184 }
185 
CARDi_InitResourceLock(void)186 void CARDi_InitResourceLock(void)
187 {
188     CARDiCommon *p = &cardi_common;
189     p->lock_owner = OS_LOCK_ID_ERROR;
190     p->lock_ref = 0;
191     p->lock_target = CARD_TARGET_NONE;
192     OS_InitThreadQueue(p->lock_queue);
193 }
194 
195 
196 
197 
198 
199 
CARDi_InitCommand(void)200 void CARDi_InitCommand(void)
201 {
202     CARDiCommon *p = &cardi_common;
203 
204 #if defined(SDK_ARM9)
205     p->cmd = &cardi_arg;
206     MI_CpuFillFast(&cardi_arg, 0x00, sizeof(cardi_arg));
207     DC_FlushRange(&cardi_arg, sizeof(cardi_arg));
208 #else
209     p->cmd = CARD_UNSYNCHRONIZED_BUFFER;
210 #endif
211 
212     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_FS, CARDi_OnFifoRecv);
213 }
214