1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - CARD - libraries
3 File: card_api.c
4
5 Copyright 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-12-05#$
14 $Rev: 9518 $
15 $Author: yosizaki $
16
17 *---------------------------------------------------------------------------*/
18
19
20 #include <nitro.h>
21
22 #include "../include/card_common.h"
23 #include "../include/card_event.h"
24 #include "../include/card_rom.h"
25
26
27 /*---------------------------------------------------------------------------*/
28 /* Variables */
29
30 static BOOL CARDi_EnableFlag = FALSE;
31
32
33 /*---------------------------------------------------------------------------*/
34 /* functions */
35
36 /*---------------------------------------------------------------------------*
37 Name: CARDi_LockBusCondition
38
39 Description: Idle until the listener structure event is complete.
40
41 Arguments: userdata : Lock ID
42
43 Returns: None.
44 *---------------------------------------------------------------------------*/
CARDi_LockBusCondition(void * userdata)45 static BOOL CARDi_LockBusCondition(void *userdata)
46 {
47 u16 lockID = *(const u16 *)userdata;
48 return (OS_TryLockCard(lockID) == OS_LOCK_SUCCESS);
49 }
50
51 /*---------------------------------------------------------------------------*
52 Name: CARD_Init
53
54 Description: Initializes the Card library.
55
56 Arguments: None.
57
58 Returns: None.
59 *---------------------------------------------------------------------------*/
CARD_Init(void)60 void CARD_Init(void)
61 {
62 CARDiCommon *p = &cardi_common;
63
64 if (!p->flag)
65 {
66 p->flag = CARD_STAT_INIT;
67
68 #if !defined(SDK_SMALL_BUILD) && defined(SDK_ARM9)
69 // The CARD-ROM header information that is stored at non-card boot is NULL at card boot, so save it here.
70 //
71 if (OS_GetBootType() == OS_BOOTTYPE_ROM)
72 {
73 MI_CpuCopy8((const void *)HW_ROM_HEADER_BUF, (void *)HW_CARD_ROM_HEADER,
74 HW_CARD_ROM_HEADER_SIZE);
75 }
76 #endif // !defined(SDK_SMALL_BUILD) && defined(SDK_ARM9)
77
78 #if defined(SDK_ARM9)
79 // Initialize internal library variables
80 p->src = 0;
81 p->dst = 0;
82 p->len = 0;
83 p->dma = MI_DMA_NOT_USE;
84 p->DmaCall = NULL;
85 p->flush_threshold_ic = 0x400;
86 p->flush_threshold_dc = 0x2400;
87 #endif
88 cardi_rom_base = 0;
89 p->priority = CARD_THREAD_PRIORITY_DEFAULT;
90
91 // Initialize source lock
92 CARDi_InitResourceLock();
93
94 // Start up task thread
95 #if defined(SDK_ARM9)
96 // The old-format wait thread is used for ARM9 for compatibility
97 p->callback = NULL;
98 p->callback_arg = NULL;
99 OS_InitThreadQueue(p->busy_q);
100 OS_CreateThread(p->thread.context,
101 CARDi_OldTypeTaskThread, NULL,
102 p->thread.stack + sizeof(p->thread.stack),
103 sizeof(p->thread.stack), p->priority);
104 OS_WakeupThreadDirect(p->thread.context);
105 #else // defined(SDK_ARM9)
106 // The stable new-format wait thread is used for ARM 7
107 CARDi_InitTaskQueue(p->task_q);
108 OS_CreateThread(p->thread.context,
109 CARDi_TaskWorkerProcedure, p->task_q,
110 p->thread.stack + sizeof(p->thread.stack),
111 sizeof(p->thread.stack), p->priority);
112 OS_WakeupThreadDirect(p->thread.context);
113 #endif
114
115 // Initialize the command communication system.
116 CARDi_InitCommand();
117
118 // Initialize ROM driver
119 CARDi_InitRom();
120
121 // Allow unconditional card access only at card boot.
122 // If card access is desired in other startup modes, it is necessary to explicitly call the CARD_Enable function according to predetermined conditions described in the Guidelines
123 //
124 //
125 if (OS_GetBootType() == OS_BOOTTYPE_ROM)
126 {
127 CARD_Enable(TRUE);
128 }
129
130 #if !defined(SDK_SMALL_BUILD)
131 //---- Detect pulled out card
132 CARD_InitPulledOutCallback();
133 #endif
134 }
135 }
136
137 /*---------------------------------------------------------------------------*
138 Name: CARD_IsAvailable
139
140 Description: Determines whether the CARD library can be used.
141
142 Arguments: None.
143
144 Returns: If the CARD_Init function is already called, TRUE.
145 *---------------------------------------------------------------------------*/
CARD_IsAvailable(void)146 BOOL CARD_IsAvailable(void)
147 {
148 CARDiCommon *const p = &cardi_common;
149 return (p->flag != 0);
150 }
151
152 /*---------------------------------------------------------------------------*
153 Name: CARD_IsEnabled
154
155 Description: Determines whether the card can be accessed.
156
157 Arguments: None.
158
159 Returns: If the system has access rights to the card, TRUE.
160 *---------------------------------------------------------------------------*/
CARD_IsEnabled(void)161 BOOL CARD_IsEnabled(void)
162 {
163 return CARDi_EnableFlag;
164 }
165
166 /*---------------------------------------------------------------------------*
167 Name: CARD_CheckEnabled
168
169 Description: Determines whether the system has access rights to the card. If no, stop forcibly.
170
171 Arguments: None.
172
173 Returns: None.
174 *---------------------------------------------------------------------------*/
CARD_CheckEnabled(void)175 void CARD_CheckEnabled(void)
176 {
177 if (!CARD_IsEnabled())
178 {
179 OS_Panic("NITRO-CARD permission denied");
180 }
181 }
182
183 /*---------------------------------------------------------------------------*
184 Name: CARD_Enable
185
186 Description: Sets the access rights to the card.
187
188 Arguments: enable: If the system has access rights, TRUE
189
190 Returns: None.
191 *---------------------------------------------------------------------------*/
CARD_Enable(BOOL enable)192 void CARD_Enable(BOOL enable)
193 {
194 CARDi_EnableFlag = enable;
195 }
196
197 /*---------------------------------------------------------------------------*
198 Name: CARD_GetThreadPriority
199
200 Description: Get priority of asynchronous processing thread in the library.
201
202 Arguments: None.
203
204 Returns: Internal thread priority.
205 *---------------------------------------------------------------------------*/
CARD_GetThreadPriority(void)206 u32 CARD_GetThreadPriority(void)
207 {
208 CARDiCommon *const p = &cardi_common;
209 SDK_ASSERT(CARD_IsAvailable());
210
211 return p->priority;
212 }
213
214 /*---------------------------------------------------------------------------*
215 Name: CARD_SetThreadPriority
216
217 Description: Set priority of asynchronous processing thread in the library.
218
219 Arguments: None.
220
221 Returns: Priority of internal thread before setting.
222 *---------------------------------------------------------------------------*/
CARD_SetThreadPriority(u32 prior)223 u32 CARD_SetThreadPriority(u32 prior)
224 {
225 CARDiCommon *const p = &cardi_common;
226 SDK_ASSERT(CARD_IsAvailable());
227
228 {
229 OSIntrMode bak_psr = OS_DisableInterrupts();
230 u32 ret = p->priority;
231 SDK_ASSERT((prior >= OS_THREAD_PRIORITY_MIN) && (prior <= OS_THREAD_PRIORITY_MAX));
232 p->priority = prior;
233 (void)OS_SetThreadPriority(p->thread.context, p->priority);
234 (void)OS_RestoreInterrupts(bak_psr);
235 return ret;
236 }
237 }
238
239 /*---------------------------------------------------------------------------*
240 Name: CARD_GetResultCode
241
242 Description: Gets the result of a CARD function called last.
243
244 Arguments: None.
245
246 Returns: The result of the CARD function called last.
247 *---------------------------------------------------------------------------*/
CARD_GetResultCode(void)248 CARDResult CARD_GetResultCode(void)
249 {
250 CARDiCommon *const p = &cardi_common;
251 SDK_ASSERT(CARD_IsAvailable());
252
253 return p->cmd->result;
254 }
255
256 /*---------------------------------------------------------------------------*
257 Name: CARD_GetRomHeader
258
259 Description: Get ROM header information for currently inserted card.
260
261 Arguments: None.
262
263 Returns: Pointer to the CARDRomHeader structure.
264 *---------------------------------------------------------------------------*/
CARD_GetRomHeader(void)265 const u8 *CARD_GetRomHeader(void)
266 {
267 return (const u8 *)HW_CARD_ROM_HEADER;
268 }
269
270 /*---------------------------------------------------------------------------*
271 Name: CARD_GetOwnRomHeader
272
273 Description: Gets the ROM header information of the program that is currently running.
274
275 Arguments: None.
276
277 Returns: Pointer to the CARDRomHeader structure.
278 *---------------------------------------------------------------------------*/
CARD_GetOwnRomHeader(void)279 const CARDRomHeader *CARD_GetOwnRomHeader(void)
280 {
281 return (const CARDRomHeader *)HW_ROM_HEADER_BUF;
282 }
283
284 #if defined(SDK_TWL)
285
286 /*---------------------------------------------------------------------------*
287 Name: CARD_GetOwnRomHeaderTWL
288
289 Description: Gets the TWL-ROM header information of the program that is currently running.
290
291 Arguments: None.
292
293 Returns: Pointer to the CARDRomHeaderTWL structure.
294 *---------------------------------------------------------------------------*/
CARD_GetOwnRomHeaderTWL(void)295 const CARDRomHeaderTWL *CARD_GetOwnRomHeaderTWL(void)
296 {
297 return (const CARDRomHeaderTWL *)HW_TWL_ROM_HEADER_BUF;
298 }
299
300 #endif // SDK_TWL
301
302 /*---------------------------------------------------------------------------*
303 Name: CARD_GetCacheFlushThreshold
304
305 Description: Gets the threshold that determines whether the entire cache will be flushed, or just a portion of it.
306
307 Arguments: icache: Pointer to the location at which the instruction cache flush threshold should be stored.
308 Ignore if NULL.
309 dcache: Pointer to the location at which the data cache flush threshold should be stored.
310 Ignore if NULL.
311
312 Returns: None.
313 *---------------------------------------------------------------------------*/
CARD_GetCacheFlushThreshold(u32 * icache,u32 * dcache)314 void CARD_GetCacheFlushThreshold(u32 *icache, u32 *dcache)
315 {
316 #if defined(SDK_ARM9)
317 SDK_ASSERT(CARD_IsAvailable());
318 if (icache)
319 {
320 *icache = cardi_common.flush_threshold_ic;
321 }
322 if (dcache)
323 {
324 *dcache = cardi_common.flush_threshold_dc;
325 }
326 #else
327 (void)icache;
328 (void)dcache;
329 #endif
330 }
331
332 /*---------------------------------------------------------------------------*
333 Name: CARD_SetCacheFlushThreshold
334
335 Description: Sets the threshold that determines whether the entire cache will be flushed, or just a portion of it.
336
337 Arguments: icache: The instruction cache flush threshold
338 dcache: The data cache flush threshold
339
340 Returns: None.
341 *---------------------------------------------------------------------------*/
CARD_SetCacheFlushThreshold(u32 icache,u32 dcache)342 void CARD_SetCacheFlushThreshold(u32 icache, u32 dcache)
343 {
344 #if defined(SDK_ARM9)
345 SDK_ASSERT(CARD_IsAvailable());
346 cardi_common.flush_threshold_ic = icache;
347 cardi_common.flush_threshold_dc = dcache;
348 #else
349 (void)icache;
350 (void)dcache;
351 #endif
352 }
353
354 /*---------------------------------------------------------------------------*
355 Name: CARD_LockRom
356
357 Description: Locks card bus for accessing ROM.
358
359 Arguments: Lock id
360
361 Returns: None.
362 *---------------------------------------------------------------------------*/
CARD_LockRom(u16 lock_id)363 void CARD_LockRom(u16 lock_id)
364 {
365 SDK_ASSERT(CARD_IsAvailable());
366
367 /* Lock the resource */
368 CARDi_LockResource(lock_id, CARD_TARGET_ROM);
369 /* Lock the card bus */
370 {
371 // If the ARM7 processor is locked, use the lightest V-Count alarm to sleep because the CPU will be blocked for a long time
372 //
373 #define CARD_USING_SLEEPY_LOCK
374 #ifdef CARD_USING_SLEEPY_LOCK
375 CARDEventListener el[1];
376 CARDi_InitEventListener(el);
377 CARDi_SetEventListener(el, CARDi_LockBusCondition, &lock_id);
378 CARDi_WaitForEvent(el);
379 #else
380 // If operations have been verified, this is unnecessary
381 (void)OS_LockCard(lock_id);
382 #endif
383 }
384 }
385
386 /*---------------------------------------------------------------------------*
387 Name: CARD_UnlockRom
388
389 Description: Frees the locked card bus.
390
391 Arguments: Lock id that is used by CARD_LockRom
392
393 Returns: None.
394 *---------------------------------------------------------------------------*/
CARD_UnlockRom(u16 lock_id)395 void CARD_UnlockRom(u16 lock_id)
396 {
397 SDK_ASSERT(CARD_IsAvailable());
398 SDK_ASSERT(cardi_common.lock_target == CARD_TARGET_ROM);
399
400 /* Unlock the card bus */
401 {
402 (void)OS_UnlockCard(lock_id);
403 }
404 /* Unlock the resource */
405 CARDi_UnlockResource(lock_id, CARD_TARGET_ROM);
406
407 }
408
409 /*---------------------------------------------------------------------------*
410 Name: CARD_LockBackup
411
412 Description: Locks the card bus for backup device access.
413
414 Arguments: lock_id: Exclusive control ID aassigned by the OS_GetLockID function
415
416 Returns: None.
417 *---------------------------------------------------------------------------*/
CARD_LockBackup(u16 lock_id)418 void CARD_LockBackup(u16 lock_id)
419 {
420 SDK_ASSERT(CARD_IsAvailable());
421
422 /* Take exclusive control of ROM/backup in processor */
423 CARDi_LockResource(lock_id, CARD_TARGET_BACKUP);
424 /* ARM7 always accesses */
425 #if defined(SDK_ARM7)
426 (void)OS_LockCard(lock_id);
427 #endif
428 }
429
430 /*---------------------------------------------------------------------------*
431 Name: CARD_UnlockBackup
432
433 Description: Frees the locked card bus for backup device access.
434
435 Arguments: lock_id: Exclusive control ID used by the CARD_LockBackup function
436
437 Returns: None.
438 *---------------------------------------------------------------------------*/
CARD_UnlockBackup(u16 lock_id)439 void CARD_UnlockBackup(u16 lock_id)
440 {
441 SDK_ASSERT(CARD_IsAvailable());
442 SDK_ASSERT(cardi_common.lock_target == CARD_TARGET_BACKUP);
443
444 #if defined(SDK_ARM9)
445 /* Blocking if an attempt is made to deallocate a bus while an asynchronous process is running */
446 if (!CARD_TryWaitBackupAsync())
447 {
448 OS_TWarning("called CARD_UnlockBackup() during backup asynchronous operation. (force to wait)\n");
449 (void)CARD_WaitBackupAsync();
450 }
451 #endif // defined(SDK_ARM9)
452
453 /* ARM7 always accesses */
454 #if defined(SDK_ARM7)
455 (void)OS_UnlockCard(lock_id);
456 #endif
457 /* Unlock the resource */
458 CARDi_UnlockResource(lock_id, CARD_TARGET_BACKUP);
459 }
460