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  */
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)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  */
DSPNode_AllocMsgBuf(DSP_HNODE hNode,UINT uSize,IN OPTIONAL struct DSP_BUFFERATTR * pAttr,OUT BYTE ** pBuffer)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  */
DSPNode_ChangePriority(DSP_HNODE hNode,INT iPriority)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  */
DSPNode_Connect(DSP_HNODE hNode,UINT uStream,DSP_HNODE hOtherNode,UINT uOtherStream,IN OPTIONAL struct DSP_STRMATTR * pAttrs)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  */
DSPNode_ConnectEx(DSP_HNODE hNode,UINT uStream,DSP_HNODE hOtherNode,UINT uOtherStream,IN OPTIONAL struct DSP_STRMATTR * pAttrs,IN OPTIONAL struct DSP_CBDATA * pConnParam)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  */
DSPNode_Create(DSP_HNODE hNode)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  */
DSPNode_Delete(DSP_HNODE hNode)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  */
DSPNode_FreeMsgBuf(DSP_HNODE hNode,IN BYTE * pBuffer,IN OPTIONAL struct DSP_BUFFERATTR * pAttr)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  */
DSPNode_GetAttr(DSP_HNODE hNode,OUT struct DSP_NODEATTR * pAttr,UINT uAttrSize)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  */
DSPNode_GetMessage(DSP_HNODE hNode,OUT struct DSP_MSG * pMessage,UINT uTimeout)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  */
GetNodeType(DSP_HNODE hNode,DSP_NODETYPE * pNodeType)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  */
DSPNode_Pause(DSP_HNODE hNode)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  */
DSPNode_PutMessage(DSP_HNODE hNode,IN CONST struct DSP_MSG * pMessage,UINT uTimeout)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
DSPNode_RegisterNotify(DSP_HNODE hNode,UINT uEventMask,UINT uNotifyType,struct DSP_NOTIFICATION * hNotification)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  */
DSPNode_Run(DSP_HNODE hNode)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  */
DSPNode_Terminate(DSP_HNODE hNode,DSP_STATUS * pStatus)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  */
DSPNode_GetUUIDProps(DSP_HPROCESSOR hProcessor,IN CONST struct DSP_UUID * pNodeID,OUT struct DSP_NDBPROPS * pNodeProps)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