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