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