1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - WM - libraries
3 File: wm_system.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-12-09#$
14 $Rev: 9606 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #include <nitro/wm.h>
19 #include "wm_arm9_private.h"
20
21 #ifdef SDK_TWL /* Strengthens checks during TWL initialization */
22 #include "wm_common.h"
23 #endif //SDK_TWL
24
25 /*---------------------------------------------------------------------------*
26 Constant Definitions
27 *---------------------------------------------------------------------------*/
28 #define WM_BUF_MSG_NUM 10
29
30
31 /*---------------------------------------------------------------------------*
32 Internal Variable Definitions
33 *---------------------------------------------------------------------------*/
34 static u16 wmInitialized = 0; // WM initialization flag
35 static WMArm9Buf *wm9buf;
36 static u32 fifoBuf[WM_BUF_MSG_NUM][WM_FIFO_BUF_SIZE / sizeof(u32)] ATTRIBUTE_ALIGN(32);
37 static OSMessageQueue bufMsgQ; // Request queue for WM7
38 static OSMessage bufMsg[WM_BUF_MSG_NUM]; // Request queue buffer for WM7
39 static PMSleepCallbackInfo sleepCbInfo; //Sleep callback information to register with the PM library
40
41
42 /*---------------------------------------------------------------------------*
43 Internal Function Definitions
44 *---------------------------------------------------------------------------*/
45 static void WmReceiveFifo(PXIFifoTag tag, u32 fifo_buf_adr, BOOL err);
46 static void WmClearFifoRecvFlag(void);
47 static WMErrCode WmInitCore(void *wmSysBuf, u16 dmaNo, u32 bufSize);
48 static u32 *WmGetCommandBuffer4Arm7(void);
49 static void WmSleepCallback(void *);
50
51 /*---------------------------------------------------------------------------*
52 Name: WM_Init
53
54 Description: Performs the initialization process for the WM library.
55 Synchronous function that only initializes ARM9.
56
57 Arguments: wmSysBuf - Pointer to the buffer allocated by the caller.
58 Only as much as WM_SYSTEM_BUF_SIZE is required for buffer size.
59 dmaNo - DMA number used by WM
60
61 Returns: WMErrCode - Returns the processing result.
62 *---------------------------------------------------------------------------*/
WM_Init(void * wmSysBuf,u16 dmaNo)63 WMErrCode WM_Init(void *wmSysBuf, u16 dmaNo)
64 {
65 WMErrCode result;
66
67 result = WmInitCore(wmSysBuf, dmaNo, WM_SYSTEM_BUF_SIZE);
68 if (result != WM_ERRCODE_SUCCESS)
69 {
70 return result;
71 }
72 wm9buf->scanOnlyFlag = FALSE;
73 return result;
74 }
75
76 /*---------------------------------------------------------------------------*
77 Name: WMi_InitForScan
78
79 Description: Performs initialization processing for WM library when using only scan.
80 Synchronous function that only initializes ARM9.
81
82 Arguments: wmSysBuf - Pointer to the buffer allocated by the caller.
83 The required buffer size is only WM_SYSTEM_BUF_SIZE_FOR_SCAN.
84 dmaNo - DMA number used by WM
85
86 Returns: WMErrCode - Returns the processing result.
87 *---------------------------------------------------------------------------*/
88 WMErrCode WMi_InitForScan(void *wmSysBuf, u16 dmaNo);
WMi_InitForScan(void * wmSysBuf,u16 dmaNo)89 WMErrCode WMi_InitForScan(void *wmSysBuf, u16 dmaNo)
90 {
91 #define WM_STATUS_BUF_SIZE_FOR_SCAN 768
92 #define WM_ARM9WM_BUF_SIZE_FOR_SCAN 320
93 #define WM_SYSTEM_BUF_SIZE_FOR_SCAN (WM_ARM9WM_BUF_SIZE_FOR_SCAN + WM_ARM7WM_BUF_SIZE + WM_STATUS_BUF_SIZE_FOR_SCAN + WM_FIFO_BUF_SIZE + WM_FIFO_BUF_SIZE)
94
95 WMErrCode result;
96 result = WmInitCore(wmSysBuf, dmaNo, WM_SYSTEM_BUF_SIZE_FOR_SCAN);
97 if (result != WM_ERRCODE_SUCCESS)
98 {
99 return result;
100 }
101 wm9buf = (WMArm9Buf *)wmSysBuf;
102 wm9buf->WM7 = (WMArm7Buf *)((u32)wm9buf + WM_ARM9WM_BUF_SIZE_FOR_SCAN);
103 wm9buf->status = (WMStatus *)((u32)(wm9buf->WM7) + WM_ARM7WM_BUF_SIZE);
104 wm9buf->fifo9to7 = (u32 *)((u32)(wm9buf->status) + WM_STATUS_BUF_SIZE_FOR_SCAN);
105 wm9buf->fifo7to9 = (u32 *)((u32)(wm9buf->fifo9to7) + WM_FIFO_BUF_SIZE);
106 wm9buf->dmaNo = dmaNo;
107 wm9buf->scanOnlyFlag = TRUE;
108
109 return result;
110 }
111
112 /*---------------------------------------------------------------------------*
113 Name: WmInitCore
114
115 Description: Library internal use function that performs WM library initialization process.
116 Synchronous function that only initializes ARM9.
117
118 Arguments: wmSysBuf - Pointer to the buffer allocated by the caller.
119 dmaNo - DMA number used by WM
120 bufSize: Buffer size allocated to WM library
121
122 Returns: WMErrCode - Returns the processing result.
123 *---------------------------------------------------------------------------*/
WmInitCore(void * wmSysBuf,u16 dmaNo,u32 bufSize)124 static WMErrCode WmInitCore(void *wmSysBuf, u16 dmaNo, u32 bufSize)
125 {
126 OSIntrMode e;
127
128 // Checks if the structure size exceeds the expected value.
129 SDK_COMPILER_ASSERT(sizeof(WMArm9Buf) <= WM_ARM9WM_BUF_SIZE);
130 SDK_COMPILER_ASSERT(sizeof(WMArm7Buf) <= WM_ARM7WM_BUF_SIZE);
131 SDK_COMPILER_ASSERT(sizeof(WMStatus) <= WM_STATUS_BUF_SIZE);
132
133 e = OS_DisableInterrupts();
134
135 #ifdef SDK_TWL
136 if( OS_IsRunOnTwl() )
137 {
138 /* Check that the NWM library has not been initialized */
139 if (NWM_CheckInitialized() != NWM_RETCODE_ILLEGAL_STATE)
140 {
141 WM_WARNING("NWM has already been initialized.\n");
142 (void)OS_RestoreInterrupts(e);
143 return WM_ERRCODE_ILLEGAL_STATE;
144 }
145 }
146 #endif
147
148 /* Confirms that the WM library initialization is complete. */
149 if (wmInitialized)
150 {
151 WM_WARNING("WM has already been initialized.\n");
152 (void)OS_RestoreInterrupts(e);
153 return WM_ERRCODE_ILLEGAL_STATE; // Initialization complete
154 }
155
156 // Check parameters
157 if (wmSysBuf == NULL)
158 {
159 WM_WARNING("Parameter \"wmSysBuf\" must not be NULL.\n");
160 (void)OS_RestoreInterrupts(e);
161 return WM_ERRCODE_INVALID_PARAM;
162 }
163 if (dmaNo > MI_DMA_MAX_NUM)
164 {
165 WM_WARNING("Parameter \"dmaNo\" is over %d.\n", MI_DMA_MAX_NUM);
166 (void)OS_RestoreInterrupts(e);
167 return WM_ERRCODE_INVALID_PARAM;
168 }
169 if ((u32)wmSysBuf & 0x01f)
170 {
171 WM_WARNING("Parameter \"wmSysBuf\" must be 32-byte aligned.\n");
172 (void)OS_RestoreInterrupts(e);
173 return WM_ERRCODE_INVALID_PARAM;
174 }
175
176 // Confirms whether the WM library has started on the ARM7
177 PXI_Init();
178 if (!PXI_IsCallbackReady(PXI_FIFO_TAG_WM, PXI_PROC_ARM7))
179 {
180 WM_WARNING("WM library on ARM7 side is not ready yet.\n");
181 (void)OS_RestoreInterrupts(e);
182 return WM_ERRCODE_WM_DISABLE;
183 }
184
185 /* If there is excess data remaining in the cache, a write-back could occur unexpectedly and interfere with state management on the ARM7.
186
187 As a countermeasure, delete the cache of all work buffers at this point. */
188 DC_InvalidateRange(wmSysBuf, bufSize);
189 // Initialization for various types of buffers
190 MI_DmaClear32(dmaNo, wmSysBuf, bufSize);
191 wm9buf = (WMArm9Buf *)wmSysBuf;
192 wm9buf->WM7 = (WMArm7Buf *)((u32)wm9buf + WM_ARM9WM_BUF_SIZE);
193 wm9buf->status = (WMStatus *)((u32)(wm9buf->WM7) + WM_ARM7WM_BUF_SIZE);
194 wm9buf->fifo9to7 = (u32 *)((u32)(wm9buf->status) + WM_STATUS_BUF_SIZE);
195 wm9buf->fifo7to9 = (u32 *)((u32)(wm9buf->fifo9to7) + WM_FIFO_BUF_SIZE);
196
197 // Clears the FIFO buffer writable flag
198 WmClearFifoRecvFlag();
199
200 // Initializes the various types of variables
201 wm9buf->dmaNo = dmaNo;
202 wm9buf->connectedAidBitmap = 0x0000;
203 wm9buf->myAid = 0;
204
205 // Initializes the callback table for each port
206 {
207 s32 i;
208
209 for (i = 0; i < WM_NUM_OF_PORT; i++)
210 {
211 wm9buf->portCallbackTable[i] = NULL;
212 wm9buf->portCallbackArgument[i] = NULL;
213 }
214 }
215
216 // Initializes the queue for entry registration
217 {
218 s32 i;
219
220 OS_InitMessageQueue(&bufMsgQ, bufMsg, WM_BUF_MSG_NUM);
221 for (i = 0; i < WM_BUF_MSG_NUM; i++)
222 {
223 // Clears the ring buffer to the usable state.
224 *((u16 *)(fifoBuf[i])) = WM_API_REQUEST_ACCEPTED;
225 DC_StoreRange(fifoBuf[i], 2);
226 (void)OS_SendMessage(&bufMsgQ, fifoBuf[i], OS_MESSAGE_BLOCK);
227 }
228 }
229
230 // Sets FIFO receive function
231 PXI_SetFifoRecvCallback(PXI_FIFO_TAG_WM, WmReceiveFifo);
232
233 wmInitialized = 1;
234 (void)OS_RestoreInterrupts(e);
235 return WM_ERRCODE_SUCCESS;
236 }
237
238 /*---------------------------------------------------------------------------*
239 Name: WM_Finish
240
241 Description: Performs termination processing for WM library. Synchronous function.
242 Restores the state before WM_Init function was called.
243
244 Arguments: None.
245
246 Returns: WMErrCode - Returns the processing result.
247 *---------------------------------------------------------------------------*/
WM_Finish(void)248 WMErrCode WM_Finish(void)
249 {
250 OSIntrMode e;
251 WMErrCode result;
252
253 e = OS_DisableInterrupts();
254 // Cannot execute if initialization is incomplete
255 result = WMi_CheckInitialized();
256 if (result != WM_ERRCODE_SUCCESS)
257 {
258 (void)OS_RestoreInterrupts(e);
259 return WM_ERRCODE_ILLEGAL_STATE;
260 }
261
262 // Cannot execute if the state is not READY
263 result = WMi_CheckState(WM_STATE_READY);
264 WM_CHECK_RESULT(result);
265
266 // Close WM library
267 WmClearFifoRecvFlag();
268 PXI_SetFifoRecvCallback(PXI_FIFO_TAG_WM, NULL);
269 wm9buf = 0;
270
271 wmInitialized = 0;
272 (void)OS_RestoreInterrupts(e);
273 return WM_ERRCODE_SUCCESS;
274 }
275
276 /*---------------------------------------------------------------------------*
277 Name: WMi_SetCallbackTable
278
279 Description: Registers the callback function for each asynchronous function.
280
281 Arguments: id: Asynchronous function's API ID.
282 callback: The callback function to be registered.
283
284 Returns: None.
285 *---------------------------------------------------------------------------*/
WMi_SetCallbackTable(WMApiid id,WMCallbackFunc callback)286 void WMi_SetCallbackTable(WMApiid id, WMCallbackFunc callback)
287 {
288 SDK_NULL_ASSERT(wm9buf);
289
290 wm9buf->CallbackTable[id] = callback;
291 }
292
293 /*---------------------------------------------------------------------------*
294 Name: WmGetCommandBuffer4Arm7
295
296 Description: Reserves from the pool a buffer for commands directed to ARM7.
297
298 Arguments: None.
299
300 Returns: If it can be reserved, it's that value; otherwise: NULL
301 *---------------------------------------------------------------------------*/
WmGetCommandBuffer4Arm7(void)302 u32 *WmGetCommandBuffer4Arm7(void)
303 {
304 u32 *tmpAddr;
305
306 if (FALSE == OS_ReceiveMessage(&bufMsgQ, (OSMessage *)&tmpAddr, OS_MESSAGE_NOBLOCK))
307 {
308 return NULL;
309 }
310
311 // Check if the ring buffer is available (queue is not full)
312 DC_InvalidateRange(tmpAddr, 2);
313 if ((*((u16 *)tmpAddr) & WM_API_REQUEST_ACCEPTED) == 0)
314 {
315 // Reserve again at the beginning of the queue (because this should be first to come available)
316 (void)OS_JamMessage(&bufMsgQ, tmpAddr, OS_MESSAGE_BLOCK);
317 // End with an error
318 return NULL;
319 }
320
321 return tmpAddr;
322 }
323
324 /*---------------------------------------------------------------------------*
325 Name: WMi_SendCommand
326
327 Description: Transmits a request to the ARM7 via the FIFO.
328 For commands accompanied by some number of u32-type parameters, specify the parameters by enumerating them.
329
330
331 Arguments: id: API ID that corresponds to the request.
332 paramNum: Number of virtual arguments.
333 ... - Virtual argument.
334
335 Returns: int: Returns WM_ERRCODE_* type processing results.
336 *---------------------------------------------------------------------------*/
WMi_SendCommand(WMApiid id,u16 paramNum,...)337 WMErrCode WMi_SendCommand(WMApiid id, u16 paramNum, ...)
338 {
339 va_list vlist;
340 s32 i;
341 int result;
342 u32 *tmpAddr;
343
344 SDK_NULL_ASSERT(wm9buf);
345
346 // Reserves a buffer for command sending
347 tmpAddr = WmGetCommandBuffer4Arm7();
348 if (tmpAddr == NULL)
349 {
350 return WM_ERRCODE_FIFO_ERROR;
351 }
352
353 // API ID
354 *(u16 *)tmpAddr = (u16)id;
355
356 // Adds the specified number of arguments
357 va_start(vlist, paramNum);
358 for (i = 0; i < paramNum; i++)
359 {
360 tmpAddr[i + 1] = va_arg(vlist, u32);
361 }
362 va_end(vlist);
363
364 DC_StoreRange(tmpAddr, WM_FIFO_BUF_SIZE);
365
366 // Notification with FIFO
367 result = PXI_SendWordByFifo(PXI_FIFO_TAG_WM, (u32)tmpAddr, FALSE);
368
369 (void)OS_SendMessage(&bufMsgQ, tmpAddr, OS_MESSAGE_BLOCK);
370
371 if (result < 0)
372 {
373 WM_WARNING("Failed to send command through FIFO.\n");
374 return WM_ERRCODE_FIFO_ERROR;
375 }
376
377 return WM_ERRCODE_OPERATING;
378 }
379
380 /*---------------------------------------------------------------------------*
381 Name: WMi_SendCommandDirect
382
383 Description: Transmits a request to the ARM7 via the FIFO.
384 Directly specifies the command sent to the ARM7.
385
386 Arguments: data: Command sent to the ARM7.
387 length: Size of the command sent to the ARM7.
388
389 Returns: int: Returns WM_ERRCODE_* type processing results.
390 *---------------------------------------------------------------------------*/
WMi_SendCommandDirect(void * data,u32 length)391 WMErrCode WMi_SendCommandDirect(void *data, u32 length)
392 {
393 int result;
394 u32 *tmpAddr;
395
396 SDK_NULL_ASSERT(wm9buf);
397 SDK_ASSERT(length <= WM_FIFO_BUF_SIZE);
398
399 // Reserves a buffer for command sending
400 tmpAddr = WmGetCommandBuffer4Arm7();
401 if (tmpAddr == NULL)
402 {
403 return WM_ERRCODE_FIFO_ERROR;
404 }
405
406 // Copies to a buffer specifically for commands sent to the ARM7.
407 MI_CpuCopy8(data, tmpAddr, length);
408
409 DC_StoreRange(tmpAddr, length);
410
411 // Notification with FIFO
412 result = PXI_SendWordByFifo(PXI_FIFO_TAG_WM, (u32)tmpAddr, FALSE);
413
414 (void)OS_SendMessage(&bufMsgQ, tmpAddr, OS_MESSAGE_BLOCK);
415
416 if (result < 0)
417 {
418 WM_WARNING("Failed to send command through FIFO.\n");
419 return WM_ERRCODE_FIFO_ERROR;
420 }
421
422 return WM_ERRCODE_OPERATING;
423 }
424
425 /*---------------------------------------------------------------------------*
426 Name: WMi_GetSystemWork
427
428 Description: Gets the pointer to the front of the buffer used internally by the WM library.
429
430 Arguments: None.
431
432 Returns: WMArm9Buf* : Returns a pointer to the internal work buffer.
433 *---------------------------------------------------------------------------*/
WMi_GetSystemWork(void)434 WMArm9Buf *WMi_GetSystemWork(void)
435 {
436 // SDK_NULL_ASSERT(wm9buf);
437 return wm9buf;
438 }
439
440 /*---------------------------------------------------------------------------*
441 Name: WMi_CheckInitialized
442
443 Description: Confirms that the WM library initialization is complete.
444
445 Arguments: None.
446
447 Returns: int: Returns WM_ERRCODE_* type processing results.
448 *---------------------------------------------------------------------------*/
WMi_CheckInitialized(void)449 WMErrCode WMi_CheckInitialized(void)
450 {
451 // Check if initialized
452 if (!wmInitialized)
453 {
454 return WM_ERRCODE_ILLEGAL_STATE;
455 }
456 return WM_ERRCODE_SUCCESS;
457 }
458
459 /*---------------------------------------------------------------------------*
460 Name: WMi_CheckIdle
461
462 Description: Confirms the internal state of the WM library, and confirms that the wireless hardware has already started.
463
464
465 Arguments: None.
466
467 Returns: int: Returns WM_ERRCODE_* type processing results.
468 *---------------------------------------------------------------------------*/
WMi_CheckIdle(void)469 WMErrCode WMi_CheckIdle(void)
470 {
471 WMErrCode result;
472
473 // Check if initialized
474 result = WMi_CheckInitialized();
475 WM_CHECK_RESULT(result);
476
477 // Confirms the current state
478 DC_InvalidateRange(&(wm9buf->status->state), 2);
479 if ((wm9buf->status->state == WM_STATE_READY) || (wm9buf->status->state == WM_STATE_STOP))
480 {
481 WM_WARNING("WM state is \"%d\" now. So can't execute request.\n", wm9buf->status->state);
482 return WM_ERRCODE_ILLEGAL_STATE;
483 }
484
485 return WM_ERRCODE_SUCCESS;
486 }
487
488 /*---------------------------------------------------------------------------*
489 Name: WMi_CheckStateEx
490
491 Description: Confirms the internal state of the WM library.
492 Specifies the WMState type parameters showing the permitted state by enumerating them.
493
494 Arguments: paramNum: Number of virtual arguments.
495 ... - Virtual argument.
496
497 Returns: int: Returns WM_ERRCODE_* type processing results.
498 *---------------------------------------------------------------------------*/
WMi_CheckStateEx(s32 paramNum,...)499 WMErrCode WMi_CheckStateEx(s32 paramNum, ...)
500 {
501 WMErrCode result;
502 u16 now;
503 u32 temp;
504 va_list vlist;
505
506 // Check if initialized
507 result = WMi_CheckInitialized();
508 WM_CHECK_RESULT(result);
509
510 // Gets the current state
511 DC_InvalidateRange(&(wm9buf->status->state), 2);
512 now = wm9buf->status->state;
513
514 // Match confirmation
515 result = WM_ERRCODE_ILLEGAL_STATE;
516 va_start(vlist, paramNum);
517 for (; paramNum; paramNum--)
518 {
519 temp = va_arg(vlist, u32);
520 if (temp == now)
521 {
522 result = WM_ERRCODE_SUCCESS;
523 }
524 }
525 va_end(vlist);
526
527 if (result == WM_ERRCODE_ILLEGAL_STATE)
528 {
529 WM_WARNING("WM state is \"%d\" now. So can't execute request.\n", now);
530 }
531
532 return result;
533 }
534
535 /*---------------------------------------------------------------------------*
536 Name: WmReceiveFifo
537
538 Description: Receives a callback from WM7 via FIFO.
539
540 Arguments: tag: Unused
541 fifo_buf_adr: Pointer to the callback parameter group.
542 err: Unused
543
544 Returns: None.
545 *---------------------------------------------------------------------------*/
WmReceiveFifo(PXIFifoTag tag,u32 fifo_buf_adr,BOOL err)546 static void WmReceiveFifo(PXIFifoTag tag, u32 fifo_buf_adr, BOOL err)
547 {
548 #pragma unused( tag )
549
550 WMCallback *callback_p = (WMCallback *)fifo_buf_adr;
551 WMArm9Buf *w9b = wm9buf; // Notify compiler that it is not volatile.
552 #ifdef WM_DEBUG_CALLBACK
553 int beginVcount = GX_GetVCount();
554 #endif
555
556 if (err)
557 return; // The WM_sp_init PXI handler is not ready
558
559 // Invalidates the FIFO command buffer (9 <- 7) cache
560 DC_InvalidateRange(w9b->fifo7to9, WM_FIFO_BUF_SIZE);
561 if (!w9b->scanOnlyFlag)
562 {
563 DC_InvalidateRange(w9b->status, WM_STATUS_BUF_SIZE);
564 }
565
566 // Checks if the response buffer is a different buffer from fifo7to9
567 if ((u32)callback_p != (u32)(w9b->fifo7to9))
568 {
569 DC_InvalidateRange(callback_p, WM_FIFO_BUF_SIZE);
570 }
571
572
573 if (callback_p->apiid >= WM_NUM_OF_CALLBACK)
574 {
575 if (callback_p->apiid == WM_APIID_INDICATION)
576 {
577 if (callback_p->errcode == WM_ERRCODE_FLASH_ERROR)
578 {
579 // ARM9 freeze
580 OS_Terminate(); // It does not return.
581 }
582 if (w9b->indCallback != NULL)
583 {
584 w9b->indCallback((void *)callback_p);
585 }
586 }
587 else if (callback_p->apiid == WM_APIID_PORT_RECV)
588 {
589 // Performs callback processing according to the port number
590 WMPortRecvCallback *cb_Port = (WMPortRecvCallback *)callback_p;
591 SDK_ASSERT(cb_Port->port < 16);
592 // Notify if a callback has been registered.
593 if (w9b->portCallbackTable[cb_Port->port] != NULL)
594 {
595 cb_Port->arg = w9b->portCallbackArgument[cb_Port->port];
596 cb_Port->connectedAidBitmap = (u16)w9b->connectedAidBitmap;
597 DC_InvalidateRange(cb_Port->recvBuf, w9b->status->mp_recvBufSize); // To Do: Too much is being invalidated here
598 (w9b->portCallbackTable[cb_Port->port]) ((void *)cb_Port);
599 }
600 #ifdef WM_DEBUG
601 else
602 {
603 WM_DPRINTF("Warning: no callback function on port %d { %04x %04x ... }\n",
604 cb_Port->port, cb_Port->data[0], cb_Port->data[1]);
605 }
606 #endif
607 }
608 else if (callback_p->apiid == WM_APIID_PORT_SEND)
609 {
610 // Performs the callback specified when the data is set
611 WMPortSendCallback *cb_Port = (WMPortSendCallback *)callback_p;
612 callback_p->apiid = WM_APIID_SET_MP_DATA; // Camouflages
613 if (cb_Port->callback != NULL)
614 {
615 (cb_Port->callback) ((void *)cb_Port);
616 }
617 }
618 else
619 {
620 OS_Printf("ARM9: no callback function\n");
621
622 }
623 }
624 else
625 {
626 // Invalidates the cache of the receive buffer
627 // When PORT_RECV is called after MPEND_IND and MP_IND, InvalidateRange has already been done, so there is no need to be concerned with the cache again.
628 //
629 if (callback_p->apiid == WM_APIID_START_MP)
630 {
631 WMStartMPCallback *cb_StartMP = (WMStartMPCallback *)callback_p;
632 if (cb_StartMP->state == WM_STATECODE_MPEND_IND
633 || cb_StartMP->state == WM_STATECODE_MP_IND)
634 {
635 if (cb_StartMP->errcode == WM_ERRCODE_SUCCESS)
636 {
637 DC_InvalidateRange(cb_StartMP->recvBuf, w9b->status->mp_recvBufSize);
638 }
639 }
640 }
641
642 // Remove the sleep callback if WM_Enable failed or WM_Disable succeeded.
643 if( ( (callback_p->apiid == WM_APIID_DISABLE || callback_p->apiid == WM_APIID_END) && callback_p->errcode == WM_ERRCODE_SUCCESS) ||
644 ( (callback_p->apiid == WM_APIID_ENABLE || callback_p->apiid == WM_APIID_INITIALIZE) && callback_p->errcode != WM_ERRCODE_SUCCESS) )
645 {
646 WMi_DeleteSleepCallback();
647 }
648
649 // WM_End post-processing
650 if (callback_p->apiid == WM_APIID_END)
651 {
652 if (callback_p->errcode == WM_ERRCODE_SUCCESS)
653 {
654 WMCallbackFunc cb = w9b->CallbackTable[callback_p->apiid];
655 // Close WM library
656 (void)WM_Finish();
657 if (cb != NULL)
658 {
659 cb((void *)callback_p);
660 }
661
662 WM_DLOGF_CALLBACK("Cb[%x]", callback_p->apiid);
663
664 return;
665 }
666 }
667
668 #if 0
669 // Post-processing for WM_Reset, WM_Disconnect, and WM_EndParent.
670 if (callback_p->apiid == WM_APIID_RESET
671 || callback_p->apiid == WM_APIID_DISCONNECT || callback_p->apiid == WM_APIID_END_PARENT)
672 {
673 if (w9b->connectedAidBitmap != 0)
674 {
675 WM_WARNING("connectedAidBitmap should be 0, but %04x", w9b->connectedAidBitmap);
676 }
677 w9b->myAid = 0;
678 w9b->connectedAidBitmap = 0;
679 }
680 #endif
681
682 // Callback processing according to apiid (does nothing if callback not set (NULL))
683 if (NULL != w9b->CallbackTable[callback_p->apiid])
684 {
685 (w9b->CallbackTable[callback_p->apiid]) ((void *)callback_p);
686 /* If WM_Finish was called in user callback and working memory was cleared, end here. */
687 if (!wmInitialized)
688 {
689 return;
690 }
691 }
692 // Post-processing
693 // Process the messages so that the callback for the port can also be notified regarding connections/disconnections.
694 if (callback_p->apiid == WM_APIID_START_PARENT
695 || callback_p->apiid == WM_APIID_START_CONNECT)
696 {
697 u16 state, aid, myAid, reason;
698 u8 *macAddress;
699 u8 *ssid;
700 u16 parentSize, childSize;
701
702 if (callback_p->apiid == WM_APIID_START_PARENT)
703 {
704 WMStartParentCallback *cb = (WMStartParentCallback *)callback_p;
705 state = cb->state;
706 aid = cb->aid;
707 myAid = 0;
708 macAddress = cb->macAddress;
709 ssid = cb->ssid;
710 reason = cb->reason;
711 parentSize = cb->parentSize;
712 childSize = cb->childSize;
713 }
714 else if (callback_p->apiid == WM_APIID_START_CONNECT)
715 {
716 WMStartConnectCallback *cb = (WMStartConnectCallback *)callback_p;
717 state = cb->state;
718 aid = 0;
719 myAid = cb->aid;
720 macAddress = cb->macAddress;
721 ssid = NULL;
722 reason = cb->reason;
723 parentSize = cb->parentSize;
724 childSize = cb->childSize;
725 }
726 if (state == WM_STATECODE_CONNECTED ||
727 state == WM_STATECODE_DISCONNECTED
728 || state == WM_STATECODE_DISCONNECTED_FROM_MYSELF)
729 {
730 // Since this is inside the interrupt handler, there's no problem if it is static.
731 static WMPortRecvCallback cb_Port;
732 u16 iPort;
733
734 // Change the connection status being managed on the WM9 side.
735 if (state == WM_STATECODE_CONNECTED)
736 {
737 #ifdef WM_DEBUG
738 if (w9b->connectedAidBitmap & (1 << aid))
739 {
740 WM_DPRINTF("Warning: someone is connecting to connected aid: %d (%04x)",
741 aid, w9b->connectedAidBitmap);
742 }
743 #endif
744 WM_DLOGF_AIDBITMAP("aid(%d) connected: %04x -> %04x", aid,
745 w9b->connectedAidBitmap,
746 w9b->connectedAidBitmap | (1 << aid));
747 w9b->connectedAidBitmap |= (1 << aid);
748 }
749 else // WM_STATECODE_DISCONNECTED || WM_STATECODE_DISCONNECTED_FROM_MYSELF
750 {
751 #ifdef WM_DEBUG
752 if (!(w9b->connectedAidBitmap & (1 << aid)))
753 {
754 WM_DPRINTF
755 ("Warning: someone is disconnecting to disconnected aid: %d (%04x)",
756 aid, w9b->connectedAidBitmap);
757 }
758 #endif
759 WM_DLOGF_AIDBITMAP("aid(%d) disconnected: %04x -> %04x", aid,
760 w9b->connectedAidBitmap,
761 w9b->connectedAidBitmap & ~(1 << aid));
762 w9b->connectedAidBitmap &= ~(1 << aid);
763 }
764 w9b->myAid = myAid;
765
766 MI_CpuClear8(&cb_Port, sizeof(WMPortRecvCallback));
767 cb_Port.apiid = WM_APIID_PORT_RECV;
768 cb_Port.errcode = WM_ERRCODE_SUCCESS;
769 cb_Port.state = state;
770 cb_Port.recvBuf = NULL;
771 cb_Port.data = NULL;
772 cb_Port.length = 0;
773 cb_Port.aid = aid;
774 cb_Port.myAid = myAid;
775 cb_Port.connectedAidBitmap = (u16)w9b->connectedAidBitmap;
776 cb_Port.seqNo = 0xffff;
777 cb_Port.reason = reason;
778 MI_CpuCopy8(macAddress, cb_Port.macAddress, WM_SIZE_MACADDR);
779 if (ssid != NULL)
780 {
781 MI_CpuCopy16(ssid, cb_Port.ssid, WM_SIZE_CHILD_SSID);
782 }
783 else
784 {
785 MI_CpuClear16(cb_Port.ssid, WM_SIZE_CHILD_SSID);
786 }
787 cb_Port.maxSendDataSize = (u16)((myAid == 0) ? parentSize : childSize);
788 cb_Port.maxRecvDataSize = (u16)((myAid == 0) ? childSize : parentSize);
789
790 // Notify all ports of connections/disconnections.
791 for (iPort = 0; iPort < WM_NUM_OF_PORT; iPort++)
792 {
793 cb_Port.port = iPort;
794 if (w9b->portCallbackTable[iPort] != NULL)
795 {
796 cb_Port.arg = w9b->portCallbackArgument[iPort];
797 (w9b->portCallbackTable[iPort]) ((void *)&cb_Port);
798 }
799 }
800 }
801 }
802 }
803 // The fifo7to9 region has been written with PORT_SEND and PORT_RECV, so the cache is invalidated so as to not be written back.
804 //
805 DC_InvalidateRange(w9b->fifo7to9, WM_FIFO_BUF_SIZE);
806 WmClearFifoRecvFlag();
807
808 // If the response buffer is a different buffer from fifo7to9, camouflage the request reception completion flag.
809 if ((u32)callback_p != (u32)(w9b->fifo7to9))
810 {
811 callback_p->apiid |= WM_API_REQUEST_ACCEPTED;
812 DC_StoreRange(callback_p, WM_FIFO_BUF_SIZE);
813 }
814
815 WM_DLOGF2_CALLBACK(beginVcount, "[CB](%x)", callback_p->apiid);
816
817 return;
818 }
819
820 /*---------------------------------------------------------------------------*
821 Name: WmClearFifoRecvFlag
822
823 Description: Notifies WM7 that reference to the FIFO data used in the WM7 callback is complete.
824
825 When using FIFO for callback in WM7, edit the next callback after waiting for this flag to unlock.
826
827
828 Arguments: None.
829
830 Returns: None.
831 *---------------------------------------------------------------------------*/
WmClearFifoRecvFlag(void)832 static void WmClearFifoRecvFlag(void)
833 {
834 if (OS_GetSystemWork()->wm_callback_control & WM_EXCEPTION_CB_MASK)
835 {
836 // Disables the CB exclusion flag
837 OS_GetSystemWork()->wm_callback_control &= ~WM_EXCEPTION_CB_MASK;
838 }
839 }
840
841 /*---------------------------------------------------------------------------*
842 Name: WMi_DebugPrintSendQueue
843
844 Description: Print outputs the contents of the port send queue.
845
846 Arguments: queue: Specifies the pointer to the port send queue.
847
848 Returns: None.
849 *---------------------------------------------------------------------------*/
WMi_DebugPrintSendQueue(WMPortSendQueue * queue)850 void WMi_DebugPrintSendQueue(WMPortSendQueue *queue)
851 {
852 WMstatus *status = wm9buf->status;
853 WMPortSendQueueData *queueData;
854 u16 index;
855
856 DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE); // Invalidates the ARM7 status region cache
857 queueData = status->sendQueueData;
858
859 OS_Printf("head = %d, tail = %d, ", queue->head, queue->tail);
860 if (queue->tail != WM_SEND_QUEUE_END)
861 {
862 OS_Printf("%s", (queueData[queue->tail].next == WM_SEND_QUEUE_END) ? "valid" : "invalid");
863 }
864 OS_Printf("\n");
865 for (index = queue->head; index != WM_SEND_QUEUE_END; index = queueData[index].next)
866 {
867 WMPortSendQueueData *data = &(queueData[index]);
868
869 OS_Printf("queueData[%d] -> %d { port=%d, destBitmap=%x, size=%d } \n", index, data->next,
870 data->port, data->destBitmap, data->size);
871 }
872
873 }
874
875 /*---------------------------------------------------------------------------*
876 Name: WMi_DebugPrintAllSendQueue
877
878 Description: Print outputs the contents of all the port send queues.
879
880 Arguments: None.
881
882 Returns: None.
883 *---------------------------------------------------------------------------*/
WMi_DebugPrintAllSendQueue(void)884 void WMi_DebugPrintAllSendQueue(void)
885 {
886 WMstatus *status = wm9buf->status;
887 #if 0
888 int iPrio;
889
890 DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE); // Invalidates the ARM7 status region cache
891 for (iPrio = 0; iPrio < WM_PRIORITY_LEVEL; iPrio++)
892 {
893 OS_Printf("== send queue [%d]\n", iPrio);
894 WMi_DebugPrintSendQueue(&status->sendQueue[iPrio]);
895 }
896 for (iPrio = 0; iPrio < WM_PRIORITY_LEVEL; iPrio++)
897 {
898 OS_Printf("== ready queue [%d]\n", iPrio);
899 WMi_DebugPrintSendQueue(&status->readyQueue[iPrio]);
900 }
901 OS_Printf("== free queue\n");
902 OS_Printf(" head: %d, tail: %d\n", status->sendQueueFreeList.head,
903 status->sendQueueFreeList.tail);
904 // WMi_DebugPrintSendQueue( &status->sendQueueFreeList );
905 #else
906 DC_InvalidateRange(wm9buf->status, WM_STATUS_BUF_SIZE); // Invalidates the ARM7 status region cache
907 OS_Printf("== ready queue [2]\n");
908 OS_Printf(" head: %d, tail: %d\n", status->readyQueue[2].head, status->readyQueue[2].tail);
909 #endif
910
911 }
912
913 /*---------------------------------------------------------------------------*
914 Name: WMi_GetStatusAddress
915
916 Description: Gets the pointer to the status structure managed internally by WM.
917 This structure is directly operated by ARM7, so writing by ARM9 is disabled.
918 Also, note that the cache line containing the portion to be referenced needs to be deleted before referencing the contents.
919
920
921 Arguments: None.
922
923 Returns: const WMStatus* : Returns a pointer to the status structure.
924 *---------------------------------------------------------------------------*/
WMi_GetStatusAddress(void)925 const WMStatus *WMi_GetStatusAddress(void)
926 {
927 // Initialization check
928 if (WMi_CheckInitialized() != WM_ERRCODE_SUCCESS)
929 {
930 return NULL;
931 }
932
933 return wm9buf->status;
934 }
935
936 /*---------------------------------------------------------------------------*
937 Name: WMi_CheckMpPacketTimeRequired
938
939 Description: Confirms that no more than 5,600 microseconds are needed to send a single MP communication packet.
940
941
942 Arguments: parentSize: Size of parent transfer data
943 childSize: Size of child transfer data.
944 childs: Number of child devices to communicate with.
945
946 Returns: BOOL: If within the acceptable range, returns TRUE.
947 If it exceeds 5,600 microseconds, returns FALSE.
948 *---------------------------------------------------------------------------*/
WMi_CheckMpPacketTimeRequired(u16 parentSize,u16 childSize,u8 childs)949 BOOL WMi_CheckMpPacketTimeRequired(u16 parentSize, u16 childSize, u8 childs)
950 {
951 s32 mp_time;
952
953 // Calculate the time it takes for one MP communication in units of microseconds
954 mp_time = (( // --- Parent send portion ---
955 96 // Preamble
956 + (24 // 802.11 Header
957 + 4 // TXOP + PollBitmap
958 + 2 // wmHeader
959 + parentSize + 4 // wmFooter( parent )
960 + 4 // FCS
961 ) * 4 // 4microseconds per 1 byte
962 ) + ( // --- Child send portion ---
963 (10 // SIFS
964 + 96 // Preamble
965 + (24 // 802.11 Header
966 + 2 // wmHeader
967 + childSize + 2 // wmFooter( child )
968 + 4 // FCS
969 ) * 4 // 4microseconds per 1 byte
970 + 6 // time to spare
971 ) * childs) + ( // --- MP ACK send portion ---
972 10 // SIFS
973 + 96 // Preamble
974 + (24 // 802.11 Header
975 + 4 // ACK
976 + 4 // FCS
977 ) * 4 // 4microseconds per 1 byte
978 ));
979
980 if (mp_time > WM_MAX_MP_PACKET_TIME)
981 {
982 OS_TWarning
983 ("It is required %dus to transfer each MP packet.\nThat should not exceed %dus.\n",
984 mp_time, WM_MAX_MP_PACKET_TIME);
985 return FALSE;
986 }
987 return TRUE;
988 }
989
990 /*---------------------------------------------------------------------------*
991 Name: WMi_IsMP
992
993 Description: Gets current MP communication state.
994
995 Arguments: None.
996
997 Returns: TRUE if in MP communication state.
998 *---------------------------------------------------------------------------*/
WMi_IsMP(void)999 BOOL WMi_IsMP(void)
1000 {
1001 WMStatus *status;
1002 BOOL isMP;
1003 OSIntrMode e;
1004
1005 #ifdef SDK_DEBUG
1006 // Initialization check
1007 if (WMi_CheckInitialized() != WM_ERRCODE_SUCCESS)
1008 {
1009 return FALSE;
1010 }
1011 #endif
1012
1013 // Disable interrupts
1014 e = OS_DisableInterrupts();
1015
1016 if (wm9buf != NULL)
1017 {
1018 status = wm9buf->status;
1019 DC_InvalidateRange(&(status->mp_flag), 4);
1020 isMP = status->mp_flag;
1021 }
1022 else
1023 {
1024 isMP = FALSE;
1025 }
1026
1027 // End disabling of interrupts
1028 (void)OS_RestoreInterrupts(e);
1029
1030 return isMP;
1031 }
1032
1033 /*---------------------------------------------------------------------------*
1034 Name: WM_GetAID
1035
1036 Description: Gets current AID.
1037 Return a valid value only when the state is one of PARENT, MP_PARENT, CHILD, or MP_CHILD.
1038
1039
1040 Arguments: None.
1041
1042 Returns: AID
1043 *---------------------------------------------------------------------------*/
WM_GetAID(void)1044 u16 WM_GetAID(void)
1045 {
1046 u16 myAid;
1047 OSIntrMode e;
1048
1049 #ifdef SDK_DEBUG
1050 // Initialization check
1051 if (WMi_CheckInitialized() != WM_ERRCODE_SUCCESS)
1052 {
1053 return 0;
1054 }
1055 #endif
1056
1057 // Disable interrupts
1058 e = OS_DisableInterrupts();
1059
1060 if (wm9buf != NULL)
1061 {
1062 myAid = wm9buf->myAid;
1063 }
1064 else
1065 {
1066 myAid = 0;
1067 }
1068
1069 // End disabling of interrupts
1070 (void)OS_RestoreInterrupts(e);
1071
1072 return myAid;
1073 }
1074
1075 /*---------------------------------------------------------------------------*
1076 Name: WM_GetConnectedAIDs
1077
1078 Description: Gets the currently connected partners in bitmap format.
1079 Return a valid value only when the state is one of PARENT, MP_PARENT, CHILD, or MP_CHILD.
1080
1081 For a child device, returns 0x0001 when the child is connected to a parent.
1082
1083 Arguments: None.
1084
1085 Returns: Bitmap of AIDs of connected partners.
1086 *---------------------------------------------------------------------------*/
WM_GetConnectedAIDs(void)1087 u16 WM_GetConnectedAIDs(void)
1088 {
1089 u32 connectedAidBitmap;
1090 OSIntrMode e;
1091
1092 #ifdef SDK_DEBUG
1093 // Initialization check
1094 if (WMi_CheckInitialized() != WM_ERRCODE_SUCCESS)
1095 {
1096 return 0;
1097 }
1098 #endif
1099
1100 // Disable interrupts
1101 e = OS_DisableInterrupts();
1102
1103 if (wm9buf != NULL)
1104 {
1105 connectedAidBitmap = wm9buf->connectedAidBitmap;
1106 }
1107 else
1108 {
1109 connectedAidBitmap = 0;
1110 }
1111
1112 // End disabling of interrupts
1113 (void)OS_RestoreInterrupts(e);
1114
1115 #ifdef WM_DEBUG
1116 /*
1117 if (WMi_CheckStateEx(4, WM_STATE_PARENT, WM_STATE_CHILD, WM_STATE_MP_PARENT, WM_STATE_MP_CHILD)
1118 != WM_ERRCODE_SUCCESS && connectedAidBitmap != 0)
1119 {
1120 WM_WARNING("connectedAidBitmap should be 0, but %04x", connectedAidBitmap);
1121 }
1122 */
1123 #endif
1124
1125 return (u16)connectedAidBitmap;
1126 }
1127
1128 /*---------------------------------------------------------------------------*
1129 Name: WMi_GetMPReadyAIDs
1130
1131 Description: From among the currently connected parties, gets a list in bitmap format of the AIDs of parties which can receive MP.
1132
1133 Return a valid value only when the state is one of PARENT, MP_PARENT, CHILD, or MP_CHILD.
1134
1135 For a child device, returns 0x0001 when the child is connected to a parent.
1136
1137 Arguments: None.
1138
1139 Returns: Bitmap of the AIDs of partners with which MP is started.
1140 *---------------------------------------------------------------------------*/
WMi_GetMPReadyAIDs(void)1141 u16 WMi_GetMPReadyAIDs(void)
1142 {
1143 WMStatus *status;
1144 u16 mpReadyAidBitmap;
1145 OSIntrMode e;
1146
1147 #ifdef SDK_DEBUG
1148 // Initialization check
1149 if (WMi_CheckInitialized() != WM_ERRCODE_SUCCESS)
1150 {
1151 return FALSE;
1152 }
1153 #endif
1154
1155 // Disable interrupts
1156 e = OS_DisableInterrupts();
1157
1158 if (wm9buf != NULL)
1159 {
1160 status = wm9buf->status;
1161 DC_InvalidateRange(&(status->mp_readyBitmap), 2);
1162 mpReadyAidBitmap = status->mp_readyBitmap;
1163 }
1164 else
1165 {
1166 mpReadyAidBitmap = FALSE;
1167 }
1168
1169 // End disabling of interrupts
1170 (void)OS_RestoreInterrupts(e);
1171
1172 return mpReadyAidBitmap;
1173 }
1174
1175 /*---------------------------------------------------------------------------*
1176 Name: WMi_RegisterSleepCallback
1177
1178 Description: Registers the callback function that will be run when shifting to Sleep Mode.
1179
1180 Arguments: None.
1181
1182 Returns: None.
1183 *---------------------------------------------------------------------------*/
WMi_RegisterSleepCallback(void)1184 void WMi_RegisterSleepCallback(void)
1185 {
1186 PM_SetSleepCallbackInfo(&sleepCbInfo, WmSleepCallback, NULL);
1187 PMi_InsertPreSleepCallbackEx(&sleepCbInfo, PM_CALLBACK_PRIORITY_WM );
1188 }
1189
1190 /*---------------------------------------------------------------------------*
1191 Name: WMi_DeleteSleepCallback
1192
1193 Description: Deletes the callback function that is run when shifting to Sleep Mode.
1194
1195 Arguments: None.
1196
1197 Returns: None.
1198 *---------------------------------------------------------------------------*/
WMi_DeleteSleepCallback(void)1199 void WMi_DeleteSleepCallback(void)
1200 {
1201 PM_DeletePreSleepCallback( &sleepCbInfo );
1202 }
1203
1204 /*---------------------------------------------------------------------------*
1205 Name: WmSleepCallback
1206
1207 Description: Prevents the program from entering Sleep Mode during wireless communications.
1208
1209 Arguments: None.
1210
1211 Returns: None.
1212 *---------------------------------------------------------------------------*/
WmSleepCallback(void *)1213 static void WmSleepCallback(void *)
1214 {
1215 /* ---------------------------------------------- *
1216 * As described in section 6.5 of the Programming Guidelines, it is prohibited to run OS_GoSleepMode() during wireless communications.
1217 *
1218 *
1219 * ---------------------------------------------- */
1220 OS_Panic("Could not sleep during wireless communications.");
1221 }
1222
1223 #ifdef SDK_TWL
1224 /*---------------------------------------------------------------------------*
1225 Name: WM_GetWirelessCommFlag
1226
1227 Description: Checks whether wireless communications can be performed now.
1228
1229 Arguments: None.
1230
1231 Returns: WM_WIRELESS_COMM_FLAG_OFF: Wireless communications are not allowed
1232 WM_WIRELESS_COMM_FLAG_ON: Wireless communications are allowed
1233 WM_WIRELESS_COMM_FLAG_UNKNOWN: This cannot be determined because the program is running on a DS
1234 *---------------------------------------------------------------------------*/
WM_GetWirelessCommFlag(void)1235 u8 WM_GetWirelessCommFlag( void )
1236 {
1237 u8 result = WM_WIRELESS_COMM_FLAG_UNKNOWN;
1238
1239 if( OS_IsRunOnTwl() )
1240 {
1241 if( WMi_CheckEnableFlag() )
1242 {
1243 result = WM_WIRELESS_COMM_FLAG_ON;
1244 }
1245 else
1246 {
1247 result = WM_WIRELESS_COMM_FLAG_OFF;
1248 }
1249 }
1250
1251 return result;
1252 }
1253
1254 /*---------------------------------------------------------------------------*
1255 Name: WMi_CheckEnableFlag
1256
1257 Description: Checks the flag that allows wireless use, configurable from the TWL System Settings.
1258
1259 Arguments: None.
1260
1261 Returns: TRUE if wireless features can be used and FALSE otherwise
1262 *---------------------------------------------------------------------------*/
WMi_CheckEnableFlag(void)1263 BOOL WMi_CheckEnableFlag(void)
1264 {
1265
1266 if( OS_IsAvailableWireless() == TRUE && OS_IsForceDisableWireless() == FALSE )
1267 {
1268 return TRUE;
1269 }
1270 return FALSE;
1271 }
1272 #endif
1273
1274 /*---------------------------------------------------------------------------*
1275 End of file
1276 *---------------------------------------------------------------------------*/
1277