1 /*
2 * dspbridge/src/api/linux/DSPStrm.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * Copyright (C) 2007 Texas Instruments, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published
10 * by the Free Software Foundation version 2.1 of the License.
11 *
12 * This program is distributed .as is. WITHOUT ANY WARRANTY of any kind,
13 * whether express or implied; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 */
17
18 /*
19 * ======== DSPStrm.c ========
20 * Description:
21 * This is the source for the DSP/BIOS Bridge API stream module. The
22 * parameters are validated at the API level, but the bulk of the
23 * work is done at the driver level through the PM STRM module.
24 *
25 * Public Functions:
26 * DSPStream_AllocateBuffers
27 * DSPStream_Close
28 * DSPStream_FreeBuffers
29 * DSPStream_GetInfo
30 * DSPStream_Idle
31 * DSPStream_Issue
32 * DSPStream_Open
33 * DSPStream_Reclaim
34 * DSPStream_RegisterNotify
35 * DSPStream_Select
36 *
37 *! Revision History
38 *! ================
39 *! 13-Mar-2002 map Checking for invalid direction in DSPStream_Open()
40 *! 12-Mar-2002 map Checking for invalid node handle in
41 *! DSPStream_Open().
42 *! 11-Mar-2002 map Checking that bufsize is not smaller than specified
43 *! number of bytes in buffer in DSPStream_Issue().
44 *! 06-Jan-2002 ag STRMMODE_ZEROCOPY(SM buffer swap) enabled.
45 *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
46 *! 04-Dec-2001 ag Changed user event name string in DSPStream_Open().
47 *! Added stream direction and index.
48 *! 16-Nov-2001 ag Added SM allocation for streaming.
49 *! 07-Jun-2001 sg Made buffer allocate/free fxn names plural.
50 *! 18-May-2001 jeh Close event handle in DSPStream_Open() if failure.
51 *! 11-Apr-2001 rr: DSPStream_UnPrepareBuffer checks for pBuffer == NULL
52 *! (not for *pBuffer).
53 *! 13-Dec-2000 jeh Return DSP_EPOINTER, not DSP_EHANDLE in
54 *! DSPStream_Select() for NULL pointers.
55 *! Also set *pMask to 0 if nStreams is 0.
56 *! 05-Dec-2000 jeh Return DSP_ESIZE, not DSP_EVALUE in DSPStream_GetInfo,
57 *! set status to DSP_SOK in DSPStream_UnprepareBuffer().
58 *! 10-Nov-2000 rr: DSP_PBUFFER modified to BYTE *. RegisterNotify
59 *! catches Invalid Events and Masks.
60 *! 23-Oct-2000 jeh Free buffers in DSPStream_FreeBuffer().
61 *! 28-Sep-2000 jeh Removed DSP_BUFFERATTR param from DSP_StreamAllocateBuffer.
62 *! 07-Sep-2000 jeh Changed type HANDLE in DSPStream_RegisterNotify to
63 *! DSP_HNOTIFICATION.
64 *! 04-Aug-2000 rr: Name changed to DSPStrm.c
65 *! 27-Jul-2000 rr: Types updated to ver 0.8 API.
66 *! 18-Jul-2000 rr: STRM API calls into the Class driver.
67 *! Only parameters are validated here.
68 *! 15-May-2000 gp: Return DSP_EHANDLE fromo DSPStream_Close().
69 *! 19-Apr-2000 ww: Updated based on code review.
70 *! 12-Apr-2000 ww: Created based on DirectDSP API specification, Version 0.6.
71 *
72 */
73
74 /* ----------------------------------- Host OS */
75 #include <host_os.h>
76
77 /* ----------------------------------- DSP/BIOS Bridge */
78 #include <std.h>
79 #include <dbdefs.h>
80 #include <errbase.h>
81
82 /* ----------------------------------- OS Adaptation Layer */
83 #include <csl.h>
84
85 /* ----------------------------------- Others */
86 #include <dsptrap.h>
87 #include <memry.h>
88
89 /* ----------------------------------- This */
90 #include "_dbdebug.h"
91
92 #include <DSPStream.h>
93
94 /* ----------------------------------- Defines, Data Structures, Typedefs */
95 #define STRM_MAXLOCKPAGES 64
96
97 /* ----------------------------------- Globals */
98 extern int hMediaFile; /* class driver handle */
99
100 /* ----------------------------------- Function Prototypes */
101 static DSP_STATUS GetStrmInfo(DSP_HSTREAM hStream, struct STRM_INFO *pStrmInfo,
102 UINT uStreamInfoSize);
103
104 /*
105 * ======== DSPStream_AllocateBuffers ========
106 * Purpose:
107 * Allocate data buffers for use with a specific stream.
108 */
DSPStream_AllocateBuffers(DSP_HSTREAM hStream,UINT uSize,OUT BYTE ** apBuffer,UINT uNumBufs)109 DBAPI DSPStream_AllocateBuffers(DSP_HSTREAM hStream, UINT uSize,
110 OUT BYTE **apBuffer, UINT uNumBufs)
111 {
112 UINT i;
113 UINT uAllocated = 0;
114 DSP_STATUS status = DSP_SOK;
115 Trapped_Args tempStruct;
116 PVOID pBuf = NULL;
117 struct STRM_INFO strmInfo;
118 struct DSP_STREAMINFO userInfo;
119
120 DEBUGMSG(DSPAPI_ZONE_FUNCTION,
121 (TEXT("NODE: DSPStream_AllocateBuffers:\r\n")));
122 if (!hStream) {
123 /* Invalid pointer */
124 status = DSP_EHANDLE;
125 DEBUGMSG(DSPAPI_ZONE_ERROR,
126 (TEXT("NODE: DSPStream_AllocateBuffers: "
127 "hStrm is Invalid \r\n")));
128 return status;
129 }
130 if (!apBuffer) {
131 /* Invalid parameter */
132 status = DSP_EPOINTER;
133 DEBUGMSG(DSPAPI_ZONE_ERROR,
134 (TEXT("NODE: DSPStream_AllocateBuffers: "
135 "Invalid pointer in the Input\r\n")));
136 return status;
137 }
138 for (i = 0; i < uNumBufs; i++)
139 apBuffer[i] = NULL;
140
141 strmInfo.pUser = &userInfo;
142 status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
143 if (!DSP_SUCCEEDED(status)) {
144 status = DSP_EFAIL;
145 DEBUGMSG(DSPAPI_ZONE_ERROR,
146 (TEXT("DSPStream_AllocateBuffers: "
147 "DSP_FAILED to get strm info\r\n")));
148 return status;
149 }
150 if (strmInfo.uSegment > 0) {
151 /* Alloc SM */
152 tempStruct.ARGS_STRM_ALLOCATEBUFFER.hStream = hStream;
153 tempStruct.ARGS_STRM_ALLOCATEBUFFER.uSize = uSize;
154 tempStruct.ARGS_STRM_ALLOCATEBUFFER.apBuffer = apBuffer;
155 tempStruct.ARGS_STRM_ALLOCATEBUFFER.uNumBufs = uNumBufs;
156 /* Call DSP Trap */
157 status = DSPTRAP_Trap(&tempStruct,
158 CMD_STRM_ALLOCATEBUFFER_OFFSET);
159 } else {
160 /* Allocate local buffers */
161 for (i = 0; i < uNumBufs; i++) {
162 pBuf = MEM_Alloc(uSize, MEM_NONPAGED);
163 if (!pBuf) {
164 status = DSP_EMEMORY;
165 uAllocated = i;
166 break;
167 } else
168 apBuffer[i] = pBuf;
169
170 }
171 if (DSP_FAILED(status)) {
172 /* Free buffers allocated so far */
173 for (i = 0; i < uAllocated; i++) {
174 MEM_Free(apBuffer[i]);
175 apBuffer[i] = NULL;
176 }
177 }
178 }
179 return status;
180 }
181
182 /*
183 * ======== DSPStream_Close ========
184 * Purpose:
185 * Close a stream and free the underlying stream object.
186 */
DSPStream_Close(DSP_HSTREAM hStream)187 DBAPI DSPStream_Close(DSP_HSTREAM hStream)
188 {
189 #ifndef LINUX
190 HANDLE hEvent;
191 #endif
192 DSP_STATUS status = DSP_SOK;
193 Trapped_Args tempStruct;
194 struct STRM_INFO strmInfo;
195 struct DSP_STREAMINFO userInfo;
196 struct CMM_OBJECT *hCmm = NULL; /* SM Mgr handle */
197 struct CMM_INFO pInfo; /* CMM info; use for virtual space allocation */
198
199 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Close:\r\n")));
200
201 if (!hStream) {
202 /* Invalid pointer */
203 status = DSP_EHANDLE;
204 DEBUGMSG(DSPAPI_ZONE_ERROR,
205 (TEXT("NODE: DSPStream_Close: hStrm is Invalid \r\n")));
206 return status;
207 }
208 /* Unmap stream's process virtual space, if any */
209 strmInfo.pUser = &userInfo;
210 status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
211 if (!DSP_SUCCEEDED(status)) {
212 status = DSP_EFAIL;
213 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Close: "
214 "ERROR in Getting Strm Info \r\n")));
215 return status;
216 }
217 if (strmInfo.pVirtBase != NULL) {
218 /* Get segment size.
219 >0 is SM segment. Get default SM Mgr */
220 tempStruct.ARGS_CMM_GETHANDLE.hProcessor = NULL;
221 tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
222 status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETHANDLE_OFFSET);
223 if (DSP_SUCCEEDED(status)) {
224 /* Get SM segment info from CMM */
225 tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
226 tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
227 status = DSPTRAP_Trap(&tempStruct,
228 CMD_CMM_GETINFO_OFFSET);
229 }
230 /* strmInfo.uSegment is probably already OK here,
231 so following checks may not be required */
232 if (DSP_SUCCEEDED(status) &&
233 (pInfo.ulNumGPPSMSegs >= strmInfo.uSegment)) {
234 /* segInfo index starts at 0 */
235 if ((pInfo.segInfo[strmInfo.uSegment-1].dwSegBasePa
236 != 0) && (pInfo.segInfo[strmInfo.uSegment-1]\
237 .ulTotalSegSize) > 0) {
238 if (munmap(strmInfo.pVirtBase,
239 pInfo.segInfo[strmInfo.uSegment-1]\
240 .ulTotalSegSize)) {
241 status = DSP_EFAIL;
242 }
243 }
244 } else
245 status = DSP_EBADSEGID; /*no SM segments */
246
247 }
248 #ifndef LINUX /* Events are handled in kernel */
249 if (DSP_SUCCEEDED(status)) {
250 /* Get the user event from the stream */
251 /* Set up the structure */
252 tempStruct.ARGS_STRM_GETEVENTHANDLE.hStream = hStream;
253 tempStruct.ARGS_STRM_GETEVENTHANDLE.phEvent = &hEvent;
254 status = DSPTRAP_Trap(&tempStruct,
255 CMD_STRM_GETEVENTHANDLE_OFFSET);
256 }
257 #endif
258 if (DSP_SUCCEEDED(status)) {
259 /* Now close the stream */
260 tempStruct.ARGS_STRM_CLOSE.hStream = hStream;
261 status = DSPTRAP_Trap(&tempStruct, CMD_STRM_CLOSE_OFFSET);
262 }
263 #ifndef LINUX /* Events are handled in kernel */
264 if (DSP_SUCCEEDED(status))
265 CloseHandle(hEvent);
266
267 #endif
268 return status;
269 }
270
271 /*
272 * ======== DSPStream_FreeBuffers ========
273 * Purpose:
274 * Free a previously allocated stream data buffer.
275 */
DSPStream_FreeBuffers(DSP_HSTREAM hStream,IN BYTE ** apBuffer,UINT uNumBufs)276 DBAPI DSPStream_FreeBuffers(DSP_HSTREAM hStream, IN BYTE **apBuffer,
277 UINT uNumBufs)
278 {
279 UINT i;
280 DSP_STATUS status = DSP_SOK;
281 Trapped_Args tempStruct;
282 struct STRM_INFO strmInfo;
283 struct DSP_STREAMINFO userInfo;
284
285 DEBUGMSG(DSPAPI_ZONE_FUNCTION,
286 (TEXT("NODE:DSPStream_FreeBuffers:\r\n")));
287
288 if (!hStream) {
289 /* Invalid pointer */
290 status = DSP_EHANDLE;
291 DEBUGMSG(DSPAPI_ZONE_ERROR,
292 (TEXT("NODE: DSPStream_FreeBuffers: "
293 "hStrm is Invalid \r\n")));
294 goto func_end;
295 }
296 if (!apBuffer) {
297 /* Invalid parameter */
298 status = DSP_EPOINTER;
299 DEBUGMSG(DSPAPI_ZONE_ERROR,
300 (TEXT("NODE: DSPStream_FreeBuffers: "
301 "Invalid pointer in the Input\r\n")));
302 goto func_end;
303 }
304 strmInfo.pUser = &userInfo; /* need valid user info ptr */
305 status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
306 if (!DSP_SUCCEEDED(status)) {
307 DEBUGMSG(DSPAPI_ZONE_ERROR,
308 (TEXT("DSPStream_FreeBuffers. "
309 "Free Failed. Bad mode.")));
310 status = DSP_EFAIL;
311 goto func_end;
312 }
313 if (strmInfo.uSegment > 0) {
314 /* Free SM allocations */
315 tempStruct.ARGS_STRM_FREEBUFFER.hStream = hStream;
316 tempStruct.ARGS_STRM_FREEBUFFER.apBuffer = apBuffer;
317 tempStruct.ARGS_STRM_FREEBUFFER.uNumBufs = uNumBufs;
318 /* Call DSP Trap */
319 status = DSPTRAP_Trap(&tempStruct, CMD_STRM_FREEBUFFER_OFFSET);
320 if (DSP_FAILED(status)) {
321 DEBUGMSG(DSPAPI_ZONE_ERROR,
322 (TEXT("DSPStream_FreeBuffers: "
323 "Failed to Free Buf")));
324 status = DSP_EFAIL;
325 }
326 } else {
327 for (i = 0; i < uNumBufs; i++) {
328 /* Free local allocation */
329 if (apBuffer[i]) {
330 MEM_Free((PVOID)apBuffer[i]);
331 apBuffer[i] = NULL;
332 }
333 } /* end for */
334 }
335 func_end:
336 /* Return DSP_SOK if OS calls returned 0 */
337 if (status == 0)
338 status = DSP_SOK;
339
340 return status;
341 }
342
343 /*
344 * ======== DSPStream_GetInfo ========
345 * Purpose:
346 * Get information about a stream.
347 */
DSPStream_GetInfo(DSP_HSTREAM hStream,OUT struct DSP_STREAMINFO * pStreamInfo,UINT uStreamInfoSize)348 DBAPI DSPStream_GetInfo(DSP_HSTREAM hStream,
349 OUT struct DSP_STREAMINFO *pStreamInfo, UINT uStreamInfoSize)
350 {
351 DSP_STATUS status = DSP_SOK;
352 struct STRM_INFO strmInfo;/* include stream's private virt addr info */
353
354 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_GetInfo:\r\n")));
355
356 strmInfo.pUser = pStreamInfo;
357 status = GetStrmInfo(hStream, &strmInfo, uStreamInfoSize);
358 /* Return DSP_SOK if OS calls returned 0 */
359 if (status == 0)
360 status = DSP_SOK;
361
362 return status;
363 }
364
365 /*
366 * ======== DSPStream_Idle ========
367 * Purpose:
368 * Terminate I/O with a particular stream, and (optionally)
369 * flush output data buffers.
370 */
DSPStream_Idle(DSP_HSTREAM hStream,bool bFlush)371 DBAPI DSPStream_Idle(DSP_HSTREAM hStream, bool bFlush)
372 {
373 DSP_STATUS status = DSP_SOK;
374 Trapped_Args tempStruct;
375
376 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Idle:\r\n")));
377
378 if (hStream) {
379 /* Set up the structure */
380 /* Call DSP Trap */
381 tempStruct.ARGS_STRM_IDLE.hStream = hStream;
382 tempStruct.ARGS_STRM_IDLE.bFlush = bFlush;
383 status = DSPTRAP_Trap(&tempStruct, CMD_STRM_IDLE_OFFSET);
384 } else {
385 /* Invalid pointer */
386 status = DSP_EHANDLE;
387 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Idle: "
388 "hStrm is Invalid \r\n")));
389 }
390 return status;
391 }
392
393 /*
394 * ======== DSPStream_Issue ========
395 * Purpose:
396 * Send a buffer of data to a stream.
397 */
DSPStream_Issue(DSP_HSTREAM hStream,IN BYTE * pBuffer,ULONG dwDataSize,ULONG dwBufSize,IN DWORD dwArg)398 DBAPI DSPStream_Issue(DSP_HSTREAM hStream, IN BYTE *pBuffer,
399 ULONG dwDataSize, ULONG dwBufSize, IN DWORD dwArg)
400 {
401 DSP_STATUS status = DSP_SOK;
402 Trapped_Args tempStruct;
403
404 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Issue:\r\n")));
405
406 if (hStream) {
407 /* Check the size of the buffer */
408 if (pBuffer) {
409 /* Check that the size isn't too small */
410 if (dwDataSize > dwBufSize) {
411 status = DSP_EINVALIDARG;
412 DEBUGMSG(DSPAPI_ZONE_ERROR,
413 (TEXT("NODE: DSPStream_Issue: "
414 "Invalid argument in the Input\r\n")));
415 } else {
416 /* Set up the structure */
417 tempStruct.ARGS_STRM_ISSUE.hStream = hStream;
418 tempStruct.ARGS_STRM_ISSUE.pBuffer = pBuffer;
419 tempStruct.ARGS_STRM_ISSUE.dwBytes = dwDataSize;
420 tempStruct.ARGS_STRM_ISSUE.dwBufSize =
421 dwBufSize;
422 tempStruct.ARGS_STRM_ISSUE.dwArg = dwArg;
423 /* Call DSP Trap */
424 status = DSPTRAP_Trap(&tempStruct,
425 CMD_STRM_ISSUE_OFFSET);
426 /* Return DSP_SOK if OS calls returned 0 */
427 if (status == 0)
428 status = DSP_SOK;
429
430 }
431 } else {
432 /* Invalid parameter */
433 status = DSP_EPOINTER;
434 DEBUGMSG(DSPAPI_ZONE_ERROR,
435 (TEXT("NODE: DSPStream_Issue: "
436 "Invalid pointer in the Input\r\n")));
437 }
438 } else {
439 /* Invalid pointer */
440 status = DSP_EHANDLE;
441 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Issue: "
442 "hStrm is Invalid \r\n")));
443 }
444
445 return status;
446 }
447
448 /*
449 * ======== DSPStream_Open ========
450 * Purpose:
451 * Retrieve a stream handle for sending/receiving data buffers
452 * to/from a task node on a DSP.
453 */
DSPStream_Open(DSP_HNODE hNode,UINT uDirection,UINT uIndex,IN OPTIONAL struct DSP_STREAMATTRIN * pAttrIn,OUT DSP_HSTREAM * phStream)454 DBAPI DSPStream_Open(DSP_HNODE hNode, UINT uDirection, UINT uIndex,
455 IN OPTIONAL struct DSP_STREAMATTRIN *pAttrIn,
456 OUT DSP_HSTREAM *phStream)
457 {
458 DSP_STATUS status = DSP_SOK;
459 Trapped_Args tempStruct;
460 struct STRM_ATTR strmAttrs;
461 #ifndef LINUX /* Events are handled in kernel */
462 CHAR szEventName[STRM_MAXEVTNAMELEN];
463 WCHAR wszEventName[STRM_MAXEVTNAMELEN];
464 CHAR szTemp[STRM_MAXEVTNAMELEN];
465 #endif
466 struct CMM_OBJECT *hCmm = NULL; /* SM Mgr handle */
467 struct CMM_INFO pInfo;/* CMM info; use for virtual space allocation */
468
469 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Open:\r\n")));
470
471 if (!hNode) {
472 status = DSP_EHANDLE;
473 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
474 "Invalid handle in the Input\r\n")));
475 return status;
476 }
477 if (uDirection != DSP_TONODE && uDirection != DSP_FROMNODE) {
478 status = DSP_EDIRECTION;
479 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
480 "Invalid direction in the Input\r\n")));
481 return status;
482 }
483 if (!phStream) {
484 status = DSP_EPOINTER;
485 DEBUGMSG(DSPAPI_ZONE_ERROR,
486 (TEXT("NODE: DSPStream_Open: "
487 "Invalid pointer in the Input\r\n")));
488 return status;
489 }
490 *phStream = NULL;
491 strmAttrs.hUserEvent = NULL;
492 #ifndef LINUX /* Events are handled in kernel */
493 /* Create a 'named' user event that is unique.*/
494 strmAttrs.pStreamAttrIn = pAttrIn;
495 szEventName[0] = 'E';
496 szEventName[1] = 'V';
497 szEventName[2] = '\0';
498 /* append hNode handle string */
499 strncat(szEventName, _ultoa((ULONG)hNode, szTemp, 16), 8);
500 /* now append stream index and direction */
501 strncat(szEventName, _ultoa((ULONG)uDirection, szTemp, 16), 2);
502 strmAttrs.pstrEventName =
503 strncat(szEventName, _ultoa((ULONG)uIndex, szTemp, 16), 3);
504 (Void)CSL_AnsiToWchar(wszEventName, szEventName, STRM_MAXEVTNAMELEN);
505 /* Create an auto reset event. */
506 strmAttrs.hUserEvent = CreateEvent(NULL,false,false,wszEventName);
507 if (!strmAttrs.hUserEvent) {
508 status = DSP_EFAIL;
509 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
510 "Failed to Create the Event \r\n")));
511 }
512 #endif
513 /* Default stream mode is PROCCOPY.
514 * Check for currently supported mode(s).*/
515 if (pAttrIn) {
516 if (pAttrIn->lMode == STRMMODE_LDMA) {
517 /* No System-DMA support */
518 status = DSP_ENOTIMPL;
519 } else
520 if ((pAttrIn->lMode != STRMMODE_PROCCOPY)
521 && (pAttrIn->lMode != STRMMODE_ZEROCOPY)
522 && (pAttrIn->lMode != STRMMODE_RDMA)) {
523 status = DSP_ESTRMMODE; /* illegal stream mode */
524 }
525 pAttrIn->uSegment = abs(pAttrIn->uSegment);
526 /* make non-neg */
527 }
528 /* If opening the stream for STRMMODE_ZEROCOPY or
529 * STRMMODE_RDMA(DSP-DMA) stream mode, then setup the
530 * stream's CMM translator for the specified SM segment.*/
531 strmAttrs.pVirtBase = NULL;
532 strmAttrs.ulVirtSize = 0;
533 if (DSP_SUCCEEDED(status) && pAttrIn) {
534 if ((pAttrIn->lMode == STRMMODE_ZEROCOPY) ||
535 (pAttrIn->lMode == STRMMODE_RDMA)) {
536 if (pAttrIn->uSegment == 0) {
537 status = DSP_ENOTSHAREDMEM; /* must be
538 SM segment */
539 goto loop_end;
540 }
541 /* >0 is SM segment. Get default SM Mgr */
542 tempStruct.ARGS_CMM_GETHANDLE.hProcessor = NULL;
543 tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
544 status = DSPTRAP_Trap(&tempStruct,
545 CMD_CMM_GETHANDLE_OFFSET);
546 if (status == DSP_SOK) {
547 /* Get SM segment info from CMM */
548 tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
549 tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
550 status = DSPTRAP_Trap(&tempStruct,
551 CMD_CMM_GETINFO_OFFSET);
552 if (status != DSP_SOK)
553 status = DSP_EFAIL;
554 } else
555 status = DSP_EFAIL;
556
557 if (!DSP_SUCCEEDED(status ||
558 !(pInfo.ulNumGPPSMSegs >= pAttrIn->uSegment))) {
559 status = DSP_EBADSEGID; /* no SM segments */
560 goto loop_end;
561 }
562 /* segInfo index starts at 0 */
563 if ((pInfo.segInfo[pAttrIn->uSegment-1].dwSegBasePa
564 == 0) || (pInfo.segInfo[pAttrIn->uSegment-1]\
565 .ulTotalSegSize) < 0) {
566 status = DSP_EFAIL;
567 DEBUGMSG(DSPAPI_ZONE_ERROR,
568 (TEXT("STRM:DSPStream_Open: "
569 "Bad SM info...why?\r\n")));
570 goto loop_end;
571 }
572 strmAttrs.pVirtBase = mmap(NULL,
573 pInfo.segInfo[pAttrIn->uSegment-1]\
574 .ulTotalSegSize, PROT_READ | PROT_WRITE,
575 MAP_SHARED | MAP_LOCKED, hMediaFile, pInfo\
576 .segInfo[pAttrIn->uSegment-1].dwSegBasePa);
577 if (strmAttrs.pVirtBase == NULL) {
578 status = DSP_EFAIL;
579 DEBUGMSG(DSPAPI_ZONE_ERROR,
580 (TEXT("STRM: DSPStream_Open: "
581 "Virt alloc failed\r\n")));
582 goto loop_end;
583 }
584 strmAttrs.ulVirtSize =
585 pInfo.segInfo[pAttrIn->uSegment-1].ulTotalSegSize;
586 }
587 }
588 loop_end:
589 if (DSP_SUCCEEDED(status)) {
590 /* Set up the structure */
591 strmAttrs.pStreamAttrIn = pAttrIn;
592 /* Call DSP Trap */
593 tempStruct.ARGS_STRM_OPEN.hNode = hNode;
594 tempStruct.ARGS_STRM_OPEN.uDirection = uDirection;
595 tempStruct.ARGS_STRM_OPEN.uIndex = uIndex;
596 tempStruct.ARGS_STRM_OPEN.pAttrIn = &strmAttrs;
597 tempStruct.ARGS_STRM_OPEN.phStream = phStream;
598 status = DSPTRAP_Trap(&tempStruct, CMD_STRM_OPEN_OFFSET);
599 #ifndef LINUX /* Events are handled in kernel */
600 if (DSP_FAILED(status))
601 CloseHandle(strmAttrs.hUserEvent);
602
603 #endif
604 }
605 return status;
606 }
607
608 /*
609 * ======== DSPStream_PrepareBuffer ========
610 * Purpose:
611 * Prepares a buffer.
612 */
DSPStream_PrepareBuffer(DSP_HSTREAM hStream,UINT uSize,BYTE * pBuffer)613 DBAPI DSPStream_PrepareBuffer(DSP_HSTREAM hStream, UINT uSize, BYTE *pBuffer)
614 {
615 DSP_STATUS status = DSP_SOK;
616 #ifndef LINUX
617 /* Pages are never swapped out (i.e. always locked in Linux) */
618 ULONG aPageTab[STRM_MAXLOCKPAGES];
619 /* Find the maximum # of pages that could be locked. x86 &
620 ARM=4Kb pages */
621 UINT cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, uSize);
622 #endif
623 /* Do error checking here to API spec. We don't call down to WCD */
624 if (!hStream)
625 status = DSP_EHANDLE;
626
627 if (DSP_SUCCEEDED(status)) {
628 if (!pBuffer)
629 status = DSP_EPOINTER;
630 }
631
632 if (DSP_SUCCEEDED(status)) {
633 if (uSize <= 0)
634 status = DSP_ESIZE;
635 }
636 #ifndef LINUX
637 /* Pages are never swapped out (i.e. always locked in Linux) */
638 if (DSP_SUCCEEDED(status)) {
639 if (cPages > STRM_MAXLOCKPAGES)
640 status = DSP_EFAIL;
641 else {
642 if (!LockPages((LPVOID)pBuffer, uSize, aPageTab,
643 LOCKFLAG_WRITE))
644 status = DSP_EFAIL;
645 }
646 }
647 #endif
648
649 return status;
650 }
651
652 /*
653 * ======== DSPStream_Reclaim ========
654 * Purpose:
655 * Request a buffer back from a stream.
656 */
DSPStream_Reclaim(DSP_HSTREAM hStream,OUT BYTE ** pBufPtr,OUT ULONG * pDataSize,OUT ULONG * pBufSize,OUT DWORD * pdwArg)657 DBAPI DSPStream_Reclaim(DSP_HSTREAM hStream, OUT BYTE **pBufPtr,
658 OUT ULONG *pDataSize, OUT ULONG *pBufSize, OUT DWORD *pdwArg)
659 {
660 DSP_STATUS status = DSP_SOK;
661 Trapped_Args tempStruct;
662
663 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Reclaim:\r\n")));
664
665 if (hStream) {
666 /* Check the size of the buffer */
667 if ((pBufPtr) && (pDataSize) && (pdwArg)) {
668 /* Set up the structure */
669 /* Call DSP Trap */
670 tempStruct.ARGS_STRM_RECLAIM.hStream = hStream;
671 tempStruct.ARGS_STRM_RECLAIM.pBufPtr = pBufPtr;
672 tempStruct.ARGS_STRM_RECLAIM.pBytes = pDataSize;
673 tempStruct.ARGS_STRM_RECLAIM.pBufSize = pBufSize;
674 tempStruct.ARGS_STRM_RECLAIM.pdwArg = pdwArg;
675 status = DSPTRAP_Trap(&tempStruct,
676 CMD_STRM_RECLAIM_OFFSET);
677 } else {
678 /* Invalid parameter */
679 status = DSP_EPOINTER;
680 DEBUGMSG(DSPAPI_ZONE_ERROR,
681 (TEXT("NODE: DSPStream_Reclaim: "
682 "Invalid pointer in the Input\r\n")));
683 }
684 } else {
685 /* Invalid pointer */
686 status = DSP_EHANDLE;
687 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Reclaim: "
688 "hStrm is Invalid \r\n")));
689 }
690
691 return status;
692 }
693
694 /*
695 * ======== DSPStream_RegisterNotify ========
696 * Purpose:
697 * Register to be notified of specific events for this stream.
698 */
699 DBAPI
DSPStream_RegisterNotify(DSP_HSTREAM hStream,UINT uEventMask,UINT uNotifyType,struct DSP_NOTIFICATION * hNotification)700 DSPStream_RegisterNotify(DSP_HSTREAM hStream, UINT uEventMask,
701 UINT uNotifyType, struct DSP_NOTIFICATION *hNotification)
702 {
703 DSP_STATUS status = DSP_SOK;
704 Trapped_Args tempStruct;
705
706 DEBUGMSG(DSPAPI_ZONE_FUNCTION,
707 (TEXT("NODE: DSPStream_RegisterNotify:\r\n")));
708
709 if ((hStream) && (hNotification)) {
710 if (IsValidStrmEvent(uEventMask)) {
711 if (IsValidNotifyMask(uNotifyType)) {
712 /* Set up the structure */
713 /* Call DSP Trap */
714 tempStruct.ARGS_STRM_REGISTERNOTIFY.hStream =
715 hStream;
716 tempStruct.ARGS_STRM_REGISTERNOTIFY.uEventMask =
717 uEventMask;
718 tempStruct.ARGS_STRM_REGISTERNOTIFY\
719 .uNotifyType = uNotifyType;
720 tempStruct.ARGS_STRM_REGISTERNOTIFY\
721 .hNotification = hNotification;
722 status = DSPTRAP_Trap(&tempStruct,
723 CMD_STRM_REGISTERNOTIFY_OFFSET);
724 } else {
725 status = DSP_ENOTIMPL;
726 DEBUGMSG(DSPAPI_ZONE_ERROR,
727 (TEXT("NODE: DSPStream_RegisterNotify: "
728 "Invalid Notify Mask \r\n")));
729 }
730 } else {
731 status = DSP_EVALUE;
732 DEBUGMSG(DSPAPI_ZONE_ERROR,
733 (TEXT("NODE: DSPStream_RegisterNotify: "
734 "Invalid Event Mask \r\n")));
735 }
736 } else {
737 /* Invalid handle */
738 status = DSP_EHANDLE;
739 DEBUGMSG(DSPAPI_ZONE_ERROR,
740 (TEXT("NODE: DSPStream_RegisterNotify: "
741 "Invalid Handle \r\n")));
742 }
743
744 return status;
745 }
746
747 /*
748 * ======== DSPStream_Select ========
749 * Purpose:
750 * Select a ready stream.
751 */
DSPStream_Select(IN DSP_HSTREAM * aStreamTab,UINT nStreams,OUT UINT * pMask,UINT uTimeout)752 DBAPI DSPStream_Select(IN DSP_HSTREAM *aStreamTab,
753 UINT nStreams, OUT UINT *pMask, UINT uTimeout)
754 {
755 DSP_STATUS status = DSP_SOK;
756 Trapped_Args tempStruct;
757
758 DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Select:\r\n")));
759
760 if ((aStreamTab) && (pMask)) {
761 if (nStreams) {
762 /* Set up the structure */
763 /* Call DSP Trap */
764 tempStruct.ARGS_STRM_SELECT.aStreamTab = aStreamTab;
765 tempStruct.ARGS_STRM_SELECT.nStreams = nStreams;
766 tempStruct.ARGS_STRM_SELECT.pMask = pMask;
767 tempStruct.ARGS_STRM_SELECT.uTimeout = uTimeout;
768 status = DSPTRAP_Trap(&tempStruct,
769 CMD_STRM_SELECT_OFFSET);
770 } else
771 /* nStreams == 0 */
772 *pMask = 0;
773 } else {
774 /* Invalid pointer */
775 status = DSP_EPOINTER;
776 DEBUGMSG(DSPAPI_ZONE_ERROR,
777 (TEXT("NODE: DSPStream_Select: hStrm is Invalid \r\n")));
778 }
779
780 return status;
781 }
782
783 /*
784 * ======== DSPStream_UnprepareBuffer ========
785 * Purpose:
786 * Unprepares a buffer.
787 */
DSPStream_UnprepareBuffer(DSP_HSTREAM hStream,UINT uSize,BYTE * pBuffer)788 DBAPI DSPStream_UnprepareBuffer(DSP_HSTREAM hStream, UINT uSize,
789 BYTE *pBuffer)
790 {
791 DSP_STATUS status = DSP_SOK;
792
793 /* Do error checking here to API spec. We don't call down to WCD */
794 if (!hStream)
795 status = DSP_EHANDLE;
796
797 if (DSP_SUCCEEDED(status)) {
798 if (!pBuffer)
799 status = DSP_EPOINTER;
800 }
801
802 if (DSP_SUCCEEDED(status)) {
803 /*|| ((LPVOID)pBuffer == NULL) - already checked above */
804 if ((uSize <= 0))
805 status = DSP_EFAIL;
806 }
807 #ifndef LINUX /* Pages are never swapped out
808 (i.e. always locked in Linux) */
809 if (DSP_SUCCEEDED(status)) {
810 if (!UnlockPages((LPVOID) pBuffer, uSize))
811 status = DSP_EFAIL;
812 }
813 #endif
814
815 return status;
816 }
817
818 /*
819 * ======== GetStrmInfo ========
820 */
GetStrmInfo(DSP_HSTREAM hStream,struct STRM_INFO * pStrmInfo,UINT uStreamInfoSize)821 static DSP_STATUS GetStrmInfo(DSP_HSTREAM hStream, struct STRM_INFO *pStrmInfo,
822 UINT uStreamInfoSize)
823 {
824 DSP_STATUS status = DSP_SOK;
825 Trapped_Args tempStruct;
826
827 if (hStream) {
828 /* Check the size of the buffer */
829 if (pStrmInfo && pStrmInfo->pUser) {
830 if (uStreamInfoSize >= sizeof(struct DSP_STREAMINFO)) {
831 /* user info */
832 /* Set up the structure */
833 /* Call DSP Trap */
834 tempStruct.ARGS_STRM_GETINFO.hStream = hStream;
835 tempStruct.ARGS_STRM_GETINFO.pStreamInfo =
836 pStrmInfo;
837 /* user returned struct DSP_STREAMINFO
838 info size */
839 tempStruct.ARGS_STRM_GETINFO.uStreamInfoSize =
840 uStreamInfoSize;
841 status = DSPTRAP_Trap(&tempStruct,
842 CMD_STRM_GETINFO_OFFSET);
843 } else {
844 status = DSP_ESIZE;
845 DEBUGMSG(DSPAPI_ZONE_ERROR,
846 (TEXT("NODE: DSPStream_GetInfo: "
847 "uStreamInfo size is less than the "
848 "size of struct DSP_STREAMINFO\r\n")));
849 }
850 } else {
851 /* Invalid parameter */
852 status = DSP_EPOINTER;
853 DEBUGMSG(DSPAPI_ZONE_ERROR,
854 (TEXT("NODE: DSPStream_GetInfo: "
855 "Invalid pointer\r\n")));
856 }
857 } else {
858 /* Invalid pointer */
859 status = DSP_EHANDLE;
860 DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
861 "NODE: DSPStream_GetInfo: hStrm is Invalid \r\n")));
862 }
863
864 return status;
865 }
866
867