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:: 2009-06-11#$
14 $Rev: 10742 $
15 $Author: yosizaki $
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 DSP_SendData(DSP_PIPE_COMMAND_REGISTER, (u16)(pipe->flags & DSP_PIPE_FLAG_PORTMASK));
473 }
474
475 /*---------------------------------------------------------------------------*
476 Name: DSP_GetPipeReadableSize
477
478 Description: Get maximum size that currently can be read from the specified DSP pipe
479
480 Arguments: pipe: Pipe information
481
482 Returns: Maximum size that currently can be read
483 *---------------------------------------------------------------------------*/
DSP_GetPipeReadableSize(const DSPPipe * pipe)484 u16 DSP_GetPipeReadableSize(const DSPPipe *pipe)
485 {
486 return DSP_BYTE_TO_UNIT(((pipe->wpos - pipe->rpos) +
487 (((pipe->rpos ^ pipe->wpos) < 0x8000) ? 0 : pipe->length)) & ~0x8000);
488 }
489
490 /*---------------------------------------------------------------------------*
491 Name: DSP_GetPipeWritableSize
492
493 Description: Get maximum size that currently can be written to the specified DSP pipe
494
495 Arguments: pipe: Pipe information
496
497 Returns: Maximum size that currently can be written
498 *---------------------------------------------------------------------------*/
DSP_GetPipeWritableSize(const DSPPipe * pipe)499 u16 DSP_GetPipeWritableSize(const DSPPipe *pipe)
500 {
501 return DSP_BYTE_TO_UNIT(((pipe->rpos - pipe->wpos) +
502 (((pipe->wpos ^ pipe->rpos) < 0x8000) ? 0 : pipe->length)) & ~0x8000);
503 }
504
505 /*---------------------------------------------------------------------------*
506 Name: DSP_ReadPipe
507
508 Description: Read data from the DSP pipe communication port
509
510 Arguments: pipe: Pipe information
511 buffer: Transfer destination buffer
512 length: Transfer size (However, the units are the word size of that environment)
513 Be careful that the ARM side is 1-byte units, and the DSP side is 2-byte units.
514
515 Returns: None.
516 *---------------------------------------------------------------------------*/
DSP_ReadPipe(DSPPipe * pipe,void * buffer,u16 length)517 void DSP_ReadPipe(DSPPipe *pipe, void *buffer, u16 length)
518 {
519 OSIntrMode bak = OS_DisableInterrupts();
520 u8 *dst = (u8 *)buffer;
521 BOOL modified = FALSE;
522 length = DSP_UNIT_TO_BYTE(length);
523 DSP_SyncPipe(pipe);
524 while (length > 0)
525 {
526 u16 rpos = pipe->rpos;
527 u16 wpos = pipe->wpos;
528 u16 phase = (u16)(rpos ^ wpos);
529 // Wait for completion if read-empty
530 if (phase == 0x0000)
531 {
532 if (modified)
533 {
534 DSP_FlushPipe(pipe);
535 modified = FALSE;
536 }
537 DSPi_WaitForPipe(pipe);
538 }
539 else
540 {
541 // If not, read from a safe range
542 u16 pos = (u16)(rpos & ~0x8000);
543 u16 end = (u16)((phase < 0x8000) ? (wpos & ~0x8000) : pipe->length);
544 u16 len = (u16)((length < end - pos) ? length : (end - pos));
545 len = (u16)(len & ~(DSP_WORD_UNIT - 1));
546 DSP_LoadData(DSP_ADDR_TO_ARM(pipe->address) + pos, dst, len);
547 length -= len;
548 dst += DSP_BYTE_TO_UNIT(len);
549 pipe->rpos = (u16)((pos + len < pipe->length) ? (rpos + len) : (~rpos & 0x8000));
550 modified = TRUE;
551 }
552 }
553 // If there is an addition, notify here
554 if (modified)
555 {
556 DSP_FlushPipe(pipe);
557 modified = FALSE;
558 }
559 (void)OS_RestoreInterrupts(bak);
560 }
561
562 /*---------------------------------------------------------------------------*
563 Name: DSP_WritePipe
564
565 Description: Writes data to the DSP pipe communication port
566
567 Arguments: pipe: Pipe information
568 buffer: Transfer source buffer
569 length: Transfer size (However, the units are the word size of that environment)
570 Note that the ARM side is 1-byte units, and the DSP side is 2-byte units.
571
572 Returns: None.
573 *---------------------------------------------------------------------------*/
DSP_WritePipe(DSPPipe * pipe,const void * buffer,u16 length)574 void DSP_WritePipe(DSPPipe *pipe, const void *buffer, u16 length)
575 {
576 OSIntrMode bak = OS_DisableInterrupts();
577 const u8 *src = (const u8 *)buffer;
578 BOOL modified = FALSE;
579 length = DSP_UNIT_TO_BYTE(length);
580 DSP_SyncPipe(pipe);
581 while (length > 0)
582 {
583 u16 rpos = pipe->rpos;
584 u16 wpos = pipe->wpos;
585 u16 phase = (u16)(rpos ^ wpos);
586 // If write-full, wait for completion
587 if (phase == 0x8000)
588 {
589 if (modified)
590 {
591 DSP_FlushPipe(pipe);
592 modified = FALSE;
593 }
594 DSPi_WaitForPipe(pipe);
595 }
596 else
597 {
598 // If not, write to a safe range
599 u16 pos = (u16)(wpos & ~0x8000);
600 u16 end = (u16)((phase < 0x8000) ? pipe->length : (rpos & ~0x8000));
601 u16 len = (u16)((length < end - pos) ? length : (end - pos));
602 len = (u16)(len & ~(DSP_WORD_UNIT - 1));
603 DSP_StoreData(DSP_ADDR_TO_ARM(pipe->address) + pos, src, len);
604 length -= len;
605 src += DSP_BYTE_TO_UNIT(len);
606 pipe->wpos = (u16)((pos + len < pipe->length) ? (wpos + len) : (~wpos & 0x8000));
607 modified = TRUE;
608 }
609 }
610 // If there is an addition, notify here
611 if (modified)
612 {
613 DSP_FlushPipe(pipe);
614 modified = FALSE;
615 }
616 (void)OS_RestoreInterrupts(bak);
617 }
618
619 /*---------------------------------------------------------------------------*
620 Name: DSP_HookPipeNotification
621
622 Description: Pipe notification hook that should be called in a DSP interrupt
623
624 Arguments: None.
625
626 Returns: None.
627 *---------------------------------------------------------------------------*/
DSP_HookPipeNotification(void)628 void DSP_HookPipeNotification(void)
629 {
630 // CR2 dedicated for pipe communication
631 // However, for some reason a CR interrupt was not generated, so currently, substitute semaphore with only one bit
632 //
633 while (((DSP_GetSemaphore() & 0x8000) != 0) || DSP_RecvDataIsReady(DSP_PIPE_COMMAND_REGISTER))
634 {
635 DSP_ClearSemaphore(0x8000);
636 while (DSP_RecvDataIsReady(DSP_PIPE_COMMAND_REGISTER))
637 {
638 // Initially, the shared structure address is notified from the DSP side
639 if (DSPiPipeMonitorAddress == 0)
640 {
641 DSPiPipeMonitorAddress = DSP_ADDR_TO_ARM(DSP_RecvData(DSP_PIPE_COMMAND_REGISTER));
642 }
643 // Thereafter, only updated pipes are notified
644 else
645 {
646 u16 recvdata = DSP_RecvData(DSP_PIPE_COMMAND_REGISTER);
647 int port = (recvdata >> 1);
648 int peer = (recvdata & 1);
649 if ((port >= 0) && (port < DSP_PIPE_PORT_MAX))
650 {
651 // If a monitoring source exists on the ARM side, verify the pipe information
652 if (DSPiCallback[port])
653 {
654 (*DSPiCallback[port])(DSPiCallbackArgument[port], port, peer);
655 }
656 else
657 {
658 DSPPipe pipe[1];
659 (void)DSP_LoadPipe(pipe, port, peer);
660 // If updating the file opened on the DSP side, notify the thread
661 if ((peer == DSP_PIPE_INPUT) && ((pipe->flags & DSP_PIPE_FLAG_BOUND) != 0))
662 {
663 DSPi_NotifyFileIOUpdation(port);
664 }
665 }
666 }
667 }
668 // Notify update to thread during blocking
669 OS_WakeupThread(DSPiBlockingQueue);
670 }
671 }
672 }
673