1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - library - dsp
3 File: dsp_pipe.c
4
5 Copyright 2007-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:: 2010-01-08#$
14 $Rev: 11275 $
15 $Author: kakemizu_hironori $
16 *---------------------------------------------------------------------------*/
17
18 #include <twl.h>
19 #include <twl/dsp.h>
20 #include <twl/dsp/common/pipe.h>
21
22
23 /*---------------------------------------------------------------------------*/
24 /* Variables */
25
26 // Base address in DSP for pipe information
27 static DSPAddrInARM DSPiPipeMonitorAddress = 0;
28 static OSThreadQueue DSPiBlockingQueue[1];
29 static DSPPipe DSPiDefaultPipe[DSP_PIPE_PORT_MAX][DSP_PIPE_PEER_MAX];
30 static DSPPipeCallback DSPiCallback[DSP_PIPE_PORT_MAX];
31 static void* (DSPiCallbackArgument[DSP_PIPE_PORT_MAX]);
32
33 // File I/O processing thread structure
34 typedef struct DSPFileIOContext
35 {
36 BOOL initialized;
37 OSThread th[1];
38 OSMessage msga[1];
39 OSMessageQueue msgq[1];
40 volatile int pollbits;
41 FSFile file[DSP_PIPE_PORT_MAX][1];
42 u8 stack[4096];
43 }
44 DSPFileIOContext;
45
46 static DSPFileIOContext DSPiThread[1];
47
48
49 /*---------------------------------------------------------------------------*/
50 /* functions */
51
52 /*---------------------------------------------------------------------------*
53 Name: DSPi_FileIOProc
54
55 Description: File I/O processing procedure
56
57 Arguments: arg: DSPFileIOThread structure
58
59 Returns: None.
60 *---------------------------------------------------------------------------*/
DSPi_FileIOProc(void * arg)61 static void DSPi_FileIOProc(void *arg)
62 {
63 DSPFileIOContext *ctx = (DSPFileIOContext *)arg;
64 for (;;)
65 {
66 // If necessary, wait for notice and get one port that is requested.
67 OSIntrMode bak = OS_DisableInterrupts();
68 int port;
69 for (;;)
70 {
71 port = (int)MATH_CTZ((u32)ctx->pollbits);
72 if (port < DSP_PIPE_PORT_MAX)
73 {
74 break;
75 }
76 else
77 {
78 OSMessage msg[1];
79 (void)OS_ReceiveMessage(ctx->msgq, msg, OS_MESSAGE_BLOCK);
80 }
81 }
82 ctx->pollbits &= ~(1 << port);
83 (void)OS_RestoreInterrupts(bak);
84 // Read command from corresponding pipe
85 {
86 FSFile *file = ctx->file[port];
87 DSPPipe in[1], out[1];
88 u16 command;
89 (void)DSP_LoadPipe(in, port, DSP_PIPE_INPUT);
90 (void)DSP_LoadPipe(out, port, DSP_PIPE_OUTPUT);
91 while (DSP_GetPipeReadableSize(in) >= sizeof(command))
92 {
93 DSP_ReadPipe(in, &command, sizeof(command));
94 switch (command)
95 {
96 case DSP_PIPE_IO_COMMAND_OPEN:
97 // fopen command
98 {
99 u16 mode;
100 u16 len;
101 char path[FS_ENTRY_LONGNAME_MAX + 1];
102 u16 result;
103 DSP_ReadPipe(in, &mode, sizeof(mode));
104 DSP_ReadPipe(in, &len, sizeof(len));
105 len = DSP_WORD_TO_ARM(len);
106 DSP_ReadPipe(in, path, len);
107 path[len] = '\0';
108 (void)FS_OpenFileEx(file, path, mode);
109 result = (u16)(FS_IsFile(file) ? 1 : 0);
110 DSP_WritePipe(out, &result, sizeof(result));
111 }
112 break;
113 case DSP_PIPE_IO_COMMAND_MEMMAP:
114 // memmap command
115 {
116 DSPAddrInARM addr;
117 DSPAddrInARM length;
118 u16 result;
119 DSP_ReadPipe(in, &addr, sizeof(addr));
120 DSP_ReadPipe(in, &length, sizeof(length));
121 addr = DSP_32BIT_TO_ARM(addr);
122 length = DSP_32BIT_TO_ARM(length);
123 length = DSP_ADDR_TO_ARM(length);
124 (void)FS_CreateFileFromMemory(file, (void*)addr, length);
125 result = (u16)(FS_IsFile(file) ? 1 : 0);
126 DSP_WritePipe(out, &result, sizeof(result));
127 }
128 break;
129 case DSP_PIPE_IO_COMMAND_CLOSE:
130 // fclose command
131 {
132 u16 result;
133 (void)FS_CloseFile(file);
134 result = 1;
135 DSP_WritePipe(out, &result, sizeof(result));
136 }
137 break;
138 case DSP_PIPE_IO_COMMAND_SEEK:
139 // fseek command
140 {
141 s32 position;
142 u16 whence;
143 s32 result;
144 DSP_ReadPipe(in, &position, sizeof(position));
145 DSP_ReadPipe(in, &whence, sizeof(whence));
146 position = (s32)DSP_32BIT_TO_ARM(position);
147 (void)FS_SeekFile(file, position, (FSSeekFileMode)whence);
148 result = (s32)FS_GetFilePosition(file);
149 result = (s32)DSP_32BIT_TO_DSP(result);
150 DSP_WritePipe(out, &result, sizeof(result));
151 }
152 break;
153 case DSP_PIPE_IO_COMMAND_READ:
154 // fread command
155 {
156 DSPWord length;
157 u32 rest;
158 u16 result;
159 DSP_ReadPipe(in, &length, sizeof(length));
160 length = DSP_WORD_TO_ARM(length);
161 // Get actual size and restrict in advance
162 rest = FS_GetFileLength(file) - FS_GetFilePosition(file);
163 length = (DSPWord)MATH_MIN(length, rest);
164 result = DSP_WORD_TO_DSP(length);
165 DSP_WritePipe(out, &result, sizeof(result));
166 while (length > 0)
167 {
168 u8 tmp[256];
169 u16 n = (u16)MATH_MIN(length, 256);
170 (void)FS_ReadFile(file, tmp, (s32)n);
171 DSP_WritePipe(out, tmp, n);
172 length -= n;
173 }
174 }
175 break;
176 case DSP_PIPE_IO_COMMAND_WRITE:
177 // fwrite command
178 {
179 DSPWord length;
180 DSP_ReadPipe(in, &length, sizeof(length));
181 length = DSP_WORD_TO_ARM(length);
182 while (length > 0)
183 {
184 u8 tmp[256];
185 u16 n = (u16)MATH_MIN(length, 256);
186 DSP_ReadPipe(in, tmp, (u16)n);
187 (void)FS_WriteFile(file, tmp, (s32)n);
188 length -= n;
189 }
190 }
191 break;
192 }
193 }
194 }
195 }
196 }
197
198 /*---------------------------------------------------------------------------*
199 Name: DSPi_NotifyFileIOUpdation
200
201 Description: Notifies update of file I/O
202
203 Arguments: port: Updated port number
204
205 Returns: None.
206 *---------------------------------------------------------------------------*/
DSPi_NotifyFileIOUpdation(int port)207 static void DSPi_NotifyFileIOUpdation(int port)
208 {
209 DSPFileIOContext *ctx = DSPiThread;
210 OSIntrMode bak = OS_DisableInterrupts();
211 // Generate thread if necessary
212 if (!ctx->initialized)
213 {
214 int i;
215 for (i = 0; i < DSP_PIPE_PORT_MAX; ++i)
216 {
217 FS_InitFile(ctx->file[i]);
218 }
219 OS_InitMessageQueue(ctx->msgq, ctx->msga, 1);
220 ctx->pollbits = 0;
221 ctx->initialized = TRUE;
222 OS_CreateThread(ctx->th, DSPi_FileIOProc, ctx,
223 &ctx->stack[sizeof(ctx->stack)], sizeof(ctx->stack), 13);
224 OS_WakeupThreadDirect(ctx->th);
225 }
226 // Throw message for notification
227 // NOBLOCK because it is acceptable for notifications not to line up in the queue if the same ones have accumulated
228 ctx->pollbits |= (1 << port);
229 (void)OS_SendMessage(ctx->msgq, (OSMessage)port, OS_MESSAGE_NOBLOCK);
230 (void)OS_RestoreInterrupts(bak);
231 }
232
233 /*---------------------------------------------------------------------------*
234 Name: DSPi_PipeCallbackToConsole
235
236 Description: DSP_PIPE_CONSOLE transmission handler
237
238 Arguments: userdata : Optional user-defined argument
239 port: Port number
240 peer: Transmission direction
241
242 Returns: None.
243 *---------------------------------------------------------------------------*/
DSPi_PipeCallbackToConsole(void * userdata,int port,int peer)244 static void DSPi_PipeCallbackToConsole(void *userdata, int port, int peer)
245 {
246 (void)userdata;
247 if (peer == DSP_PIPE_INPUT)
248 {
249 DSPPipe pipe[1];
250 (void)DSP_LoadPipe(pipe, port, peer);
251 {
252 u16 max = DSP_GetPipeReadableSize(pipe);
253 u16 pos = 0;
254 while (pos < max)
255 {
256 enum { tmplen = 128 };
257 char buffer[tmplen + 2];
258 u16 length = (u16)((max - pos < tmplen) ? (max - pos) : tmplen);
259 DSP_ReadPipe(pipe, buffer, length);
260 pos += length;
261 // Debug output of the console output from DSP
262 // Each printf output is delivered padded in u16 units, be careful that '\0' is inserted at irregular intervals.
263 //
264 {
265 const char *str = (const char *)buffer;
266 int current = 0;
267 int pos;
268 for (pos = 0; pos < length; ++pos)
269 {
270 if (str[pos] == '\0')
271 {
272 OS_TPrintf("%s", &str[current]);
273 current = pos + 1;
274 }
275 }
276 if (current < length)
277 {
278 OS_TPrintf("%.*s", (length - current), &str[current]);
279 }
280 }
281 }
282 }
283 }
284 }
285
286 /*---------------------------------------------------------------------------*
287 Name: DSPi_PipeCallbackForDMA
288
289 Description: DSP_PIPE_DMA transmission handler
290
291 Arguments: userdata : Optional user-defined argument
292 port: Port number
293 peer: Transmission direction
294
295 Returns: None.
296 *---------------------------------------------------------------------------*/
DSPi_PipeCallbackForDMA(void * userdata,int port,int peer)297 static void DSPi_PipeCallbackForDMA(void *userdata, int port, int peer)
298 {
299 (void)userdata;
300 if (peer == DSP_PIPE_INPUT)
301 {
302 DSPPipe pipe[1];
303 (void)DSP_LoadPipe(pipe, port, peer);
304 {
305 u16 max = DSP_GetPipeReadableSize(pipe);
306 u16 pos = 0;
307 while (pos < max)
308 {
309 enum { tmplen = 128 };
310 char buffer[tmplen + 2];
311 u16 length = (u16)((max - pos < tmplen) ? (max - pos) : tmplen);
312 DSP_ReadPipe(pipe, buffer, length);
313 pos += length;
314 // Debug output of the console output from DSP
315 // Each printf output is delivered padded in u16 units, be careful that '\0' is inserted at irregular intervals.
316 //
317 {
318 const char *str = (const char *)buffer;
319 int current = 0;
320 int pos;
321 for (pos = 0; pos < length; ++pos)
322 {
323 if (str[pos] == '\0')
324 {
325 OS_TPrintf("%s", &str[current]);
326 current = pos + 1;
327 }
328 }
329 if (current < length)
330 {
331 OS_TPrintf("%.*s", (length - current), &str[current]);
332 }
333 }
334 }
335 }
336 }
337 }
338
339 /*---------------------------------------------------------------------------*
340 Name: DSPi_WaitForPipe
341
342 Description: Idling update specified DSP pipe information
343
344 Arguments: pipe: Pipe information
345
346 Returns: None.
347 *---------------------------------------------------------------------------*/
DSPi_WaitForPipe(DSPPipe * pipe)348 static void DSPi_WaitForPipe(DSPPipe *pipe)
349 {
350 OS_SleepThread(DSPiBlockingQueue);
351 (void)DSP_SyncPipe(pipe);
352 }
353
354 /*---------------------------------------------------------------------------*
355 Name: DSP_InitPipe
356
357 Description: Initializes DSP pipe communication.
358 Occupy DSP command replay register 2
359
360 Arguments: None.
361
362 Returns: None.
363 *---------------------------------------------------------------------------*/
DSP_InitPipe(void)364 void DSP_InitPipe(void)
365 {
366 int i;
367 DSPiPipeMonitorAddress = 0;
368 OS_InitThreadQueue(DSPiBlockingQueue);
369 for (i = 0; i < DSP_PIPE_PORT_MAX; ++i)
370 {
371 DSPiCallback[i] = NULL;
372 DSPiCallbackArgument[i] = NULL;
373 }
374 // DSP_PIPE_CONSOLE is the debug console for DSP
375 DSPiCallback[DSP_PIPE_CONSOLE] = DSPi_PipeCallbackToConsole;
376 }
377
378 /*---------------------------------------------------------------------------*
379 Name: DSP_SetPipeCallback
380
381 Description: Sets the DSP pipe communcation callback
382
383 Arguments: port: Pipe port number
384 callback: Callback for readable/writable events
385 userdata : Optional user-defined argument
386
387 Returns: None.
388 *---------------------------------------------------------------------------*/
DSP_SetPipeCallback(int port,void (* callback)(void *,int,int),void * userdata)389 void DSP_SetPipeCallback(int port, void (*callback)(void *, int, int), void *userdata)
390 {
391 DSPiCallback[port] = callback;
392 DSPiCallbackArgument[port] = userdata;
393 }
394
395 /*---------------------------------------------------------------------------*
396 Name: DSP_LoadPipe
397
398 Description: Loads DSP pipe information
399
400 Arguments: pipe: Storage destination of pipe information (Not NULL on the DSP side)
401 port: Pipe port number
402 peer: DSP_PIPE_INPUT or DSP_PIPE_OUTPUT
403
404 Returns: Pointer of the loaded pipe information
405 *---------------------------------------------------------------------------*/
DSP_LoadPipe(DSPPipe * pipe,int port,int peer)406 DSPPipe* DSP_LoadPipe(DSPPipe *pipe, int port, int peer)
407 {
408 // Idle until notified of the monitor address
409 OSIntrMode bak = OS_DisableInterrupts();
410 while (!DSPiPipeMonitorAddress)
411 {
412 OS_SleepThread(DSPiBlockingQueue);
413 }
414 (void)OS_RestoreInterrupts(bak);
415 if (((port >= 0) && (port < DSP_PIPE_PORT_MAX)) &&
416 ((peer >= 0) && (peer < DSP_PIPE_PEER_MAX)))
417 {
418 DSPPipeMonitor *monitor = (DSPPipeMonitor *)DSPiPipeMonitorAddress;
419 DSPPipe *target = &monitor->pipe[port][peer];
420 if (!pipe)
421 {
422 pipe = &DSPiDefaultPipe[port][peer];
423 }
424 DSP_LoadData((DSPAddrInARM)target, pipe, sizeof(*pipe));
425 }
426 return pipe;
427 }
428
429 /*---------------------------------------------------------------------------*
430 Name: DSP_SyncPipe
431
432 Description: Update DSP pipe information to the latest content.
433
434 Arguments: pipe: Pipe information
435
436 Returns: None.
437 *---------------------------------------------------------------------------*/
DSP_SyncPipe(DSPPipe * pipe)438 void DSP_SyncPipe(DSPPipe *pipe)
439 {
440 (void)DSP_LoadPipe(pipe,
441 ((pipe->flags & DSP_PIPE_FLAG_PORTMASK) >> 1),
442 (pipe->flags & 1));
443 }
444
445 /*---------------------------------------------------------------------------*
446 Name: DSP_FlushPipe
447
448 Description: Flushes the DSP pipe stream
449
450 Arguments: pipe: Pipe information
451 port: Pipe port number
452 peer: DSP_PIPE_INPUT or DSP_PIPE_OUTPUT
453
454 Returns: None.
455 *---------------------------------------------------------------------------*/
DSP_FlushPipe(DSPPipe * pipe)456 void DSP_FlushPipe(DSPPipe *pipe)
457 {
458 // Write back to the DSP only the pointer updated from the ARM side
459 int port = ((pipe->flags & DSP_PIPE_FLAG_PORTMASK) >> 1);
460 int peer = (pipe->flags & 1);
461 DSPPipeMonitor *monitor = (DSPPipeMonitor *)DSPiPipeMonitorAddress;
462 DSPPipe *target = &monitor->pipe[port][peer];
463 if (peer == DSP_PIPE_INPUT)
464 {
465 DSP_StoreData((DSPAddrInARM)&target->rpos, &pipe->rpos, sizeof(target->rpos));
466 }
467 else
468 {
469 DSP_StoreData((DSPAddrInARM)&target->wpos, &pipe->wpos, sizeof(target->wpos));
470 }
471 // Update notification to DSP side
472 OS_SpinWaitSysCycles(4);
473 while ((reg_DSP_PSTS & REG_DSP_PSTS_WFEI_MASK) == 0 || (reg_DSP_PSTS & REG_DSP_PSTS_WTIP_MASK) != 0) {}
474 DSP_SendData(DSP_PIPE_COMMAND_REGISTER, (u16)(pipe->flags & DSP_PIPE_FLAG_PORTMASK));
475 }
476
477 /*---------------------------------------------------------------------------*
478 Name: DSP_GetPipeReadableSize
479
480 Description: Get maximum size that currently can be read from the specified DSP pipe
481
482 Arguments: pipe: Pipe information
483
484 Returns: Maximum size that currently can be read
485 *---------------------------------------------------------------------------*/
DSP_GetPipeReadableSize(const DSPPipe * pipe)486 u16 DSP_GetPipeReadableSize(const DSPPipe *pipe)
487 {
488 return DSP_BYTE_TO_UNIT(((pipe->wpos - pipe->rpos) +
489 (((pipe->rpos ^ pipe->wpos) < 0x8000) ? 0 : pipe->length)) & ~0x8000);
490 }
491
492 /*---------------------------------------------------------------------------*
493 Name: DSP_GetPipeWritableSize
494
495 Description: Get maximum size that currently can be written to the specified DSP pipe
496
497 Arguments: pipe: Pipe information
498
499 Returns: Maximum size that currently can be written
500 *---------------------------------------------------------------------------*/
DSP_GetPipeWritableSize(const DSPPipe * pipe)501 u16 DSP_GetPipeWritableSize(const DSPPipe *pipe)
502 {
503 return DSP_BYTE_TO_UNIT(((pipe->rpos - pipe->wpos) +
504 (((pipe->wpos ^ pipe->rpos) < 0x8000) ? 0 : pipe->length)) & ~0x8000);
505 }
506
507 /*---------------------------------------------------------------------------*
508 Name: DSP_ReadPipe
509
510 Description: Read data from the DSP pipe communication port
511
512 Arguments: pipe: Pipe information
513 buffer: Transfer destination buffer
514 length: Transfer size (However, the units are the word size of that environment)
515 Be careful that the ARM side is 1-byte units, and the DSP side is 2-byte units.
516
517 Returns: None.
518 *---------------------------------------------------------------------------*/
DSP_ReadPipe(DSPPipe * pipe,void * buffer,u16 length)519 void DSP_ReadPipe(DSPPipe *pipe, void *buffer, u16 length)
520 {
521 OSIntrMode bak = OS_DisableInterrupts();
522 u8 *dst = (u8 *)buffer;
523 BOOL modified = FALSE;
524 length = DSP_UNIT_TO_BYTE(length);
525 DSP_SyncPipe(pipe);
526 while (length > 0)
527 {
528 u16 rpos = pipe->rpos;
529 u16 wpos = pipe->wpos;
530 u16 phase = (u16)(rpos ^ wpos);
531 // Wait for completion if read-empty
532 if (phase == 0x0000)
533 {
534 if (modified)
535 {
536 DSP_FlushPipe(pipe);
537 modified = FALSE;
538 }
539 DSPi_WaitForPipe(pipe);
540 }
541 else
542 {
543 // If not, read from a safe range
544 u16 pos = (u16)(rpos & ~0x8000);
545 u16 end = (u16)((phase < 0x8000) ? (wpos & ~0x8000) : pipe->length);
546 u16 len = (u16)((length < end - pos) ? length : (end - pos));
547 len = (u16)(len & ~(DSP_WORD_UNIT - 1));
548 DSP_LoadData(DSP_ADDR_TO_ARM(pipe->address) + pos, dst, len);
549 length -= len;
550 dst += DSP_BYTE_TO_UNIT(len);
551 pipe->rpos = (u16)((pos + len < pipe->length) ? (rpos + len) : (~rpos & 0x8000));
552 modified = TRUE;
553 }
554 }
555 // If there is an addition, notify here
556 if (modified)
557 {
558 DSP_FlushPipe(pipe);
559 modified = FALSE;
560 }
561 (void)OS_RestoreInterrupts(bak);
562 }
563
564 /*---------------------------------------------------------------------------*
565 Name: DSP_WritePipe
566
567 Description: Writes data to the DSP pipe communication port
568
569 Arguments: pipe: Pipe information
570 buffer: Transfer source buffer
571 length: Transfer size (However, the units are the word size of that environment)
572 Note that the ARM side is 1-byte units, and the DSP side is 2-byte units.
573
574 Returns: None.
575 *---------------------------------------------------------------------------*/
DSP_WritePipe(DSPPipe * pipe,const void * buffer,u16 length)576 void DSP_WritePipe(DSPPipe *pipe, const void *buffer, u16 length)
577 {
578 OSIntrMode bak = OS_DisableInterrupts();
579 const u8 *src = (const u8 *)buffer;
580 BOOL modified = FALSE;
581 length = DSP_UNIT_TO_BYTE(length);
582 DSP_SyncPipe(pipe);
583 while (length > 0)
584 {
585 u16 rpos = pipe->rpos;
586 u16 wpos = pipe->wpos;
587 u16 phase = (u16)(rpos ^ wpos);
588 // If write-full, wait for completion
589 if (phase == 0x8000)
590 {
591 if (modified)
592 {
593 DSP_FlushPipe(pipe);
594 modified = FALSE;
595 }
596 DSPi_WaitForPipe(pipe);
597 }
598 else
599 {
600 // If not, write to a safe range
601 u16 pos = (u16)(wpos & ~0x8000);
602 u16 end = (u16)((phase < 0x8000) ? pipe->length : (rpos & ~0x8000));
603 u16 len = (u16)((length < end - pos) ? length : (end - pos));
604 len = (u16)(len & ~(DSP_WORD_UNIT - 1));
605 DSP_StoreData(DSP_ADDR_TO_ARM(pipe->address) + pos, src, len);
606 length -= len;
607 src += DSP_BYTE_TO_UNIT(len);
608 pipe->wpos = (u16)((pos + len < pipe->length) ? (wpos + len) : (~wpos & 0x8000));
609 modified = TRUE;
610 }
611 }
612 // If there is an addition, notify here
613 if (modified)
614 {
615 DSP_FlushPipe(pipe);
616 modified = FALSE;
617 }
618 (void)OS_RestoreInterrupts(bak);
619 }
620
621 /*---------------------------------------------------------------------------*
622 Name: DSP_HookPipeNotification
623
624 Description: Pipe notification hook that should be called in a DSP interrupt
625
626 Arguments: None.
627
628 Returns: None.
629 *---------------------------------------------------------------------------*/
DSP_HookPipeNotification(void)630 void DSP_HookPipeNotification(void)
631 {
632 // CR2 dedicated for pipe communication
633 // However, for some reason a CR interrupt was not generated, so currently, substitute semaphore with only one bit
634 //
635 while (((DSP_GetSemaphore() & 0x8000) != 0) || DSP_RecvDataIsReady(DSP_PIPE_COMMAND_REGISTER))
636 {
637 DSP_ClearSemaphore(0x8000);
638 while (DSP_RecvDataIsReady(DSP_PIPE_COMMAND_REGISTER))
639 {
640 // Initially, the shared structure address is notified from the DSP side
641 if (DSPiPipeMonitorAddress == 0)
642 {
643 DSPiPipeMonitorAddress = DSP_ADDR_TO_ARM(DSP_RecvData(DSP_PIPE_COMMAND_REGISTER));
644 }
645 // Thereafter, only updated pipes are notified
646 else
647 {
648 u16 recvdata = DSP_RecvData(DSP_PIPE_COMMAND_REGISTER);
649 int port = (recvdata >> 1);
650 int peer = (recvdata & 1);
651 if ((port >= 0) && (port < DSP_PIPE_PORT_MAX))
652 {
653 // If a monitoring source exists on the ARM side, verify the pipe information
654 if (DSPiCallback[port])
655 {
656 (*DSPiCallback[port])(DSPiCallbackArgument[port], port, peer);
657 }
658 else
659 {
660 DSPPipe pipe[1];
661 (void)DSP_LoadPipe(pipe, port, peer);
662 // If updating the file opened on the DSP side, notify the thread
663 if ((peer == DSP_PIPE_INPUT) && ((pipe->flags & DSP_PIPE_FLAG_BOUND) != 0))
664 {
665 DSPi_NotifyFileIOUpdation(port);
666 }
667 }
668 }
669 }
670 // Notify update to thread during blocking
671 OS_WakeupThread(DSPiBlockingQueue);
672 }
673 }
674 }
675