866 lines
25 KiB
C
866 lines
25 KiB
C
/*
|
|
* dspbridge/src/api/linux/DSPStrm.c
|
|
*
|
|
* DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
|
*
|
|
* Copyright (C) 2007 Texas Instruments, Inc.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU Lesser General Public License as published
|
|
* by the Free Software Foundation version 2.1 of the License.
|
|
*
|
|
* This program is distributed .as is. WITHOUT ANY WARRANTY of any kind,
|
|
* whether express or implied; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* Lesser General Public License for more details.
|
|
*/
|
|
|
|
/*
|
|
* ======== DSPStrm.c ========
|
|
* Description:
|
|
* This is the source for the DSP/BIOS Bridge API stream module. The
|
|
* parameters are validated at the API level, but the bulk of the
|
|
* work is done at the driver level through the PM STRM module.
|
|
*
|
|
* Public Functions:
|
|
* DSPStream_AllocateBuffers
|
|
* DSPStream_Close
|
|
* DSPStream_FreeBuffers
|
|
* DSPStream_GetInfo
|
|
* DSPStream_Idle
|
|
* DSPStream_Issue
|
|
* DSPStream_Open
|
|
* DSPStream_Reclaim
|
|
* DSPStream_RegisterNotify
|
|
* DSPStream_Select
|
|
*
|
|
*! Revision History
|
|
*! ================
|
|
*! 13-Mar-2002 map Checking for invalid direction in DSPStream_Open()
|
|
*! 12-Mar-2002 map Checking for invalid node handle in
|
|
*! DSPStream_Open().
|
|
*! 11-Mar-2002 map Checking that bufsize is not smaller than specified
|
|
*! number of bytes in buffer in DSPStream_Issue().
|
|
*! 06-Jan-2002 ag STRMMODE_ZEROCOPY(SM buffer swap) enabled.
|
|
*! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
|
|
*! 04-Dec-2001 ag Changed user event name string in DSPStream_Open().
|
|
*! Added stream direction and index.
|
|
*! 16-Nov-2001 ag Added SM allocation for streaming.
|
|
*! 07-Jun-2001 sg Made buffer allocate/free fxn names plural.
|
|
*! 18-May-2001 jeh Close event handle in DSPStream_Open() if failure.
|
|
*! 11-Apr-2001 rr: DSPStream_UnPrepareBuffer checks for pBuffer == NULL
|
|
*! (not for *pBuffer).
|
|
*! 13-Dec-2000 jeh Return DSP_EPOINTER, not DSP_EHANDLE in
|
|
*! DSPStream_Select() for NULL pointers.
|
|
*! Also set *pMask to 0 if nStreams is 0.
|
|
*! 05-Dec-2000 jeh Return DSP_ESIZE, not DSP_EVALUE in DSPStream_GetInfo,
|
|
*! set status to DSP_SOK in DSPStream_UnprepareBuffer().
|
|
*! 10-Nov-2000 rr: DSP_PBUFFER modified to BYTE *. RegisterNotify
|
|
*! catches Invalid Events and Masks.
|
|
*! 23-Oct-2000 jeh Free buffers in DSPStream_FreeBuffer().
|
|
*! 28-Sep-2000 jeh Removed DSP_BUFFERATTR param from DSP_StreamAllocateBuffer.
|
|
*! 07-Sep-2000 jeh Changed type HANDLE in DSPStream_RegisterNotify to
|
|
*! DSP_HNOTIFICATION.
|
|
*! 04-Aug-2000 rr: Name changed to DSPStrm.c
|
|
*! 27-Jul-2000 rr: Types updated to ver 0.8 API.
|
|
*! 18-Jul-2000 rr: STRM API calls into the Class driver.
|
|
*! Only parameters are validated here.
|
|
*! 15-May-2000 gp: Return DSP_EHANDLE fromo DSPStream_Close().
|
|
*! 19-Apr-2000 ww: Updated based on code review.
|
|
*! 12-Apr-2000 ww: Created based on DirectDSP API specification, Version 0.6.
|
|
*
|
|
*/
|
|
|
|
/* ----------------------------------- Host OS */
|
|
#include <host_os.h>
|
|
|
|
/* ----------------------------------- DSP/BIOS Bridge */
|
|
#include <std.h>
|
|
#include <dbdefs.h>
|
|
#include <errbase.h>
|
|
|
|
/* ----------------------------------- OS Adaptation Layer */
|
|
#include <csl.h>
|
|
|
|
/* ----------------------------------- Others */
|
|
#include <dsptrap.h>
|
|
#include <memry.h>
|
|
|
|
/* ----------------------------------- This */
|
|
#include "_dbdebug.h"
|
|
|
|
#include <DSPStream.h>
|
|
|
|
/* ----------------------------------- Defines, Data Structures, Typedefs */
|
|
#define STRM_MAXLOCKPAGES 64
|
|
|
|
/* ----------------------------------- Globals */
|
|
extern int hMediaFile; /* class driver handle */
|
|
|
|
/* ----------------------------------- Function Prototypes */
|
|
static DSP_STATUS GetStrmInfo(DSP_HSTREAM hStream, struct STRM_INFO *pStrmInfo,
|
|
UINT uStreamInfoSize);
|
|
|
|
/*
|
|
* ======== DSPStream_AllocateBuffers ========
|
|
* Purpose:
|
|
* Allocate data buffers for use with a specific stream.
|
|
*/
|
|
DBAPI DSPStream_AllocateBuffers(DSP_HSTREAM hStream, UINT uSize,
|
|
OUT BYTE **apBuffer, UINT uNumBufs)
|
|
{
|
|
UINT i;
|
|
UINT uAllocated = 0;
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
PVOID pBuf = NULL;
|
|
struct STRM_INFO strmInfo;
|
|
struct DSP_STREAMINFO userInfo;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPStream_AllocateBuffers:\r\n")));
|
|
if (!hStream) {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_AllocateBuffers: "
|
|
"hStrm is Invalid \r\n")));
|
|
return status;
|
|
}
|
|
if (!apBuffer) {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_AllocateBuffers: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
return status;
|
|
}
|
|
for (i = 0; i < uNumBufs; i++)
|
|
apBuffer[i] = NULL;
|
|
|
|
strmInfo.pUser = &userInfo;
|
|
status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("DSPStream_AllocateBuffers: "
|
|
"DSP_FAILED to get strm info\r\n")));
|
|
return status;
|
|
}
|
|
if (strmInfo.uSegment > 0) {
|
|
/* Alloc SM */
|
|
tempStruct.ARGS_STRM_ALLOCATEBUFFER.hStream = hStream;
|
|
tempStruct.ARGS_STRM_ALLOCATEBUFFER.uSize = uSize;
|
|
tempStruct.ARGS_STRM_ALLOCATEBUFFER.apBuffer = apBuffer;
|
|
tempStruct.ARGS_STRM_ALLOCATEBUFFER.uNumBufs = uNumBufs;
|
|
/* Call DSP Trap */
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_ALLOCATEBUFFER_OFFSET);
|
|
} else {
|
|
/* Allocate local buffers */
|
|
for (i = 0; i < uNumBufs; i++) {
|
|
pBuf = MEM_Alloc(uSize, MEM_NONPAGED);
|
|
if (!pBuf) {
|
|
status = DSP_EMEMORY;
|
|
uAllocated = i;
|
|
break;
|
|
} else
|
|
apBuffer[i] = pBuf;
|
|
|
|
}
|
|
if (DSP_FAILED(status)) {
|
|
/* Free buffers allocated so far */
|
|
for (i = 0; i < uAllocated; i++) {
|
|
MEM_Free(apBuffer[i]);
|
|
apBuffer[i] = NULL;
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Close ========
|
|
* Purpose:
|
|
* Close a stream and free the underlying stream object.
|
|
*/
|
|
DBAPI DSPStream_Close(DSP_HSTREAM hStream)
|
|
{
|
|
#ifndef LINUX
|
|
HANDLE hEvent;
|
|
#endif
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
struct STRM_INFO strmInfo;
|
|
struct DSP_STREAMINFO userInfo;
|
|
struct CMM_OBJECT *hCmm = NULL; /* SM Mgr handle */
|
|
struct CMM_INFO pInfo; /* CMM info; use for virtual space allocation */
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Close:\r\n")));
|
|
|
|
if (!hStream) {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Close: hStrm is Invalid \r\n")));
|
|
return status;
|
|
}
|
|
/* Unmap stream's process virtual space, if any */
|
|
strmInfo.pUser = &userInfo;
|
|
status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Close: "
|
|
"ERROR in Getting Strm Info \r\n")));
|
|
return status;
|
|
}
|
|
if (strmInfo.pVirtBase != NULL) {
|
|
/* Get segment size.
|
|
>0 is SM segment. Get default SM Mgr */
|
|
tempStruct.ARGS_CMM_GETHANDLE.hProcessor = NULL;
|
|
tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETHANDLE_OFFSET);
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Get SM segment info from CMM */
|
|
tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
|
|
tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_CMM_GETINFO_OFFSET);
|
|
}
|
|
/* strmInfo.uSegment is probably already OK here,
|
|
so following checks may not be required */
|
|
if (DSP_SUCCEEDED(status) &&
|
|
(pInfo.ulNumGPPSMSegs >= strmInfo.uSegment)) {
|
|
/* segInfo index starts at 0 */
|
|
if ((pInfo.segInfo[strmInfo.uSegment-1].dwSegBasePa
|
|
!= 0) && (pInfo.segInfo[strmInfo.uSegment-1]\
|
|
.ulTotalSegSize) > 0) {
|
|
if (munmap(strmInfo.pVirtBase,
|
|
pInfo.segInfo[strmInfo.uSegment-1]\
|
|
.ulTotalSegSize)) {
|
|
status = DSP_EFAIL;
|
|
}
|
|
}
|
|
} else
|
|
status = DSP_EBADSEGID; /*no SM segments */
|
|
|
|
}
|
|
#ifndef LINUX /* Events are handled in kernel */
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Get the user event from the stream */
|
|
/* Set up the structure */
|
|
tempStruct.ARGS_STRM_GETEVENTHANDLE.hStream = hStream;
|
|
tempStruct.ARGS_STRM_GETEVENTHANDLE.phEvent = &hEvent;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_GETEVENTHANDLE_OFFSET);
|
|
}
|
|
#endif
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Now close the stream */
|
|
tempStruct.ARGS_STRM_CLOSE.hStream = hStream;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_STRM_CLOSE_OFFSET);
|
|
}
|
|
#ifndef LINUX /* Events are handled in kernel */
|
|
if (DSP_SUCCEEDED(status))
|
|
CloseHandle(hEvent);
|
|
|
|
#endif
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_FreeBuffers ========
|
|
* Purpose:
|
|
* Free a previously allocated stream data buffer.
|
|
*/
|
|
DBAPI DSPStream_FreeBuffers(DSP_HSTREAM hStream, IN BYTE **apBuffer,
|
|
UINT uNumBufs)
|
|
{
|
|
UINT i;
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
struct STRM_INFO strmInfo;
|
|
struct DSP_STREAMINFO userInfo;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE:DSPStream_FreeBuffers:\r\n")));
|
|
|
|
if (!hStream) {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_FreeBuffers: "
|
|
"hStrm is Invalid \r\n")));
|
|
goto func_end;
|
|
}
|
|
if (!apBuffer) {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_FreeBuffers: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
goto func_end;
|
|
}
|
|
strmInfo.pUser = &userInfo; /* need valid user info ptr */
|
|
status = GetStrmInfo(hStream, &strmInfo, sizeof(struct DSP_STREAMINFO));
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("DSPStream_FreeBuffers. "
|
|
"Free Failed. Bad mode.")));
|
|
status = DSP_EFAIL;
|
|
goto func_end;
|
|
}
|
|
if (strmInfo.uSegment > 0) {
|
|
/* Free SM allocations */
|
|
tempStruct.ARGS_STRM_FREEBUFFER.hStream = hStream;
|
|
tempStruct.ARGS_STRM_FREEBUFFER.apBuffer = apBuffer;
|
|
tempStruct.ARGS_STRM_FREEBUFFER.uNumBufs = uNumBufs;
|
|
/* Call DSP Trap */
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_STRM_FREEBUFFER_OFFSET);
|
|
if (DSP_FAILED(status)) {
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("DSPStream_FreeBuffers: "
|
|
"Failed to Free Buf")));
|
|
status = DSP_EFAIL;
|
|
}
|
|
} else {
|
|
for (i = 0; i < uNumBufs; i++) {
|
|
/* Free local allocation */
|
|
if (apBuffer[i]) {
|
|
MEM_Free((PVOID)apBuffer[i]);
|
|
apBuffer[i] = NULL;
|
|
}
|
|
} /* end for */
|
|
}
|
|
func_end:
|
|
/* Return DSP_SOK if OS calls returned 0 */
|
|
if (status == 0)
|
|
status = DSP_SOK;
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_GetInfo ========
|
|
* Purpose:
|
|
* Get information about a stream.
|
|
*/
|
|
DBAPI DSPStream_GetInfo(DSP_HSTREAM hStream,
|
|
OUT struct DSP_STREAMINFO *pStreamInfo, UINT uStreamInfoSize)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
struct STRM_INFO strmInfo;/* include stream's private virt addr info */
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_GetInfo:\r\n")));
|
|
|
|
strmInfo.pUser = pStreamInfo;
|
|
status = GetStrmInfo(hStream, &strmInfo, uStreamInfoSize);
|
|
/* Return DSP_SOK if OS calls returned 0 */
|
|
if (status == 0)
|
|
status = DSP_SOK;
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Idle ========
|
|
* Purpose:
|
|
* Terminate I/O with a particular stream, and (optionally)
|
|
* flush output data buffers.
|
|
*/
|
|
DBAPI DSPStream_Idle(DSP_HSTREAM hStream, bool bFlush)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Idle:\r\n")));
|
|
|
|
if (hStream) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_IDLE.hStream = hStream;
|
|
tempStruct.ARGS_STRM_IDLE.bFlush = bFlush;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_STRM_IDLE_OFFSET);
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Idle: "
|
|
"hStrm is Invalid \r\n")));
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Issue ========
|
|
* Purpose:
|
|
* Send a buffer of data to a stream.
|
|
*/
|
|
DBAPI DSPStream_Issue(DSP_HSTREAM hStream, IN BYTE *pBuffer,
|
|
ULONG dwDataSize, ULONG dwBufSize, IN DWORD dwArg)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Issue:\r\n")));
|
|
|
|
if (hStream) {
|
|
/* Check the size of the buffer */
|
|
if (pBuffer) {
|
|
/* Check that the size isn't too small */
|
|
if (dwDataSize > dwBufSize) {
|
|
status = DSP_EINVALIDARG;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Issue: "
|
|
"Invalid argument in the Input\r\n")));
|
|
} else {
|
|
/* Set up the structure */
|
|
tempStruct.ARGS_STRM_ISSUE.hStream = hStream;
|
|
tempStruct.ARGS_STRM_ISSUE.pBuffer = pBuffer;
|
|
tempStruct.ARGS_STRM_ISSUE.dwBytes = dwDataSize;
|
|
tempStruct.ARGS_STRM_ISSUE.dwBufSize =
|
|
dwBufSize;
|
|
tempStruct.ARGS_STRM_ISSUE.dwArg = dwArg;
|
|
/* Call DSP Trap */
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_ISSUE_OFFSET);
|
|
/* Return DSP_SOK if OS calls returned 0 */
|
|
if (status == 0)
|
|
status = DSP_SOK;
|
|
|
|
}
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Issue: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Issue: "
|
|
"hStrm is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Open ========
|
|
* Purpose:
|
|
* Retrieve a stream handle for sending/receiving data buffers
|
|
* to/from a task node on a DSP.
|
|
*/
|
|
DBAPI DSPStream_Open(DSP_HNODE hNode, UINT uDirection, UINT uIndex,
|
|
IN OPTIONAL struct DSP_STREAMATTRIN *pAttrIn,
|
|
OUT DSP_HSTREAM *phStream)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
struct STRM_ATTR strmAttrs;
|
|
#ifndef LINUX /* Events are handled in kernel */
|
|
CHAR szEventName[STRM_MAXEVTNAMELEN];
|
|
WCHAR wszEventName[STRM_MAXEVTNAMELEN];
|
|
CHAR szTemp[STRM_MAXEVTNAMELEN];
|
|
#endif
|
|
struct CMM_OBJECT *hCmm = NULL; /* SM Mgr handle */
|
|
struct CMM_INFO pInfo;/* CMM info; use for virtual space allocation */
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Open:\r\n")));
|
|
|
|
if (!hNode) {
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
|
|
"Invalid handle in the Input\r\n")));
|
|
return status;
|
|
}
|
|
if (uDirection != DSP_TONODE && uDirection != DSP_FROMNODE) {
|
|
status = DSP_EDIRECTION;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
|
|
"Invalid direction in the Input\r\n")));
|
|
return status;
|
|
}
|
|
if (!phStream) {
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Open: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
return status;
|
|
}
|
|
*phStream = NULL;
|
|
strmAttrs.hUserEvent = NULL;
|
|
#ifndef LINUX /* Events are handled in kernel */
|
|
/* Create a 'named' user event that is unique.*/
|
|
strmAttrs.pStreamAttrIn = pAttrIn;
|
|
szEventName[0] = 'E';
|
|
szEventName[1] = 'V';
|
|
szEventName[2] = '\0';
|
|
/* append hNode handle string */
|
|
strncat(szEventName, _ultoa((ULONG)hNode, szTemp, 16), 8);
|
|
/* now append stream index and direction */
|
|
strncat(szEventName, _ultoa((ULONG)uDirection, szTemp, 16), 2);
|
|
strmAttrs.pstrEventName =
|
|
strncat(szEventName, _ultoa((ULONG)uIndex, szTemp, 16), 3);
|
|
(Void)CSL_AnsiToWchar(wszEventName, szEventName, STRM_MAXEVTNAMELEN);
|
|
/* Create an auto reset event. */
|
|
strmAttrs.hUserEvent = CreateEvent(NULL,false,false,wszEventName);
|
|
if (!strmAttrs.hUserEvent) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Open: "
|
|
"Failed to Create the Event \r\n")));
|
|
}
|
|
#endif
|
|
/* Default stream mode is PROCCOPY.
|
|
* Check for currently supported mode(s).*/
|
|
if (pAttrIn) {
|
|
if (pAttrIn->lMode == STRMMODE_LDMA) {
|
|
/* No System-DMA support */
|
|
status = DSP_ENOTIMPL;
|
|
} else
|
|
if ((pAttrIn->lMode != STRMMODE_PROCCOPY)
|
|
&& (pAttrIn->lMode != STRMMODE_ZEROCOPY)
|
|
&& (pAttrIn->lMode != STRMMODE_RDMA)) {
|
|
status = DSP_ESTRMMODE; /* illegal stream mode */
|
|
}
|
|
pAttrIn->uSegment = abs(pAttrIn->uSegment);
|
|
/* make non-neg */
|
|
}
|
|
/* If opening the stream for STRMMODE_ZEROCOPY or
|
|
* STRMMODE_RDMA(DSP-DMA) stream mode, then setup the
|
|
* stream's CMM translator for the specified SM segment.*/
|
|
strmAttrs.pVirtBase = NULL;
|
|
strmAttrs.ulVirtSize = 0;
|
|
if (DSP_SUCCEEDED(status) && pAttrIn) {
|
|
if ((pAttrIn->lMode == STRMMODE_ZEROCOPY) ||
|
|
(pAttrIn->lMode == STRMMODE_RDMA)) {
|
|
if (pAttrIn->uSegment == 0) {
|
|
status = DSP_ENOTSHAREDMEM; /* must be
|
|
SM segment */
|
|
goto loop_end;
|
|
}
|
|
/* >0 is SM segment. Get default SM Mgr */
|
|
tempStruct.ARGS_CMM_GETHANDLE.hProcessor = NULL;
|
|
tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_CMM_GETHANDLE_OFFSET);
|
|
if (status == DSP_SOK) {
|
|
/* Get SM segment info from CMM */
|
|
tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
|
|
tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_CMM_GETINFO_OFFSET);
|
|
if (status != DSP_SOK)
|
|
status = DSP_EFAIL;
|
|
} else
|
|
status = DSP_EFAIL;
|
|
|
|
if (!DSP_SUCCEEDED(status ||
|
|
!(pInfo.ulNumGPPSMSegs >= pAttrIn->uSegment))) {
|
|
status = DSP_EBADSEGID; /* no SM segments */
|
|
goto loop_end;
|
|
}
|
|
/* segInfo index starts at 0 */
|
|
if ((pInfo.segInfo[pAttrIn->uSegment-1].dwSegBasePa
|
|
== 0) || (pInfo.segInfo[pAttrIn->uSegment-1]\
|
|
.ulTotalSegSize) < 0) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("STRM:DSPStream_Open: "
|
|
"Bad SM info...why?\r\n")));
|
|
goto loop_end;
|
|
}
|
|
strmAttrs.pVirtBase = mmap(NULL,
|
|
pInfo.segInfo[pAttrIn->uSegment-1]\
|
|
.ulTotalSegSize, PROT_READ | PROT_WRITE,
|
|
MAP_SHARED | MAP_LOCKED, hMediaFile, pInfo\
|
|
.segInfo[pAttrIn->uSegment-1].dwSegBasePa);
|
|
if (strmAttrs.pVirtBase == NULL) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("STRM: DSPStream_Open: "
|
|
"Virt alloc failed\r\n")));
|
|
goto loop_end;
|
|
}
|
|
strmAttrs.ulVirtSize =
|
|
pInfo.segInfo[pAttrIn->uSegment-1].ulTotalSegSize;
|
|
}
|
|
}
|
|
loop_end:
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Set up the structure */
|
|
strmAttrs.pStreamAttrIn = pAttrIn;
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_OPEN.hNode = hNode;
|
|
tempStruct.ARGS_STRM_OPEN.uDirection = uDirection;
|
|
tempStruct.ARGS_STRM_OPEN.uIndex = uIndex;
|
|
tempStruct.ARGS_STRM_OPEN.pAttrIn = &strmAttrs;
|
|
tempStruct.ARGS_STRM_OPEN.phStream = phStream;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_STRM_OPEN_OFFSET);
|
|
#ifndef LINUX /* Events are handled in kernel */
|
|
if (DSP_FAILED(status))
|
|
CloseHandle(strmAttrs.hUserEvent);
|
|
|
|
#endif
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_PrepareBuffer ========
|
|
* Purpose:
|
|
* Prepares a buffer.
|
|
*/
|
|
DBAPI DSPStream_PrepareBuffer(DSP_HSTREAM hStream, UINT uSize, BYTE *pBuffer)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
#ifndef LINUX
|
|
/* Pages are never swapped out (i.e. always locked in Linux) */
|
|
ULONG aPageTab[STRM_MAXLOCKPAGES];
|
|
/* Find the maximum # of pages that could be locked. x86 &
|
|
ARM=4Kb pages */
|
|
UINT cPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(NULL, uSize);
|
|
#endif
|
|
/* Do error checking here to API spec. We don't call down to WCD */
|
|
if (!hStream)
|
|
status = DSP_EHANDLE;
|
|
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (!pBuffer)
|
|
status = DSP_EPOINTER;
|
|
}
|
|
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (uSize <= 0)
|
|
status = DSP_ESIZE;
|
|
}
|
|
#ifndef LINUX
|
|
/* Pages are never swapped out (i.e. always locked in Linux) */
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (cPages > STRM_MAXLOCKPAGES)
|
|
status = DSP_EFAIL;
|
|
else {
|
|
if (!LockPages((LPVOID)pBuffer, uSize, aPageTab,
|
|
LOCKFLAG_WRITE))
|
|
status = DSP_EFAIL;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Reclaim ========
|
|
* Purpose:
|
|
* Request a buffer back from a stream.
|
|
*/
|
|
DBAPI DSPStream_Reclaim(DSP_HSTREAM hStream, OUT BYTE **pBufPtr,
|
|
OUT ULONG *pDataSize, OUT ULONG *pBufSize, OUT DWORD *pdwArg)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Reclaim:\r\n")));
|
|
|
|
if (hStream) {
|
|
/* Check the size of the buffer */
|
|
if ((pBufPtr) && (pDataSize) && (pdwArg)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_RECLAIM.hStream = hStream;
|
|
tempStruct.ARGS_STRM_RECLAIM.pBufPtr = pBufPtr;
|
|
tempStruct.ARGS_STRM_RECLAIM.pBytes = pDataSize;
|
|
tempStruct.ARGS_STRM_RECLAIM.pBufSize = pBufSize;
|
|
tempStruct.ARGS_STRM_RECLAIM.pdwArg = pdwArg;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_RECLAIM_OFFSET);
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Reclaim: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPStream_Reclaim: "
|
|
"hStrm is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_RegisterNotify ========
|
|
* Purpose:
|
|
* Register to be notified of specific events for this stream.
|
|
*/
|
|
DBAPI
|
|
DSPStream_RegisterNotify(DSP_HSTREAM hStream, UINT uEventMask,
|
|
UINT uNotifyType, struct DSP_NOTIFICATION *hNotification)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPStream_RegisterNotify:\r\n")));
|
|
|
|
if ((hStream) && (hNotification)) {
|
|
if (IsValidStrmEvent(uEventMask)) {
|
|
if (IsValidNotifyMask(uNotifyType)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_REGISTERNOTIFY.hStream =
|
|
hStream;
|
|
tempStruct.ARGS_STRM_REGISTERNOTIFY.uEventMask =
|
|
uEventMask;
|
|
tempStruct.ARGS_STRM_REGISTERNOTIFY\
|
|
.uNotifyType = uNotifyType;
|
|
tempStruct.ARGS_STRM_REGISTERNOTIFY\
|
|
.hNotification = hNotification;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_REGISTERNOTIFY_OFFSET);
|
|
} else {
|
|
status = DSP_ENOTIMPL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_RegisterNotify: "
|
|
"Invalid Notify Mask \r\n")));
|
|
}
|
|
} else {
|
|
status = DSP_EVALUE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_RegisterNotify: "
|
|
"Invalid Event Mask \r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid handle */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_RegisterNotify: "
|
|
"Invalid Handle \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_Select ========
|
|
* Purpose:
|
|
* Select a ready stream.
|
|
*/
|
|
DBAPI DSPStream_Select(IN DSP_HSTREAM *aStreamTab,
|
|
UINT nStreams, OUT UINT *pMask, UINT uTimeout)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPStream_Select:\r\n")));
|
|
|
|
if ((aStreamTab) && (pMask)) {
|
|
if (nStreams) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_SELECT.aStreamTab = aStreamTab;
|
|
tempStruct.ARGS_STRM_SELECT.nStreams = nStreams;
|
|
tempStruct.ARGS_STRM_SELECT.pMask = pMask;
|
|
tempStruct.ARGS_STRM_SELECT.uTimeout = uTimeout;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_SELECT_OFFSET);
|
|
} else
|
|
/* nStreams == 0 */
|
|
*pMask = 0;
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_Select: hStrm is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPStream_UnprepareBuffer ========
|
|
* Purpose:
|
|
* Unprepares a buffer.
|
|
*/
|
|
DBAPI DSPStream_UnprepareBuffer(DSP_HSTREAM hStream, UINT uSize,
|
|
BYTE *pBuffer)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
|
|
/* Do error checking here to API spec. We don't call down to WCD */
|
|
if (!hStream)
|
|
status = DSP_EHANDLE;
|
|
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (!pBuffer)
|
|
status = DSP_EPOINTER;
|
|
}
|
|
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/*|| ((LPVOID)pBuffer == NULL) - already checked above */
|
|
if ((uSize <= 0))
|
|
status = DSP_EFAIL;
|
|
}
|
|
#ifndef LINUX /* Pages are never swapped out
|
|
(i.e. always locked in Linux) */
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (!UnlockPages((LPVOID) pBuffer, uSize))
|
|
status = DSP_EFAIL;
|
|
}
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== GetStrmInfo ========
|
|
*/
|
|
static DSP_STATUS GetStrmInfo(DSP_HSTREAM hStream, struct STRM_INFO *pStrmInfo,
|
|
UINT uStreamInfoSize)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
if (hStream) {
|
|
/* Check the size of the buffer */
|
|
if (pStrmInfo && pStrmInfo->pUser) {
|
|
if (uStreamInfoSize >= sizeof(struct DSP_STREAMINFO)) {
|
|
/* user info */
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_STRM_GETINFO.hStream = hStream;
|
|
tempStruct.ARGS_STRM_GETINFO.pStreamInfo =
|
|
pStrmInfo;
|
|
/* user returned struct DSP_STREAMINFO
|
|
info size */
|
|
tempStruct.ARGS_STRM_GETINFO.uStreamInfoSize =
|
|
uStreamInfoSize;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_STRM_GETINFO_OFFSET);
|
|
} else {
|
|
status = DSP_ESIZE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_GetInfo: "
|
|
"uStreamInfo size is less than the "
|
|
"size of struct DSP_STREAMINFO\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPStream_GetInfo: "
|
|
"Invalid pointer\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
|
|
"NODE: DSPStream_GetInfo: hStrm is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|