962 lines
26 KiB
C
962 lines
26 KiB
C
/*
|
|
* dspbridge/src/api/linux/DSPNode.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.
|
|
*/
|
|
|
|
|
|
/*
|
|
* ======== DSPNode.c ========
|
|
* Description:
|
|
* This is the source for the DSP/BIOS Bridge API node module. The
|
|
* parameters are validated at the API level, but the bulk of the
|
|
* work is done at the driver level through the RM NODE module.
|
|
*
|
|
* Public Functions:
|
|
* DSPNode_Allocate
|
|
* DSPNode_AllocMsgBuf
|
|
* DSPNode_ChangePriority
|
|
* DSPNode_Connect
|
|
* DSPNode_ConnectEx
|
|
* DSPNode_Create
|
|
* DSPNode_Delete
|
|
* DSPNode_FreeMsgBuf
|
|
* DSPNode_GetAttr
|
|
* DSPNode_GetMessage
|
|
* DSPNode_Pause
|
|
* DSPNode_PutMessage
|
|
* DSPNode_RegisterNotify
|
|
* DSPNode_Run
|
|
* DSPNode_Terminate
|
|
*
|
|
*! Revision History
|
|
*! ================
|
|
*! 14-Mar-2002 map Set *pBuffer to null before returning error status in
|
|
*! DSPNode_AllocMsgBuf.
|
|
*! 01-Oct-2001 rr CMM error codes are converted to DSP_STATUS in
|
|
*! DSPNode_Allocate.
|
|
*! 11-Sep-2001 ag Zero-copy message support.
|
|
*! 08-Jun-2001 jeh Fixed priority range check in DSPNode_ChangePriority.
|
|
*! 23-Apr-2001 jeh Added pStatus parameter to DSPNode_Terminate.
|
|
*! 06-Feb-2001 kc: Added check for alignment value in DSPNode_AllocMsgBuf
|
|
*! 08-Dec-2000 ag Added alignment to DSPNode_AllocMsgBuf().
|
|
*! 05-Dec-2000 ag Added SM support to DSPNode_[Alloc][Free]MsgBuf().
|
|
*! 09-Nov-2000 rr: Code cleaned up. Use of IsValidEvent/Mask Macros.
|
|
*! 27-Oct-2000 jeh Updated to version 0.9 of API spec.
|
|
*! 07-Sep-2000 jeh Changed type HANDLE in DSPNode_RegisterNotify to
|
|
*! DSP_HNOTIFICATION. Added DSP_STRMATTR param to
|
|
*! DSPNode_Connect.
|
|
*! 04-Aug-2000 rr: Name changed to DSPNode.c
|
|
*! 27-Jul-2000 rr: Types updated to ver 0.8 API.
|
|
*! 18-Jul-2000 rr: Node calls into the Class driver.
|
|
*! Only parameters are validated here.
|
|
*! 17-May-2000 rr: DSPNode_Connect checks for GHPPNODE.
|
|
*! 15-May-2000 gp: Made input args to DSPNode_Allocate() CONST.
|
|
*! Return DSP_ENOTIMPL from DSPNode_ChangePriority().
|
|
*! 02-May-2000 rr: Reg functions use SERVICES.
|
|
*! 12-Apr-2000 ww: Created based on DirectDSP API specification, Version 0.6.
|
|
*
|
|
*/
|
|
|
|
/* ----------------------------------- Host OS */
|
|
#include <host_os.h>
|
|
#include <stdlib.h>
|
|
#include <malloc.h>
|
|
|
|
/* ----------------------------------- DSP/BIOS Bridge */
|
|
#include <dbdefs.h>
|
|
#include <errbase.h>
|
|
|
|
/* ----------------------------------- Trace & Debug */
|
|
#include <dbg.h>
|
|
#include <dbg_zones.h>
|
|
|
|
/* ----------------------------------- Resource Manager */
|
|
#include <memry.h>
|
|
|
|
/* ----------------------------------- Others */
|
|
#include <dsptrap.h>
|
|
|
|
/* ----------------------------------- This */
|
|
#include "_dbdebug.h"
|
|
#include "_dbpriv.h"
|
|
|
|
#include <DSPNode.h>
|
|
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
#include <perfutils.h>
|
|
#endif
|
|
|
|
/* ----------------------------------- Globals */
|
|
extern int hMediaFile; /* class driver handle */
|
|
|
|
/* Declared here, not to users */
|
|
DSP_STATUS GetNodeType(DSP_HNODE hNode, DSP_NODETYPE *pNodeType);
|
|
|
|
/*
|
|
* ======== DSPNode_Allocate ========
|
|
* Purpose:
|
|
* Allocate data structures for controlling and communicating
|
|
* with a node on a specific DSP processor..
|
|
*/
|
|
DBAPI DSPNode_Allocate(DSP_HPROCESSOR hProcessor,
|
|
IN CONST struct DSP_UUID *pNodeID,
|
|
IN CONST OPTIONAL struct DSP_CBDATA *pArgs,
|
|
IN OPTIONAL struct DSP_NODEATTRIN *pAttrIn,
|
|
OUT DSP_HNODE *phNode)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
struct CMM_OBJECT *hCmm; /* shared memory mngr handle */
|
|
struct CMM_INFO pInfo; /* Used for virtual space allocation */
|
|
PVOID pVirtBase;
|
|
struct DSP_BUFFERATTR bufAttr;
|
|
DSP_NODETYPE nodeType;
|
|
struct DSP_NDBPROPS nodeProps;
|
|
UINT heapSize = 0;
|
|
PVOID pGPPVirtAddr = NULL;
|
|
UINT uProfileID;
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Allocate:\r\n")));
|
|
if (!hProcessor) {
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_Allocate: "
|
|
"hProcessor is Invalid \r\n")));
|
|
goto func_cont;
|
|
}
|
|
if (!(pNodeID) || !(phNode)) {
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Allocate: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
goto func_cont;
|
|
}
|
|
/* First get the NODE properties, allocate, reserve
|
|
memory for Node heap */
|
|
if (pAttrIn) {
|
|
status = DSPNode_GetUUIDProps(hProcessor, pNodeID, &nodeProps);
|
|
pAttrIn->pGPPVirtAddr = NULL;
|
|
if (DSP_SUCCEEDED(status)) {
|
|
uProfileID = pAttrIn->uProfileID;
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
("DSPNodeAllocate: User requested"
|
|
"node heap profile \n"));
|
|
if (uProfileID < nodeProps.uCountProfiles)
|
|
heapSize =
|
|
nodeProps.aProfiles[uProfileID].ulHeapSize;
|
|
if (heapSize) {
|
|
/* allocate heap memory */
|
|
/* Make heap size multiple of page size * */
|
|
heapSize = PG_ALIGN_HIGH(heapSize, PG_SIZE_4K);
|
|
/* align memory on cache line boundary * */
|
|
pGPPVirtAddr = memalign(GEM_CACHE_LINE_SIZE,
|
|
heapSize);
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
("DSPNodeAllocate: Node heap memory"
|
|
"addr, size \n"));
|
|
if ((pGPPVirtAddr == NULL))
|
|
status = DSP_EMEMORY;
|
|
pAttrIn->uHeapSize = heapSize;
|
|
pAttrIn->pGPPVirtAddr = pGPPVirtAddr;
|
|
}
|
|
} else {
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
|
|
"NODE:DSPNode_Allocate: Failed to get Node "
|
|
"UUID properties \r\n")));
|
|
}
|
|
}
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Set up the structure Call DSP Trap */
|
|
tempStruct.ARGS_NODE_ALLOCATE.hProcessor = hProcessor;
|
|
tempStruct.ARGS_NODE_ALLOCATE.pNodeID =
|
|
(struct DSP_UUID *)pNodeID;
|
|
tempStruct.ARGS_NODE_ALLOCATE.pArgs =
|
|
(struct DSP_CBDATA *)pArgs;
|
|
tempStruct.ARGS_NODE_ALLOCATE.pAttrIn =
|
|
(struct DSP_NODEATTRIN *)pAttrIn;
|
|
tempStruct.ARGS_NODE_ALLOCATE.phNode = phNode;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_ALLOCATE_OFFSET);
|
|
}
|
|
func_cont:
|
|
/* If 1st SM segment is configured then allocate and map it to
|
|
this process.*/
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
if (pGPPVirtAddr)
|
|
free(pGPPVirtAddr);
|
|
return status;
|
|
}
|
|
tempStruct.ARGS_CMM_GETHANDLE.hProcessor = hProcessor;
|
|
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);
|
|
if (DSP_FAILED(status)) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
|
|
"NODE: DSPNode_Allocate: "
|
|
"Failed to get SM segment\r\n")));
|
|
} else
|
|
status = DSP_SOK;
|
|
|
|
} else {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
|
|
"NODE: DSPNode_Allocate:Failed to CMM handle\r\n")));
|
|
}
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
free(pGPPVirtAddr);
|
|
return status;
|
|
}
|
|
|
|
GetNodeType(*phNode, &nodeType);
|
|
if ((nodeType != NODE_DEVICE) && (pInfo.ulNumGPPSMSegs > 0)) {
|
|
/* Messaging uses 1st segment */
|
|
if ((pInfo.segInfo[0].dwSegBasePa != 0) &&
|
|
(pInfo.segInfo[0].ulTotalSegSize) > 0) {
|
|
pVirtBase = mmap(NULL, pInfo.segInfo[0].ulTotalSegSize,
|
|
PROT_READ | PROT_WRITE, MAP_SHARED |
|
|
MAP_LOCKED, hMediaFile,
|
|
pInfo.segInfo[0].dwSegBasePa);
|
|
if (!pVirtBase) {
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: "
|
|
"DSPNode_Allocate:Virt alloc failed\r\n")));
|
|
status = DSP_EMEMORY;
|
|
/* Clean up */
|
|
tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
|
|
DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_DELETE_OFFSET);
|
|
return status;
|
|
}
|
|
/* set node translator's virt addr range for seg */
|
|
bufAttr.uAlignment = 0;
|
|
bufAttr.uSegment = 1 | MEMRY_SETVIRTUALSEGID;
|
|
bufAttr.cbStruct = 0;
|
|
status = DSPNode_AllocMsgBuf(*phNode,
|
|
pInfo.segInfo[0].ulTotalSegSize,
|
|
&bufAttr, (BYTE **)&pVirtBase);
|
|
if (DSP_FAILED(status)) {
|
|
/* If failed to set segment, unmap */
|
|
munmap(pVirtBase,
|
|
pInfo.segInfo[0].ulTotalSegSize);
|
|
/* Clean up */
|
|
tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
|
|
DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_DELETE_OFFSET);
|
|
}
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_AllocMsgBuf ========
|
|
*/
|
|
DBAPI DSPNode_AllocMsgBuf(DSP_HNODE hNode, UINT uSize,
|
|
IN OPTIONAL struct DSP_BUFFERATTR *pAttr, OUT BYTE **pBuffer)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPNode_AllocMsgBuf:\r\n")));
|
|
|
|
if (uSize == 0) {
|
|
status = DSP_ESIZE;
|
|
if (pBuffer)
|
|
*pBuffer = NULL;
|
|
|
|
} else if (hNode) {
|
|
if (pBuffer) {
|
|
/* Set up the structure */
|
|
tempStruct.ARGS_NODE_ALLOCMSGBUF.hNode = hNode;
|
|
tempStruct.ARGS_NODE_ALLOCMSGBUF.uSize = uSize;
|
|
tempStruct.ARGS_NODE_ALLOCMSGBUF.pAttr = pAttr;
|
|
/* Va Base */
|
|
tempStruct.ARGS_NODE_ALLOCMSGBUF.pBuffer = pBuffer;
|
|
/* Call DSP Trap */
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_ALLOCMSGBUF_OFFSET);
|
|
if (DSP_SUCCEEDED(status)) {
|
|
if (*pBuffer == NULL) {
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPNode_AllocMsgBuf: "
|
|
"No SM\r\n")));
|
|
status = DSP_EMEMORY; /* No SM */
|
|
}
|
|
} else
|
|
*pBuffer = NULL;
|
|
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: "
|
|
"DSPNode_AllocBuf: Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid handle */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_AllocMsgBuf: "
|
|
"hNode is Invalid \r\n")));
|
|
if (pBuffer)
|
|
*pBuffer = NULL;
|
|
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_ChangePriority ========
|
|
* Purpose:
|
|
* Change a task node's runtime priority within the DSP RTOS.
|
|
*/
|
|
DBAPI DSPNode_ChangePriority(DSP_HNODE hNode, INT iPriority)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPNode_ChangePriority:\r\n")));
|
|
|
|
if (hNode) {
|
|
/* Set up the structure */
|
|
if (iPriority >= DSP_NODE_MIN_PRIORITY &&
|
|
iPriority <= DSP_NODE_MAX_PRIORITY) {
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_CHANGEPRIORITY.hNode = hNode;
|
|
tempStruct.ARGS_NODE_CHANGEPRIORITY.iPriority =
|
|
iPriority;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_CHANGEPRIORITY_OFFSET);
|
|
} else
|
|
status = DSP_ERANGE;
|
|
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_ChangePriority: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Connect ========
|
|
* Purpose:
|
|
* Make a stream connection, either between two nodes on a DSP,
|
|
* or between a node on a DSP and the GPP.
|
|
*/
|
|
DBAPI DSPNode_Connect(DSP_HNODE hNode, UINT uStream, DSP_HNODE hOtherNode,
|
|
UINT uOtherStream, IN OPTIONAL struct DSP_STRMATTR *pAttrs)
|
|
{
|
|
return DSPNode_ConnectEx(hNode, uStream, hOtherNode, uOtherStream,
|
|
pAttrs, NULL);
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_ConnectEx ========
|
|
* Purpose:
|
|
* Make a stream connection, either between two nodes on a DSP,
|
|
* or between a node on a DSP and the GPP.
|
|
*/
|
|
DBAPI DSPNode_ConnectEx(DSP_HNODE hNode, UINT uStream, DSP_HNODE hOtherNode,
|
|
UINT uOtherStream, IN OPTIONAL struct DSP_STRMATTR *pAttrs,
|
|
IN OPTIONAL struct DSP_CBDATA *pConnParam)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_ConnectEx:\r\n")));
|
|
|
|
if ((hNode) && (hOtherNode)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_CONNECT.hNode = hNode;
|
|
tempStruct.ARGS_NODE_CONNECT.uStream = uStream;
|
|
tempStruct.ARGS_NODE_CONNECT.hOtherNode = hOtherNode;
|
|
tempStruct.ARGS_NODE_CONNECT.uOtherStream = uOtherStream;
|
|
tempStruct.ARGS_NODE_CONNECT.pAttrs = pAttrs;
|
|
tempStruct.ARGS_NODE_CONNECT.pConnParam = pConnParam;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_CONNECT_OFFSET);
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Connect: "
|
|
"hNode or hOtherNode is Invalid Handle\r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Create ========
|
|
* Purpose:
|
|
* Create a node in a pre-run (i.e., inactive) state on its
|
|
* DSP processor.
|
|
*/
|
|
DBAPI DSPNode_Create(DSP_HNODE hNode)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
struct timeval tv_beg;
|
|
struct timeval tv_end;
|
|
struct timezone tz;
|
|
int timeRetVal = 0;
|
|
|
|
timeRetVal = getTimeStamp(&tv_beg);
|
|
#endif
|
|
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Create:\r\n")));
|
|
|
|
if (hNode) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_CREATE.hNode = hNode;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_CREATE_OFFSET);
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_Create: hNode is Invalid Handle\r\n")));
|
|
}
|
|
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
timeRetVal = getTimeStamp(&tv_end);
|
|
PrintStatistics(&tv_beg, &tv_end, "DSPNode_Create", 0);
|
|
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Delete ========
|
|
* Purpose:
|
|
* Delete all DSP-side and GPP-side resources for the node.
|
|
*/
|
|
DBAPI DSPNode_Delete(DSP_HNODE hNode)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
BYTE *pVirtBase = NULL;
|
|
struct DSP_BUFFERATTR bufAttr;
|
|
struct CMM_OBJECT *hCmm; /* shared memory mngr handle */
|
|
struct CMM_INFO pInfo; /* Used for virtual space allocation */
|
|
DSP_NODETYPE nodeType;
|
|
struct DSP_NODEATTR nodeAttr;
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
struct timeval tv_beg;
|
|
struct timeval tv_end;
|
|
struct timezone tz;
|
|
int timeRetVal = 0;
|
|
|
|
timeRetVal = getTimeStamp(&tv_beg);
|
|
#endif
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Delete:\r\n")));
|
|
if (!hNode) {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Delete: "
|
|
"hNode is Invalid Handle\r\n")));
|
|
return status;
|
|
}
|
|
/* 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);
|
|
if (DSP_FAILED(status)) {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_Delete:"
|
|
" Failed to get SM segment\r\n")));
|
|
} else
|
|
status = DSP_SOK;
|
|
|
|
} else {
|
|
status = DSP_EFAIL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Delete: "
|
|
"Failed to CMM handle\r\n")));
|
|
}
|
|
if (!DSP_SUCCEEDED(status)) {
|
|
status = DSP_EBADSEGID; /* no SM segments*/
|
|
return status;
|
|
}
|
|
status = DSPNode_GetAttr(hNode, &nodeAttr, sizeof(nodeAttr));
|
|
GetNodeType(hNode, &nodeType);
|
|
if (nodeType != NODE_DEVICE) {
|
|
/*segInfo index starts at 0.These checks may not be required*/
|
|
if ((pInfo.segInfo[0].dwSegBasePa != 0) &&
|
|
(pInfo.segInfo[0].ulTotalSegSize) > 0) {
|
|
/* get node translator's virtual address range
|
|
so we can free it */
|
|
bufAttr.uAlignment = 0;
|
|
bufAttr.uSegment = 1 | MEMRY_GETVIRTUALSEGID;
|
|
DSPNode_AllocMsgBuf(hNode, 1, &bufAttr, &pVirtBase);
|
|
/* Free virtual space */
|
|
if (!pVirtBase)
|
|
goto loop_end;
|
|
|
|
if (munmap(pVirtBase,
|
|
pInfo.segInfo[0].ulTotalSegSize)) {
|
|
status = DSP_EFAIL;
|
|
}
|
|
}
|
|
}
|
|
loop_end:
|
|
if (DSP_SUCCEEDED(status)) {
|
|
/* Set up the structure Call DSP Trap */
|
|
tempStruct.ARGS_NODE_DELETE.hNode = hNode;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_DELETE_OFFSET);
|
|
/* Free any node heap memory */
|
|
if (nodeAttr.inNodeAttrIn.pGPPVirtAddr) {
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("DSPNodeDelete:"
|
|
"Freeing Node heap addr \n")));
|
|
free(nodeAttr.inNodeAttrIn.pGPPVirtAddr);
|
|
}
|
|
}
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
timeRetVal = getTimeStamp(&tv_end);
|
|
PrintStatistics(&tv_beg, &tv_end, "DSPNode_Delete", 0);
|
|
#endif
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_FreeMsgBuf ========
|
|
*/
|
|
DBAPI DSPNode_FreeMsgBuf(DSP_HNODE hNode, IN BYTE *pBuffer,
|
|
IN OPTIONAL struct DSP_BUFFERATTR *pAttr)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_FreeMsgBuf:\r\n")));
|
|
|
|
if (hNode) {
|
|
if (pBuffer) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_FREEMSGBUF.hNode = hNode;
|
|
tempStruct.ARGS_NODE_FREEMSGBUF.pBuffer = pBuffer;
|
|
tempStruct.ARGS_NODE_FREEMSGBUF.pAttr = pAttr;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_FREEMSGBUF_OFFSET);
|
|
if (DSP_FAILED(status)) {
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: "
|
|
"DSPNode_FreeMsgBuf:"
|
|
"Failed to Free SM buf\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_FreeMsgBuf: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_FreeMsgBuf: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_GetAttr ========
|
|
* Purpose:
|
|
* Copy the current attributes of the specified node.
|
|
*/
|
|
DBAPI DSPNode_GetAttr(DSP_HNODE hNode, OUT struct DSP_NODEATTR *pAttr,
|
|
UINT uAttrSize)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_GetAttr:\r\n")));
|
|
|
|
if (hNode) {
|
|
if (pAttr) {
|
|
if (uAttrSize >= sizeof(struct DSP_NODEATTR)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_GETATTR.hNode = hNode;
|
|
tempStruct.ARGS_NODE_GETATTR.pAttr = pAttr;
|
|
tempStruct.ARGS_NODE_GETATTR.uAttrSize =
|
|
uAttrSize;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_GETATTR_OFFSET);
|
|
} else {
|
|
status = DSP_ESIZE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetAttr: "
|
|
"Size is too small \r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetAttr: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetAttr: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_GetMessage ========
|
|
* Purpose:
|
|
* Retrieve an event message from a task node.
|
|
*/
|
|
DBAPI DSPNode_GetMessage(DSP_HNODE hNode, OUT struct DSP_MSG *pMessage,
|
|
UINT uTimeout)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
struct timeval tv_beg;
|
|
struct timeval tv_end;
|
|
struct timezone tz;
|
|
int timeRetVal = 0;
|
|
|
|
timeRetVal = getTimeStamp(&tv_beg);
|
|
|
|
#endif
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_GetMessage:\r\n")));
|
|
|
|
if (hNode) {
|
|
if (pMessage) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_GETMESSAGE.hNode = hNode;
|
|
tempStruct.ARGS_NODE_GETMESSAGE.pMessage = pMessage;
|
|
tempStruct.ARGS_NODE_GETMESSAGE.uTimeout = uTimeout;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_GETMESSAGE_OFFSET);
|
|
} else {
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetMessage:"
|
|
"pMessage is Invalid \r\n")));
|
|
}
|
|
} else {
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetMessage: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
timeRetVal = getTimeStamp(&tv_end);
|
|
PrintStatistics(&tv_beg, &tv_end, "DSPNode_GetMessage", 0);
|
|
#endif
|
|
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== GetNodeType ========
|
|
* Purpose:
|
|
* Return the node type
|
|
*/
|
|
DSP_STATUS GetNodeType(DSP_HNODE hNode, DSP_NODETYPE *pNodeType)
|
|
{
|
|
/*DSP_STATUS status;*/
|
|
DSP_STATUS status = DSP_SOK;
|
|
struct DSP_NODEATTR nodeAttr;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("GetNodeType:\r\n")));
|
|
|
|
if (hNode) {
|
|
status = DSPNode_GetAttr(hNode, &nodeAttr, sizeof(nodeAttr));
|
|
if (DSP_SUCCEEDED(status)) {
|
|
*pNodeType =
|
|
nodeAttr.iNodeInfo.nbNodeDatabaseProps.uNodeType;
|
|
}
|
|
} else {
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("GetNodeType: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Pause ========
|
|
* Purpose:
|
|
* Temporarily suspend execution of a node that is currently running
|
|
* on a DSP.
|
|
*/
|
|
DBAPI DSPNode_Pause(DSP_HNODE hNode)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Pause:\r\n")));
|
|
|
|
if (hNode) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_PAUSE.hNode = hNode;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_PAUSE_OFFSET);
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Pause: "
|
|
"hNode is Invalid Handle\r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_PutMessage ========
|
|
* Purpose:
|
|
* Send an event message to a task node.
|
|
*/
|
|
DBAPI DSPNode_PutMessage(DSP_HNODE hNode, IN CONST struct DSP_MSG *pMessage,
|
|
UINT uTimeout)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
struct timeval tv_beg;
|
|
struct timeval tv_end;
|
|
struct timeval tz;
|
|
int timeRetVal = 0;
|
|
|
|
timeRetVal = getTimeStamp(&tv_beg);
|
|
#endif
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_PutMessage:\r\n")));
|
|
|
|
if (hNode) {
|
|
if (pMessage) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_PUTMESSAGE.hNode = hNode;
|
|
tempStruct.ARGS_NODE_PUTMESSAGE.pMessage =
|
|
(struct DSP_MSG *)pMessage;
|
|
tempStruct.ARGS_NODE_PUTMESSAGE.uTimeout = uTimeout;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_PUTMESSAGE_OFFSET);
|
|
} else {
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_PutMessage: "
|
|
"pMessage is Invalid \r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_PutMessage: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
#ifdef DEBUG_BRIDGE_PERF
|
|
timeRetVal = getTimeStamp(&tv_end);
|
|
PrintStatistics(&tv_beg, &tv_end, "DSPNode_PutMessage", 0);
|
|
#endif
|
|
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_RegisterNotify ========
|
|
* Purpose:
|
|
* Register to be notified of specific events for this node.
|
|
*/
|
|
DBAPI
|
|
DSPNode_RegisterNotify(DSP_HNODE hNode, UINT uEventMask,
|
|
UINT uNotifyType, struct DSP_NOTIFICATION *hNotification)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE: DSPNode_RegisterNotify:\r\n")));
|
|
|
|
if ((hNode) && (hNotification)) {
|
|
if (IsValidNodeEvent(uEventMask)) {
|
|
if (IsValidNotifyMask(uNotifyType)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_REGISTERNOTIFY.hNode =
|
|
hNode;
|
|
tempStruct.ARGS_NODE_REGISTERNOTIFY.uEventMask =
|
|
uEventMask;
|
|
tempStruct.ARGS_NODE_REGISTERNOTIFY\
|
|
.uNotifyType = uNotifyType;
|
|
tempStruct.ARGS_NODE_REGISTERNOTIFY\
|
|
.hNotification = hNotification;
|
|
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_REGISTERNOTIFY_OFFSET);
|
|
} else {
|
|
status = DSP_ENOTIMPL;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_RegisterNotify: "
|
|
"Invalid Notification Mask \r\n")));
|
|
}
|
|
} else {
|
|
status = DSP_EVALUE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_RegisterNotify:"
|
|
"Invalid Event type\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_RegisterNotify: "
|
|
"hNode is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Run ========
|
|
* Purpose:
|
|
* Start a task node running.
|
|
*/
|
|
DBAPI DSPNode_Run(DSP_HNODE hNode)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Run:\r\n")));
|
|
|
|
if (hNode) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_RUN.hNode = hNode;
|
|
status = DSPTRAP_Trap(&tempStruct, CMD_NODE_RUN_OFFSET);
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Run: "
|
|
"hNode is Invalid Handle\r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
/*
|
|
* ======== DSPNode_Terminate ========
|
|
* Purpose:
|
|
* Signal a task node running on a DSP processor that it should
|
|
* exit its execute-phase function.
|
|
*/
|
|
DBAPI DSPNode_Terminate(DSP_HNODE hNode, DSP_STATUS *pStatus)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Terminate:\r\n")));
|
|
|
|
if (hNode) {
|
|
/* !DSP_ValidWritePtr means it is a valid write ptr */
|
|
if (!DSP_ValidWritePtr(pStatus, sizeof(DSP_STATUS))) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_TERMINATE.hNode = hNode;
|
|
tempStruct.ARGS_NODE_TERMINATE.pStatus = pStatus;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_TERMINATE_OFFSET);
|
|
} else
|
|
status = DSP_EPOINTER;
|
|
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_Terminate: "
|
|
"hNode is Invalid Handle\r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* ======== DSPNode_GetUUIDProps ========
|
|
* Purpose:
|
|
* Get Node properties from DCD/DOF file given the UUID
|
|
*/
|
|
DBAPI DSPNode_GetUUIDProps(DSP_HPROCESSOR hProcessor,
|
|
IN CONST struct DSP_UUID *pNodeID,
|
|
OUT struct DSP_NDBPROPS *pNodeProps)
|
|
{
|
|
DSP_STATUS status = DSP_SOK;
|
|
Trapped_Args tempStruct;
|
|
|
|
DEBUGMSG(DSPAPI_ZONE_FUNCTION,
|
|
(TEXT("NODE:DSPNode_GetUUIDProps:\r\n")));
|
|
|
|
if (hProcessor) {
|
|
if ((pNodeID) && (pNodeProps)) {
|
|
/* Set up the structure */
|
|
/* Call DSP Trap */
|
|
tempStruct.ARGS_NODE_GETUUIDPROPS.hProcessor =
|
|
hProcessor;
|
|
tempStruct.ARGS_NODE_GETUUIDPROPS.pNodeID =
|
|
(struct DSP_UUID *)pNodeID;
|
|
tempStruct.ARGS_NODE_GETUUIDPROPS.pNodeProps =
|
|
(struct DSP_NDBPROPS *) pNodeProps;
|
|
status = DSPTRAP_Trap(&tempStruct,
|
|
CMD_NODE_GETUUIDPROPS_OFFSET);
|
|
} else {
|
|
/* Invalid parameter */
|
|
status = DSP_EPOINTER;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetUUIDProps: "
|
|
"Invalid pointer in the Input\r\n")));
|
|
}
|
|
} else {
|
|
/* Invalid pointer */
|
|
status = DSP_EHANDLE;
|
|
DEBUGMSG(DSPAPI_ZONE_ERROR,
|
|
(TEXT("NODE: DSPNode_GetUUIDProps: "
|
|
"hProcessor is Invalid \r\n")));
|
|
}
|
|
|
|
return status;
|
|
}
|
|
|