1 /*---------------------------------------------------------------------------*
2   Project:  TwlSDK - WM - libraries
3   File:     wm_mp.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-17#$
14   $Rev: 8556 $
15   $Author: okubata_ryoma $
16  *---------------------------------------------------------------------------*/
17 
18 #include    <nitro/wm.h>
19 #include    "wm_arm9_private.h"
20 
21 
22 /*---------------------------------------------------------------------------*
23     Internal Function Definitions
24  *---------------------------------------------------------------------------*/
25 
26 /*---------------------------------------------------------------------------*
27     function definitions
28  *---------------------------------------------------------------------------*/
29 
30 /*---------------------------------------------------------------------------*
31   Name:         WMi_StartMP
32 
33   Description:  Starts the MP communication. Function that is common to parent and child.
34 
35   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
36                 recvBuf     -   Receive data storage buffer.
37                                 Pay attention to cache because ARM7 writes out data directly.
38                 recvBufSize -   Size of the receive data storage buffer.
39                                 It must be larger than the return value of WM_GetReceiveBufferSize().
40                 sendBuf     -   Buffer that stores the send data.
41                                 Pay attention to cache because ARM7 writes out data directly.
42                 sendBufSize -   Size of the send data storage buffer.
43                                 It must be larger than the return value of WM_GetSendBufferSize().
44                 tmpParam       -   MP communications temporary parameter structure set before MP starts.
45 
46   Returns:      WMErrCode   -   Returns the processing result.
47                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
48 
49  *---------------------------------------------------------------------------*/
WMi_StartMP(WMCallbackFunc callback,u16 * recvBuf,u16 recvBufSize,u16 * sendBuf,u16 sendBufSize,WMMPTmpParam * tmpParam)50 WMErrCode WMi_StartMP(WMCallbackFunc callback,
51                       u16 *recvBuf,
52                       u16 recvBufSize, u16 *sendBuf, u16 sendBufSize, WMMPTmpParam* tmpParam)
53 {
54     WMErrCode result;
55     WMArm9Buf *p = WMi_GetSystemWork();
56     WMStatus *status = p->status;
57 
58     // Check the state
59     result = WMi_CheckStateEx(2, WM_STATE_PARENT, WM_STATE_CHILD);
60     WM_CHECK_RESULT(result);
61 
62     // If the child device is not in power save mode, do not start MP
63     DC_InvalidateRange(&(status->aid), 2);
64     DC_InvalidateRange(&(status->pwrMgtMode), 2);
65     if (status->aid != 0 && status->pwrMgtMode != 1)
66     {
67         WM_WARNING("Could not start MP. Power save mode is illegal.\n");
68         return WM_ERRCODE_ILLEGAL_STATE;
69     }
70 
71     // MP state confirmation
72     DC_InvalidateRange(&(status->mp_flag), 4);  // Invalidates the ARM7 status region cache
73     if (status->mp_flag == TRUE)
74     {
75         WM_WARNING("Already started MP protocol. So can't execute request.\n");
76         return WM_ERRCODE_ILLEGAL_STATE;
77     }
78 
79     // Check parameters
80     if ((recvBufSize & 0x3f) != 0)     // recvBufSize/2 must be a multiple of 32 bytes
81     {
82         WM_WARNING("Parameter \"recvBufSize\" is not a multiple of 64.\n");
83         return WM_ERRCODE_INVALID_PARAM;
84     }
85     if ((sendBufSize & 0x1f) != 0)     // sendBufSize must be a multiple of 32 bytes
86     {
87         WM_WARNING("Parameter \"sendBufSize\" is not a multiple of 32.\n");
88         return WM_ERRCODE_INVALID_PARAM;
89     }
90     if ((u32)recvBuf & 0x01f)
91     {
92         // Alignment check is a warning only, not an error
93         WM_WARNING("Parameter \"recvBuf\" is not 32-byte aligned.\n");
94     }
95     if ((u32)sendBuf & 0x01f)
96     {
97         // Alignment check is a warning only, not an error
98         WM_WARNING("Parameter \"sendBuf\" is not 32-byte aligned.\n");
99     }
100 
101     DC_InvalidateRange(&(status->mp_ignoreSizePrecheckMode),
102                        sizeof(status->mp_ignoreSizePrecheckMode));
103     if (status->mp_ignoreSizePrecheckMode == FALSE)
104     {
105         // Runs a preliminary check of the send/receive size.
106         if (recvBufSize < WM_GetMPReceiveBufferSize())
107         {
108             WM_WARNING("Parameter \"recvBufSize\" is not enough size.\n");
109             return WM_ERRCODE_INVALID_PARAM;
110         }
111         if (sendBufSize < WM_GetMPSendBufferSize())
112         {
113             WM_WARNING("Parameter \"sendBufSize\" is not enough size.\n");
114             return WM_ERRCODE_INVALID_PARAM;
115         }
116 #ifndef SDK_FINALROM
117         // Check time needed to send data
118         DC_InvalidateRange(&(status->state), 2);
119         if (status->state == WM_STATE_PARENT)
120         {
121             DC_InvalidateRange(&(status->pparam), sizeof(WMParentParam));
122             (void)WMi_CheckMpPacketTimeRequired(status->pparam.parentMaxSize,
123                                                 status->pparam.childMaxSize,
124                                                 (u8)(status->pparam.maxEntry));
125         }
126 #endif
127     }
128 
129     // Register callback function
130     WMi_SetCallbackTable(WM_APIID_START_MP, callback);
131 
132     // Notify ARM7 with FIFO
133     {
134         WMStartMPReq Req;
135 
136         MI_CpuClear32(&Req, sizeof(Req));
137 
138         Req.apiid = WM_APIID_START_MP;
139         Req.recvBuf = (u32 *)recvBuf;
140         Req.recvBufSize = (u32)(recvBufSize / 2);       // Size of one buffer
141         Req.sendBuf = (u32 *)sendBuf;
142         Req.sendBufSize = (u32)sendBufSize;
143 
144         MI_CpuClear32(&Req.param, sizeof(Req.param)); // unused
145         MI_CpuCopy32(tmpParam, &Req.tmpParam, sizeof(Req.tmpParam));
146 
147         result = WMi_SendCommandDirect(&Req, sizeof(Req));
148         WM_CHECK_RESULT(result);
149     }
150 
151     return WM_ERRCODE_OPERATING;
152 }
153 
154 /*---------------------------------------------------------------------------*
155   Name:         WM_StartMPEx
156 
157   Description:  Starts the MP communication. Detailed operation mode can be specified. Function that is common to parent and child.
158 
159   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
160                 recvBuf     -   Receive data storage buffer.
161                                     Pay attention to cache because ARM7 writes out data directly.
162                 recvBufSize -   Size of the receive data storage buffer.
163                                     It must be larger than the return value of WM_GetReceiveBufferSize().
164                 sendBuf     -   Buffer that stores the send data.
165                                     Pay attention to cache because ARM7 writes out data directly.
166                 sendBufSize -   Size of the send data storage buffer.
167                                     It must be larger than the return value of WM_GetSendBufferSize().
168                 mpFreq      -   How many times MP communication is performed in one frame.
169                                     0 is continuous send mode. This carries a meaning only for the parent.
170                 defaultRetryCount - The standard number of retries when transmission fails during communication on ports 0-7.
171                                      Specify 0 to not retry.
172                 minPollBmpMode - Operating mode that suppresses the pollBitmap during MP communications to the minimum bit set of devices according to the address to which packets are sent.
173 
174                 singlePacketMode - Special operating mode that sends only a single packet per MP.
175 
176                 fixFreqMode     -   Special operation mode that prohibits the increase of the MP communication by retries.
177                                     Fixed to exactly mpFreq times for the number of times during the MP communication in a frame.
178 
179                 ignoreFatalError -  Stops performing AutoDisconnect when FatalError was generated.
180 
181   Returns:      WMErrCode   -   Returns the processing result.
182                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
183 
184  *---------------------------------------------------------------------------*/
185 WMErrCode
WM_StartMPEx(WMCallbackFunc callback,u16 * recvBuf,u16 recvBufSize,u16 * sendBuf,u16 sendBufSize,u16 mpFreq,u16 defaultRetryCount,BOOL minPollBmpMode,BOOL singlePacketMode,BOOL fixFreqMode,BOOL ignoreFatalError)186 WM_StartMPEx(WMCallbackFunc callback,
187              u16 *recvBuf,
188              u16 recvBufSize,
189              u16 *sendBuf,
190              u16 sendBufSize,
191              u16 mpFreq,
192              u16 defaultRetryCount,
193              BOOL minPollBmpMode, BOOL singlePacketMode, BOOL fixFreqMode, BOOL ignoreFatalError)
194 {
195     WMMPTmpParam tmpParam;
196 
197     MI_CpuClear32(&tmpParam, sizeof(tmpParam));
198 
199     tmpParam.mask = WM_MP_TMP_PARAM_MIN_FREQUENCY | WM_MP_TMP_PARAM_FREQUENCY | WM_MP_TMP_PARAM_DEFAULT_RETRY_COUNT
200         | WM_MP_TMP_PARAM_MIN_POLL_BMP_MODE | WM_MP_TMP_PARAM_SINGLE_PACKET_MODE |
201         WM_MP_TMP_PARAM_IGNORE_FATAL_ERROR_MODE;
202     tmpParam.minFrequency = mpFreq;
203     tmpParam.frequency = mpFreq;
204     tmpParam.defaultRetryCount = defaultRetryCount;
205     tmpParam.minPollBmpMode = (u8)minPollBmpMode;
206     tmpParam.singlePacketMode = (u8)singlePacketMode;
207     tmpParam.ignoreFatalErrorMode = (u8)ignoreFatalError;
208 
209     if (fixFreqMode != FALSE && mpFreq != 0)
210     {
211         tmpParam.mask |= WM_MP_TMP_PARAM_MAX_FREQUENCY;
212         tmpParam.maxFrequency = mpFreq;
213     }
214 
215     return WMi_StartMP(callback, recvBuf, recvBufSize, sendBuf, sendBufSize, &tmpParam);
216 }
217 
218 /*---------------------------------------------------------------------------*
219   Name:         WM_StartMP
220 
221   Description:  Starts the MP communication. Function that is common to parent and child.
222 
223   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
224                 recvBuf     -   Receive data storage buffer.
225                                 Pay attention to cache because ARM7 writes out data directly.
226                 recvBufSize -   Size of the receive data storage buffer.
227                                 It must be larger than the return value of WM_GetReceiveBufferSize().
228                 sendBuf     -   Buffer that stores the send data.
229                                 Pay attention to cache because ARM7 writes out data directly.
230                 sendBufSize -   Size of the send data storage buffer.
231                                 It must be larger than the return value of WM_GetSendBufferSize().
232                 mpFreq      -   How many times MP communication is performed in one frame.
233                                 0 is continuous send mode. This carries a meaning only for the parent.
234 
235   Returns:      WMErrCode   -   Returns the processing result.
236                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
237 
238  *---------------------------------------------------------------------------*/
WM_StartMP(WMCallbackFunc callback,u16 * recvBuf,u16 recvBufSize,u16 * sendBuf,u16 sendBufSize,u16 mpFreq)239 WMErrCode WM_StartMP(WMCallbackFunc callback,
240                      u16 *recvBuf, u16 recvBufSize, u16 *sendBuf, u16 sendBufSize, u16 mpFreq)
241 {
242     WMMPTmpParam tmpParam;
243 
244     MI_CpuClear32(&tmpParam, sizeof(tmpParam));
245 
246     tmpParam.mask = WM_MP_TMP_PARAM_FREQUENCY | WM_MP_TMP_PARAM_MIN_FREQUENCY;
247     tmpParam.minFrequency = mpFreq;
248     tmpParam.frequency = mpFreq;
249 
250     return WMi_StartMP(callback, recvBuf, recvBufSize, sendBuf, sendBufSize, &tmpParam);
251 }
252 
253 /*---------------------------------------------------------------------------*
254   Name:         WM_SetMPParameter
255 
256   Description:  Configures the different parameters for MP communications
257 
258   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
259                 param       -   Pointer to the structure where the parameters for MP communications are stored
260 
261   Returns:      WMErrCode   -   Returns the processing result.
262                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
263 
264  *---------------------------------------------------------------------------*/
WM_SetMPParameter(WMCallbackFunc callback,const WMMPParam * param)265 WMErrCode WM_SetMPParameter(WMCallbackFunc callback, const WMMPParam * param)
266 {
267     WMErrCode result;
268     WMArm9Buf *p = WMi_GetSystemWork();
269 
270     // Check the state
271     result = WMi_CheckInitialized();
272     WM_CHECK_RESULT(result);
273 
274     // Register callback function
275     WMi_SetCallbackTable(WM_APIID_SET_MP_PARAMETER, callback);
276 
277     // Notify ARM7 with FIFO
278     {
279         WMSetMPParameterReq Req;
280 
281         MI_CpuClear32(&Req, sizeof(Req));
282 
283         Req.apiid = WM_APIID_SET_MP_PARAMETER;
284         MI_CpuCopy32(param, &Req.param, sizeof(Req.param));
285 
286         result = WMi_SendCommandDirect(&Req, sizeof(Req));
287         WM_CHECK_RESULT(result);
288     }
289 
290     return WM_ERRCODE_OPERATING;
291 }
292 
293 /*---------------------------------------------------------------------------*
294   Name:         WM_SetMPChildSize
295 
296   Description:  Sets the number of bytes a child can send in one MP communication.
297 
298   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
299                 childSize   -   Number of send bytes for a child
300 
301   Returns:      WMErrCode   -   Returns the processing result.
302                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
303 
304  *---------------------------------------------------------------------------*/
WM_SetMPChildSize(WMCallbackFunc callback,u16 childSize)305 WMErrCode WM_SetMPChildSize(WMCallbackFunc callback, u16 childSize)
306 {
307     WMMPParam param;
308 
309     MI_CpuClear32(&param, sizeof(param));
310     param.mask = WM_MP_PARAM_CHILD_SIZE;
311     param.childSize = childSize;
312 
313     return WM_SetMPParameter(callback, &param);
314 }
315 
316 /*---------------------------------------------------------------------------*
317   Name:         WM_SetMPParentSize
318 
319   Description:  Sets the number of bytes a parent can send in one MP communication.
320 
321   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
322                 childSize   -   Number of send bytes for a parent.
323 
324   Returns:      WMErrCode   -   Returns the processing result.
325                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
326 
327  *---------------------------------------------------------------------------*/
WM_SetMPParentSize(WMCallbackFunc callback,u16 parentSize)328 WMErrCode WM_SetMPParentSize(WMCallbackFunc callback, u16 parentSize)
329 {
330     WMMPParam param;
331 
332     MI_CpuClear32(&param, sizeof(param));
333     param.mask = WM_MP_PARAM_PARENT_SIZE;
334     param.parentSize = parentSize;
335 
336     return WM_SetMPParameter(callback, &param);
337 }
338 
339 /*---------------------------------------------------------------------------*
340   Name:         WM_SetMPFrequency
341 
342   Description:  Switches how many times to perform the MP communication in one frame. Function for parent device.
343 
344   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
345                 mpFreq      -   How many times MP communication is performed in one frame.
346                                 0 is continuous send mode.
347 
348   Returns:      WMErrCode   -   Returns the processing result.
349                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
350 
351  *---------------------------------------------------------------------------*/
WM_SetMPFrequency(WMCallbackFunc callback,u16 mpFreq)352 WMErrCode WM_SetMPFrequency(WMCallbackFunc callback, u16 mpFreq)
353 {
354     WMMPParam param;
355 
356     MI_CpuClear32(&param, sizeof(param));
357     param.mask = WM_MP_PARAM_FREQUENCY | WM_MP_PARAM_MIN_FREQUENCY;
358     param.minFrequency = mpFreq;
359     param.frequency = mpFreq;
360 
361     return WM_SetMPParameter(callback, &param);
362 }
363 
364 /*---------------------------------------------------------------------------*
365   Name:         WM_SetMPInterval
366 
367   Description:  Sets the interval in which a connection can be made and MP communications carried out in one frame.
368 
369   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
370                 parentInterval - The interval in which a connection can be made and MP communications carried out by a parent in one frame (ms)
371                 childInterval  - The interval in which a connection can be made and MP communications carried out by a child in one frame (ms)
372 
373   Returns:      WMErrCode   -   Returns the processing result.
374                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
375 
376  *---------------------------------------------------------------------------*/
WM_SetMPInterval(WMCallbackFunc callback,u16 parentInterval,u16 childInterval)377 WMErrCode WM_SetMPInterval(WMCallbackFunc callback, u16 parentInterval, u16 childInterval)
378 {
379     WMMPParam param;
380 
381     MI_CpuClear32(&param, sizeof(param));
382     param.mask = WM_MP_PARAM_PARENT_INTERVAL | WM_MP_PARAM_CHILD_INTERVAL;
383     param.parentInterval = parentInterval;
384     param.childInterval = childInterval;
385 
386     return WM_SetMPParameter(callback, &param);
387 }
388 
389 /*---------------------------------------------------------------------------*
390   Name:         WM_SetMPTiming
391 
392   Description:  Sets the preparation start timing for MP communications when in frame synchronous communication mode.
393 
394   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
395                 parentVCount -  The parent operation start V Count when in frame simultaneous communications
396                 childVCount -  The child operation start V Count when in frame simultaneous communications
397 
398   Returns:      WMErrCode   -   Returns the processing result.
399                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
400 
401  *---------------------------------------------------------------------------*/
WM_SetMPTiming(WMCallbackFunc callback,u16 parentVCount,u16 childVCount)402 WMErrCode WM_SetMPTiming(WMCallbackFunc callback, u16 parentVCount, u16 childVCount)
403 {
404     WMMPParam param;
405 
406     MI_CpuClear32(&param, sizeof(param));
407     param.mask = WM_MP_PARAM_PARENT_VCOUNT | WM_MP_PARAM_CHILD_VCOUNT;
408     param.parentVCount = parentVCount;
409     param.childVCount = childVCount;
410 
411     return WM_SetMPParameter(callback, &param);
412 }
413 
414 /*---------------------------------------------------------------------------*
415   Name:         WM_SetMPDataToPortEx
416 
417   Description:  Reserves data with MP communication. Function that is common to parent and child.
418 
419   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
420                 arg         -   Argument to be passed to callback
421                 sendData    -   Pointer to the data to reserve send.
422                                 Note that the entity of this data is forcibly stored in cache.
423                 sendDataSize -  Size of the data to reserve send.
424                 destBitmap  -   Specifies bitmap of aid that indicates the send destination child.
425                 port        -   Port number to send
426                 prio        -   Priority (0: highest -- 3: lowest)
427 
428   Returns:      WMErrCode   -   Returns the processing result.
429                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
430 
431  *---------------------------------------------------------------------------*/
432 WMErrCode
WM_SetMPDataToPortEx(WMCallbackFunc callback,void * arg,const u16 * sendData,u16 sendDataSize,u16 destBitmap,u16 port,u16 prio)433 WM_SetMPDataToPortEx(WMCallbackFunc callback, void *arg, const u16 *sendData, u16 sendDataSize,
434                      u16 destBitmap, u16 port, u16 prio)
435 {
436     WMErrCode result;
437     BOOL    isParent;
438     u16     mpReadyBitmap = 0x0001;
439     u16     childBitmap = 0x0001;
440     WMArm9Buf *p = WMi_GetSystemWork();
441     WMStatus *status = p->status;
442 
443     // Check the state
444     result = WMi_CheckStateEx(2, WM_STATE_MP_PARENT, WM_STATE_MP_CHILD);
445     WM_CHECK_RESULT(result);
446 
447     // Get the required data from the WMStatus structure
448     DC_InvalidateRange(&(status->aid), 2);
449     isParent = (status->aid == 0) ? TRUE : FALSE;
450     if (isParent == TRUE)
451     {
452         DC_InvalidateRange(&(status->child_bitmap), 2);
453         childBitmap = status->child_bitmap;
454         DC_InvalidateRange(&(status->mp_readyBitmap), 2);
455         mpReadyBitmap = status->mp_readyBitmap;
456     }
457 
458     // Check parameters
459     if (sendData == NULL)
460     {
461         WM_WARNING("Parameter \"sendData\" must not be NULL.\n");
462         return WM_ERRCODE_INVALID_PARAM;
463     }
464     if (childBitmap == 0)
465     {
466         WM_WARNING("There is no child connected.\n");
467         return WM_ERRCODE_NO_CHILD;
468     }
469     if ((u32)sendData & 0x01f)
470     {
471         // Alignment check is a warning only, not an error
472         WM_WARNING("Parameter \"sendData\" is not 32-byte aligned.\n");
473     }
474     DC_InvalidateRange(&(status->mp_sendBuf), 2);
475     if ((void *)sendData == (void *)status->mp_sendBuf)
476     {
477         WM_WARNING
478             ("Parameter \"sendData\" must not be equal to the WM_StartMP argument \"sendBuf\".\n");
479         return WM_ERRCODE_INVALID_PARAM;
480     }
481 
482     // Check the transmission size.
483     if (sendDataSize > WM_SIZE_MP_DATA_MAX)
484     {
485         WM_WARNING("Parameter \"sendDataSize\" is over limit.\n");
486         return WM_ERRCODE_INVALID_PARAM;
487     }
488 
489     if (sendDataSize == 0)
490     {
491         WM_WARNING("Parameter \"sendDataSize\" must not be 0.\n");
492         return WM_ERRCODE_INVALID_PARAM;
493     }
494 
495 #ifndef SDK_FINALROM
496     // Check time needed to send data
497     DC_InvalidateRange(&(status->mp_current_minPollBmpMode), 2);
498     if (isParent && status->mp_current_minPollBmpMode)
499     {
500         DC_InvalidateRange(&(status->pparam), sizeof(WMParentParam));
501         (void)WMi_CheckMpPacketTimeRequired(status->pparam.parentMaxSize,
502                                             status->pparam.childMaxSize,
503                                             (u8)MATH_CountPopulation((u32)destBitmap));
504     }
505 #endif
506 
507     // Write out the specified buffer's cache
508     DC_StoreRange((void *)sendData, sendDataSize);
509 
510     // No need to register the callback function
511 
512     // Notify ARM7 with FIFO
513     result = WMi_SendCommand(WM_APIID_SET_MP_DATA, 7,
514                              (u32)sendData,
515                              (u32)sendDataSize,
516                              (u32)destBitmap, (u32)port, (u32)prio, (u32)callback, (u32)arg);
517     WM_CHECK_RESULT(result);
518 
519     return WM_ERRCODE_OPERATING;
520 }
521 
522 /*---------------------------------------------------------------------------*
523   Name:         WM_EndMP
524 
525   Description:  Stops MP communication. Function that is common to parent and child.
526 
527   Arguments:    callback    -   Callback function that is called when the asynchronous process completes.
528 
529   Returns:      WMErrCode   -   Returns the processing result.
530                                 Returns WM_ERRCODE_OPERATING if asynchronous processing started successfully. Afterwards, the asynchronous processing results will be passed to the callback.
531 
532  *---------------------------------------------------------------------------*/
WM_EndMP(WMCallbackFunc callback)533 WMErrCode WM_EndMP(WMCallbackFunc callback)
534 {
535     WMErrCode result;
536     WMArm9Buf *p = WMi_GetSystemWork();
537 
538     // Check the state
539     result = WMi_CheckStateEx(2, WM_STATE_MP_PARENT, WM_STATE_MP_CHILD);
540     WM_CHECK_RESULT(result);
541 
542     // MP state confirmation
543     DC_InvalidateRange(&(p->status->mp_flag), 4);
544     if (p->status->mp_flag == FALSE)
545     {
546         WM_WARNING("It is not MP mode now.\n");
547         return WM_ERRCODE_ILLEGAL_STATE;
548     }
549 
550     // Register callback function
551     WMi_SetCallbackTable(WM_APIID_END_MP, callback);
552 
553     // Notify ARM7 with FIFO
554     result = WMi_SendCommand(WM_APIID_END_MP, 0);
555     WM_CHECK_RESULT(result);
556 
557     return WM_ERRCODE_OPERATING;
558 }
559 
560 /*---------------------------------------------------------------------------*
561     End of file
562  *---------------------------------------------------------------------------*/
563