1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WVR - libraries
3   File:     wvr.c
4 
5   Copyright 2003-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-09-18#$
14   $Rev: 8573 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include    <nitro/wvr/common/wvr_common.h>
19 #include    <nitro/wvr/ARM9/wvr.h>
20 #include    <nitro/pxi.h>
21 #include    <nitro/os/ARM9/vramExclusive.h>
22 #include    <nitro/gx/gx_vramcnt.h>
23 #include    <nitro/wm.h>
24 
25 
26 /*---------------------------------------------------------------------------*
27     Internal Function Definitions
28  *---------------------------------------------------------------------------*/
29 static void WvrReceiveCallback(PXIFifoTag tag, u32 data, BOOL err);
30 static void WvrDummyAsyncCallback(void *arg, WVRResult result);
31 
32 
33 /*---------------------------------------------------------------------------*
34     Internal Variable Definitions
35  *---------------------------------------------------------------------------*/
36 static WVRCallbackFunc wvrCallback = NULL;
37 static void *wvrArg = NULL;
38 static vu16 wvrVRam = 0;
39 static vu16 wvrLockId = 0;
40 
41 
42 /*---------------------------------------------------------------------------*
43   Name:         WVR_StartUpAsync
44 
45   Description:  Starts operations of the wireless library.
46                 Until forcibly stopped, access to the specified VRAM (C or D) is prohibited.
47 
48   Arguments:    vram:           Specifies VRAM bank allocated to ARM7.
49                 callback:       Specifies the callback function for when processing completes.
50                 arg:            Specifies arguments passed to the callback function.
51 
52   Returns:      Returns the processing result.
53  *---------------------------------------------------------------------------*/
WVR_StartUpAsync(GXVRamARM7 vram,WVRCallbackFunc callback,void * arg)54 WVRResult WVR_StartUpAsync(GXVRamARM7 vram, WVRCallbackFunc callback, void *arg)
55 {
56     OSIntrMode e;
57 
58     // Check whether component supports WVR
59     PXI_Init();
60     if (!PXI_IsCallbackReady(PXI_FIFO_TAG_WVR, PXI_PROC_ARM7))
61     {
62         return WVR_RESULT_DISABLE;
63     }
64 
65     // If an ID for exclusion has not been obtained, do so
66     while (wvrLockId == 0)
67     {
68         s32     result = OS_GetLockID();
69 
70         if (result == OS_LOCK_ID_ERROR)
71         {
72             return WVR_RESULT_FATAL_ERROR;
73         }
74         wvrLockId = (u16)result;
75     }
76 
77     // Disable interrupts
78     e = OS_DisableInterrupts();
79 
80     // Check if a WVR asynchronous function is not running
81     if (wvrCallback != NULL)
82     {
83         (void)OS_RestoreInterrupts(e);
84         return WVR_RESULT_ILLEGAL_STATUS;
85     }
86 
87     // Check the VRAM exclusive state
88     if (wvrVRam)
89     {
90         // Already made exclusive
91         (void)OS_RestoreInterrupts(e);
92         return WVR_RESULT_ILLEGAL_STATUS;
93     }
94     switch (vram)
95     {
96     case GX_VRAM_ARM7_128_C:
97         // Exclusively lock VRAM-C
98         if (!OSi_TryLockVram(OS_VRAM_BANK_ID_C, wvrLockId))
99         {
100             // Lock on VRAM-C fails
101             (void)OS_RestoreInterrupts(e);
102             return WVR_RESULT_VRAM_LOCKED;
103         }
104         wvrVRam = OS_VRAM_BANK_ID_C;
105         // Register setting process corresponding to GX_SetBankForARM7( GX_VRAM_ARM7_128_C )
106         reg_GX_VRAMCNT_C = ((2 << REG_GX_VRAMCNT_C_MST_SHIFT) |
107                             (0 << REG_GX_VRAMCNT_C_OFS_SHIFT) | (1 << REG_GX_VRAMCNT_C_E_SHIFT));
108         break;
109     case GX_VRAM_ARM7_128_D:
110         // Exclusively lock VRAM-D
111         if (!OSi_TryLockVram(OS_VRAM_BANK_ID_D, wvrLockId))
112         {
113             // Lock on VRAM-D fails
114             (void)OS_RestoreInterrupts(e);
115             return WVR_RESULT_VRAM_LOCKED;
116         }
117         wvrVRam = OS_VRAM_BANK_ID_D;
118         // Register setting process corresponding to GX_SetBankForARM7( GX_VRAM_ARM7_128_D )
119         reg_GX_VRAMCNT_D = ((2 << REG_GX_VRAMCNT_D_MST_SHIFT) |
120                             (0 << REG_GX_VRAMCNT_D_OFS_SHIFT) | (1 << REG_GX_VRAMCNT_D_E_SHIFT));
121         break;
122     case GX_VRAM_ARM7_256_CD:
123         // Exclusively lock VRAM-C/D
124         if (!OSi_TryLockVram((OS_VRAM_BANK_ID_C | OS_VRAM_BANK_ID_D), wvrLockId))
125         {
126             // Locks on VRAM-C/D fail
127             (void)OS_RestoreInterrupts(e);
128             return WVR_RESULT_VRAM_LOCKED;
129         }
130         wvrVRam = OS_VRAM_BANK_ID_C | OS_VRAM_BANK_ID_D;
131         // Register setting process that corresponds to GX_SetBankForARM7( GX_VRAM_ARM7_256_CD )
132         reg_GX_VRAMCNT_C = ((2 << REG_GX_VRAMCNT_C_MST_SHIFT) |
133                             (0 << REG_GX_VRAMCNT_C_OFS_SHIFT) | (1 << REG_GX_VRAMCNT_C_E_SHIFT));
134         reg_GX_VRAMCNT_D = ((2 << REG_GX_VRAMCNT_D_MST_SHIFT) |
135                             (1 << REG_GX_VRAMCNT_D_OFS_SHIFT) | (1 << REG_GX_VRAMCNT_D_E_SHIFT));
136         break;
137     default:
138         (void)OS_RestoreInterrupts(e);
139         return WVR_RESULT_INVALID_PARAM;
140     }
141 
142     // Set the PXI callback function
143     if (!PXI_IsCallbackReady(PXI_FIFO_TAG_WVR, PXI_PROC_ARM9))
144     {
145         PXI_SetFifoRecvCallback(PXI_FIFO_TAG_WVR, WvrReceiveCallback);
146     }
147 
148     // Save the callback function
149     if (callback == NULL)
150     {
151         wvrCallback = WvrDummyAsyncCallback;
152     }
153     else
154     {
155         wvrCallback = callback;
156     }
157     wvrArg = arg;
158 
159     // Notify of StartUp via PXI
160     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_WVR, WVR_PXI_COMMAND_STARTUP, FALSE))
161     {
162         // Unlocks VRAM that had temporarily been exclusively locked
163         OSi_UnlockVram(wvrVRam, wvrLockId);
164         wvrVRam = 0;
165         wvrCallback = NULL;
166         (void)OS_RestoreInterrupts(e);
167         return WVR_RESULT_FIFO_ERROR;
168     }
169 
170     // Start/end asynchronous processing normally
171     (void)OS_RestoreInterrupts(e);
172     return WVR_RESULT_OPERATING;
173 }
174 
175 /*---------------------------------------------------------------------------*
176   Name:         WVR_TerminateAsync
177 
178   Description:  Forcibly stops operations of the wireless library.
179                 Access to VRAM (C or D) is permitted after asynchronous processing is completed.
180 
181   Arguments:    callback:       Specifies the callback function for when processing completes.
182                 arg:            Specifies arguments passed to the callback function.
183 
184   Returns:      Returns the processing result.
185  *---------------------------------------------------------------------------*/
WVR_TerminateAsync(WVRCallbackFunc callback,void * arg)186 WVRResult WVR_TerminateAsync(WVRCallbackFunc callback, void *arg)
187 {
188     OSIntrMode e;
189 
190     // Check component compatibility
191     PXI_Init();
192     if (!PXI_IsCallbackReady(PXI_FIFO_TAG_WVR, PXI_PROC_ARM7))
193     {
194         return WVR_RESULT_DISABLE;
195     }
196 
197     // Disable interrupts
198     e = OS_DisableInterrupts();
199 
200     // Check if a WVR asynchronous function is not running
201     if (wvrCallback != NULL)
202     {
203         (void)OS_RestoreInterrupts(e);
204         return WVR_RESULT_ILLEGAL_STATUS;
205     }
206 
207     // Set the PXI callback function
208     if (!PXI_IsCallbackReady(PXI_FIFO_TAG_WVR, PXI_PROC_ARM9))
209     {
210         PXI_SetFifoRecvCallback(PXI_FIFO_TAG_WVR, WvrReceiveCallback);
211     }
212 
213     // Save the callback function
214     if (callback == NULL)
215     {
216         wvrCallback = WvrDummyAsyncCallback;
217     }
218     else
219     {
220         wvrCallback = callback;
221     }
222     wvrArg = arg;
223 
224     // Notify of Terminate via PXI
225     if (0 > PXI_SendWordByFifo(PXI_FIFO_TAG_WVR, WVR_PXI_COMMAND_TERMINATE, FALSE))
226     {
227         wvrCallback = NULL;
228         (void)OS_RestoreInterrupts(e);
229         return WVR_RESULT_FIFO_ERROR;
230     }
231 
232     // Start/end asynchronous processing normally
233     (void)OS_RestoreInterrupts(e);
234     return WVR_RESULT_OPERATING;
235 }
236 
237 /*---------------------------------------------------------------------------*
238   Name:         WvrReceiveCallback
239 
240   Description:  Receives a callback from ARM7 via FIFO.
241 
242   Arguments:    tag:           Not used.
243                 data:          Data received from ARM7.
244                 err:           Not used.
245 
246   Returns:      None.
247  *---------------------------------------------------------------------------*/
WvrReceiveCallback(PXIFifoTag tag,u32 data,BOOL err)248 static void WvrReceiveCallback(PXIFifoTag tag, u32 data, BOOL err)
249 {
250 #pragma unused( tag , err )
251 
252     WVRCallbackFunc cb = wvrCallback;
253     void   *cbArg = wvrArg;
254     WVRResult result = (WVRResult)(data & 0x000000ff);
255 
256     // Sort processing according to command type
257     switch (data & 0xffff0000)
258     {
259     case WVR_PXI_COMMAND_STARTUP:
260         switch (result)
261         {
262         case WVR_RESULT_FATAL_ERROR:
263             // Unlock VRAM
264             if ((wvrVRam != 0) && (wvrLockId != 0))
265             {
266                 OSi_UnlockVram(wvrVRam, wvrLockId);
267                 wvrVRam = 0;
268             }
269             break;
270         }
271         break;
272     case WVR_PXI_COMMAND_TERMINATE:
273         switch (result)
274         {
275         case WVR_RESULT_SUCCESS:
276             // Unlock VRAM
277             if ((wvrVRam != 0) && (wvrLockId != 0))
278             {
279                 OSi_UnlockVram(wvrVRam, wvrLockId);
280                 wvrVRam = 0;
281             }
282             break;
283         }
284         // PXI callback destination settings cleared to NULL
285         PXI_SetFifoRecvCallback(PXI_FIFO_TAG_WVR, NULL);
286         break;
287     }
288 
289     // Call the user callback
290     if (cb != NULL)
291     {
292         wvrCallback = NULL;
293         wvrArg = NULL;
294         cb(cbArg, result);
295     }
296 }
297 
298 /*---------------------------------------------------------------------------*
299   Name:         WvrDummyAsyncCallback
300 
301   Description:  Dummy callback function set to asynchronous functions.
302 
303   Arguments:    arg: Unused
304                 result:     Result of asynchronous processing.
305 
306   Returns:      None.
307  *---------------------------------------------------------------------------*/
WvrDummyAsyncCallback(void * arg,WVRResult result)308 static void WvrDummyAsyncCallback(void *arg, WVRResult result)
309 {
310 #pragma unused( arg , result )
311 }
312 
313 /*---------------------------------------------------------------------------*
314     End of file
315  *---------------------------------------------------------------------------*/
316