Home | History | Annotate | Download | only in libbridge
      1 /*
      2  * dspbridge/src/api/linux/DSPNode.c
      3  *
      4  * DSP-BIOS Bridge driver support functions for TI OMAP processors.
      5  *
      6  * Copyright (C) 2007 Texas Instruments, Inc.
      7  *
      8  * This program is free software; you can redistribute it and/or modify it
      9  * under the terms of the GNU Lesser General Public License as published
     10  * by the Free Software Foundation version 2.1 of the License.
     11  *
     12  * This program is distributed .as is. WITHOUT ANY WARRANTY of any kind,
     13  * whether express or implied; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * Lesser General Public License for more details.
     16  */
     17 
     18 
     19 /*
     20  *  ======== DSPNode.c ========
     21  *  Description:
     22  *      This is the source for the DSP/BIOS Bridge API node module. The
     23  *      parameters are validated at the API level, but the bulk of the
     24  *      work is done at the driver level through the RM NODE module.
     25  *
     26  *  Public Functions:
     27  *      DSPNode_Allocate
     28  *      DSPNode_AllocMsgBuf
     29  *      DSPNode_ChangePriority
     30  *      DSPNode_Connect
     31  *      DSPNode_ConnectEx
     32  *      DSPNode_Create
     33  *      DSPNode_Delete
     34  *      DSPNode_FreeMsgBuf
     35  *      DSPNode_GetAttr
     36  *      DSPNode_GetMessage
     37  *      DSPNode_Pause
     38  *      DSPNode_PutMessage
     39  *      DSPNode_RegisterNotify
     40  *      DSPNode_Run
     41  *      DSPNode_Terminate
     42  *
     43  *! Revision History
     44  *! ================
     45  *! 14-Mar-2002 map Set *pBuffer to null before returning error status in
     46  *!		            DSPNode_AllocMsgBuf.
     47  *! 01-Oct-2001 rr  CMM error codes are converted to DSP_STATUS in
     48  *!                 DSPNode_Allocate.
     49  *! 11-Sep-2001 ag  Zero-copy message support.
     50  *! 08-Jun-2001 jeh Fixed priority range check in DSPNode_ChangePriority.
     51  *! 23-Apr-2001 jeh Added pStatus parameter to DSPNode_Terminate.
     52  *! 06-Feb-2001 kc: Added check for alignment value in DSPNode_AllocMsgBuf
     53  *! 08-Dec-2000 ag  Added alignment to DSPNode_AllocMsgBuf().
     54  *! 05-Dec-2000 ag  Added SM support to DSPNode_[Alloc][Free]MsgBuf().
     55  *! 09-Nov-2000 rr: Code cleaned up. Use of IsValidEvent/Mask Macros.
     56  *! 27-Oct-2000 jeh Updated to version 0.9 of API spec.
     57  *! 07-Sep-2000 jeh Changed type HANDLE in DSPNode_RegisterNotify to
     58  *!                 DSP_HNOTIFICATION. Added DSP_STRMATTR param to
     59  *!                 DSPNode_Connect.
     60  *! 04-Aug-2000 rr: Name changed to DSPNode.c
     61  *! 27-Jul-2000 rr: Types updated to ver 0.8 API.
     62  *! 18-Jul-2000 rr: Node calls into the Class driver.
     63  *!                 Only parameters are validated here.
     64  *! 17-May-2000 rr: DSPNode_Connect checks for GHPPNODE.
     65  *! 15-May-2000 gp: Made input args to DSPNode_Allocate() CONST.
     66  *!                 Return DSP_ENOTIMPL from DSPNode_ChangePriority().
     67  *! 02-May-2000 rr: Reg functions use SERVICES.
     68  *! 12-Apr-2000 ww: Created based on DirectDSP API specification, Version 0.6.
     69  *
     70  */
     71 
     72 /*  ----------------------------------- Host OS */
     73 #include <host_os.h>
     74 #include <stdlib.h>
     75 #include <malloc.h>
     76 
     77 /*  ----------------------------------- DSP/BIOS Bridge */
     78 #include <dbdefs.h>
     79 #include <errbase.h>
     80 
     81 /*  ----------------------------------- Trace & Debug */
     82 #include <dbg.h>
     83 #include <dbg_zones.h>
     84 
     85 /*  ----------------------------------- Resource Manager */
     86 #include <memry.h>
     87 
     88 /*  ----------------------------------- Others */
     89 #include <dsptrap.h>
     90 
     91 /*  ----------------------------------- This */
     92 #include "_dbdebug.h"
     93 #include "_dbpriv.h"
     94 
     95 #include <DSPNode.h>
     96 
     97 #ifdef DEBUG_BRIDGE_PERF
     98 #include <perfutils.h>
     99 #endif
    100 
    101 /*  ----------------------------------- Globals */
    102 extern int hMediaFile;		/* class driver handle */
    103 
    104 /* Declared here, not to users */
    105 DSP_STATUS GetNodeType(DSP_HNODE hNode, DSP_NODETYPE *pNodeType);
    106 
    107 /*
    108  *  ======== DSPNode_Allocate ========
    109  *  Purpose:
    110  *      Allocate data structures for controlling and communicating
    111  *      with a node on a specific DSP processor..
    112  */
    113 DBAPI DSPNode_Allocate(DSP_HPROCESSOR hProcessor,
    114 		 IN CONST struct DSP_UUID *pNodeID,
    115 		 IN CONST OPTIONAL struct DSP_CBDATA *pArgs,
    116 		 IN OPTIONAL struct DSP_NODEATTRIN *pAttrIn,
    117 		 OUT DSP_HNODE *phNode)
    118 {
    119 	DSP_STATUS status = DSP_SOK;
    120 	Trapped_Args tempStruct;
    121 	struct CMM_OBJECT *hCmm;		/* shared memory mngr handle */
    122 	struct CMM_INFO pInfo;		/* Used for virtual space allocation */
    123 	PVOID pVirtBase;
    124 	struct DSP_BUFFERATTR bufAttr;
    125     DSP_NODETYPE nodeType;
    126     struct DSP_NDBPROPS    nodeProps;
    127     UINT            heapSize = 0;
    128     PVOID           pGPPVirtAddr = NULL;
    129     UINT            uProfileID;
    130 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Allocate:\r\n")));
    131 	if (!hProcessor) {
    132 		status = DSP_EHANDLE;
    133 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    134 			(TEXT("NODE: DSPNode_Allocate: "
    135 				"hProcessor is Invalid \r\n")));
    136 		goto func_cont;
    137 	}
    138 	if (!(pNodeID) || !(phNode)) {
    139 		status = DSP_EPOINTER;
    140 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Allocate: "
    141 			"Invalid pointer in the Input\r\n")));
    142 		goto func_cont;
    143 	}
    144 	/* First get the NODE properties, allocate, reserve
    145 				memory for Node heap */
    146 	if (pAttrIn) {
    147 		status = DSPNode_GetUUIDProps(hProcessor, pNodeID, &nodeProps);
    148 		pAttrIn->pGPPVirtAddr = NULL;
    149 		if (DSP_SUCCEEDED(status)) {
    150 			uProfileID = pAttrIn->uProfileID;
    151 			DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    152 					("DSPNodeAllocate: User requested"
    153 						  "node heap profile \n"));
    154 			if (uProfileID < nodeProps.uCountProfiles)
    155 				heapSize =
    156 				nodeProps.aProfiles[uProfileID].ulHeapSize;
    157 			if (heapSize) {
    158 				/* allocate heap memory */
    159 				/* Make heap size multiple of page size * */
    160 				heapSize = PG_ALIGN_HIGH(heapSize, PG_SIZE_4K);
    161 				/* align memory on cache line boundary * */
    162 				pGPPVirtAddr = memalign(GEM_CACHE_LINE_SIZE,
    163 							heapSize);
    164 				DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    165 					("DSPNodeAllocate: Node heap memory"
    166 							  "addr, size \n"));
    167 				if ((pGPPVirtAddr == NULL))
    168 					status = DSP_EMEMORY;
    169 				pAttrIn->uHeapSize = heapSize;
    170 				pAttrIn->pGPPVirtAddr = pGPPVirtAddr;
    171 			}
    172 		} else {
    173 			DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
    174 				"NODE:DSPNode_Allocate: Failed to get Node "
    175 				"UUID properties \r\n")));
    176 		}
    177 	}
    178 	if (DSP_SUCCEEDED(status)) {
    179 		/* Set up the structure  Call DSP Trap */
    180 		tempStruct.ARGS_NODE_ALLOCATE.hProcessor = hProcessor;
    181 		tempStruct.ARGS_NODE_ALLOCATE.pNodeID =
    182 						(struct DSP_UUID *)pNodeID;
    183 		tempStruct.ARGS_NODE_ALLOCATE.pArgs =
    184 						(struct DSP_CBDATA *)pArgs;
    185 		tempStruct.ARGS_NODE_ALLOCATE.pAttrIn =
    186 					(struct DSP_NODEATTRIN *)pAttrIn;
    187 		tempStruct.ARGS_NODE_ALLOCATE.phNode = phNode;
    188 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_ALLOCATE_OFFSET);
    189 	}
    190 func_cont:
    191 	 /* If 1st SM segment is configured then allocate and map it to
    192 		this process.*/
    193 	if (!DSP_SUCCEEDED(status)) {
    194 		if (pGPPVirtAddr)
    195 			free(pGPPVirtAddr);
    196 		return status;
    197 	}
    198 	tempStruct.ARGS_CMM_GETHANDLE.hProcessor = hProcessor;
    199 	tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
    200 	status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETHANDLE_OFFSET);
    201 	if (DSP_SUCCEEDED(status)) {
    202 		/* Get SM segment info from CMM */
    203 		tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
    204 		tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
    205 		status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETINFO_OFFSET);
    206 		if (DSP_FAILED(status)) {
    207 			status = DSP_EFAIL;
    208 			DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
    209 			"NODE: DSPNode_Allocate: "
    210 			"Failed to get SM segment\r\n")));
    211 		} else
    212 			status = DSP_SOK;
    213 
    214 	} else {
    215 		status = DSP_EFAIL;
    216 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT(
    217 			"NODE: DSPNode_Allocate:Failed to CMM handle\r\n")));
    218 	}
    219 	if (!DSP_SUCCEEDED(status)) {
    220 		free(pGPPVirtAddr);
    221 		return status;
    222 	}
    223 
    224 	GetNodeType(*phNode, &nodeType);
    225 	if ((nodeType != NODE_DEVICE) && (pInfo.ulNumGPPSMSegs > 0)) {
    226 		/* Messaging uses 1st segment */
    227 		if ((pInfo.segInfo[0].dwSegBasePa != 0) &&
    228 		    (pInfo.segInfo[0].ulTotalSegSize) > 0) {
    229 			pVirtBase = mmap(NULL, pInfo.segInfo[0].ulTotalSegSize,
    230 				 PROT_READ | PROT_WRITE, MAP_SHARED |
    231 				 MAP_LOCKED, hMediaFile,
    232 				 pInfo.segInfo[0].dwSegBasePa);
    233 			if (!pVirtBase) {
    234 				DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: "
    235 				"DSPNode_Allocate:Virt alloc failed\r\n")));
    236 				status = DSP_EMEMORY;
    237 				/* Clean up */
    238 				tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
    239 				DSPTRAP_Trap(&tempStruct,
    240 					CMD_NODE_DELETE_OFFSET);
    241 				return status;
    242 			}
    243 			/* set node translator's virt addr range for seg */
    244 			bufAttr.uAlignment = 0;
    245 			bufAttr.uSegment = 1 | MEMRY_SETVIRTUALSEGID;
    246 			bufAttr.cbStruct = 0;
    247 			status = DSPNode_AllocMsgBuf(*phNode,
    248 					pInfo.segInfo[0].ulTotalSegSize,
    249 					&bufAttr, (BYTE **)&pVirtBase);
    250 			if (DSP_FAILED(status)) {
    251 				/* If failed to set segment, unmap */
    252 				munmap(pVirtBase,
    253 					pInfo.segInfo[0].ulTotalSegSize);
    254 				/* Clean up */
    255 				tempStruct.ARGS_NODE_DELETE.hNode = *phNode;
    256 				DSPTRAP_Trap(&tempStruct,
    257 					CMD_NODE_DELETE_OFFSET);
    258 			}
    259 		}
    260 	}
    261     return status;
    262 }
    263 
    264 /*
    265  *  ======== DSPNode_AllocMsgBuf ========
    266  */
    267 DBAPI DSPNode_AllocMsgBuf(DSP_HNODE hNode, UINT uSize,
    268 		   IN OPTIONAL struct DSP_BUFFERATTR *pAttr, OUT BYTE **pBuffer)
    269 {
    270 	DSP_STATUS status = DSP_SOK;
    271 	Trapped_Args tempStruct;
    272 	DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    273 		(TEXT("NODE: DSPNode_AllocMsgBuf:\r\n")));
    274 
    275 	if (uSize == 0) {
    276 		status = DSP_ESIZE;
    277 		if (pBuffer)
    278 			*pBuffer = NULL;
    279 
    280 	} else if (hNode) {
    281 		if (pBuffer) {
    282 			/* Set up the structure */
    283 			tempStruct.ARGS_NODE_ALLOCMSGBUF.hNode = hNode;
    284 			tempStruct.ARGS_NODE_ALLOCMSGBUF.uSize = uSize;
    285 			tempStruct.ARGS_NODE_ALLOCMSGBUF.pAttr = pAttr;
    286 			/* Va Base */
    287 			tempStruct.ARGS_NODE_ALLOCMSGBUF.pBuffer = pBuffer;
    288 			/* Call DSP Trap */
    289 			status = DSPTRAP_Trap(&tempStruct,
    290 				CMD_NODE_ALLOCMSGBUF_OFFSET);
    291 			if (DSP_SUCCEEDED(status)) {
    292 				if (*pBuffer == NULL) {
    293 					DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    294 					(TEXT("NODE: DSPNode_AllocMsgBuf: "
    295 					"No SM\r\n")));
    296 					status = DSP_EMEMORY;	/* No SM */
    297 				}
    298 			} else
    299 				*pBuffer = NULL;
    300 
    301 		} else {
    302 			/* Invalid pointer */
    303 			status = DSP_EPOINTER;
    304 			DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: "
    305 			"DSPNode_AllocBuf: Invalid pointer in the Input\r\n")));
    306 		}
    307 	} else {
    308 		/* Invalid handle */
    309 		status = DSP_EHANDLE;
    310 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_AllocMsgBuf: "
    311 						"hNode is Invalid \r\n")));
    312 		if (pBuffer)
    313 			*pBuffer = NULL;
    314 
    315 	}
    316 
    317 	return status;
    318 }
    319 
    320 /*
    321  *  ======== DSPNode_ChangePriority ========
    322  *  Purpose:
    323  *      Change a task node's runtime priority within the DSP RTOS.
    324  */
    325 DBAPI DSPNode_ChangePriority(DSP_HNODE hNode, INT iPriority)
    326 {
    327 	DSP_STATUS status = DSP_SOK;
    328 	Trapped_Args tempStruct;
    329 
    330 	DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    331 			(TEXT("NODE: DSPNode_ChangePriority:\r\n")));
    332 
    333 	if (hNode) {
    334 		/* Set up the structure */
    335 		if (iPriority >= DSP_NODE_MIN_PRIORITY &&
    336 		    iPriority <= DSP_NODE_MAX_PRIORITY) {
    337 			/* Call DSP Trap */
    338 			tempStruct.ARGS_NODE_CHANGEPRIORITY.hNode = hNode;
    339 			tempStruct.ARGS_NODE_CHANGEPRIORITY.iPriority =
    340 							iPriority;
    341 			status = DSPTRAP_Trap(&tempStruct,
    342 					CMD_NODE_CHANGEPRIORITY_OFFSET);
    343 		} else
    344 			status = DSP_ERANGE;
    345 
    346 	} else {
    347 		/* Invalid pointer */
    348 		status = DSP_EHANDLE;
    349 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    350 			(TEXT("NODE: DSPNode_ChangePriority: "
    351 			"hNode is Invalid \r\n")));
    352 	}
    353 
    354 	return status;
    355 }
    356 
    357 /*
    358  *  ======== DSPNode_Connect ========
    359  *  Purpose:
    360  *      Make a stream connection, either between two nodes on a DSP,
    361  *      or between a node on a DSP and the GPP.
    362  */
    363 DBAPI DSPNode_Connect(DSP_HNODE hNode, UINT uStream, DSP_HNODE hOtherNode,
    364 		UINT uOtherStream, IN OPTIONAL struct DSP_STRMATTR *pAttrs)
    365 {
    366 	return DSPNode_ConnectEx(hNode, uStream, hOtherNode, uOtherStream,
    367 				 pAttrs, NULL);
    368 }
    369 
    370 /*
    371  *  ======== DSPNode_ConnectEx ========
    372  *  Purpose:
    373  *      Make a stream connection, either between two nodes on a DSP,
    374  *      or between a node on a DSP and the GPP.
    375  */
    376 DBAPI DSPNode_ConnectEx(DSP_HNODE hNode, UINT uStream, DSP_HNODE hOtherNode,
    377 		  UINT uOtherStream, IN OPTIONAL struct DSP_STRMATTR *pAttrs,
    378 		  IN OPTIONAL struct DSP_CBDATA *pConnParam)
    379 {
    380 	DSP_STATUS status = DSP_SOK;
    381 	Trapped_Args tempStruct;
    382 
    383 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_ConnectEx:\r\n")));
    384 
    385 	if ((hNode) && (hOtherNode)) {
    386 		/* Set up the structure */
    387 		/* Call DSP Trap */
    388 		tempStruct.ARGS_NODE_CONNECT.hNode = hNode;
    389 		tempStruct.ARGS_NODE_CONNECT.uStream = uStream;
    390 		tempStruct.ARGS_NODE_CONNECT.hOtherNode = hOtherNode;
    391 		tempStruct.ARGS_NODE_CONNECT.uOtherStream = uOtherStream;
    392 		tempStruct.ARGS_NODE_CONNECT.pAttrs = pAttrs;
    393 		tempStruct.ARGS_NODE_CONNECT.pConnParam = pConnParam;
    394 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_CONNECT_OFFSET);
    395 	} else {
    396 		/* Invalid pointer */
    397 		status = DSP_EHANDLE;
    398 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Connect: "
    399 		"hNode or hOtherNode is Invalid Handle\r\n")));
    400 	}
    401 
    402 	return status;
    403 }
    404 
    405 /*
    406  *  ======== DSPNode_Create ========
    407  *  Purpose:
    408  *      Create a node in a pre-run (i.e., inactive) state on its
    409  *		DSP processor.
    410  */
    411 DBAPI DSPNode_Create(DSP_HNODE hNode)
    412 {
    413 	DSP_STATUS status = DSP_SOK;
    414 	Trapped_Args tempStruct;
    415 #ifdef DEBUG_BRIDGE_PERF
    416 	struct timeval tv_beg;
    417 	struct timeval tv_end;
    418 	struct timezone tz;
    419 	int timeRetVal = 0;
    420 
    421 	timeRetVal = getTimeStamp(&tv_beg);
    422 #endif
    423 
    424 
    425 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Create:\r\n")));
    426 
    427 	if (hNode) {
    428 		/* Set up the structure */
    429 		/* Call DSP Trap */
    430 		tempStruct.ARGS_NODE_CREATE.hNode = hNode;
    431 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_CREATE_OFFSET);
    432 	} else {
    433 		/* Invalid pointer */
    434 		status = DSP_EHANDLE;
    435 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    436 		(TEXT("NODE: DSPNode_Create: hNode is Invalid Handle\r\n")));
    437 	}
    438 
    439 #ifdef DEBUG_BRIDGE_PERF
    440 	timeRetVal = getTimeStamp(&tv_end);
    441 	PrintStatistics(&tv_beg, &tv_end, "DSPNode_Create", 0);
    442 
    443 #endif
    444 
    445 	return status;
    446 }
    447 
    448 /*
    449  *  ======== DSPNode_Delete ========
    450  *  Purpose:
    451  *      Delete all DSP-side and GPP-side resources for the node.
    452  */
    453 DBAPI DSPNode_Delete(DSP_HNODE hNode)
    454 {
    455 	DSP_STATUS status = DSP_SOK;
    456 	Trapped_Args tempStruct;
    457 	BYTE *pVirtBase = NULL;
    458 	struct DSP_BUFFERATTR bufAttr;
    459 	struct CMM_OBJECT *hCmm;		/* shared memory mngr handle */
    460 	struct CMM_INFO pInfo;		/* Used for virtual space allocation */
    461 	DSP_NODETYPE nodeType;
    462 	struct DSP_NODEATTR    nodeAttr;
    463 #ifdef DEBUG_BRIDGE_PERF
    464 	struct timeval tv_beg;
    465 	struct timeval tv_end;
    466 	struct timezone tz;
    467 	int timeRetVal = 0;
    468 
    469 	timeRetVal = getTimeStamp(&tv_beg);
    470 #endif
    471 
    472 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Delete:\r\n")));
    473 	if (!hNode) {
    474 		/* Invalid pointer */
    475 		status = DSP_EHANDLE;
    476 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Delete: "
    477 					"hNode is Invalid Handle\r\n")));
    478 		return status;
    479 	}
    480 	/* Get segment size.
    481 	 >0 is SM segment. Get default SM Mgr*/
    482 	tempStruct.ARGS_CMM_GETHANDLE.hProcessor = NULL;
    483 	tempStruct.ARGS_CMM_GETHANDLE.phCmmMgr = &hCmm;
    484 	status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETHANDLE_OFFSET);
    485 	if (DSP_SUCCEEDED(status)) {
    486 		/* Get SM segment info from CMM */
    487 		tempStruct.ARGS_CMM_GETINFO.hCmmMgr = hCmm;
    488 		tempStruct.ARGS_CMM_GETINFO.pCmmInfo = &pInfo;
    489 		status = DSPTRAP_Trap(&tempStruct, CMD_CMM_GETINFO_OFFSET);
    490 		if (DSP_FAILED(status)) {
    491 			status = DSP_EFAIL;
    492 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    493 				(TEXT("NODE: DSPNode_Delete:"
    494 					" Failed to get SM segment\r\n")));
    495 		} else
    496 			status = DSP_SOK;
    497 
    498 	} else {
    499 		status = DSP_EFAIL;
    500 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Delete: "
    501 					"Failed to CMM handle\r\n")));
    502 	}
    503 	if (!DSP_SUCCEEDED(status)) {
    504 		status = DSP_EBADSEGID;	/* no SM segments*/
    505 		return status;
    506 	}
    507     status = DSPNode_GetAttr(hNode, &nodeAttr, sizeof(nodeAttr));
    508 	GetNodeType(hNode, &nodeType);
    509 	if (nodeType != NODE_DEVICE) {
    510 		/*segInfo index starts at 0.These checks may not be required*/
    511 		if ((pInfo.segInfo[0].dwSegBasePa != 0) &&
    512 		    (pInfo.segInfo[0].ulTotalSegSize) > 0) {
    513 			/* get node translator's virtual address range
    514 			   so we can free it */
    515 			bufAttr.uAlignment = 0;
    516 			bufAttr.uSegment = 1 | MEMRY_GETVIRTUALSEGID;
    517 			DSPNode_AllocMsgBuf(hNode, 1, &bufAttr, &pVirtBase);
    518 			/* Free virtual space */
    519 			if (!pVirtBase)
    520 				goto loop_end;
    521 
    522 			if (munmap(pVirtBase,
    523 					pInfo.segInfo[0].ulTotalSegSize)) {
    524 				status = DSP_EFAIL;
    525 			}
    526 		}
    527 	}
    528 loop_end:
    529 	if (DSP_SUCCEEDED(status)) {
    530 		/* Set up the structure Call DSP Trap */
    531 		tempStruct.ARGS_NODE_DELETE.hNode = hNode;
    532 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_DELETE_OFFSET);
    533 		/* Free any node heap memory */
    534 		if (nodeAttr.inNodeAttrIn.pGPPVirtAddr) {
    535 			DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("DSPNodeDelete:"
    536 					"Freeing Node heap addr \n")));
    537 			free(nodeAttr.inNodeAttrIn.pGPPVirtAddr);
    538 		}
    539 	}
    540 #ifdef DEBUG_BRIDGE_PERF
    541 	timeRetVal = getTimeStamp(&tv_end);
    542 	PrintStatistics(&tv_beg, &tv_end, "DSPNode_Delete", 0);
    543 #endif
    544 
    545 	return status;
    546 }
    547 
    548 /*
    549  *  ======== DSPNode_FreeMsgBuf ========
    550  */
    551 DBAPI DSPNode_FreeMsgBuf(DSP_HNODE hNode, IN BYTE *pBuffer,
    552 				IN OPTIONAL struct DSP_BUFFERATTR *pAttr)
    553 {
    554 	DSP_STATUS status = DSP_SOK;
    555 	Trapped_Args tempStruct;
    556 
    557 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_FreeMsgBuf:\r\n")));
    558 
    559 	if (hNode) {
    560 		if (pBuffer) {
    561 			/* Set up the structure */
    562 			/* Call DSP Trap */
    563 			tempStruct.ARGS_NODE_FREEMSGBUF.hNode = hNode;
    564 			tempStruct.ARGS_NODE_FREEMSGBUF.pBuffer = pBuffer;
    565 			tempStruct.ARGS_NODE_FREEMSGBUF.pAttr = pAttr;
    566 			status = DSPTRAP_Trap(&tempStruct,
    567 				CMD_NODE_FREEMSGBUF_OFFSET);
    568 			if (DSP_FAILED(status)) {
    569 				DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: "
    570 						"DSPNode_FreeMsgBuf:"
    571 						"Failed to Free SM buf\r\n")));
    572 			}
    573 		} else {
    574 			/* Invalid parameter */
    575 			status = DSP_EPOINTER;
    576 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    577 				(TEXT("NODE: DSPNode_FreeMsgBuf: "
    578 				"Invalid pointer in the Input\r\n")));
    579 		}
    580 	} else {
    581 		/* Invalid pointer */
    582 		status = DSP_EHANDLE;
    583 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    584 				(TEXT("NODE: DSPNode_FreeMsgBuf: "
    585 				"hNode is Invalid \r\n")));
    586 	}
    587 
    588 	return status;
    589 }
    590 
    591 /*
    592  *  ======== DSPNode_GetAttr ========
    593  *  Purpose:
    594  *      Copy the current attributes of the specified node.
    595  */
    596 DBAPI DSPNode_GetAttr(DSP_HNODE hNode, OUT struct DSP_NODEATTR *pAttr,
    597 		UINT uAttrSize)
    598 {
    599 	DSP_STATUS status = DSP_SOK;
    600 	Trapped_Args tempStruct;
    601 
    602 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_GetAttr:\r\n")));
    603 
    604 	if (hNode) {
    605 		if (pAttr) {
    606 			if (uAttrSize >= sizeof(struct DSP_NODEATTR)) {
    607 				/* Set up the structure */
    608 				/* Call DSP Trap */
    609 				tempStruct.ARGS_NODE_GETATTR.hNode = hNode;
    610 				tempStruct.ARGS_NODE_GETATTR.pAttr = pAttr;
    611 				tempStruct.ARGS_NODE_GETATTR.uAttrSize =
    612 								uAttrSize;
    613 				status = DSPTRAP_Trap(&tempStruct,
    614 					CMD_NODE_GETATTR_OFFSET);
    615 			} else {
    616 				status = DSP_ESIZE;
    617 				DEBUGMSG(DSPAPI_ZONE_ERROR,
    618 					(TEXT("NODE: DSPNode_GetAttr: "
    619 					"Size is too small \r\n")));
    620 			}
    621 		} else {
    622 			/* Invalid parameter */
    623 			status = DSP_EPOINTER;
    624 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    625 				(TEXT("NODE: DSPNode_GetAttr: "
    626 				"Invalid pointer in the Input\r\n")));
    627 		}
    628 	} else {
    629 		/* Invalid pointer */
    630 		status = DSP_EHANDLE;
    631 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    632 			(TEXT("NODE: DSPNode_GetAttr: "
    633 			"hNode is Invalid \r\n")));
    634 	}
    635 
    636 	return status;
    637 }
    638 
    639 /*
    640  *  ======== DSPNode_GetMessage ========
    641  *  Purpose:
    642  *      Retrieve an event message from a task node.
    643  */
    644 DBAPI DSPNode_GetMessage(DSP_HNODE hNode, OUT struct DSP_MSG *pMessage,
    645 				UINT uTimeout)
    646 {
    647 	DSP_STATUS status = DSP_SOK;
    648 	Trapped_Args tempStruct;
    649 #ifdef DEBUG_BRIDGE_PERF
    650 	struct timeval tv_beg;
    651 	struct timeval tv_end;
    652 	struct timezone tz;
    653 	int timeRetVal = 0;
    654 
    655 	timeRetVal = getTimeStamp(&tv_beg);
    656 
    657 #endif
    658 
    659 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_GetMessage:\r\n")));
    660 
    661 	if (hNode) {
    662 		if (pMessage) {
    663 			/* Set up the structure */
    664 			/* Call DSP Trap */
    665 			tempStruct.ARGS_NODE_GETMESSAGE.hNode = hNode;
    666 			tempStruct.ARGS_NODE_GETMESSAGE.pMessage = pMessage;
    667 			tempStruct.ARGS_NODE_GETMESSAGE.uTimeout = uTimeout;
    668 			status = DSPTRAP_Trap(&tempStruct,
    669 				CMD_NODE_GETMESSAGE_OFFSET);
    670 		} else {
    671 			status = DSP_EPOINTER;
    672 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    673 				(TEXT("NODE: DSPNode_GetMessage:"
    674 				"pMessage is Invalid \r\n")));
    675 		}
    676 	} else {
    677 		status = DSP_EHANDLE;
    678 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    679 			(TEXT("NODE: DSPNode_GetMessage: "
    680 			"hNode is Invalid \r\n")));
    681 	}
    682 #ifdef DEBUG_BRIDGE_PERF
    683 	timeRetVal = getTimeStamp(&tv_end);
    684 	PrintStatistics(&tv_beg, &tv_end, "DSPNode_GetMessage", 0);
    685 #endif
    686 
    687 
    688 	return status;
    689 }
    690 
    691 /*
    692  *  ======== GetNodeType ========
    693  *  Purpose:
    694  *      Return the node type
    695  */
    696 DSP_STATUS GetNodeType(DSP_HNODE hNode, DSP_NODETYPE *pNodeType)
    697 {
    698 	/*DSP_STATUS status;*/
    699 	DSP_STATUS status = DSP_SOK;
    700 	struct DSP_NODEATTR nodeAttr;
    701 
    702 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("GetNodeType:\r\n")));
    703 
    704 	if (hNode) {
    705 		status = DSPNode_GetAttr(hNode, &nodeAttr, sizeof(nodeAttr));
    706 		if (DSP_SUCCEEDED(status)) {
    707 			*pNodeType =
    708 			nodeAttr.iNodeInfo.nbNodeDatabaseProps.uNodeType;
    709 		}
    710 	} else {
    711 		status = DSP_EHANDLE;
    712 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("GetNodeType: "
    713 					"hNode is Invalid \r\n")));
    714 	}
    715 
    716 	return status;
    717 }
    718 
    719 /*
    720  *  ======== DSPNode_Pause ========
    721  *  Purpose:
    722  *      Temporarily suspend execution of a node that is currently running
    723  *      on a DSP.
    724  */
    725 DBAPI DSPNode_Pause(DSP_HNODE hNode)
    726 {
    727 	DSP_STATUS status = DSP_SOK;
    728 	Trapped_Args tempStruct;
    729 
    730 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Pause:\r\n")));
    731 
    732 	if (hNode) {
    733 		/* Set up the structure */
    734 		/* Call DSP Trap */
    735 		tempStruct.ARGS_NODE_PAUSE.hNode = hNode;
    736 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_PAUSE_OFFSET);
    737 	} else {
    738 		/* Invalid pointer */
    739 		status = DSP_EHANDLE;
    740 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Pause: "
    741 				"hNode is Invalid Handle\r\n")));
    742 	}
    743 
    744 	return status;
    745 }
    746 
    747 /*
    748  *  ======== DSPNode_PutMessage ========
    749  *  Purpose:
    750  *      Send an event message to a task node.
    751  */
    752 DBAPI DSPNode_PutMessage(DSP_HNODE hNode, IN CONST struct DSP_MSG *pMessage,
    753 						UINT uTimeout)
    754 {
    755 	DSP_STATUS status = DSP_SOK;
    756 	Trapped_Args tempStruct;
    757 #ifdef DEBUG_BRIDGE_PERF
    758 	struct timeval tv_beg;
    759 	struct timeval tv_end;
    760 	struct timeval tz;
    761 	int timeRetVal = 0;
    762 
    763 	timeRetVal = getTimeStamp(&tv_beg);
    764 #endif
    765 
    766 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_PutMessage:\r\n")));
    767 
    768 	if (hNode) {
    769 		if (pMessage) {
    770 			/* Set up the structure */
    771 			/* Call DSP Trap */
    772 			tempStruct.ARGS_NODE_PUTMESSAGE.hNode = hNode;
    773 			tempStruct.ARGS_NODE_PUTMESSAGE.pMessage =
    774 						(struct DSP_MSG *)pMessage;
    775 			tempStruct.ARGS_NODE_PUTMESSAGE.uTimeout = uTimeout;
    776 			status = DSPTRAP_Trap(&tempStruct,
    777 				CMD_NODE_PUTMESSAGE_OFFSET);
    778 		} else {
    779 			status = DSP_EPOINTER;
    780 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    781 				(TEXT("NODE: DSPNode_PutMessage: "
    782 						"pMessage is Invalid \r\n")));
    783 		}
    784 	} else {
    785 		/* Invalid pointer */
    786 		status = DSP_EHANDLE;
    787 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    788 			(TEXT("NODE: DSPNode_PutMessage: "
    789 					"hNode is Invalid \r\n")));
    790 	}
    791 #ifdef DEBUG_BRIDGE_PERF
    792 	timeRetVal = getTimeStamp(&tv_end);
    793 	PrintStatistics(&tv_beg, &tv_end, "DSPNode_PutMessage", 0);
    794 #endif
    795 
    796 
    797 	return status;
    798 }
    799 
    800 /*
    801  *  ======== DSPNode_RegisterNotify ========
    802  *  Purpose:
    803  *      Register to be notified of specific events for this node.
    804  */
    805 DBAPI
    806 DSPNode_RegisterNotify(DSP_HNODE hNode, UINT uEventMask,
    807 		       UINT uNotifyType, struct DSP_NOTIFICATION *hNotification)
    808 {
    809 	DSP_STATUS status = DSP_SOK;
    810 	Trapped_Args tempStruct;
    811 
    812 	DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    813 			(TEXT("NODE: DSPNode_RegisterNotify:\r\n")));
    814 
    815 	if ((hNode) && (hNotification)) {
    816 		if (IsValidNodeEvent(uEventMask)) {
    817 			if (IsValidNotifyMask(uNotifyType)) {
    818 				/* Set up the structure */
    819 				/* Call DSP Trap */
    820 				tempStruct.ARGS_NODE_REGISTERNOTIFY.hNode =
    821 							hNode;
    822 				tempStruct.ARGS_NODE_REGISTERNOTIFY.uEventMask =
    823 							uEventMask;
    824 				tempStruct.ARGS_NODE_REGISTERNOTIFY\
    825 					.uNotifyType = uNotifyType;
    826 				tempStruct.ARGS_NODE_REGISTERNOTIFY\
    827 					.hNotification = hNotification;
    828 
    829 				status = DSPTRAP_Trap(&tempStruct,
    830 						CMD_NODE_REGISTERNOTIFY_OFFSET);
    831 			} else {
    832 				status = DSP_ENOTIMPL;
    833 				DEBUGMSG(DSPAPI_ZONE_ERROR,
    834 					(TEXT("NODE: DSPNode_RegisterNotify: "
    835 					"Invalid Notification Mask \r\n")));
    836 			}
    837 		} else {
    838 			status = DSP_EVALUE;
    839 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    840 				(TEXT("NODE: DSPNode_RegisterNotify:"
    841 						"Invalid Event type\r\n")));
    842 		}
    843 	} else {
    844 		/* Invalid pointer */
    845 		status = DSP_EHANDLE;
    846 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    847 			(TEXT("NODE: DSPNode_RegisterNotify: "
    848 				"hNode is Invalid \r\n")));
    849 	}
    850 
    851 	return status;
    852 }
    853 
    854 /*
    855  *  ======== DSPNode_Run ========
    856  *  Purpose:
    857  *      Start a task node running.
    858  */
    859 DBAPI DSPNode_Run(DSP_HNODE hNode)
    860 {
    861 	DSP_STATUS status = DSP_SOK;
    862 	Trapped_Args tempStruct;
    863 
    864 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Run:\r\n")));
    865 
    866 	if (hNode) {
    867 		/* Set up the structure */
    868 		/* Call DSP Trap */
    869 		tempStruct.ARGS_NODE_RUN.hNode = hNode;
    870 		status = DSPTRAP_Trap(&tempStruct, CMD_NODE_RUN_OFFSET);
    871 	} else {
    872 		/* Invalid pointer */
    873 		status = DSP_EHANDLE;
    874 		DEBUGMSG(DSPAPI_ZONE_ERROR, (TEXT("NODE: DSPNode_Run: "
    875 					"hNode is Invalid Handle\r\n")));
    876 	}
    877 
    878 	return status;
    879 }
    880 
    881 /*
    882  *  ======== DSPNode_Terminate ========
    883  *  Purpose:
    884  *      Signal a task node running on a  DSP processor that it should
    885  *      exit its execute-phase function.
    886  */
    887 DBAPI DSPNode_Terminate(DSP_HNODE hNode, DSP_STATUS *pStatus)
    888 {
    889 	DSP_STATUS status = DSP_SOK;
    890 	Trapped_Args tempStruct;
    891 
    892 	DEBUGMSG(DSPAPI_ZONE_FUNCTION, (TEXT("NODE: DSPNode_Terminate:\r\n")));
    893 
    894 	if (hNode) {
    895 		/* !DSP_ValidWritePtr means it is a valid write ptr */
    896 		if (!DSP_ValidWritePtr(pStatus, sizeof(DSP_STATUS))) {
    897 			/* Set up the structure */
    898 			/* Call DSP Trap */
    899 			tempStruct.ARGS_NODE_TERMINATE.hNode = hNode;
    900 			tempStruct.ARGS_NODE_TERMINATE.pStatus = pStatus;
    901 			status = DSPTRAP_Trap(&tempStruct,
    902 				CMD_NODE_TERMINATE_OFFSET);
    903 		} else
    904 			status = DSP_EPOINTER;
    905 
    906 	} else {
    907 		/* Invalid pointer */
    908 		status = DSP_EHANDLE;
    909 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    910 			(TEXT("NODE: DSPNode_Terminate: "
    911 					"hNode is Invalid Handle\r\n")));
    912 	}
    913 
    914 	return status;
    915 }
    916 
    917 
    918 /*
    919  *  ======== DSPNode_GetUUIDProps ========
    920  *  Purpose:
    921  *      Get Node properties from DCD/DOF file given the UUID
    922  */
    923 DBAPI DSPNode_GetUUIDProps(DSP_HPROCESSOR hProcessor,
    924 		IN CONST struct DSP_UUID *pNodeID,
    925 		 OUT struct DSP_NDBPROPS *pNodeProps)
    926 {
    927 	DSP_STATUS status = DSP_SOK;
    928 	Trapped_Args tempStruct;
    929 
    930 	DEBUGMSG(DSPAPI_ZONE_FUNCTION,
    931 				(TEXT("NODE:DSPNode_GetUUIDProps:\r\n")));
    932 
    933 	if (hProcessor) {
    934 		if ((pNodeID) && (pNodeProps)) {
    935 			/* Set up the structure */
    936 			/* Call DSP Trap */
    937 			tempStruct.ARGS_NODE_GETUUIDPROPS.hProcessor =
    938 						hProcessor;
    939 			tempStruct.ARGS_NODE_GETUUIDPROPS.pNodeID =
    940 						(struct DSP_UUID *)pNodeID;
    941 			tempStruct.ARGS_NODE_GETUUIDPROPS.pNodeProps =
    942 					(struct DSP_NDBPROPS *) pNodeProps;
    943 			status = DSPTRAP_Trap(&tempStruct,
    944 				CMD_NODE_GETUUIDPROPS_OFFSET);
    945 		} else {
    946 			/* Invalid parameter */
    947 			status = DSP_EPOINTER;
    948 			DEBUGMSG(DSPAPI_ZONE_ERROR,
    949 				(TEXT("NODE: DSPNode_GetUUIDProps: "
    950 				       "Invalid pointer in the Input\r\n")));
    951 		}
    952 	} else {
    953 		/* Invalid pointer */
    954 		status = DSP_EHANDLE;
    955 		DEBUGMSG(DSPAPI_ZONE_ERROR,
    956 			(TEXT("NODE: DSPNode_GetUUIDProps: "
    957 					"hProcessor is Invalid \r\n")));
    958 	}
    959 
    960 	return status;
    961 }
    962 
    963