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