1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - NWM - libraries
3 File: nwm_system.c
4
5 Copyright 2007-2009 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:: 2009-06-19#$
14 $Rev: 10786 $
15 $Author: okajima_manabu $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl.h>
19 #include "nwm_arm9_private.h"
20 #include "nwm_common_private.h"
21
22 NWMArm9Buf *nwm9buf = NULL;
23 static PMSleepCallbackInfo sleepCbInfo; //Sleep callback information to register with the PM library
24
25 #ifdef NWM_SUPPORT_HWRESET
26 PMExitCallbackInfo hwResetCbInfo;
27 #endif
28
29 static void NwmSleepCallback(void *);
30
31 /*---------------------------------------------------------------------------*
32 Name: NWMi_GetSystemWork
33
34 Description: Gets a pointer to the start of the buffer used internally by the new WM library.
35
36 Arguments: None.
37
38 Returns: NWMArm9Buf*: Returns a pointer to the internal work buffer.
39 *---------------------------------------------------------------------------*/
NWMi_GetSystemWork(void)40 NWMArm9Buf *NWMi_GetSystemWork(void)
41 {
42 // SDK_NULL_ASSERT(nwm9buf);
43 return nwm9buf;
44 }
45
46
47 /*---------------------------------------------------------------------------*
48 Name: NWMi_ClearFifoRecvFlag
49
50 Description: Notifies the new WM7 that access to FIFO data used by a callback from the new WM7 is complete.
51
52 When using a FIFO in a new WM7 callback, wait for this flag to unlock before editing the next callback.
53
54
55 Arguments: None.
56
57 Returns: None.
58 *---------------------------------------------------------------------------*/
59
NWMi_ClearFifoRecvFlag(void)60 void NWMi_ClearFifoRecvFlag(void)
61 {
62 NWMArm7Buf *w7b;
63
64 if (nwm9buf == NULL) {
65 return;
66 }
67
68 w7b = nwm9buf->NWM7;
69
70 // The ARM7 will read the updated value, so invalidate the ARM9 cache
71 DC_InvalidateRange(&w7b->callbackSyncFlag, 1);
72
73 if (w7b->callbackSyncFlag & NWM_EXCEPTION_CB_MASK)
74 {
75 // Clears the CB exclusion flag
76 w7b->callbackSyncFlag &= ~NWM_EXCEPTION_CB_MASK;
77 // Store cache immediately
78 DC_StoreRange(&w7b->callbackSyncFlag, 1);
79 }
80 }
81
82
83 /*---------------------------------------------------------------------------*
84 Name: NWMi_ReceiveFifo9
85
86 Description: Receives a callback from the new WM7 through a FIFO.
87
88 Arguments: tag: Unused
89 fifo_buf_adr: Pointer to the callback parameter group
90 err: Unused
91
92 Returns: None.
93 *---------------------------------------------------------------------------*/
94
NWMi_ReceiveFifo9(PXIFifoTag tag,u32 fifo_buf_adr,BOOL err)95 void NWMi_ReceiveFifo9(PXIFifoTag tag, u32 fifo_buf_adr, BOOL err)
96 {
97 #pragma unused( tag )
98 NWMCallback *pCallback = (NWMCallback *)fifo_buf_adr;
99 NWMCallbackFunc callback;
100 NWMArm9Buf *w9b = nwm9buf;
101
102 if (w9b == NULL) {
103 return;
104 }
105
106 if (err) {
107 NWM_WARNING("NWM9 FIFO receive error. :%d\n", err);
108 return;
109 }
110
111 if (!fifo_buf_adr) {
112 NWM_WARNING("NWM9 FIFO receive error.(NULL address) :%d\n", err);
113 return;
114 }
115
116 // When 'apiid' is an unexpected value (NWM_APIID_ASYNC_KIND_MAX or more)
117 if(pCallback->apiid >= NWM_APIID_ASYNC_KIND_MAX)
118 {
119 NWM_WARNING("Receive Unknown APIID(%d)\n",pCallback->apiid);
120 return;
121 }
122
123 DC_InvalidateRange(w9b->fifo7to9, NWM_APIFIFO_BUF_SIZE);
124 DC_InvalidateRange(w9b->status, NWM_STATUS_BUF_SIZE);
125 if ((u32)pCallback != (u32)(w9b->fifo7to9))
126 {
127 DC_InvalidateRange(pCallback, NWM_APIFIFO_BUF_SIZE);
128 }
129
130 NWM_DPRINTF("APIID%04x\n", pCallback->apiid);
131
132 // Remove the sleep callback if NWM_LoadDevice failed or WM_UnloadDevice succeeded.
133 if( (pCallback->apiid == NWM_APIID_LOAD_DEVICE && pCallback->retcode != NWM_RETCODE_SUCCESS) ||
134 (pCallback->apiid == NWM_APIID_UNLOAD_DEVICE && pCallback->retcode == NWM_RETCODE_SUCCESS) ||
135 pCallback->apiid == NWM_APIID_INSTALL_FIRMWARE )
136 {
137 NWMi_DeleteSleepCallback();
138 }
139
140 // Callback processing according to apiid (does nothing if callback not set (NULL))
141 {
142 NWMSendFrameCallback *pSfcb = (NWMSendFrameCallback *)pCallback;
143 NWMRetCode result = NWM_RETCODE_FAILED;
144
145 if (pCallback->apiid == NWM_APIID_SEND_FRAME)
146 {
147 if (pCallback->retcode != NWM_RETCODE_INDICATION && NULL != pSfcb->callback)
148 {
149 NWM_DPRINTF("Execute CallbackFunc APIID 0x%04x\n", pCallback->apiid);
150 (pSfcb->callback)((void *)pCallback);
151 }
152
153 }
154 }
155
156 // In the case of several special APIs
157 if (pCallback->apiid == NWM_APIID_SEND_FRAME) {
158 NWMSendFrameCallback *pSfcb = (NWMSendFrameCallback *)pCallback;
159
160 } else {
161
162 #ifdef NWM_SUPPORT_HWRESET
163 if (pCallback->apiid == NWM_APIID_UNLOAD_DEVICE
164 || pCallback->apiid == NWM_APIID_INSTALL_FIRMWARE
165 || (pCallback->apiid == NWM_APIID_LOAD_DEVICE
166 && pCallback->retcode != NWM_RETCODE_SUCCESS)) {
167 // Delete HW reset callback
168 PM_DeletePostExitCallback(&hwResetCbInfo);
169 }
170 #endif
171
172 // Other APIs
173 callback = w9b->callbackTable[pCallback->apiid];
174
175 // In case START_SCAN callback, scan buffer cache must be invalidated.
176 if (pCallback->apiid == NWM_APIID_START_SCAN) {
177 NWMStartScanCallback *psscb = (NWMStartScanCallback *)pCallback;
178
179 DC_InvalidateRange(psscb->bssDesc[0], psscb->allBssDescSize);
180 }
181
182 if (NULL != callback)
183 {
184 NWM_DPRINTF("Execute CallbackFunc APIID 0x%04x\n", pCallback->apiid);
185 (callback) ((void *)pCallback);
186 }
187
188 }
189
190 MI_CpuClear8(pCallback, NWM_APIFIFO_BUF_SIZE);
191 DC_StoreRange(pCallback, NWM_APIFIFO_BUF_SIZE);
192 if (w9b) { // NWM might be terminated after callback
193 NWMi_ClearFifoRecvFlag();
194 }
195
196 }
197
198 /*---------------------------------------------------------------------------*
199 Name: NWM_GetState
200
201 Description: Checks the internal state of the NWM library.
202 The purpose for using this is similar to NWMi_CheckState, but its application is largely different so it is provided separately.
203
204
205 Arguments: None.
206
207 Returns: u16: Integer that indicates the internal NWM state
208 *---------------------------------------------------------------------------*/
NWM_GetState(void)209 u16 NWM_GetState(void)
210 {
211 NWMStatus* nwmStatus;
212 NWMArm9Buf* sys = NWMi_GetSystemWork();
213 u16 state = NWM_STATE_NONE;
214
215 if (sys) {
216 nwmStatus = sys->status;
217 DC_InvalidateRange(nwmStatus, 2);
218 state = nwmStatus->state;
219 }
220
221 return state;
222 }
223
224 /*---------------------------------------------------------------------------*
225 Name: NWMi_CheckState
226
227 Description: Checks the internal state of the NWM library.
228 Specifies the WMState type parameters showing the permitted state by enumerating them.
229
230 Arguments: paramNum: Number of virtual arguments
231 ...: Virtual argument
232
233 Returns: int: Returns the result of the process as an NWM_RETCODE_* value.
234 *---------------------------------------------------------------------------*/
NWMi_CheckState(s32 paramNum,...)235 NWMRetCode NWMi_CheckState(s32 paramNum, ...)
236 {
237 NWMRetCode result;
238 u16 now;
239 u32 temp;
240 va_list vlist;
241 NWMArm9Buf *sys = NWMi_GetSystemWork();
242
243 SDK_NULL_ASSERT(sys);
244
245 // Check if initialized
246 result = NWMi_CheckInitialized();
247 NWM_CHECK_RESULT(result);
248
249 // Gets the current state
250 DC_InvalidateRange(&(sys->status->state), 2);
251 now = sys->status->state;
252
253 // Match confirmation
254 result = NWM_RETCODE_ILLEGAL_STATE;
255 va_start(vlist, paramNum);
256 for (; paramNum; paramNum--)
257 {
258 temp = va_arg(vlist, u32);
259 if (temp == now)
260 {
261 result = NWM_RETCODE_SUCCESS;
262 }
263 }
264 va_end(vlist);
265
266 if (result == NWM_RETCODE_ILLEGAL_STATE)
267 {
268 NWM_WARNING("New WM state is \"0x%04x\" now. So can't execute request.\n", now);
269 }
270
271 return result;
272 }
273
274 /*---------------------------------------------------------------------------*
275 Name: NWM_GetAllowedChannel
276
277 Description: Gets the IEEE 802.11b/g channel list that can be used with the new wireless functions.
278
279 Arguments: None.
280
281 Returns: u16: Returns a channel bitmap in the same format as the WM library.
282 *---------------------------------------------------------------------------*/
NWM_GetAllowedChannel(void)283 u16 NWM_GetAllowedChannel(void)
284 {
285 NWMArm9Buf *sys = NWMi_GetSystemWork();
286
287 return sys->status->allowedChannel;
288 }
289
290 /*---------------------------------------------------------------------------*
291 Name: NWM_CalcLinkLevel
292
293 Description: Calculates the link level from the threshold value defined in nwm_common_private.h.
294
295 Arguments: s16: RSSI value sent with a notification from the Atheros driver
296
297 Returns: u16: The same link level as the WM library.
298 *---------------------------------------------------------------------------*/
NWM_CalcLinkLevel(s16 rssi)299 u16 NWM_CalcLinkLevel(s16 rssi)
300 {
301
302 /* [TODO] Does this need to be switched depending on the operating mode? If this is necessary, the conditional statement must be revised. */
303
304 if(1) /* Infra Structure Mode */
305 {
306 if(rssi < NWM_RSSI_INFRA_LINK_LEVEL_1)
307 {
308 return WM_LINK_LEVEL_0;
309 }
310 if(rssi < NWM_RSSI_INFRA_LINK_LEVEL_2)
311 {
312 return WM_LINK_LEVEL_1;
313 }
314 if(rssi < NWM_RSSI_INFRA_LINK_LEVEL_3)
315 {
316 return WM_LINK_LEVEL_2;
317 }
318
319 return WM_LINK_LEVEL_3;
320 }
321 else if(0) /*Ad Hoc Mode*/
322 {
323 if(rssi < NWM_RSSI_ADHOC_LINK_LEVEL_1)
324 {
325 return WM_LINK_LEVEL_0;
326 }
327 if(rssi < NWM_RSSI_ADHOC_LINK_LEVEL_2)
328 {
329 return WM_LINK_LEVEL_1;
330 }
331 if(rssi < NWM_RSSI_ADHOC_LINK_LEVEL_3)
332 {
333 return WM_LINK_LEVEL_2;
334 }
335 return WM_LINK_LEVEL_3;
336 }
337
338 }
339
340 /*---------------------------------------------------------------------------*
341 Name: NWM_GetDispersionScanPeriod
342
343 Description: Gets the time limit that should be set on searching for an AP or DS parent device as an STA.
344
345 Arguments: u16 scanType: Scan type, either NWM_SCANTYPE_PASSIVE or NWM_SCANTYPE_ACTIVE
346
347 Returns: u16: Search limit time that should be set (ms).
348 *---------------------------------------------------------------------------*/
NWM_GetDispersionScanPeriod(u16 scanType)349 u16 NWM_GetDispersionScanPeriod(u16 scanType)
350 {
351 u8 mac[6];
352 u16 ret;
353 s32 i;
354
355 OS_GetMacAddress(mac);
356 for (i = 0, ret = 0; i < 6; i++)
357 {
358 ret += mac[i];
359 }
360 ret += OS_GetVBlankCount();
361 ret *= 13;
362
363 if( scanType == NWM_SCANTYPE_ACTIVE )
364 {
365 ret = (u16)(NWM_DEFAULT_ACTIVE_SCAN_PERIOD + (ret % 10));
366 }
367 else /* An unknown scan type is treated in the same way as a passive scan */
368 {
369 ret = (u16)(NWM_DEFAULT_PASSIVE_SCAN_PERIOD + (ret % 10));
370 }
371 return ret;
372 }
373
374 /*---------------------------------------------------------------------------*
375 Name: NWMi_RegisterSleepCallback
376
377 Description: Registers the callback function that will be run when shifting to Sleep Mode.
378
379 Arguments: None.
380
381 Returns: None.
382 *---------------------------------------------------------------------------*/
NWMi_RegisterSleepCallback(void)383 void NWMi_RegisterSleepCallback(void)
384 {
385 PM_SetSleepCallbackInfo(&sleepCbInfo, NwmSleepCallback, NULL);
386 PMi_InsertPreSleepCallbackEx(&sleepCbInfo, PM_CALLBACK_PRIORITY_NWM );
387 }
388
389 /*---------------------------------------------------------------------------*
390 Name: NWMi_DeleteSleepCallback
391
392 Description: Deletes the callback function that is run when shifting to Sleep Mode.
393
394 Arguments: None.
395
396 Returns: None.
397 *---------------------------------------------------------------------------*/
NWMi_DeleteSleepCallback(void)398 void NWMi_DeleteSleepCallback(void)
399 {
400 PM_DeletePreSleepCallback( &sleepCbInfo );
401 }
402
403 /*---------------------------------------------------------------------------*
404 Name: NwmSleepCallback
405
406 Description: Prevents the program from entering Sleep Mode during wireless communications.
407
408 Arguments: None.
409
410 Returns: None.
411 *---------------------------------------------------------------------------*/
NwmSleepCallback(void *)412 static void NwmSleepCallback(void *)
413 {
414 /* ---------------------------------------------- *
415 * As described in the Programming Guidelines, it is prohibited to run the OS_GoSleepMode function during wireless communications. *
416 * *
417 * *
418 * ---------------------------------------------- */
419 OS_TPanic("Could not sleep during wireless communications.");
420 }
421
422 /*---------------------------------------------------------------------------*
423 End of file
424 *---------------------------------------------------------------------------*/
425