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