1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - CTRDG - libraries - ARM9
3   File:     ctrdg_proc.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:: 2007-11-15#$
14   $Rev: 2414 $
15   $Author: hatamoto_minoru $
16  *---------------------------------------------------------------------------*/
17 #include <nitro.h>
18 #include <../include/ctrdg_work.h>
19 
20 extern void CTRDGi_InitCommon(void);
21 extern void CTRDGi_SendtoPxi(u32 data);
22 
23 //---- PXI callbacks
24 static void CTRDGi_CallbackForInitModuleInfo(PXIFifoTag tag, u32 data, BOOL err);
25 static void CTRDGi_PulledOutCallback(PXIFifoTag tag, u32 data, BOOL err);
26 static void CTRDGi_CallbackForSetPhi(PXIFifoTag tag, u32 data, BOOL err);
27 
28 extern CTRDGWork CTRDGi_Work;
29 
30 //---- Lock for pxi
31 static int CTRDGi_Lock = FALSE;
32 
33 //---- User callback
34 CTRDGPulledOutCallback CTRDG_UserCallback = NULL;
35 
36 /* Game Pak removal callback is not called twice */
37 static BOOL isCartridgePullOut = FALSE;
38 static BOOL skipCheck = FALSE;
39 static BOOL ctrdg_already_pullout = FALSE;
40 
41 #ifndef SDK_TWLLTD
42 //---- initialized flag
43 static BOOL isInitialized = FALSE;
44 #endif
45 
46 //================================================================================
47 //            INIT
48 //================================================================================
49 /*---------------------------------------------------------------------------*
50   Name:         CTRDGi_IsInitialized
51 
52   Description:  check weather ctrdg library is initialized
53                 (for internal use)
54 
55   Arguments:    None
56 
57   Returns:      TRUE ... initialized already
58                 FALSE... not initialized
59  *---------------------------------------------------------------------------*/
60 #ifndef SDK_TWLLTD
CTRDGi_IsInitialized(void)61 BOOL CTRDGi_IsInitialized(void)
62 {
63     return isInitialized;
64 }
65 #endif
66 
67 /*---------------------------------------------------------------------------*
68   Name:         CTRDG_Init
69 
70   Description:  initialize cartridge functions
71 
72   Arguments:    None
73 
74   Returns:      None
75  *---------------------------------------------------------------------------*/
76 #ifndef SDK_TWLLTD
CTRDG_Init(void)77 SDK_WEAK_SYMBOL void CTRDG_Init(void)
78 {
79     if (isInitialized)
80     {
81         return;
82     }
83     isInitialized = TRUE;
84 
85     CTRDGi_InitCommon();
86 
87     /* So that the Game Pak removal callback cannot be called two or more times */
88     ctrdg_already_pullout = FALSE;
89 
90 #ifndef SDK_SMALL_BUILD
91     //---- Setting PXI
92     PXI_Init();
93     while (!PXI_IsCallbackReady(PXI_FIFO_TAG_CTRDG, PXI_PROC_ARM7))
94     {
95     }
96     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG, CTRDGi_CallbackForInitModuleInfo);
97 
98     CTRDGi_InitModuleInfo();
99 
100     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG, NULL);  // To avoid warning by overriding
101     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG, CTRDGi_PulledOutCallback);
102 
103     //---- Init user callback
104     CTRDG_UserCallback = NULL;
105 
106     // Create a TaskThread to use the asynchronous version of the AGBBackup access function
107     {
108         static CTRDGiTaskWork CTRDGTaskList;
109         CTRDGi_InitTaskThread(&CTRDGTaskList);
110     }
111 
112     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG_PHI, CTRDGi_CallbackForSetPhi);
113 
114     /*
115      * Access is disabled, as long as the user has not explicitly specified 'enable'.
116      * (If it is not an option Game Pak, writing is also not allowed)
117      */
118 #if defined(SDK_ARM9)
119     CTRDG_Enable(FALSE);
120 #endif
121 #endif // SDK_SMALL_BUILD
122 }
123 #endif // SDK_TWLLTD
124 
125 /*---------------------------------------------------------------------------*
126   Name:         CTRDGi_InitModuleInfo
127 
128   Description:  Initialize the information of peripheral device around cartridge.
129 
130                 Because try lock cartridge, in case another processor had locked,
131                 wait until it was released.
132 
133                 To avoid other bus master interrupts,
134                 DMA1 is used for accessing cartridge.
135                 This is a compatibility in future.
136 
137   Arguments:    None.
138 
139   Returns:      None.
140  *---------------------------------------------------------------------------*/
141 static CTRDGHeader headerBuf ATTRIBUTE_ALIGN(32);
142 
CTRDGi_InitModuleInfo(void)143 void CTRDGi_InitModuleInfo(void)
144 {
145 #ifndef SDK_SMALL_BUILD
146 
147     static BOOL isInfoInitialized;
148     CTRDGLockByProc lockInfo;
149     OSIrqMask lastIE;
150     BOOL    lastIME;
151 
152     if (isInfoInitialized)
153     {
154         return;
155     }
156     isInfoInitialized = TRUE;
157 
158     if (!(reg_OS_PAUSE & REG_OS_PAUSE_CHK_MASK))
159     {
160         return;
161     }
162 
163     lastIE = OS_SetIrqMask(OS_IE_SPFIFO_RECV);
164     lastIME = OS_EnableIrq();
165 
166     //---- Get privilege for accessing cartridge
167     CTRDGi_LockByProcessor(CTRDGi_Work.lockID, &lockInfo);
168 
169     //---- Read information of peripheral devices
170     {
171         MIProcessor proc = MI_GetMainMemoryPriority();
172         CTRDGRomCycle rc;
173 
174         // Set the latest access cycle
175         CTRDGi_ChangeLatestAccessCycle(&rc);
176 
177         // Set main memory priority for avoiding DMA stole by ARM7 access
178         MI_SetMainMemoryPriority(MI_PROCESSOR_ARM9);
179 
180         // 16-bit access to have much enough access interval
181         DC_InvalidateRange(&((u8 *)&headerBuf)[0x80], sizeof(headerBuf) - 0x80);
182         MI_DmaCopy16(1, (void *)(HW_CTRDG_ROM + 0x80),
183                      &((u8 *)&headerBuf)[0x80], sizeof(headerBuf) - 0x80);
184 
185         // Restore main memory priority
186         MI_SetMainMemoryPriority(proc);
187 
188         // Restore access cycle
189         CTRDGi_RestoreAccessCycle(&rc);
190     }
191 
192     //---- Release privilege for accessing Game Pak
193     CTRDGi_UnlockByProcessor(CTRDGi_Work.lockID, &lockInfo);
194 
195     // Update Game Pak data only if a Game Pak was inserted during the previous check or if a software reset has not even been executed once
196     //
197     if ((*(u8 *)HW_IS_CTRDG_EXIST) || !(*(u8 *)HW_SET_CTRDG_MODULE_INFO_ONCE))
198     {
199         //---- Copy the information of peripheral devices to system area
200         int     i;
201         CTRDGHeader *chb = &headerBuf;
202         CTRDGModuleInfo *cip = CTRDGi_GetModuleInfoAddr();
203 
204         cip->moduleID.raw = chb->moduleID;
205         for (i = 0; i < 3; i++)
206         {
207             cip->exLsiID[i] = chb->exLsiID[i];
208         }
209         cip->makerCode = chb->makerCode;
210         cip->gameCode = chb->gameCode;
211 
212         // Check whether or not a Game Pak is inserted
213         *(u8 *)HW_IS_CTRDG_EXIST = (u8)((CTRDG_IsExisting())? 1 : 0);
214         // TRUE if the Game Pak information has been updated even once
215         (*(u8 *)HW_SET_CTRDG_MODULE_INFO_ONCE) = TRUE;
216     }
217 
218     //---- Copy Nintendo logo data in the ARM9 system ROM to main memory
219     MI_CpuCopy32((void *)CTRDG_SYSROM9_NINLOGO_ADR, &headerBuf.nintendoLogo,
220                  sizeof(headerBuf.nintendoLogo));
221     DC_FlushAll();
222 
223     //---- Send message to ARM7
224     CTRDGi_SendtoPxi(CTRDG_PXI_COMMAND_INIT_MODULE_INFO |
225                      (((u32)&headerBuf - HW_MAIN_MEM) >> 5) << CTRDG_PXI_COMMAND_PARAM_SHIFT);
226 
227     //---- Wait until ARM7 finishes initializing
228     while (CTRDGi_Work.subpInitialized != TRUE)
229     {
230         SVC_WaitByLoop(1);
231     }
232 
233     (void)OS_RestoreIrq(lastIME);
234     (void)OS_SetIrqMask(lastIE);
235 
236 #endif // SDK_SMALL_BUILD
237 }
238 
239 /*---------------------------------------------------------------------------*
240   Name:         CTRDGi_CallbackForInitModuleInfo
241 
242   Description:  Callback to receive data from PXI.
243 
244   Arguments:    tag: Tag from PXI (unused)
245                 data: Data from PXI
246                 err: Error bit (unused)
247 
248   Returns:      None.
249  *---------------------------------------------------------------------------*/
CTRDGi_CallbackForInitModuleInfo(PXIFifoTag tag,u32 data,BOOL err)250 static void CTRDGi_CallbackForInitModuleInfo(PXIFifoTag tag, u32 data, BOOL err)
251 {
252 #pragma unused( tag, err )
253 
254     if ((data & CTRDG_PXI_COMMAND_MASK) == CTRDG_PXI_COMMAND_INIT_MODULE_INFO)
255     {
256         CTRDGi_Work.subpInitialized = TRUE;
257     }
258     else
259     {
260 #ifndef SDK_FINALROM
261         OS_Panic("illegal Cartridge pxi command.");
262 #else
263         OS_Panic("");
264 #endif
265     }
266 }
267 
268 /*---------------------------------------------------------------------------*
269   Name:         CTRDG_DummyInit
270 
271   Description:  Initialize for smaller CTRDG.
272                 Called from user defined CTRDG_Init.
273 
274   Arguments:    None
275 
276   Returns:      None
277  *---------------------------------------------------------------------------*/
278 #ifndef SDK_TWLLTD
279 static void CTRDGi_DummyCallback(PXIFifoTag tag, u32 data, BOOL err);
CTRDG_DummyInit(void)280 void CTRDG_DummyInit(void)
281 {
282     CTRDGi_InitCommon();
283 
284     //---- set dummy callback
285     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG, NULL);  // to avoid warning by overriding
286     PXI_SetFifoRecvCallback(PXI_FIFO_TAG_CTRDG, CTRDGi_DummyCallback);
287 
288     //---- send INIT_MODULE_INFO for sync with ARM7
289     CTRDGi_SendtoPxi(CTRDG_PXI_COMMAND_INIT_MODULE_INFO);
290 }
291 
292 //---- dummy callback for smaller CTRDG.
CTRDGi_DummyCallback(PXIFifoTag tag,u32 data,BOOL err)293 static void CTRDGi_DummyCallback(PXIFifoTag tag, u32 data, BOOL err)
294 {
295 #pragma unused( tag, data, err )
296     // do nothing
297 }
298 #endif // ifndef SDK_TWLLTD
299 
300 //================================================================================
301 //            PULLOUT PROCS
302 //================================================================================
303 /*---------------------------------------------------------------------------*
304   Name:         CTRDGi_PulledOutCallback
305 
306   Description:  Callback to receive data from PXI.
307 
308   Arguments:    tag: Tag from PXI (unused)
309                 data: Data from PXI
310                 err: Error bit (unused)
311 
312   Returns:      None.
313  *---------------------------------------------------------------------------*/
CTRDGi_PulledOutCallback(PXIFifoTag tag,u32 data,BOOL err)314 static void CTRDGi_PulledOutCallback(PXIFifoTag tag, u32 data, BOOL err)
315 {
316 #pragma unused( tag, err )
317 
318     //---- Receive message 'pulled out'
319     if ((data & CTRDG_PXI_COMMAND_MASK) == CTRDG_PXI_COMMAND_PULLED_OUT)
320     {
321         if (ctrdg_already_pullout == FALSE)
322         {
323             BOOL    isTerminateImm = FALSE;
324 
325             //---- Call user callback
326             if (CTRDG_UserCallback)
327             {
328                 isTerminateImm = CTRDG_UserCallback();
329             }
330 
331             //---- Terminate
332             if (isTerminateImm)
333             {
334                 CTRDG_TerminateForPulledOut();
335             }
336             /* If called once, it is not called again */
337             ctrdg_already_pullout = TRUE;
338         }
339     }
340     else
341     {
342 #ifndef SDK_FINALROM
343         OS_Panic("illegal Cartridge pxi command.");
344 #else
345         OS_Panic("");
346 #endif
347     }
348 }
349 
350 /*---------------------------------------------------------------------------*
351   Name:         CTRDG_SetPulledOutCallback
352 
353   Description:  Set user callback for being pulled-out Game Pak.
354 
355   Arguments:    callback: Callback
356 
357   Returns:      None.
358  *---------------------------------------------------------------------------*/
CTRDG_SetPulledOutCallback(CTRDGPulledOutCallback callback)359 void CTRDG_SetPulledOutCallback(CTRDGPulledOutCallback callback)
360 {
361 #ifndef SDK_TWLLTD
362     SDK_ASSERT(CTRDGi_IsInitialized());
363 #endif
364     CTRDG_UserCallback = callback;
365 }
366 
367 /*---------------------------------------------------------------------------*
368   Name:         CTRDG_TerminateForPulledOut
369 
370   Description:  Terminate for pulling out Game Pak.
371                 Send message to do termination to ARM7.
372 
373   Arguments:    None.
374 
375   Returns:      None.
376  *---------------------------------------------------------------------------*/
CTRDG_TerminateForPulledOut(void)377 void CTRDG_TerminateForPulledOut(void)
378 {
379 #ifndef SDK_TWLLTD
380     SDK_ASSERT(CTRDGi_IsInitialized());
381 #endif
382 
383     //---- Send 'TERMINATE' command to ARM7 and terminate itself immediately
384     CTRDGi_SendtoPxi(CTRDG_PXI_COMMAND_TERMINATE);
385 
386     OS_Terminate();
387 }
388 
389 /*---------------------------------------------------------------------------*
390   Name:         CTRDG_SendToARM7
391 
392   Description:  Send data to ARM7.
393 
394   Arguments:    arg: Data to send
395 
396   Returns:      None.
397  *---------------------------------------------------------------------------*/
CTRDG_SendToARM7(void * arg)398 void CTRDG_SendToARM7(void *arg)
399 {
400     (void)PXI_SendWordByFifo(PXI_FIFO_TAG_CTRDG_Ex, (u32)arg, FALSE);
401 }
402 
403 /*---------------------------------------------------------------------------*
404   Name:         CTRDG_CheckPulledOut
405 
406   Description:  Game Pak is pulled out.
407 
408   Arguments:    None.
409 
410   Returns:      None.
411  *---------------------------------------------------------------------------*/
CTRDG_CheckPulledOut(void)412 void CTRDG_CheckPulledOut(void)
413 {
414 #ifndef SDK_TWLLTD
415     SDK_ASSERT(CTRDGi_IsInitialized());
416 #endif
417 
418     //---- If skip flag or Game Pak already pulled out.
419     if (skipCheck || isCartridgePullOut)
420     {
421         return;
422     }
423 
424     //---------------- Check Game Pak pulled out
425     //---- Check Game Pak
426     isCartridgePullOut = CTRDG_IsPulledOut();
427 
428     //---- If no Game Pak...
429     if (!CTRDG_IsExisting())
430     {
431         if (!isCartridgePullOut)
432         {
433             skipCheck = TRUE;
434             return;
435         }
436     }
437 
438     //---------------- If Game Pak pulled out, tell that to ARM9
439     if (isCartridgePullOut)
440     {
441         /* Call in the same way as functions that are called by PXI from ARM7. */
442         /* Arguments forcibly set to those used when processing occurs. */
443         CTRDGi_PulledOutCallback(PXI_FIFO_TAG_CTRDG, CTRDG_PXI_COMMAND_PULLED_OUT, NULL);
444     }
445 }
446 
447 /*---------------------------------------------------------------------------*
448   Name:         CTRDG_SetPhiClock
449 
450   Description:  Set ARM9 and ARM7 PHI output clock.
451 
452   Arguments:    clock:    PHI clock to set (MIPhiClock value)
453 
454   Returns:      None.
455  *---------------------------------------------------------------------------*/
CTRDG_SetPhiClock(CTRDGPhiClock clock)456 void CTRDG_SetPhiClock(CTRDGPhiClock clock)
457 {
458     u32     data = ((u32)clock << CTRDG_PXI_COMMAND_PARAM_SHIFT) | CTRDG_PXI_COMMAND_SET_PHI;
459 
460 #ifndef SDK_TWLLTD
461     SDK_ASSERT(CTRDGi_IsInitialized());
462 #endif
463 
464     //---- Check parameter range
465     SDK_ASSERT((u32)clock <= CTRDG_PHI_CLOCK_16MHZ);
466 
467     //---- Set ARM9 PHI output clock
468     MIi_SetPhiClock((MIiPhiClock) clock);
469 
470     //---- Send command to set ARM7 phi clock
471     CTRDGi_Lock = TRUE;
472     while (PXI_SendWordByFifo(PXI_FIFO_TAG_CTRDG_PHI, data, FALSE) != PXI_FIFO_SUCCESS)
473     {
474         SVC_WaitByLoop(1);
475     }
476 
477     //---- Wait response
478     while (CTRDGi_Lock)
479     {
480         SVC_WaitByLoop(1);
481     }
482 }
483 
484 /*---------------------------------------------------------------------------*
485   Name:         CTRDG_CallbackForSetPhi
486 
487   Description:  Callback from ARM7 to receive PHI clock setting.
488 
489   Arguments:    tag: Tag from PXI (unused)
490                 data: Data from PXI
491                 err: Error bit (unused)
492 
493   Returns:      None.
494  *---------------------------------------------------------------------------*/
CTRDGi_CallbackForSetPhi(PXIFifoTag tag,u32 data,BOOL err)495 static void CTRDGi_CallbackForSetPhi(PXIFifoTag tag, u32 data, BOOL err)
496 {
497 #pragma unused(tag, data, err)
498     CTRDGi_Lock = FALSE;
499 }
500