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