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