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(¶m, sizeof(param));
310 param.mask = WM_MP_PARAM_CHILD_SIZE;
311 param.childSize = childSize;
312
313 return WM_SetMPParameter(callback, ¶m);
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(¶m, sizeof(param));
333 param.mask = WM_MP_PARAM_PARENT_SIZE;
334 param.parentSize = parentSize;
335
336 return WM_SetMPParameter(callback, ¶m);
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(¶m, 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, ¶m);
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(¶m, 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, ¶m);
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(¶m, 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, ¶m);
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