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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 */ 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 */ 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 */ 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