Update from omapzoom 18-Aug-2008
[bridge-dev.git] / 0007-TI-DSP-BRIDGE-Resource-Manager.patch
blobb84be2f01eb47059005c41e5e2da9e8babc996b6
1 From 80f59ea6126f9866e2143e0e586a4db3b41fc19b Mon Sep 17 00:00:00 2001
2 From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
3 Date: Fri, 15 Aug 2008 01:55:54 +0300
4 Subject: [PATCH 07/10] TI DSP BRIDGE: Resource Manager
6 Initial port from omapzoom
7 http://omapzoom.org/gf/project/omapbridge
9 For details,
10 http://omapzoom.org/gf/project/omapbridge/docman/?subdir=3
12 Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
13 ---
14 drivers/dsp/bridge/rmgr/dbdcd.c | 1599 +++++++++++++++
15 drivers/dsp/bridge/rmgr/disp.c | 915 +++++++++
16 drivers/dsp/bridge/rmgr/drv.c | 1883 +++++++++++++++++
17 drivers/dsp/bridge/rmgr/drv_interface.c | 780 +++++++
18 drivers/dsp/bridge/rmgr/drv_interface.h | 40 +
19 drivers/dsp/bridge/rmgr/dspdrv.c | 276 +++
20 drivers/dsp/bridge/rmgr/mgr.c | 491 +++++
21 drivers/dsp/bridge/rmgr/nldr.c | 1966 ++++++++++++++++++
22 drivers/dsp/bridge/rmgr/node.c | 3365 +++++++++++++++++++++++++++++++
23 drivers/dsp/bridge/rmgr/proc.c | 1958 ++++++++++++++++++
24 drivers/dsp/bridge/rmgr/pwr.c | 184 ++
25 drivers/dsp/bridge/rmgr/rmm.c | 604 ++++++
26 drivers/dsp/bridge/rmgr/strm.c | 1053 ++++++++++
27 13 files changed, 15114 insertions(+), 0 deletions(-)
28 create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
29 create mode 100644 drivers/dsp/bridge/rmgr/disp.c
30 create mode 100644 drivers/dsp/bridge/rmgr/drv.c
31 create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
32 create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
33 create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
34 create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
35 create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
36 create mode 100644 drivers/dsp/bridge/rmgr/node.c
37 create mode 100644 drivers/dsp/bridge/rmgr/proc.c
38 create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
39 create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
40 create mode 100644 drivers/dsp/bridge/rmgr/strm.c
42 Index: lk/drivers/dsp/bridge/rmgr/dbdcd.c
43 ===================================================================
44 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
45 +++ lk/drivers/dsp/bridge/rmgr/dbdcd.c 2008-08-18 10:38:37.000000000 +0300
46 @@ -0,0 +1,1599 @@
47 +/*
48 + * linux/drivers/dsp/bridge/rmgr/dbdcd.c
49 + *
50 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
51 + *
52 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
53 + *
54 + * This package is free software; you can redistribute it and/or modify
55 + * it under the terms of the GNU General Public License version 2 as
56 + * published by the Free Software Foundation.
57 + *
58 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
59 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
60 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
61 + */
64 +/*
65 + * ======== dbdcd.c ========
66 + * Description:
67 + * This file contains the implementation of the DSP/BIOS Bridge
68 + * Configuration Database (DCD).
69 + *
70 + * Notes:
71 + * The fxn DCD_GetObjects can apply a callback fxn to each DCD object
72 + * that is located in a specified COFF file. At the moment,
73 + * DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
74 + * DCD_GetObjects.
75 + *
76 + *! Revision History
77 + *! ================
78 + *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
79 + *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
80 + *! to include phase information
81 + *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
82 + *! libraries
83 + *! 26-Feb-2003 kc Updated DCD_AutoUnregister and DCD_GetObjects to simplify
84 + *! DCD implementation.
85 + *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
86 + *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
87 + *! 18-Feb-2003 vp Code review updates
88 + *! 18-Oct-2002 vp Ported to Linux platform
89 + *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
90 + *! data. Added DCD_GetLibraryName().
91 + *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
92 + *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
93 + *! DSP-MMU setup. These are private attributes.
94 + *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
95 + *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
96 + *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
97 + *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
98 + *! GetAttrsFromBuf
99 + *! 22-Nov-2000 kc: Replaced sprintf() calls with CSL_Strncat.
100 + *! 09-Nov-2000 kc: Optimized DCD module.
101 + *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
102 + *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
103 + *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
104 + *! to replace atoi(), until cdb generation can output in
105 + *! decimal format.
106 + *! 26-Jul-2000 kc: Created.
107 + *!
108 + */
110 +/* ----------------------------------- Host OS */
111 +#include <host_os.h>
113 +/* ----------------------------------- DSP/BIOS Bridge */
114 +#include <std.h>
115 +#include <dbdefs.h>
116 +#include <errbase.h>
117 +/* ----------------------------------- Trace & Debug */
118 +#include <dbc.h>
119 +#include <gt.h>
121 +/* ----------------------------------- OS Adaptation Layer */
122 +#include <csl.h>
123 +#include <mem.h>
124 +#include <reg.h>
126 +/* ----------------------------------- Platform Manager */
127 +#include <cod.h>
129 +/* ----------------------------------- Others */
130 +#include <uuidutil.h>
132 +/* ----------------------------------- This */
133 +#include <dbdcd.h>
135 +/* ----------------------------------- Global defines. */
136 +#define SIGNATURE 0x5f444344 /* "DCD_" (in reverse). */
138 +#define IsValidHandle(h) (((h) != NULL) && (h->dwSignature == SIGNATURE))
140 +#define MAX_INT2CHAR_LENGTH 16 /* Maximum int2char len of 32 bit int. */
142 +/* Name of section containing dependent libraries */
143 +#define DEPLIBSECT ".dspbridge_deplibs"
145 +/* DCD specific structures. */
146 +struct DCD_MANAGER {
147 + u32 dwSignature; /* Used for object validation. */
148 + struct COD_MANAGER *hCodMgr; /* Handle to COD manager object. */
151 +/* Global reference variables. */
152 +static u32 cRefs;
153 +static u32 cEnumRefs;
155 +extern struct GT_Mask curTrace;
157 +/* helper function prototypes. */
158 +static s32 Atoi(char *pszBuf);
160 +static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
161 + enum DSP_DCDOBJTYPE objType,
162 + struct DCD_GENERICOBJ *pGenObj);
164 +static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
166 +static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
168 +static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
169 + IN struct DSP_UUID *pUuid,
170 + IN OUT u16 *pNumLibs,
171 + OPTIONAL OUT u16 *pNumPersLibs,
172 + OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
173 + OPTIONAL OUT bool *pPersistentDepLibs,
174 + IN enum NLDR_PHASE phase);
177 + * ======== DCD_AutoRegister ========
178 + * Purpose:
179 + * Parses the supplied image and resigsters with DCD.
180 + */
182 +DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
183 + IN char *pszCoffPath)
185 + DSP_STATUS status = DSP_SOK;
187 + DBC_Require(cRefs > 0);
189 + GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
190 + hDcdMgr);
192 + if (IsValidHandle(hDcdMgr)) {
193 + status = DCD_GetObjects(hDcdMgr, pszCoffPath,
194 + (DCD_REGISTERFXN)DCD_RegisterObject,
195 + (void *)pszCoffPath);
196 + } else {
197 + status = DSP_EHANDLE;
198 + GT_0trace(curTrace, GT_6CLASS,
199 + "DCD_AutoRegister: invalid DCD manager handle.\n");
202 + return status;
206 + * ======== DCD_AutoUnregister ========
207 + * Purpose:
208 + * Parses the supplied DSP image and unresiters from DCD.
209 + */
210 +DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
211 + IN char *pszCoffPath)
213 + DSP_STATUS status = DSP_SOK;
215 + DBC_Require(cRefs > 0);
217 + GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
218 + hDcdMgr);
220 + if (IsValidHandle(hDcdMgr)) {
221 + status = DCD_GetObjects(hDcdMgr, pszCoffPath,
222 + (DCD_REGISTERFXN)DCD_RegisterObject,
223 + NULL);
224 + } else {
225 + status = DSP_EHANDLE;
226 + GT_0trace(curTrace, GT_6CLASS,
227 + "DCD_AutoUnregister: invalid DCD manager"
228 + " handle.\n");
231 + return status;
235 + * ======== DCD_CreateManager ========
236 + * Purpose:
237 + * Creates DCD manager.
238 + */
239 +DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
240 + OUT struct DCD_MANAGER **phDcdMgr)
242 + struct COD_MANAGER *hCodMgr; /* COD manager handle */
243 + struct DCD_MANAGER *pDcdMgr = NULL; /* DCD Manager pointer */
244 + DSP_STATUS status = DSP_SOK;
246 + DBC_Require(cRefs >= 0);
247 + DBC_Require(phDcdMgr);
249 + GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
250 + phDcdMgr);
252 + status = COD_Create(&hCodMgr, pszZlDllName, NULL);
253 + if (DSP_SUCCEEDED(status)) {
255 + /* Create a DCD object. */
256 + MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
257 + if (pDcdMgr != NULL) {
259 + /* Fill out the object. */
260 + pDcdMgr->hCodMgr = hCodMgr;
262 + /* Return handle to this DCD interface. */
263 + *phDcdMgr = pDcdMgr;
265 + GT_2trace(curTrace, GT_5CLASS,
266 + "DCD_CreateManager: pDcdMgr 0x%x, "
267 + " hCodMgr 0x%x", pDcdMgr, hCodMgr);
268 + } else {
269 + status = DSP_EMEMORY;
271 + /*
272 + * If allocation of DcdManager object failed, delete the
273 + * COD manager.
274 + */
275 + COD_Delete(hCodMgr);
277 + GT_0trace(curTrace, GT_6CLASS,
278 + "DCD_CreateManager: MEM_AllocObject failed\n");
280 + } else {
281 + status = DSP_EFAIL;
282 + GT_0trace(curTrace, GT_6CLASS,
283 + "DCD_CreateManager: COD_Create failed\n");
286 + DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
287 + (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
288 + (status == DSP_EMEMORY)));
290 + return status;
294 + * ======== DCD_DestroyManager ========
295 + * Purpose:
296 + * Frees DCD Manager object.
297 + */
298 +DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
300 + struct DCD_MANAGER *pDcdMgr = hDcdMgr;
301 + DSP_STATUS status = DSP_EHANDLE;
303 + DBC_Require(cRefs >= 0);
305 + GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
306 + hDcdMgr);
308 + if (IsValidHandle(hDcdMgr)) {
310 + /* Delete the COD manager. */
311 + COD_Delete(pDcdMgr->hCodMgr);
313 + /* Deallocate a DCD manager object. */
314 + MEM_FreeObject(pDcdMgr);
316 + status = DSP_SOK;
317 + } else {
318 + GT_0trace(curTrace, GT_6CLASS,
319 + "DCD_DestroyManager: invalid DCD manager handle.\n");
322 + return status;
326 + * ======== DCD_EnumerateObject ========
327 + * Purpose:
328 + * Enumerates objects in the DCD.
329 + */
330 +DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
331 + OUT struct DSP_UUID *pUuid)
333 + DSP_STATUS status = DSP_SOK;
334 + char szRegKey[REG_MAXREGPATHLENGTH];
335 + char szValue[REG_MAXREGPATHLENGTH];
336 + char szData[REG_MAXREGPATHLENGTH];
337 + u32 dwValueSize;
338 + u32 dwDataSize;
339 + struct DSP_UUID dspUuid;
340 + char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
341 + u32 dwKeyLen = 0;
343 + DBC_Require(cRefs >= 0);
344 + DBC_Require(cIndex >= 0);
345 + DBC_Require(pUuid != NULL);
347 + GT_3trace(curTrace, GT_ENTER,
348 + "DCD_EnumerateObject: cIndex %d, objType %d, "
349 + " pUuid 0x%x\n", cIndex, objType, pUuid);
351 + if ((cIndex != 0) && (cEnumRefs == 0)) {
352 + /*
353 + * If an enumeration is being performed on an index greater
354 + * than zero, then the current cEnumRefs must have been
355 + * incremented to greater than zero.
356 + */
357 + status = DSP_ECHANGEDURINGENUM;
358 + } else {
359 + /* Enumerate a specific key in the registry by index. */
360 + dwValueSize = REG_MAXREGPATHLENGTH;
361 + dwDataSize = REG_MAXREGPATHLENGTH;
363 + /*
364 + * Pre-determine final key length. It's length of DCD_REGKEY +
365 + * "_\0" + length of szObjType string + terminating NULL.
366 + */
367 + dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
368 + DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
370 + /* Create proper REG key; concatenate DCD_REGKEY with
371 + * objType. */
372 + CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
373 + if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) <
374 + REG_MAXREGPATHLENGTH) {
375 + CSL_Strncat(szRegKey, "_\0", 2);
376 + } else {
377 + status = DSP_EFAIL;
380 + /* This snprintf is guaranteed not to exceed max size of an
381 + * integer. */
382 + status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
383 + objType);
385 + if (status == -1) {
386 + status = DSP_EFAIL;
387 + } else {
388 + status = DSP_SOK;
389 + if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
390 + REG_MAXREGPATHLENGTH) {
391 + CSL_Strncat(szRegKey, szObjType,
392 + CSL_Strlen(szObjType) + 1);
393 + } else {
394 + status = DSP_EFAIL;
398 + if (DSP_SUCCEEDED(status)) {
399 + status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
400 + &dwValueSize, szData,
401 + &dwDataSize);
404 + if (DSP_SUCCEEDED(status)) {
405 + /* Create UUID value using string retrieved from
406 + * registry. */
407 + UUID_UuidFromString(szValue, &dspUuid);
409 + *pUuid = dspUuid;
411 + /* Increment cEnumRefs to update reference count. */
412 + cEnumRefs++;
414 + status = DSP_SOK;
415 + } else if (status == REG_E_NOMOREITEMS) {
416 + /* At the end of enumeration. Reset cEnumRefs. */
417 + cEnumRefs = 0;
419 + status = DSP_SENUMCOMPLETE;
420 + } else {
421 + status = DSP_EFAIL;
422 + GT_1trace(curTrace, GT_6CLASS,
423 + "DCD_EnumerateObject: REG_EnumValue"
424 + " failed, status = 0x%x\n", status);
428 + DBC_Ensure(pUuid || (status == DSP_EFAIL));
430 + return status;
434 + * ======== DCD_Exit ========
435 + * Purpose:
436 + * Discontinue usage of the DCD module.
437 + */
438 +void DCD_Exit(void)
440 + DBC_Require(cRefs > 0);
442 + GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
444 + cRefs--;
445 + if (cRefs == 0) {
446 + REG_Exit();
447 + COD_Exit();
448 + MEM_Exit();
451 + DBC_Ensure(cRefs >= 0);
455 + * ======== DCD_GetDepLibs ========
456 + */
457 +DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
458 + IN struct DSP_UUID *pUuid,
459 + u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
460 + OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
462 + DSP_STATUS status = DSP_SOK;
464 + DBC_Require(cRefs > 0);
465 + DBC_Require(IsValidHandle(hDcdMgr));
466 + DBC_Require(pUuid != NULL);
467 + DBC_Require(pDepLibUuids != NULL);
468 + DBC_Require(pPersistentDepLibs != NULL);
470 + GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
471 + hDcdMgr);
473 + status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
474 + pPersistentDepLibs, phase);
476 + return status;
480 + * ======== DCD_GetNumDepLibs ========
481 + */
482 +DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
483 + IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
484 + OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
486 + DSP_STATUS status = DSP_SOK;
488 + DBC_Require(cRefs > 0);
489 + DBC_Require(IsValidHandle(hDcdMgr));
490 + DBC_Require(pNumLibs != NULL);
491 + DBC_Require(pNumPersLibs != NULL);
492 + DBC_Require(pUuid != NULL);
494 + GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
495 + hDcdMgr);
497 + status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
498 + NULL, NULL, phase);
500 + return status;
504 + * ======== DCD_GetObjectDef ========
505 + * Purpose:
506 + * Retrieves the properties of a node or processor based on the UUID and
507 + * object type.
508 + */
509 +DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
510 + IN struct DSP_UUID *pObjUuid,
511 + IN enum DSP_DCDOBJTYPE objType,
512 + OUT struct DCD_GENERICOBJ *pObjDef)
514 + struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
515 + struct COD_LIBRARYOBJ *lib = NULL;
516 + DSP_STATUS status = DSP_SOK;
517 + u32 ulAddr = 0; /* Used by COD_GetSection */
518 + u32 ulLen = 0; /* Used by COD_GetSection */
519 + u32 dwBufSize; /* Used by REG functions */
520 + char szRegKey[REG_MAXREGPATHLENGTH];
521 + char *szUuid; /*[MAXUUIDLEN];*/
522 + char szRegData[MAXUUIDLEN];
523 + char szSectName[MAXUUIDLEN + 2]; /* ".[UUID]\0" */
524 + char *pszCoffBuf;
525 + u32 dwKeyLen; /* Len of REG key. */
526 + char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
527 +#ifdef _DB_TIOMAP
528 + char *pTempCoffBuf;
529 +#endif
530 + DBC_Require(cRefs > 0);
531 + DBC_Require(pObjDef != NULL);
532 + DBC_Require(pObjUuid != NULL);
534 + GT_4trace(curTrace, GT_ENTER,
535 + "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
536 + " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
537 + objType, pObjDef);
538 + szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
539 + if (!szUuid)
540 + return status = DSP_EMEMORY;
542 + if (!IsValidHandle(hDcdMgr)) {
543 + status = DSP_EHANDLE;
544 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
545 + "DCD manager handle.\n");
546 + goto func_end;
548 + /* Pre-determine final key length. It's length of DCD_REGKEY +
549 + * "_\0" + length of szObjType string + terminating NULL */
550 + dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
551 + DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
552 + /* Create proper REG key; concatenate DCD_REGKEY with objType. */
553 + CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
555 + if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
556 + CSL_Strncat(szRegKey, "_\0", 2);
557 + else
558 + status = DSP_EFAIL;
560 + status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
561 + if (status == -1) {
562 + status = DSP_EFAIL;
563 + } else {
564 + status = DSP_SOK;
566 + if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
567 + REG_MAXREGPATHLENGTH) {
568 + CSL_Strncat(szRegKey, szObjType,
569 + CSL_Strlen(szObjType) + 1);
570 + } else {
571 + status = DSP_EFAIL;
573 + /* Create UUID value to set in registry. */
574 + UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
576 + if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
577 + REG_MAXREGPATHLENGTH) {
578 + CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
579 + } else {
580 + status = DSP_EFAIL;
582 + /* Retrieve paths from the registry based on struct DSP_UUID */
583 + dwBufSize = REG_MAXREGPATHLENGTH;
585 + if (DSP_SUCCEEDED(status)) {
586 + status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
587 + &dwBufSize);
589 + if (DSP_FAILED(status)) {
590 + status = DSP_EUUID;
591 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
592 + "REG_GetValue() failed\n");
593 + goto func_end;
595 + /* Open COFF file. */
596 + status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
597 + if (DSP_FAILED(status)) {
598 + status = DSP_EDCDLOADBASE;
599 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
600 + "COD_OpenBase() failed\n");
601 + goto func_end;
603 + /* Ensure szUuid + 1 is not greater than sizeof szSectName. */
604 + DBC_Assert((CSL_Strlen(szUuid) + 1) < sizeof(szSectName));
605 + /* Create section name based on node UUID. A period is
606 + * pre-pended to the UUID string to form the section name.
607 + * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
608 + CSL_Strcpyn(szSectName, ".", 2);
609 + CSL_Strncat(szSectName, szUuid, CSL_Strlen(szUuid));
610 + /* Get section information. */
611 + status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
612 + if (DSP_FAILED(status)) {
613 + status = DSP_EDCDGETSECT;
614 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
615 + " COD_GetSection() failed\n");
616 + goto func_end;
618 + /* Allocate zeroed buffer. */
619 + pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
620 +#ifdef _DB_TIOMAP
621 + pTempCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
623 + if (CSL_Strstr(szRegData, "iva") == NULL) {
624 + /* Locate section by objectID and read its content. */
625 + status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
626 + } else {
627 + status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
628 + GT_0trace(curTrace, GT_4CLASS,
629 + "Skipped Byte swap for IVA !!\n");
631 +#else
632 + status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
633 +#endif
634 + if (DSP_SUCCEEDED(status)) {
635 + /* Compres DSP buffer to conform to PC format. */
636 + if (CSL_Strstr(szRegData, "iva") == NULL) {
637 + CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
638 + } else {
639 + CompressBuf(pszCoffBuf, ulLen, 1);
640 + GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
641 + "COFF buffer by 1 for IVA !!\n");
643 + /* Parse the content of the COFF buffer. */
644 + status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
645 + if (DSP_FAILED(status)) {
646 + status = DSP_EDCDPARSESECT;
647 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
648 + "GetAttrsFromBuf() failed\n");
650 + } else {
651 + status = DSP_EDCDREADSECT;
652 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
653 + "COD_ReadSection() failed\n");
655 + /* Free the previously allocated dynamic buffer. */
656 + MEM_Free(pszCoffBuf);
657 +#ifdef _DB_TIOMAP
658 + MEM_Free(pTempCoffBuf);
659 +#endif
660 +func_end:
661 + if (lib)
662 + COD_Close(lib);
664 + if (szUuid)
665 + MEM_Free(szUuid);
666 + return status;
670 + * ======== DCD_GetObjects ========
671 + */
672 +DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
673 + DCD_REGISTERFXN registerFxn, void *handle)
675 + struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
676 + DSP_STATUS status = DSP_SOK;
677 + char *pszCoffBuf;
678 + char *pszCur;
679 +#ifdef _DB_TIOMAP
680 + char *pTempCoffBuf;
681 +#endif
682 + struct COD_LIBRARYOBJ *lib = NULL;
683 + u32 ulAddr = 0; /* Used by COD_GetSection */
684 + u32 ulLen = 0; /* Used by COD_GetSection */
685 + char seps[] = ":, ";
686 + char *pToken = NULL;
687 + struct DSP_UUID dspUuid;
688 + s32 cObjectType;
689 + DBC_Require(cRefs > 0);
690 + GT_1trace(curTrace, GT_ENTER,
691 + "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
692 + if (!IsValidHandle(hDcdMgr)) {
693 + status = DSP_EHANDLE;
694 + GT_0trace(curTrace, GT_6CLASS,
695 + "DCD_GetObjects: invalid DCD manager handle.\n");
696 + goto func_end;
698 + /* Open DSP coff file, don't load symbols. */
699 + status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
700 + if (DSP_FAILED(status)) {
701 + status = DSP_EDCDLOADBASE;
702 + GT_0trace(curTrace, GT_6CLASS,
703 + "DCD_AutoRegister: COD_Open() failed\n");
704 + goto func_cont;
706 + /* Get DCD_RESIGER_SECTION section information. */
707 + status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
708 + if (DSP_FAILED(status) || !(ulLen > 0)) {
709 + status = DSP_EDCDNOAUTOREGISTER;
710 + GT_0trace(curTrace, GT_6CLASS,
711 + "DCD_GetObjects: COD_GetSection() "
712 + "- no auto register section\n");
713 + goto func_cont;
715 + /* Allocate zeroed buffer. */
716 + pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
717 +#ifdef _DB_TIOMAP
718 + pTempCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
719 + if (strstr(pszCoffPath, "iva") == NULL) {
720 + /* Locate section by objectID and read its content. */
721 + status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
722 + pszCoffBuf, ulLen);
723 + } else {
724 + GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
725 + status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
726 + pszCoffBuf, ulLen);
728 +#else
729 + status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
730 +#endif
731 + if (DSP_SUCCEEDED(status)) {
732 + /* Compress DSP buffer to conform to PC format. */
733 + GT_0trace(curTrace, GT_4CLASS,
734 + "Successfully read section !!\n");
735 + if (strstr(pszCoffPath, "iva") == NULL) {
736 + CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
737 + } else {
738 + CompressBuf(pszCoffBuf, ulLen, 1);
739 + GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
740 + "with 1 word for IVA !!\n");
742 + /* Read from buffer and register object in buffer. */
743 + pToken = CSL_Strtokr(pszCoffBuf, seps, &pszCur);
744 + while (pToken != NULL) {
745 + /* Retrieve UUID string. */
746 + UUID_UuidFromString(pToken, &dspUuid);
747 + /* Retrieve object type */
748 + pToken = CSL_Strtokr(NULL, seps, &pszCur);
749 + /* Retrieve object type */
750 + cObjectType = Atoi(pToken);
751 + /*
752 + * Apply registerFxn to the found DCD object.
753 + * Possible actions include:
755 + * 1) Register found DCD object.
756 + * 2) Unregister found DCD object (when handle == NULL)
757 + * 3) Add overlay node.
758 + */
759 + GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
760 + "%d \n", cObjectType);
761 + status = registerFxn(&dspUuid, cObjectType, handle);
762 + if (DSP_SUCCEEDED(status)) {
763 + GT_1trace(curTrace, GT_5CLASS,
764 + "DCD_GetObjects: status 0x%x\n",
765 + status);
766 + } else {
767 + GT_0trace(curTrace, GT_6CLASS,
768 + "DCD_GetObjects: "
769 + "registration() failed\n");
770 + /* if error occurs, break from while loop. */
771 + break;
773 + /* Get next token */
774 + pToken = CSL_Strtokr(NULL, seps, &pszCur);
776 + } else {
777 + status = DSP_EDCDREADSECT;
778 + GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
779 + "COD_ReadSection() failed\n");
781 + /* Free the previously allocated dynamic buffer. */
782 + MEM_Free(pszCoffBuf);
783 +#ifdef _DB_TIOMAP
784 + MEM_Free(pTempCoffBuf);
785 +#endif
786 +func_cont:
787 + if (lib)
788 + COD_Close(lib);
790 +func_end:
791 + return status;
795 + * ======== DCD_GetLibraryName ========
796 + * Purpose:
797 + * Retrieves the library name for the given UUID.
799 + */
800 +DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
801 + IN struct DSP_UUID *pUuid,
802 + IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
803 + enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
805 + char szRegKey[REG_MAXREGPATHLENGTH];
806 + char szUuid[MAXUUIDLEN];
807 + u32 dwKeyLen; /* Len of REG key. */
808 + char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
809 + DSP_STATUS status = DSP_SOK;
811 + DBC_Require(pUuid != NULL);
812 + DBC_Require(pstrLibName != NULL);
813 + DBC_Require(pdwSize != NULL);
814 + DBC_Require(IsValidHandle(hDcdMgr));
816 + GT_4trace(curTrace, GT_ENTER,
817 + "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
818 + " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
819 + pstrLibName, pdwSize);
820 + /*
821 + * Pre-determine final key length. It's length of DCD_REGKEY +
822 + * "_\0" + length of szObjType string + terminating NULL.
823 + */
824 + dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
825 + DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
826 + /* Create proper REG key; concatenate DCD_REGKEY with objType. */
827 + CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
828 + if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
829 + CSL_Strncat(szRegKey, "_\0", 2);
830 + else
831 + status = DSP_EFAIL;
833 + switch (phase) {
834 + case NLDR_CREATE:
835 + /* create phase type */
836 + sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
837 + break;
838 + case NLDR_EXECUTE:
839 + /* execute phase type */
840 + sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
841 + break;
842 + case NLDR_DELETE:
843 + /* delete phase type */
844 + sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
845 + break;
846 + case NLDR_NOPHASE:
847 + /* known to be a dependent library */
848 + sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
849 + break;
850 + default:
851 + status = -1;
852 + DBC_Assert(false);
854 + if (status == -1) {
855 + status = DSP_EFAIL;
856 + } else {
857 + status = DSP_SOK;
858 + if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType))
859 + < REG_MAXREGPATHLENGTH) {
860 + CSL_Strncat(szRegKey, szObjType,
861 + CSL_Strlen(szObjType) + 1);
862 + } else {
863 + status = DSP_EFAIL;
865 + /* Create UUID value to find match in registry. */
866 + UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
867 + if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
868 + REG_MAXREGPATHLENGTH) {
869 + CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
870 + } else {
871 + status = DSP_EFAIL;
874 + if (DSP_SUCCEEDED(status)) {
875 + /* Retrieve path from the registry based on DSP_UUID */
876 + status = REG_GetValue(NULL, szRegKey, szRegKey,
877 + (u8 *)pstrLibName, pdwSize);
879 + /* If can't find, phases might be registered as generic LIBRARYTYPE */
880 + if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
881 + if (fPhaseSplit)
882 + *fPhaseSplit = false;
884 + CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
885 + if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) <
886 + REG_MAXREGPATHLENGTH) {
887 + CSL_Strncat(szRegKey, "_\0", 2);
888 + } else {
889 + status = DSP_EFAIL;
891 + sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
892 + if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType))
893 + < REG_MAXREGPATHLENGTH) {
894 + CSL_Strncat(szRegKey, szObjType,
895 + CSL_Strlen(szObjType) + 1);
896 + } else {
897 + status = DSP_EFAIL;
899 + UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
900 + if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
901 + REG_MAXREGPATHLENGTH) {
902 + CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
903 + } else {
904 + status = DSP_EFAIL;
906 + status = REG_GetValue(NULL, szRegKey, szRegKey,
907 + (u8 *)pstrLibName, pdwSize);
910 + return status;
914 + * ======== DCD_Init ========
915 + * Purpose:
916 + * Initialize the DCD module.
917 + */
918 +bool DCD_Init(void)
920 + bool fInitMEM;
921 + bool fInitREG;
922 + bool fInitCOD;
923 + bool fInit = true;
925 + DBC_Require(cRefs >= 0);
927 + GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
928 + cRefs);
930 + if (cRefs == 0) {
932 + /* Initialize required modules. */
933 + fInitMEM = MEM_Init();
934 + fInitCOD = COD_Init();
935 + fInitREG = REG_Init();
936 + if (!fInitMEM || !fInitCOD || !fInitREG) {
937 + fInit = false;
938 + GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
939 + /* Exit initialized modules. */
940 + if (fInitMEM)
941 + MEM_Exit();
943 + if (fInitCOD)
944 + COD_Exit();
946 + if (fInitREG)
947 + REG_Exit();
952 + if (fInit)
953 + cRefs++;
956 + GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
957 + cRefs);
959 + DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
961 + return fInit;
965 + * ======== DCD_RegisterObject ========
966 + * Purpose:
967 + * Registers a node or a processor with the DCD.
968 + * If pszPathName == NULL, unregister the specified DCD object.
969 + */
970 +DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
971 + IN enum DSP_DCDOBJTYPE objType,
972 + IN char *pszPathName)
974 + DSP_STATUS status = DSP_SOK;
975 + char szRegKey[REG_MAXREGPATHLENGTH];
976 + char szUuid[MAXUUIDLEN + 1];
977 + u32 dwPathSize = 0;
978 + u32 dwKeyLen; /* Len of REG key. */
979 + char szObjType[MAX_INT2CHAR_LENGTH]; /* str. rep. of objType. */
981 + DBC_Require(cRefs > 0);
982 + DBC_Require(pUuid != NULL);
983 + DBC_Require((objType == DSP_DCDNODETYPE) ||
984 + (objType == DSP_DCDPROCESSORTYPE) ||
985 + (objType == DSP_DCDLIBRARYTYPE) ||
986 + (objType == DSP_DCDCREATELIBTYPE) ||
987 + (objType == DSP_DCDEXECUTELIBTYPE) ||
988 + (objType == DSP_DCDDELETELIBTYPE));
990 + GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
991 + "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
992 + /*
993 + * Pre-determine final key length. It's length of DCD_REGKEY +
994 + * "_\0" + length of szObjType string + terminating NULL.
995 + */
996 + dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
997 + DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
998 + /* Create proper REG key; concatenate DCD_REGKEY with objType. */
999 + CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
1000 + if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
1001 + CSL_Strncat(szRegKey, "_\0", 2);
1002 + else
1003 + status = DSP_EFAIL;
1005 + status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
1006 + if (status == -1) {
1007 + status = DSP_EFAIL;
1008 + } else {
1009 + status = DSP_SOK;
1010 + if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
1011 + REG_MAXREGPATHLENGTH) {
1012 + CSL_Strncat(szRegKey, szObjType,
1013 + CSL_Strlen(szObjType) + 1);
1014 + } else {
1015 + status = DSP_EFAIL;
1017 + /* Create UUID value to set in registry. */
1018 + UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
1019 + if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
1020 + REG_MAXREGPATHLENGTH) {
1021 + CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
1022 + } else {
1023 + status = DSP_EFAIL;
1027 + if (DSP_SUCCEEDED(status)) {
1028 + /*
1029 + * If pszPathName != NULL, perform registration, otherwise,
1030 + * perform unregistration.
1031 + */
1032 + if (pszPathName) {
1033 + /* Add new reg value (UUID+objType) with COFF path
1034 + * info. */
1035 + dwPathSize = CSL_Strlen(pszPathName) + 1;
1036 + status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
1037 + (u8 *)pszPathName, dwPathSize);
1038 + GT_3trace(curTrace, GT_6CLASS,
1039 + "REG_SetValue REG_SZ=%d, "
1040 + "(u8 *)pszPathName=%s, dwPathSize=%d\n",
1041 + REG_SZ, pszPathName, dwPathSize);
1042 + if (DSP_FAILED(status)) {
1043 + status = DSP_EFAIL;
1044 + GT_0trace(curTrace, GT_6CLASS,
1045 + "DCD_RegisterObject: REG_SetValue failed!\n");
1047 + } else {
1048 + /* Deregister an existing object. */
1049 + status = REG_DeleteValue(NULL, szRegKey, szRegKey);
1050 + if (DSP_FAILED(status)) {
1051 + status = DSP_EFAIL;
1052 + GT_0trace(curTrace, GT_6CLASS,
1053 + "DCD_UnregisterObject: "
1054 + "REG_DeleteValue failed!\n");
1059 + if (DSP_SUCCEEDED(status)) {
1060 + /*
1061 + * Because the node database has been updated through a
1062 + * successful object registration/de-registration operation,
1063 + * we need to reset the object enumeration counter to allow
1064 + * current enumerations to reflect this update in the node
1065 + * database.
1066 + */
1068 + cEnumRefs = 0;
1071 + return status;
1075 + * ======== DCD_UnregisterObject ========
1076 + * Call DCD_Register object with pszPathName set to NULL to
1077 + * perform actual object de-registration.
1078 + */
1079 +DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
1080 + IN enum DSP_DCDOBJTYPE objType)
1082 + DSP_STATUS status = DSP_SOK;
1084 + DBC_Require(cRefs > 0);
1085 + DBC_Require(pUuid != NULL);
1086 + DBC_Require((objType == DSP_DCDNODETYPE) ||
1087 + (objType == DSP_DCDPROCESSORTYPE) ||
1088 + (objType == DSP_DCDLIBRARYTYPE) ||
1089 + (objType == DSP_DCDCREATELIBTYPE) ||
1090 + (objType == DSP_DCDEXECUTELIBTYPE) ||
1091 + (objType == DSP_DCDDELETELIBTYPE));
1093 + GT_2trace(curTrace, GT_ENTER,
1094 + "DCD_UnregisterObject: object UUID 0x%x, "
1095 + "objType %d\n", pUuid, objType);
1097 + /*
1098 + * When DCD_RegisterObject is called with NULL as pathname,
1099 + * it indicates an unregister object operation.
1100 + */
1101 + status = DCD_RegisterObject(pUuid, objType, NULL);
1103 + return status;
1107 + **********************************************************************
1108 + * DCD Helper Functions
1109 + **********************************************************************
1110 + */
1113 + * ======== Atoi ========
1114 + * Purpose:
1115 + * This function converts strings in decimal or hex format to integers.
1116 + */
1117 +static s32 Atoi(char *pszBuf)
1119 + s32 result = 0;
1120 + char *pch = pszBuf;
1121 + char c;
1122 + char first;
1123 + s32 base = 10;
1124 + s32 len;
1126 + while (isspace(*pch))
1127 + pch++;
1129 + first = *pch;
1130 + if (first == '-' || first == '+') {
1131 + pch++;
1132 + } else {
1133 + /* Determine if base 10 or base 16 */
1134 + len = strlen(pch);
1135 + if (len > 1) {
1136 + c = pch[1];
1137 + if ((*pch == '0' && (c == 'x' || c == 'X'))) {
1138 + base = 16;
1139 + pch += 2;
1141 + c = pch[len - 1];
1142 + if (c == 'h' || c == 'H')
1143 + base = 16;
1148 + while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
1149 + result *= base;
1150 + if ('A' <= c && c <= 'F') {
1151 + c = c - 'A' + 10;
1152 + } else {
1153 + if ('a' <= c && c <= 'f')
1154 + c = c - 'a' + 10;
1155 + else
1156 + c -= '0';
1159 + result += c;
1160 + ++pch;
1163 + return result;
1167 + * ======== GetAttrsFromBuf ========
1168 + * Purpose:
1169 + * Parse the content of a buffer filled with DSP-side data and
1170 + * retrieve an object's attributes from it. IMPORTANT: Assume the
1171 + * buffer has been converted from DSP format to GPP format.
1172 + */
1173 +static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
1174 + enum DSP_DCDOBJTYPE objType,
1175 + struct DCD_GENERICOBJ *pGenObj)
1177 + DSP_STATUS status = DSP_SOK;
1178 + char seps[] = ", ";
1179 + char *pszCur;
1180 + char *token;
1181 + s32 cLen = 0;
1182 + u32 i = 0;
1183 +#ifdef _DB_TIOMAP
1184 + s32 iEntry;
1185 +#endif
1187 + DBC_Require(pszBuf != NULL);
1188 + DBC_Require(ulBufSize != 0);
1189 + DBC_Require((objType == DSP_DCDNODETYPE)
1190 + || (objType == DSP_DCDPROCESSORTYPE));
1191 + DBC_Require(pGenObj != NULL);
1193 + switch (objType) {
1194 + case DSP_DCDNODETYPE:
1195 + /*
1196 + * Parse COFF sect buffer to retrieve individual tokens used
1197 + * to fill in object attrs.
1198 + */
1199 + token = CSL_Strtokr(pszBuf, seps, &pszCur);
1201 + /* u32 cbStruct */
1202 + pGenObj->objData.nodeObj.ndbProps.cbStruct =
1203 + (u32) Atoi(token);
1204 + token = CSL_Strtokr(NULL, seps, &pszCur);
1206 + /* DSP_UUID uiNodeID */
1207 + UUID_UuidFromString(token,
1208 + &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
1209 + token = CSL_Strtokr(NULL, seps, &pszCur);
1211 + /* acName */
1212 + cLen = strlen(token);
1213 + if (cLen > DSP_MAXNAMELEN - 1)
1214 + cLen = DSP_MAXNAMELEN - 1;
1216 + CSL_Strcpyn(pGenObj->objData.nodeObj.ndbProps.acName,
1217 + token, cLen);
1218 + pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
1219 + token = CSL_Strtokr(NULL, seps, &pszCur);
1220 + /* u32 uNodeType */
1221 + pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
1222 + token = CSL_Strtokr(NULL, seps, &pszCur);
1223 + /* u32 bCacheOnGPP */
1224 + pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
1225 + token = CSL_Strtokr(NULL, seps, &pszCur);
1226 + /* DSP_RESOURCEREQMTS dspResourceReqmts */
1227 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
1228 + (u32) Atoi(token);
1229 + token = CSL_Strtokr(NULL, seps, &pszCur);
1231 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1232 + uStaticDataSize = Atoi(token);
1233 + token = CSL_Strtokr(NULL, seps, &pszCur);
1234 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1235 + uGlobalDataSize = Atoi(token);
1236 + token = CSL_Strtokr(NULL, seps, &pszCur);
1237 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1238 + uProgramMemSize = Atoi(token);
1239 + token = CSL_Strtokr(NULL, seps, &pszCur);
1240 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1241 + uWCExecutionTime = Atoi(token);
1242 + token = CSL_Strtokr(NULL, seps, &pszCur);
1243 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1244 + uWCPeriod = Atoi(token);
1245 + token = CSL_Strtokr(NULL, seps, &pszCur);
1247 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1248 + uWCDeadline = Atoi(token);
1249 + token = CSL_Strtokr(NULL, seps, &pszCur);
1251 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1252 + uAvgExectionTime = Atoi(token);
1253 + token = CSL_Strtokr(NULL, seps, &pszCur);
1255 + pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
1256 + uMinimumPeriod = Atoi(token);
1257 + token = CSL_Strtokr(NULL, seps, &pszCur);
1259 + /* s32 iPriority */
1260 + pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
1261 + token = CSL_Strtokr(NULL, seps, &pszCur);
1263 + /* u32 uStackSize */
1264 + pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
1265 + token = CSL_Strtokr(NULL, seps, &pszCur);
1267 + /* u32 uSysStackSize */
1268 + pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
1269 + token = CSL_Strtokr(NULL, seps, &pszCur);
1271 + /* u32 uStackSeg */
1272 + pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
1273 + token = CSL_Strtokr(NULL, seps, &pszCur);
1275 + /* u32 uMessageDepth */
1276 + pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
1277 + token = CSL_Strtokr(NULL, seps, &pszCur);
1279 + /* u32 uNumInputStreams */
1280 + pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
1281 + Atoi(token);
1282 + token = CSL_Strtokr(NULL, seps, &pszCur);
1284 + /* u32 uNumOutputStreams */
1285 + pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
1286 + Atoi(token);
1287 + token = CSL_Strtokr(NULL, seps, &pszCur);
1289 + /* u32 uTimeout */
1290 + pGenObj->objData.nodeObj.ndbProps.uTimeout =
1291 + Atoi(token);
1292 + token = CSL_Strtokr(NULL, seps, &pszCur);
1294 + /* char * pstrCreatePhaseFxn */
1295 + cLen = strlen(token);
1296 + pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
1297 + MEM_Calloc(cLen + 1, MEM_PAGED);
1298 + strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
1299 + token, cLen);
1300 + pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
1301 + token = CSL_Strtokr(NULL, seps, &pszCur);
1303 + /* char * pstrExecutePhaseFxn */
1304 + cLen = strlen(token);
1305 + pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
1306 + MEM_Calloc(cLen + 1, MEM_PAGED);
1307 + strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
1308 + token, cLen);
1309 + pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
1310 + token = CSL_Strtokr(NULL, seps, &pszCur);
1312 + /* char * pstrDeletePhaseFxn */
1313 + cLen = strlen(token);
1314 + pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
1315 + MEM_Calloc(cLen + 1, MEM_PAGED);
1316 + strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
1317 + token, cLen);
1318 + pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
1319 + token = CSL_Strtokr(NULL, seps, &pszCur);
1321 + /* Segment id for message buffers */
1322 + pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
1323 + token = CSL_Strtokr(NULL, seps, &pszCur);
1325 + /* Message notification type */
1326 + pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
1327 + token = CSL_Strtokr(NULL, seps, &pszCur);
1329 + /* char * pstrIAlgName */
1330 + if (token) {
1331 + cLen = strlen(token);
1332 + pGenObj->objData.nodeObj.pstrIAlgName =
1333 + MEM_Calloc(cLen + 1, MEM_PAGED);
1334 + strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
1335 + token, cLen);
1336 + pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
1337 + token = CSL_Strtokr(NULL, seps, &pszCur);
1340 + /* Load type (static, dynamic, or overlay) */
1341 + if (token) {
1342 + pGenObj->objData.nodeObj.usLoadType = Atoi(token);
1343 + token = CSL_Strtokr(NULL, seps, &pszCur);
1346 + /* Dynamic load data requirements */
1347 + if (token) {
1348 + pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
1349 + token = CSL_Strtokr(NULL, seps, &pszCur);
1352 + /* Dynamic load code requirements */
1353 + if (token) {
1354 + pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
1355 + token = CSL_Strtokr(NULL, seps, &pszCur);
1358 + /* Extract node profiles into node properties */
1359 + if (token) {
1361 + pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
1362 + Atoi(token);
1363 + for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
1364 + uCountProfiles; i++) {
1365 + token = CSL_Strtokr(NULL, seps, &pszCur);
1366 + if (token) {
1367 + /* Heap Size for the node */
1368 + pGenObj->objData.nodeObj.ndbProps.
1369 + aProfiles[i].ulHeapSize =
1370 + Atoi(token);
1374 + token = CSL_Strtokr(NULL, seps, &pszCur);
1375 + if (token) {
1376 + pGenObj->objData.nodeObj.ndbProps.uStackSegName =
1377 + (u32)(token);
1380 + break;
1382 + case DSP_DCDPROCESSORTYPE:
1383 + /*
1384 + * Parse COFF sect buffer to retrieve individual tokens used
1385 + * to fill in object attrs.
1386 + */
1387 + token = CSL_Strtokr(pszBuf, seps, &pszCur);
1389 + pGenObj->objData.procObj.cbStruct = Atoi(token);
1390 + token = CSL_Strtokr(NULL, seps, &pszCur);
1392 + pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
1393 + token = CSL_Strtokr(NULL, seps, &pszCur);
1395 + pGenObj->objData.procObj.uProcessorType = Atoi(token);
1396 + token = CSL_Strtokr(NULL, seps, &pszCur);
1398 + pGenObj->objData.procObj.uClockRate = Atoi(token);
1399 + token = CSL_Strtokr(NULL, seps, &pszCur);
1401 + pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
1402 + token = CSL_Strtokr(NULL, seps, &pszCur);
1404 + pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
1405 + token = CSL_Strtokr(NULL, seps, &pszCur);
1407 + pGenObj->objData.procObj.uProcessorID = Atoi(token);
1408 + token = CSL_Strtokr(NULL, seps, &pszCur);
1410 + pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
1411 + token = CSL_Strtokr(NULL, seps, &pszCur);
1413 + pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
1414 + token = CSL_Strtokr(NULL, seps, &pszCur);
1416 + pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
1418 +#ifdef _DB_TIOMAP
1419 + /* Proc object may contain additional(extended) attributes. */
1420 + /* attr must match proc.hxx */
1421 + for (iEntry = 0; iEntry < 7; iEntry++) {
1422 + token = CSL_Strtokr(NULL, seps, &pszCur);
1423 + pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
1424 + Atoi(token);
1426 + token = CSL_Strtokr(NULL, seps, &pszCur);
1427 + pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
1428 + Atoi(token);
1430 +#endif
1432 + break;
1434 + default:
1435 + status = DSP_EFAIL;
1436 + break;
1439 + return status;
1443 + * ======== CompressBuffer ========
1444 + * Purpose:
1445 + * Compress the DSP buffer, if necessary, to conform to PC format.
1446 + */
1447 +static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
1449 + char *p;
1450 + char ch;
1451 + char *q;
1453 + p = pszBuf;
1454 + if (p == NULL)
1455 + return;
1457 + for (q = pszBuf; q < (pszBuf + ulBufSize);) {
1459 + ch = DspChar2GppChar(q, cCharSize);
1460 + if (ch == '\\') {
1461 + q += cCharSize;
1462 + ch = DspChar2GppChar(q, cCharSize);
1463 + switch (ch) {
1464 + case 't':
1465 + *p = '\t';
1466 + break;
1468 + case 'n':
1469 + *p = '\n';
1470 + break;
1472 + case 'r':
1473 + *p = '\r';
1474 + break;
1476 + case '0':
1477 + *p = '\0';
1478 + break;
1480 + default:
1481 + *p = ch;
1482 + break;
1484 + } else {
1485 + *p = ch;
1487 + p++;
1488 + q += cCharSize;
1491 + /* NULL out remainder of buffer. */
1492 + while (p < q)
1493 + *p++ = '\0';
1498 + * ======== DspChar2GppChar ========
1499 + * Purpose:
1500 + * Convert DSP char to host GPP char in a portable manner
1501 + */
1502 +static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
1504 + char ch = '\0';
1505 + char *chSrc;
1506 + s32 i;
1508 + for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
1509 + ch |= *chSrc++;
1511 + return ch;
1515 + * ======== GetDepLibInfo ========
1516 + */
1517 +static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
1518 + IN struct DSP_UUID *pUuid,
1519 + IN OUT u16 *pNumLibs,
1520 + OPTIONAL OUT u16 *pNumPersLibs,
1521 + OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
1522 + OPTIONAL OUT bool *pPersistentDepLibs,
1523 + enum NLDR_PHASE phase)
1525 + struct DCD_MANAGER *pDcdMgr = hDcdMgr; /* pointer to DCD manager */
1526 + char *pszCoffBuf = NULL;
1527 + char *pszCur;
1528 + char *pszFileName = NULL;
1529 + struct COD_LIBRARYOBJ *lib = NULL;
1530 +#ifdef _DB_TIOMAP
1531 + char *pTempCoffBuf;
1532 +#endif
1533 + u32 ulAddr = 0; /* Used by COD_GetSection */
1534 + u32 ulLen = 0; /* Used by COD_GetSection */
1535 + u32 dwDataSize = COD_MAXPATHLENGTH;
1536 + char seps[] = ", ";
1537 + char *pToken = NULL;
1538 + bool fGetUuids = (pDepLibUuids != NULL);
1539 + u16 nDepLibs = 0;
1540 + DSP_STATUS status = DSP_SOK;
1542 + DBC_Require(cRefs > 0);
1544 + DBC_Require(IsValidHandle(hDcdMgr));
1545 + DBC_Require(pNumLibs != NULL);
1546 + DBC_Require(pUuid != NULL);
1548 + GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
1549 + hDcdMgr);
1551 + /* Initialize to 0 dependent libraries, if only counting number of
1552 + * dependent libraries */
1553 + if (!fGetUuids) {
1554 + *pNumLibs = 0;
1555 + *pNumPersLibs = 0;
1558 + /* Allocate a buffer for file name */
1559 + pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
1560 + if (pszFileName == NULL) {
1561 + status = DSP_EMEMORY;
1562 + } else {
1563 + /* Get the name of the library */
1564 + status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
1565 + &dwDataSize, phase, NULL);
1567 + /* Open the library */
1568 + if (DSP_SUCCEEDED(status)) {
1569 + status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
1570 + COD_NOLOAD, &lib);
1572 + if (DSP_SUCCEEDED(status)) {
1573 + /* Get dependent library section information. */
1574 + status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
1576 + if (DSP_FAILED(status)) {
1577 + /* Ok, no dependent libraries */
1578 + ulLen = 0;
1579 + status = DSP_SNODEPENDENTLIBS;
1583 + if (DSP_FAILED(status) || !(ulLen > 0))
1584 + goto func_cont;
1586 + /* Allocate zeroed buffer. */
1587 + pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
1588 + if (pszCoffBuf == NULL)
1589 + status = DSP_EMEMORY;
1591 +#ifdef _DB_TIOMAP
1592 + pTempCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
1593 + if (pTempCoffBuf == NULL)
1594 + status = DSP_EMEMORY;
1596 +#endif
1597 + /* Read section contents. */
1598 + status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
1599 + if (DSP_FAILED(status))
1600 + goto func_cont;
1602 + /* Compress and format DSP buffer to conform to PC format. */
1603 + CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
1604 + /* Read from buffer */
1605 + pToken = CSL_Strtokr(pszCoffBuf, seps, &pszCur);
1606 + while (pToken != NULL) {
1607 + if (fGetUuids) {
1608 + if (nDepLibs >= *pNumLibs) {
1609 + /* Gone beyond the limit */
1610 + break;
1611 + } else {
1612 + /* Retrieve UUID string. */
1613 + UUID_UuidFromString(pToken,
1614 + &(pDepLibUuids[nDepLibs]));
1615 + /* Is this library persistent? */
1616 + pToken = CSL_Strtokr(NULL, seps, &pszCur);
1617 + pPersistentDepLibs[nDepLibs] = Atoi(pToken);
1618 + nDepLibs++;
1620 + } else {
1621 + /* Advanc to next token */
1622 + pToken = CSL_Strtokr(NULL, seps, &pszCur);
1623 + if (Atoi(pToken))
1624 + (*pNumPersLibs)++;
1626 + /* Just counting number of dependent libraries */
1627 + (*pNumLibs)++;
1629 + /* Get next token */
1630 + pToken = CSL_Strtokr(NULL, seps, &pszCur);
1632 +func_cont:
1633 + if (lib)
1634 + COD_Close(lib);
1636 + /* Free previously allocated dynamic buffers. */
1637 + if (pszFileName)
1638 + MEM_Free(pszFileName);
1640 + if (pszCoffBuf)
1641 + MEM_Free(pszCoffBuf);
1643 + return status;
1646 Index: lk/drivers/dsp/bridge/rmgr/disp.c
1647 ===================================================================
1648 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
1649 +++ lk/drivers/dsp/bridge/rmgr/disp.c 2008-08-18 10:38:37.000000000 +0300
1650 @@ -0,0 +1,915 @@
1652 + * linux/drivers/dsp/bridge/rmgr/disp.c
1654 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
1656 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
1658 + * This package is free software; you can redistribute it and/or modify
1659 + * it under the terms of the GNU General Public License version 2 as
1660 + * published by the Free Software Foundation.
1662 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
1663 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
1664 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
1665 + */
1669 + * ======== disp.c ========
1671 + * Description:
1672 + * Node Dispatcher interface. Communicates with Resource Manager Server
1673 + * (RMS) on DSP. Access to RMS is synchronized in NODE.
1675 + * Public Functions:
1676 + * DISP_Create
1677 + * DISP_Delete
1678 + * DISP_Exit
1679 + * DISP_Init
1680 + * DISP_NodeChangePriority
1681 + * DISP_NodeCreate
1682 + * DISP_NodeDelete
1683 + * DISP_NodePause
1684 + * DISP_NodeRun
1686 + *! Revision History:
1687 + *! =================
1688 + *! 18-Feb-2003 vp Code review updates
1689 + *! 18-Oct-2002 vp Ported to Linux platform
1690 + *! 16-May-2002 jeh Added DISP_DoCinit().
1691 + *! 24-Apr-2002 jeh Added DISP_MemWrite().
1692 + *! 13-Feb-2002 jeh Pass system stack size to RMS.
1693 + *! 16-Jan-2002 ag Added bufsize param to _ChnlAddIOReq() fxn
1694 + *! 10-May-2001 jeh Code Review cleanup.
1695 + *! 26-Sep-2000 jeh Fixed status values in SendMessage().
1696 + *! 19-Jun-2000 jeh Created.
1697 + */
1699 +/* ----------------------------------- Host OS */
1700 +#include <host_os.h>
1702 +/* ----------------------------------- DSP/BIOS Bridge */
1703 +#include <std.h>
1704 +#include <dbdefs.h>
1705 +#include <errbase.h>
1707 +/* ----------------------------------- Trace & Debug */
1708 +#include <gt.h>
1709 +#include <dbc.h>
1711 +/* ----------------------------------- OS Adaptation Layer */
1712 +#include <dev.h>
1713 +#include <mem.h>
1714 +#include <sync.h>
1715 +#include <csl.h>
1717 +/* ----------------------------------- Link Driver */
1718 +#include <wmd.h>
1720 +/* ----------------------------------- Platform Manager */
1721 +#include <dev.h>
1722 +#include <chnldefs.h>
1724 +/* ----------------------------------- Resource Manager */
1725 +#include <nodedefs.h>
1726 +#include <nodepriv.h>
1727 +#include <rms_sh.h>
1729 +/* ----------------------------------- This */
1730 +#include <disp.h>
1732 +#define DISP_SIGNATURE 0x50534944 /* "PSID" */
1734 +/* Size of a reply from RMS */
1735 +#define REPLYSIZE (3 * sizeof(RMS_WORD))
1737 +/* Reserved channel offsets for communication with RMS */
1738 +#define CHNLTORMSOFFSET 0
1739 +#define CHNLFROMRMSOFFSET 1
1741 +#define CHNLIOREQS 1
1743 +#define SwapWord(x) (((u32)(x) >> 16) | ((u32)(x) << 16))
1746 + * ======== DISP_OBJECT ========
1747 + */
1748 +struct DISP_OBJECT {
1749 + u32 dwSignature; /* Used for object validation */
1750 + struct DEV_OBJECT *hDevObject; /* Device for this processor */
1751 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
1752 + struct CHNL_MGR *hChnlMgr; /* Channel manager */
1753 + struct CHNL_OBJECT *hChnlToDsp; /* Channel for commands to RMS */
1754 + struct CHNL_OBJECT *hChnlFromDsp; /* Channel for replies from RMS */
1755 + u8 *pBuf; /* Buffer for commands, replies */
1756 + u32 ulBufsize; /* pBuf size in bytes */
1757 + u32 ulBufsizeRMS; /* pBuf size in RMS words */
1758 + u32 uCharSize; /* Size of DSP character */
1759 + u32 uWordSize; /* Size of DSP word */
1760 + u32 uDataMauSize; /* Size of DSP Data MAU */
1763 +static u32 cRefs;
1765 +/* Debug msgs: */
1766 +#if GT_TRACE
1767 +static struct GT_Mask DISP_DebugMask = { NULL, NULL };
1768 +#endif
1770 +static void DeleteDisp(struct DISP_OBJECT *hDisp);
1771 +static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
1772 + struct NODE_STRMDEF strmDef, u32 max,
1773 + u32 uCharsInRMSWord);
1774 +static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
1775 + u32 ulBytes, OUT u32 *pdwArg);
1778 + * ======== DISP_Create ========
1779 + * Create a NODE Dispatcher object.
1780 + */
1781 +DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
1782 + struct DEV_OBJECT *hDevObject,
1783 + IN CONST struct DISP_ATTRS *pDispAttrs)
1785 + struct DISP_OBJECT *pDisp;
1786 + struct WMD_DRV_INTERFACE *pIntfFxns;
1787 + u32 ulChnlId;
1788 + struct CHNL_ATTRS chnlAttrs;
1789 + DSP_STATUS status = DSP_SOK;
1790 + u32 devType;
1792 + DBC_Require(cRefs > 0);
1793 + DBC_Require(phDispObject != NULL);
1794 + DBC_Require(pDispAttrs != NULL);
1795 + DBC_Require(hDevObject != NULL);
1797 + GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
1798 + "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
1799 + hDevObject, pDispAttrs);
1801 + *phDispObject = NULL;
1803 + /* Allocate Node Dispatcher object */
1804 + MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
1805 + if (pDisp == NULL) {
1806 + status = DSP_EMEMORY;
1807 + GT_0trace(DISP_DebugMask, GT_6CLASS,
1808 + "DISP_Create: MEM_AllocObject() failed!\n");
1809 + } else {
1810 + pDisp->hDevObject = hDevObject;
1813 + /* Get Channel manager and WMD function interface */
1814 + if (DSP_SUCCEEDED(status)) {
1815 + status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
1816 + if (DSP_SUCCEEDED(status)) {
1817 + (void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
1818 + pDisp->pIntfFxns = pIntfFxns;
1819 + } else {
1820 + GT_1trace(DISP_DebugMask, GT_6CLASS,
1821 + "DISP_Create: Failed to get "
1822 + "channel manager! status = 0x%x\n", status);
1826 + /* check device type and decide if streams or messag'ing is used for
1827 + * RMS/EDS */
1828 + if (DSP_FAILED(status))
1829 + goto func_cont;
1831 + status = DEV_GetDevType(hDevObject, &devType);
1832 + GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
1833 + "device = 0x%x\n", devType);
1834 + if (DSP_FAILED(status))
1835 + goto func_cont;
1837 + if (devType != DSP_UNIT) {
1838 + GT_0trace(DISP_DebugMask, GT_6CLASS,
1839 + "DISP_Create: Unkown device "
1840 + "type in Device object !! \n");
1841 + status = DSP_EFAIL;
1842 + goto func_cont;
1844 + if (DSP_SUCCEEDED(status)) {
1845 + pDisp->uCharSize = DSPWORDSIZE;
1846 + pDisp->uWordSize = DSPWORDSIZE;
1847 + pDisp->uDataMauSize = DSPWORDSIZE;
1848 + /* Open channels for communicating with the RMS */
1849 + chnlAttrs.uIOReqs = CHNLIOREQS;
1850 + chnlAttrs.hEvent = NULL;
1851 + ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
1852 + status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
1853 + pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
1854 + if (DSP_FAILED(status)) {
1855 + GT_2trace(DISP_DebugMask, GT_6CLASS,
1856 + "DISP_Create: Channel to RMS "
1857 + "open failed, chnl id = %d, status = 0x%x\n",
1858 + ulChnlId, status);
1861 + if (DSP_SUCCEEDED(status)) {
1862 + ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
1863 + status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
1864 + pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
1865 + &chnlAttrs);
1866 + if (DSP_FAILED(status)) {
1867 + GT_2trace(DISP_DebugMask, GT_6CLASS,
1868 + "DISP_Create: Channel from RMS "
1869 + "open failed, chnl id = %d, status = 0x%x\n",
1870 + ulChnlId, status);
1873 + if (DSP_SUCCEEDED(status)) {
1874 + /* Allocate buffer for commands, replies */
1875 + pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
1876 + pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
1877 + pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
1878 + if (pDisp->pBuf == NULL) {
1879 + status = DSP_EMEMORY;
1880 + GT_0trace(DISP_DebugMask, GT_6CLASS,
1881 + "DISP_Create: Failed "
1882 + "to allocate channel buffer!\n");
1885 +func_cont:
1886 + if (DSP_SUCCEEDED(status))
1887 + *phDispObject = pDisp;
1888 + else
1889 + DeleteDisp(pDisp);
1891 + DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
1892 + ((DSP_SUCCEEDED(status)) &&
1893 + (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
1894 + return status;
1898 + * ======== DISP_Delete ========
1899 + * Delete the NODE Dispatcher.
1900 + */
1901 +void DISP_Delete(struct DISP_OBJECT *hDisp)
1903 + DBC_Require(cRefs > 0);
1904 + DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
1906 + GT_1trace(DISP_DebugMask, GT_ENTER,
1907 + "DISP_Delete: hDisp: 0x%x\n", hDisp);
1909 + DeleteDisp(hDisp);
1911 + DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
1915 + * ======== DISP_Exit ========
1916 + * Discontinue usage of DISP module.
1917 + */
1918 +void DISP_Exit(void)
1920 + DBC_Require(cRefs > 0);
1922 + cRefs--;
1924 + GT_1trace(DISP_DebugMask, GT_5CLASS,
1925 + "Entered DISP_Exit, ref count: 0x%x\n", cRefs);
1927 + DBC_Ensure(cRefs >= 0);
1931 + * ======== DISP_Init ========
1932 + * Initialize the DISP module.
1933 + */
1934 +bool DISP_Init(void)
1936 + bool fRetVal = true;
1938 + DBC_Require(cRefs >= 0);
1940 + if (cRefs == 0) {
1941 + DBC_Assert(!DISP_DebugMask.flags);
1942 + GT_create(&DISP_DebugMask, "DI"); /* "DI" for DIspatcher */
1945 + if (fRetVal)
1946 + cRefs++;
1948 + GT_1trace(DISP_DebugMask, GT_5CLASS,
1949 + "DISP_Init(), ref count: 0x%x\n", cRefs);
1951 + DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
1952 + return fRetVal;
1956 + * ======== DISP_NodeChangePriority ========
1957 + * Change the priority of a node currently running on the target.
1958 + */
1959 +DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
1960 + struct NODE_OBJECT *hNode,
1961 + u32 ulRMSFxn, NODE_ENV nodeEnv,
1962 + s32 nPriority)
1964 + u32 dwArg;
1965 + struct RMS_Command *pCommand;
1966 + DSP_STATUS status = DSP_SOK;
1968 + DBC_Require(cRefs > 0);
1969 + DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
1970 + DBC_Require(hNode != NULL);
1972 + GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
1973 + "0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
1974 + hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
1976 + /* Send message to RMS to change priority */
1977 + pCommand = (struct RMS_Command *)(hDisp->pBuf);
1978 + pCommand->fxn = (RMS_WORD)(ulRMSFxn);
1979 + pCommand->arg1 = (RMS_WORD)nodeEnv;
1980 + pCommand->arg2 = nPriority;
1981 + status = SendMessage(hDisp, NODE_GetTimeout(hNode),
1982 + sizeof(struct RMS_Command), &dwArg);
1983 + if (DSP_FAILED(status)) {
1984 + GT_1trace(DISP_DebugMask, GT_6CLASS,
1985 + "DISP_NodeChangePriority failed! "
1986 + "status = 0x%x\n", status);
1988 + return status;
1992 + * ======== DISP_NodeCreate ========
1993 + * Create a node on the DSP by remotely calling the node's create function.
1994 + */
1995 +DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
1996 + u32 ulRMSFxn, u32 ulCreateFxn,
1997 + IN CONST struct NODE_CREATEARGS *pArgs,
1998 + OUT NODE_ENV *pNodeEnv)
2000 + struct NODE_MSGARGS msgArgs;
2001 + struct NODE_TASKARGS taskArgs;
2002 + struct RMS_Command *pCommand;
2003 + struct RMS_MsgArgs *pMsgArgs;
2004 + struct RMS_MoreTaskArgs *pMoreTaskArgs;
2005 + enum NODE_TYPE nodeType;
2006 + u32 dwLength;
2007 + RMS_WORD *pdwBuf = NULL;
2008 + u32 ulBytes;
2009 + u32 i;
2010 + u32 total;
2011 + u32 uCharsInRMSWord;
2012 + s32 taskArgsOffset;
2013 + s32 sioInDefOffset;
2014 + s32 sioOutDefOffset;
2015 + s32 sioDefsOffset;
2016 + s32 argsOffset = -1;
2017 + s32 offset;
2018 + struct NODE_STRMDEF strmDef;
2019 + u32 max;
2020 + DSP_STATUS status = DSP_SOK;
2021 + struct DSP_NODEINFO nodeInfo;
2022 + u32 devType;
2024 + DBC_Require(cRefs > 0);
2025 + DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
2026 + DBC_Require(hNode != NULL);
2027 + DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
2028 + DBC_Require(pNodeEnv != NULL);
2030 + GT_6trace(DISP_DebugMask, GT_ENTER,
2031 + "DISP_NodeCreate: hDisp: 0x%x\thNode:"
2032 + " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
2033 + " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
2035 + status = DEV_GetDevType(hDisp->hDevObject, &devType);
2037 + GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
2038 + "for device = 0x%x\n", devType);
2040 + if (DSP_FAILED(status))
2041 + goto func_end;
2043 + if (devType != DSP_UNIT) {
2044 + GT_1trace(DISP_DebugMask, GT_7CLASS,
2045 + "DISP_NodeCreate unknown device "
2046 + "type = 0x%x\n", devType);
2047 + goto func_end;
2049 + DBC_Require(pArgs != NULL);
2050 + nodeType = NODE_GetType(hNode);
2051 + msgArgs = pArgs->asa.msgArgs;
2052 + max = hDisp->ulBufsizeRMS; /*Max # of RMS words that can be sent */
2053 + DBC_Assert(max == RMS_COMMANDBUFSIZE);
2054 + uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
2055 + /* Number of RMS words needed to hold arg data */
2056 + dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
2057 + /* Make sure msg args and command fit in buffer */
2058 + total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
2059 + sizeof(struct RMS_MsgArgs)
2060 + / sizeof(RMS_WORD) - 1 + dwLength;
2061 + if (total >= max) {
2062 + status = DSP_EFAIL;
2063 + GT_2trace(DISP_DebugMask, GT_6CLASS,
2064 + "DISP_NodeCreate: Message args too"
2065 + " large for buffer! Message args size = %d, max = %d\n",
2066 + total, max);
2068 + /*
2069 + * Fill in buffer to send to RMS.
2070 + * The buffer will have the following format:
2072 + * RMS command:
2073 + * Address of RMS_CreateNode()
2074 + * Address of node's create function
2075 + * dummy argument
2076 + * node type
2078 + * Message Args:
2079 + * max number of messages
2080 + * segid for message buffer allocation
2081 + * notification type to use when message is received
2082 + * length of message arg data
2083 + * message args data
2085 + * Task Args (if task or socket node):
2086 + * priority
2087 + * stack size
2088 + * system stack size
2089 + * stack segment
2090 + * misc
2091 + * number of input streams
2092 + * pSTRMInDef[] - offsets of STRM definitions for input streams
2093 + * number of output streams
2094 + * pSTRMOutDef[] - offsets of STRM definitions for output
2095 + * streams
2096 + * STRMInDef[] - array of STRM definitions for input streams
2097 + * STRMOutDef[] - array of STRM definitions for output streams
2099 + * Socket Args (if DAIS socket node):
2101 + */
2102 + if (DSP_SUCCEEDED(status)) {
2103 + total = 0; /* Total number of words in buffer so far */
2104 + pdwBuf = (RMS_WORD *)hDisp->pBuf;
2105 + pCommand = (struct RMS_Command *)pdwBuf;
2106 + pCommand->fxn = (RMS_WORD)(ulRMSFxn);
2107 + pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
2108 + if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
2109 + /* Flush ICACHE on Load */
2110 + pCommand->arg2 = 1; /* dummy argument */
2111 + } else {
2112 + /* Do not flush ICACHE */
2113 + pCommand->arg2 = 0; /* dummy argument */
2115 + pCommand->data = NODE_GetType(hNode);
2116 + /*
2117 + * argsOffset is the offset of the data field in struct
2118 + * RMS_Command structure. We need this to calculate stream
2119 + * definition offsets.
2120 + */
2121 + argsOffset = 3;
2122 + total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
2123 + /* Message args */
2124 + pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
2125 + pMsgArgs->maxMessages = msgArgs.uMaxMessages;
2126 + pMsgArgs->segid = msgArgs.uSegid;
2127 + pMsgArgs->notifyType = msgArgs.uNotifyType;
2128 + pMsgArgs->argLength = msgArgs.uArgLength;
2129 + total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
2130 + memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
2131 + total += dwLength;
2133 + if (DSP_FAILED(status))
2134 + goto func_end;
2136 + /* If node is a task node, copy task create arguments into buffer */
2137 + if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
2138 + taskArgs = pArgs->asa.taskArgs;
2139 + taskArgsOffset = total;
2140 + total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
2141 + 1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
2142 + /* Copy task arguments */
2143 + if (total < max) {
2144 + total = taskArgsOffset;
2145 + pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
2146 + total);
2147 + /*
2148 + * Get some important info about the node. Note that we
2149 + * don't just reach into the hNode struct because
2150 + * that would break the node object's abstraction.
2151 + */
2152 + GetNodeInfo(hNode, &nodeInfo);
2153 + GT_2trace(DISP_DebugMask, GT_ENTER,
2154 + "uExecutionPriority %x, nPriority %x\n",
2155 + nodeInfo.uExecutionPriority,
2156 + taskArgs.nPriority);
2157 + pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
2158 + pMoreTaskArgs->stackSize = taskArgs.uStackSize;
2159 + pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
2160 + pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
2161 + pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
2162 + pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
2163 + pMoreTaskArgs->misc = taskArgs.ulDaisArg;
2164 + pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
2165 + total +=
2166 + sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
2167 + GT_2trace(DISP_DebugMask, GT_7CLASS,
2168 + "DISP::::uDSPHeapAddr %x, "
2169 + "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
2170 + taskArgs.uHeapSize);
2171 + /* Keep track of pSIOInDef[] and pSIOOutDef[]
2172 + * positions in the buffer, since this needs to be
2173 + * filled in later. */
2174 + sioInDefOffset = total;
2175 + total += taskArgs.uNumInputs;
2176 + pdwBuf[total++] = taskArgs.uNumOutputs;
2177 + sioOutDefOffset = total;
2178 + total += taskArgs.uNumOutputs;
2179 + sioDefsOffset = total;
2180 + /* Fill SIO defs and offsets */
2181 + offset = sioDefsOffset;
2182 + for (i = 0; i < taskArgs.uNumInputs; i++) {
2183 + if (DSP_FAILED(status))
2184 + break;
2186 + pdwBuf[sioInDefOffset + i] =
2187 + (offset - argsOffset)
2188 + * (sizeof(RMS_WORD) / DSPWORDSIZE);
2189 + strmDef = taskArgs.strmInDef[i];
2190 + status = FillStreamDef(pdwBuf, &total, offset,
2191 + strmDef, max, uCharsInRMSWord);
2192 + offset = total;
2194 + for (i = 0; (i < taskArgs.uNumOutputs) &&
2195 + (DSP_SUCCEEDED(status)); i++) {
2196 + pdwBuf[sioOutDefOffset + i] =
2197 + (offset - argsOffset)
2198 + * (sizeof(RMS_WORD) / DSPWORDSIZE);
2199 + strmDef = taskArgs.strmOutDef[i];
2200 + status = FillStreamDef(pdwBuf, &total, offset,
2201 + strmDef, max, uCharsInRMSWord);
2202 + offset = total;
2204 + if (DSP_FAILED(status)) {
2205 + GT_2trace(DISP_DebugMask, GT_6CLASS,
2206 + "DISP_NodeCreate: Message"
2207 + " args to large for buffer! Message args"
2208 + " size = %d, max = %d\n", total, max);
2210 + } else {
2211 + /* Args won't fit */
2212 + status = DSP_EFAIL;
2213 + GT_2trace(DISP_DebugMask, GT_6CLASS,
2214 + "DISP_NodeCreate: Message args "
2215 + " too large for buffer! Message args size = %d"
2216 + ", max = %d\n", total, max);
2219 + if (DSP_SUCCEEDED(status)) {
2220 + ulBytes = total * sizeof(RMS_WORD);
2221 + DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
2222 + status = SendMessage(hDisp, NODE_GetTimeout(hNode),
2223 + ulBytes, pNodeEnv);
2224 + if (DSP_FAILED(status)) {
2225 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2226 + "DISP_NodeCreate failed! "
2227 + "status = 0x%x\n", status);
2228 + } else {
2229 + /*
2230 + * Message successfully received from RMS.
2231 + * Return the status of the Node's create function
2232 + * on the DSP-side
2233 + */
2234 + status = (((RMS_WORD *)(hDisp->pBuf))[0]);
2235 + if (DSP_FAILED(status)) {
2236 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2237 + "DISP_NodeCreate, "
2238 + "DSP-side Node Create failed: 0x%x\n",
2239 + status);
2244 +func_end:
2245 + return status;
2249 + * ======== DISP_NodeDelete ========
2250 + * purpose:
2251 + * Delete a node on the DSP by remotely calling the node's delete function.
2253 + */
2254 +DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
2255 + u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
2257 + u32 dwArg;
2258 + struct RMS_Command *pCommand;
2259 + DSP_STATUS status = DSP_SOK;
2260 + u32 devType;
2262 + DBC_Require(cRefs > 0);
2263 + DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
2264 + DBC_Require(hNode != NULL);
2266 + GT_5trace(DISP_DebugMask, GT_ENTER,
2267 + "DISP_NodeDelete: hDisp: 0x%xthNode: "
2268 + "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
2269 + hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
2271 + status = DEV_GetDevType(hDisp->hDevObject, &devType);
2273 + if (DSP_SUCCEEDED(status)) {
2275 + if (devType == DSP_UNIT) {
2277 + /*
2278 + * Fill in buffer to send to RMS
2279 + */
2280 + pCommand = (struct RMS_Command *)hDisp->pBuf;
2281 + pCommand->fxn = (RMS_WORD)(ulRMSFxn);
2282 + pCommand->arg1 = (RMS_WORD)nodeEnv;
2283 + pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
2284 + pCommand->data = NODE_GetType(hNode);
2286 + status = SendMessage(hDisp, NODE_GetTimeout(hNode),
2287 + sizeof(struct RMS_Command), &dwArg);
2288 + if (DSP_FAILED(status)) {
2289 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2290 + "DISP_NodeDelete failed!"
2291 + "status = 0x%x\n", status);
2292 + } else {
2293 + /*
2294 + * Message successfully received from RMS.
2295 + * Return the status of the Node's delete
2296 + * function on the DSP-side
2297 + */
2298 + status = (((RMS_WORD *)(hDisp->pBuf))[0]);
2299 + if (DSP_FAILED(status)) {
2300 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2301 + "DISP_NodeDelete, "
2302 + "DSP-side Node Delete failed: 0x%x\n",
2303 + status);
2310 + return status;
2314 + * ======== DISP_NodeRun ========
2315 + * purpose:
2316 + * Start execution of a node's execute phase, or resume execution of a node
2317 + * that has been suspended (via DISP_NodePause()) on the DSP.
2318 + */
2319 +DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
2320 + u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
2322 + u32 dwArg;
2323 + struct RMS_Command *pCommand;
2324 + DSP_STATUS status = DSP_SOK;
2325 + u32 devType;
2326 + DBC_Require(cRefs > 0);
2327 + DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
2328 + DBC_Require(hNode != NULL);
2330 + GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
2331 + 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
2332 + hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
2334 + status = DEV_GetDevType(hDisp->hDevObject, &devType);
2336 + if (DSP_SUCCEEDED(status)) {
2338 + if (devType == DSP_UNIT) {
2340 + /*
2341 + * Fill in buffer to send to RMS.
2342 + */
2343 + pCommand = (struct RMS_Command *) hDisp->pBuf;
2344 + pCommand->fxn = (RMS_WORD) (ulRMSFxn);
2345 + pCommand->arg1 = (RMS_WORD) nodeEnv;
2346 + pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
2347 + pCommand->data = NODE_GetType(hNode);
2349 + status = SendMessage(hDisp, NODE_GetTimeout(hNode),
2350 + sizeof(struct RMS_Command), &dwArg);
2351 + if (DSP_FAILED(status)) {
2352 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2353 + "DISP_NodeRun failed!"
2354 + "status = 0x%x\n", status);
2355 + } else {
2356 + /*
2357 + * Message successfully received from RMS.
2358 + * Return the status of the Node's execute
2359 + * function on the DSP-side
2360 + */
2361 + status = (((RMS_WORD *)(hDisp->pBuf))[0]);
2362 + if (DSP_FAILED(status)) {
2363 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2364 + "DISP_NodeRun, DSP-side Node "
2365 + "Execute failed: 0x%x\n",
2366 + status);
2373 + return status;
2377 + * ======== DeleteDisp ========
2378 + * purpose:
2379 + * Frees the resources allocated for the dispatcher.
2380 + */
2381 +static void DeleteDisp(struct DISP_OBJECT *hDisp)
2383 + DSP_STATUS status = DSP_SOK;
2384 + struct WMD_DRV_INTERFACE *pIntfFxns;
2386 + if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
2387 + pIntfFxns = hDisp->pIntfFxns;
2389 + /* Free Node Dispatcher resources */
2390 + if (hDisp->hChnlFromDsp) {
2391 + /* Channel close can fail only if the channel handle
2392 + * is invalid. */
2393 + status = (*pIntfFxns->pfnChnlClose)
2394 + (hDisp->hChnlFromDsp);
2395 + if (DSP_FAILED(status)) {
2396 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2397 + "DISP_Delete: Failed to "
2398 + "close channel from RMS: 0x%x\n",
2399 + status);
2402 + if (hDisp->hChnlToDsp) {
2403 + status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
2404 + if (DSP_FAILED(status)) {
2405 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2406 + "DISP_Delete: Failed to "
2407 + "close channel to RMS: 0x%x\n",
2408 + status);
2411 + if (hDisp->pBuf)
2412 + MEM_Free(hDisp->pBuf);
2414 + MEM_FreeObject(hDisp);
2419 + * ======== FillStreamDef ========
2420 + * purpose:
2421 + * Fills stream definitions.
2422 + */
2423 +static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
2424 + struct NODE_STRMDEF strmDef, u32 max,
2425 + u32 uCharsInRMSWord)
2427 + struct RMS_StrmDef *pStrmDef;
2428 + u32 total = *ptotal;
2429 + u32 uNameLen;
2430 + u32 dwLength;
2431 + DSP_STATUS status = DSP_SOK;
2433 + if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
2434 + status = DSP_EFAIL;
2435 + } else {
2436 + pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
2437 + pStrmDef->bufsize = strmDef.uBufsize;
2438 + pStrmDef->nbufs = strmDef.uNumBufs;
2439 + pStrmDef->segid = strmDef.uSegid;
2440 + pStrmDef->align = strmDef.uAlignment;
2441 + pStrmDef->timeout = strmDef.uTimeout;
2444 + if (DSP_SUCCEEDED(status)) {
2445 + /*
2446 + * Since we haven't added the device name yet, subtract
2447 + * 1 from total.
2448 + */
2449 + total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
2450 + dwLength = CSL_Strlen(strmDef.szDevice) + 1;
2452 + /* Number of RMS_WORDS needed to hold device name */
2453 + uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
2455 + if (total + uNameLen >= max) {
2456 + status = DSP_EFAIL;
2457 + } else {
2458 + /*
2459 + * Zero out last word, since the device name may not
2460 + * extend to completely fill this word.
2461 + */
2462 + pdwBuf[total + uNameLen - 1] = 0;
2463 + /** TODO USE SERVICES **/
2464 + memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
2465 + total += uNameLen;
2466 + *ptotal = total;
2470 + return status;
2474 + * ======== SendMessage ======
2475 + * Send command message to RMS, get reply from RMS.
2476 + */
2477 +static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
2478 + u32 ulBytes, u32 *pdwArg)
2480 + struct WMD_DRV_INTERFACE *pIntfFxns;
2481 + struct CHNL_OBJECT *hChnl;
2482 + u32 dwArg = 0;
2483 + u8 *pBuf;
2484 + struct CHNL_IOC chnlIOC;
2485 + DSP_STATUS status = DSP_SOK;
2487 + DBC_Require(pdwArg != NULL);
2489 + *pdwArg = (u32) NULL;
2490 + pIntfFxns = hDisp->pIntfFxns;
2491 + hChnl = hDisp->hChnlToDsp;
2492 + pBuf = hDisp->pBuf;
2494 + /* Send the command */
2495 + status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
2496 + 0L, dwArg);
2498 + if (DSP_FAILED(status)) {
2499 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2500 + "SendMessage: Channel AddIOReq to"
2501 + " RMS failed! Status = 0x%x\n", status);
2502 + goto func_cont;
2504 + status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
2505 + if (DSP_SUCCEEDED(status)) {
2506 + if (!CHNL_IsIOComplete(chnlIOC)) {
2507 + if (CHNL_IsTimedOut(chnlIOC)) {
2508 + status = DSP_ETIMEOUT;
2509 + } else {
2510 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2511 + "SendMessage failed! "
2512 + "Channel IOC status = 0x%x\n",
2513 + chnlIOC.status);
2514 + status = DSP_EFAIL;
2517 + } else {
2518 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2519 + "SendMessage: Channel GetIOC to"
2520 + " RMS failed! Status = 0x%x\n", status);
2522 +func_cont:
2523 + /* Get the reply */
2524 + if (DSP_FAILED(status))
2525 + goto func_end;
2527 + hChnl = hDisp->hChnlFromDsp;
2528 + ulBytes = REPLYSIZE;
2529 + status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
2530 + 0, 0L, dwArg);
2531 + if (DSP_FAILED(status)) {
2532 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2533 + "SendMessage: Channel AddIOReq "
2534 + "from RMS failed! Status = 0x%x\n", status);
2535 + goto func_end;
2537 + status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
2538 + if (DSP_SUCCEEDED(status)) {
2539 + if (CHNL_IsTimedOut(chnlIOC)) {
2540 + status = DSP_ETIMEOUT;
2541 + } else if (chnlIOC.cBytes < ulBytes) {
2542 + /* Did not get all of the reply from the RMS */
2543 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2544 + "SendMessage: Did not get all"
2545 + "of reply from RMS! Bytes received: %d\n",
2546 + chnlIOC.cBytes);
2547 + status = DSP_EFAIL;
2548 + } else {
2549 + if (CHNL_IsIOComplete(chnlIOC)) {
2550 + DBC_Assert(chnlIOC.pBuf == pBuf);
2551 + status = (*((RMS_WORD *)chnlIOC.pBuf));
2552 + *pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
2553 + } else {
2554 + status = DSP_EFAIL;
2557 + } else {
2558 + /* GetIOC failed */
2559 + GT_1trace(DISP_DebugMask, GT_6CLASS,
2560 + "SendMessage: Failed to get "
2561 + "reply from RMS! Status = 0x%x\n", status);
2563 +func_end:
2564 + return status;
2566 Index: lk/drivers/dsp/bridge/rmgr/drv.c
2567 ===================================================================
2568 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
2569 +++ lk/drivers/dsp/bridge/rmgr/drv.c 2008-08-18 10:38:37.000000000 +0300
2570 @@ -0,0 +1,1883 @@
2572 + * linux/drivers/dsp/bridge/rmgr/drv.c
2574 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
2576 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
2578 + * This package is free software; you can redistribute it and/or modify
2579 + * it under the terms of the GNU General Public License version 2 as
2580 + * published by the Free Software Foundation.
2582 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
2583 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
2584 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2585 + */
2589 + * ======== drv.c ========
2590 + * Description:
2591 + * DSP/BIOS Bridge resource allocation module.
2593 + * Public Functions:
2594 + * DRV_Create
2595 + * DRV_Destroy
2596 + * DRV_Exit
2597 + * DRV_GetDevObject
2598 + * DRV_GetDevExtension
2599 + * DRV_GetFirstDevObject
2600 + * DRV_GetNextDevObject
2601 + * DRV_GetNextDevExtension
2602 + * DRV_Init
2603 + * DRV_InsertDevObject
2604 + * DRV_RemoveDevObject
2605 + * DRV_RequestResources
2606 + * DRV_ReleaseResources
2608 + *! Revision History
2609 + *! ======== ========
2610 + *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
2611 + MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
2612 + *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
2613 + *! 05-Jan-2004 vp: Updated for 24xx platform
2614 + *! 21-Mar-2003 sb: Get SHM size from registry
2615 + *! 10-Feb-2003 vp: Code review updates
2616 + *! 18-Oct-2002 vp: Ported to Linux platform
2617 + *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
2618 + *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
2619 + *! RequestISAResources()
2620 + *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
2621 + *! RequestISAResources.
2622 + *! 07-Aug-2000 rr: static list of dev objects removed.
2623 + *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
2624 + *! Device extension created to hold the DevNodeString.
2625 + *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
2626 + *! Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
2627 + *! DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
2628 + *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
2629 + *! instead of MEM_Alloc.
2630 + *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
2631 + *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
2632 + *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
2633 + *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
2634 + *! struct CFG_HOSTRES Structure.
2635 + *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
2636 + *! DBC_Ensure checks for sucess and pDevice != NULL
2637 + *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
2638 + *! 09-Dec-1999 rr: windows.h included to remove warnings.
2639 + *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
2640 + *! status while making call to Reg functions.
2641 + *! 23-Nov-1999 rr: windows.h included
2642 + *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
2643 + *! fixed.
2644 + *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
2645 + *! Hardcoded bIRQRegister define removed.
2646 + *! 05-Nov-1999 rr: Added hardcoded device interrupt.
2647 + *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
2648 + *! Resource structure directly.
2649 + *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
2650 + *! dwBusType taken from the registry.Hard coded
2651 + *! registry entries removed.
2652 + *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
2653 + *! MiniDriver has been renamed to DRV_RequestResources.
2654 + *! DRV_UnRegisterMiniDriver fxn removed.
2655 + *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
2656 + *! Now it is simpler. IT stores the dev node in the
2657 + *! registry, assign resources and calls the DEV_Start.
2658 + *! 10-Sep-1999 rr: Register Minidriver modified.
2659 + *! - Resource structure follows the NT model
2660 + *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
2661 + */
2663 +/* ----------------------------------- Host OS */
2664 +#include <host_os.h>
2666 +/* ----------------------------------- DSP/BIOS Bridge */
2667 +#include <std.h>
2668 +#include <dbdefs.h>
2669 +#include <errbase.h>
2671 +/* ----------------------------------- Trace & Debug */
2672 +#include <dbc.h>
2673 +#include <gt.h>
2675 +/* ----------------------------------- OS Adaptation Layer */
2676 +#include <cfg.h>
2677 +#include <csl.h>
2678 +#include <list.h>
2679 +#include <mem.h>
2680 +#include <reg.h>
2682 +/* ----------------------------------- Others */
2683 +#include <dbreg.h>
2685 +/* ----------------------------------- This */
2686 +#include <drv.h>
2687 +#include <dev.h>
2689 +#ifndef RES_CLEANUP_DISABLE
2690 +#include <prcs.h>
2691 +#include <node.h>
2692 +#include <proc.h>
2693 +#include <strm.h>
2694 +#include <nodepriv.h>
2695 +#include <wmdchnl.h>
2696 +#endif
2698 +/* ----------------------------------- Defines, Data Structures, Typedefs */
2699 +#define SIGNATURE 0x5f52474d /* "DRV_" (in reverse) */
2701 +struct DRV_OBJECT {
2702 + u32 dwSignature;
2703 + struct LST_LIST *devList;
2704 + struct LST_LIST *devNodeString;
2705 +#ifndef RES_CLEANUP_DISABLE
2706 + struct PROCESS_CONTEXT *procCtxtList;
2707 +#endif
2711 + * This is the Device Extension. Named with the Prefix
2712 + * DRV_ since it is living in this module
2713 + */
2714 +struct DRV_EXT {
2715 + struct LST_ELEM link;
2716 + char szString[MAXREGPATHLENGTH];
2719 +/* ----------------------------------- Globals */
2720 +static s32 cRefs;
2722 +#if GT_TRACE
2723 +extern struct GT_Mask curTrace;
2724 +#endif
2726 +/* ----------------------------------- Function Prototypes */
2727 +static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
2728 +static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
2730 +#ifndef RES_CLEANUP_DISABLE
2733 +/* GPP PROCESS CLEANUP CODE */
2734 +static DSP_STATUS PrintProcessInformation(void);
2736 +extern enum NODE_STATE NODE_GetState(HANDLE hNode);
2738 +/* Get the process context list from driver object */
2740 +/* Set the Process ID */
2741 +DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
2743 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
2744 + DSP_STATUS status = DSP_SOK;
2746 + DBC_Assert(hPCtxt != NULL);
2748 + pCtxt->pid = hProcess;
2749 + return status;
2753 +/* Getting the head of the process context list */
2754 +DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
2755 + struct DRV_OBJECT *hDrvObject)
2757 + DSP_STATUS status = DSP_SOK;
2758 + struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
2760 + DBC_Assert(hDrvObject != NULL);
2761 + GT_2trace(curTrace, GT_ENTER,
2762 + "DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
2763 + ":%x", *pPctxt, pDrvObject);
2764 + *pPctxt = pDrvObject->procCtxtList;
2765 + GT_2trace(curTrace, GT_ENTER,
2766 + "DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
2767 + ":%x", *pPctxt, pDrvObject);
2768 + return status;
2773 +/* Get a particular process context based on process handle (phProcess) */
2774 +DSP_STATUS DRV_GetProcContext(u32 phProcess,
2775 + struct DRV_OBJECT *hDrvObject,
2776 + HANDLE hPCtxt, DSP_HNODE hNode,
2777 + u32 pMapAddr)
2779 + struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
2780 + DSP_STATUS status = DSP_SOK;
2781 + struct PROCESS_CONTEXT *pCtxtList = NULL;
2782 + struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
2783 + struct NODE_RES_OBJECT *pTempNode2 = NULL;
2784 + struct NODE_RES_OBJECT *pTempNode = NULL;
2785 + struct DMM_RES_OBJECT *pTempDMM2 = NULL;
2786 + struct DMM_RES_OBJECT *pTempDMM = NULL;
2787 + s32 pCtxtFound = 0;
2789 + DBC_Assert(pDrvObject != NULL);
2790 + pCtxtList = pDrvObject->procCtxtList;
2791 + GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
2792 + while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
2793 + pCtxtList = pCtxtList->next;
2794 + GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
2796 + if (pCtxtList == NULL) {
2797 + if (hNode != NULL) {
2798 + pCtxtList = pDrvObject->procCtxtList;
2799 + while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
2800 + pTempNode = pCtxtList->pNodeList;
2801 + while ((pTempNode != NULL) &&
2802 + (pTempNode->hNode != hNode)) {
2803 + pTempNode2 = pTempNode;
2804 + pTempNode = pTempNode->next;
2806 + if (pTempNode != NULL) {
2807 + pCtxtFound = 1;
2808 + status = DSP_SOK;
2809 + } else {
2810 + pCtxtList = pCtxtList->next;
2813 + } else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
2814 + pCtxtList = pDrvObject->procCtxtList;
2815 + while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
2816 + pTempDMM = pCtxtList->pDMMList;
2817 + while ((pTempDMM != NULL) &&
2818 + (pTempDMM->ulDSPAddr != pMapAddr)) {
2819 + pTempDMM2 = pTempDMM;
2820 + pTempDMM = pTempDMM->next;
2822 + if (pTempDMM != NULL) {
2823 + pCtxtFound = 1;
2824 + status = DSP_SOK;
2825 + } else {
2826 + pCtxtList = pCtxtList->next;
2829 + if (pCtxtList == NULL)
2830 + status = DSP_ENOTFOUND;
2833 + } else{
2834 + status = DSP_SOK;
2836 + GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
2837 + *pCtxt = pCtxtList;
2838 + return status;
2842 +/* Add a new process context to process context list */
2843 +DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
2845 + struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
2846 + DSP_STATUS status = DSP_SOK;
2847 + struct PROCESS_CONTEXT *pCtxtList = NULL;
2848 + struct DRV_OBJECT *hDRVObject;
2850 + GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
2851 + status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
2852 + DBC_Assert(hDRVObject != NULL);
2853 + *pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
2854 + GT_0trace(curTrace, GT_ENTER,
2855 + "\n In DRV_InsertProcContext Calling "
2856 + "DRV_GetProcCtxtList\n");
2857 + DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
2858 + GT_0trace(curTrace, GT_ENTER,
2859 + "\n In DRV_InsertProcContext After Calling "
2860 + "DRV_GetProcCtxtList\n");
2861 + if (pCtxtList != NULL) {
2862 + GT_0trace(curTrace, GT_ENTER,
2863 + "\n In DRV_InsertProcContext and pCtxt is "
2864 + "not Null\n");
2865 + while (pCtxtList->next != NULL)
2866 + pCtxtList = pCtxtList->next;
2868 + pCtxtList->next = *pCtxt;
2869 + } else {
2870 + GT_0trace(curTrace, GT_ENTER,
2871 + "\n In DRV_InsertProcContext and "
2872 + "pCtxt is Null\n");
2873 + hDRVObject->procCtxtList = *pCtxt;
2875 + return status;
2878 +/* Delete a process context from process resource context list */
2879 +DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
2880 + HANDLE hPCtxt, HANDLE hProcess)
2882 + DSP_STATUS status = DSP_SOK;
2883 + struct PROCESS_CONTEXT *pCtxt2 = NULL;
2884 + struct PROCESS_CONTEXT *pTmp = NULL;
2885 + struct PROCESS_CONTEXT *pCtxtList = NULL;
2887 + DBC_Assert(hDRVObject != NULL);
2888 + DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
2890 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
2891 + DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
2892 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
2893 + pTmp = pCtxtList;
2894 + while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
2895 + pTmp = pCtxtList;
2896 + pCtxtList = pCtxtList->next;
2897 + GT_0trace(curTrace, GT_ENTER,
2898 + "DRV_RemoveProcContext: 2");
2900 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
2901 + if (hDRVObject->procCtxtList == pCtxt2)
2902 + hDRVObject->procCtxtList = pCtxt2->next;
2904 + if (pCtxtList == NULL)
2905 + return DSP_ENOTFOUND;
2906 + else if (pTmp->next != NULL)
2907 + pTmp->next = pTmp->next->next;
2909 + MEM_Free(pCtxt2);
2910 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
2912 + return status;
2915 +/* Update the state of process context */
2916 +DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
2918 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
2919 + DSP_STATUS status1 = DSP_SOK;
2920 + if (pCtxt != NULL) {
2921 + pCtxt->resState = status;
2922 + } else {
2923 + GT_0trace(curTrace, GT_ENTER,
2924 + "DRV_ProcUpdatestate: Failed to update "
2925 + "process state");
2927 + return status1;
2930 +/* Allocate and add a node resource element
2931 +* This function is called from .Node_Allocate. */
2932 +DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
2933 + HANDLE hPCtxt)
2935 + struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
2936 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
2937 + DSP_STATUS status = DSP_SOK;
2938 + struct NODE_RES_OBJECT *pTempNodeRes = NULL;
2939 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
2940 + *pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
2941 + (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
2942 + DBC_Assert(hPCtxt != NULL);
2943 + if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
2944 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
2945 + status = DSP_EHANDLE;
2947 + if (DSP_SUCCEEDED(status)) {
2948 + (*pNodeRes)->hNode = hNode;
2949 + if (pCtxt->pNodeList != NULL) {
2950 + pTempNodeRes = pCtxt->pNodeList;
2951 + while (pTempNodeRes->next != NULL)
2952 + pTempNodeRes = pTempNodeRes->next;
2954 + pTempNodeRes->next = *pNodeRes;
2955 + GT_0trace(curTrace, GT_ENTER,
2956 + "DRV_InsertNodeResElement: 2");
2957 + } else {
2958 + pCtxt->pNodeList = *pNodeRes;
2959 + GT_0trace(curTrace, GT_ENTER,
2960 + "DRV_InsertNodeResElement: 3");
2963 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
2964 + return status;
2967 +/* Release all Node resources and its context
2968 +* This is called from .Node_Delete. */
2969 +DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
2971 + struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
2972 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
2973 + DSP_STATUS status = DSP_SOK;
2974 + struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
2975 + struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
2977 + DBC_Assert(hPCtxt != NULL);
2978 + GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
2979 + while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
2980 + pTempNode2 = pTempNode;
2981 + pTempNode = pTempNode->next;
2983 + if (pCtxt->pNodeList == pNodeRes)
2984 + pCtxt->pNodeList = pNodeRes->next;
2986 + if (pTempNode == NULL)
2987 + return DSP_ENOTFOUND;
2988 + else if (pTempNode2->next != NULL)
2989 + pTempNode2->next = pTempNode2->next->next;
2991 + MEM_Free(pTempNode);
2992 + return status;
2995 +/* Actual Node De-Allocation */
2996 +DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
2998 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
2999 + DSP_STATUS status = DSP_SOK;
3000 + struct NODE_RES_OBJECT *pNodeList = NULL;
3001 + struct NODE_RES_OBJECT *pNodeRes = NULL;
3003 + DBC_Assert(hPCtxt != NULL);
3004 + pNodeList = pCtxt->pNodeList;
3005 + while (pNodeList != NULL) {
3006 + GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
3007 + pNodeRes = pNodeList;
3008 + pNodeList = pNodeList->next;
3009 + if (pNodeRes->nodeAllocated) {
3010 + if (NODE_GetState(pNodeRes->hNode) &
3011 + (NODE_ALLOCATED | NODE_CREATED |
3012 + NODE_RUNNING | NODE_PAUSED/*| NODE_TERMINATING */)) {
3013 + GT_1trace(curTrace, GT_5CLASS,
3014 + "Calling Node_Terminate for Node:"
3015 + " 0x%x\n", pNodeRes->hNode);
3016 + status = NODE_Terminate
3017 + (pNodeRes->hNode, &status);
3018 + GT_1trace(curTrace, GT_5CLASS,
3019 + "Calling Node_Delete for Node:"
3020 + " 0x%x\n", pNodeRes->hNode);
3021 + status = NODE_Delete(pNodeRes->hNode);
3022 + GT_1trace(curTrace, GT_5CLASS,
3023 + "the status after the NodeDelete %x\n",
3024 + status);
3025 + } else /*if (NODE_GetState(pNodeRes->hNode)
3026 + == NODE_DONE)*/ {
3027 + status = NODE_Delete(pNodeRes->hNode);
3029 + pNodeRes->nodeAllocated = 0;
3032 + return status;
3035 +/* Allocate the DMM resource element
3036 +* This is called from Proc_Map. after the actual resource is allocated */
3037 +DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
3039 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3040 + struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
3041 + DSP_STATUS status = DSP_SOK;
3042 + struct DMM_RES_OBJECT *pTempDMMRes = NULL;
3044 + *pDMMRes = (struct DMM_RES_OBJECT *)
3045 + MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
3046 + DBC_Assert(hPCtxt != NULL);
3047 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
3048 + if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
3049 + GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
3050 + status = DSP_EHANDLE;
3052 + if (DSP_SUCCEEDED(status)) {
3053 + if (pCtxt->pDMMList != NULL) {
3054 + GT_0trace(curTrace, GT_5CLASS,
3055 + "DRV_InsertDMMResElement: 3");
3056 + pTempDMMRes = pCtxt->pDMMList;
3057 + while (pTempDMMRes->next != NULL)
3058 + pTempDMMRes = pTempDMMRes->next;
3060 + pTempDMMRes->next = *pDMMRes;
3061 + } else {
3062 + pCtxt->pDMMList = *pDMMRes;
3063 + GT_0trace(curTrace, GT_5CLASS,
3064 + "DRV_InsertDMMResElement: 4");
3067 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
3068 + return status;
3073 +/* Release DMM resource element context
3074 +* This is called from Proc_UnMap. after the actual resource is freed */
3075 +DSP_STATUS DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
3077 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3078 + struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
3079 + DSP_STATUS status = DSP_SOK;
3080 + struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
3081 + struct DMM_RES_OBJECT *pTempDMMRes = NULL;
3083 + DBC_Assert(hPCtxt != NULL);
3084 + pTempDMMRes2 = pCtxt->pDMMList;
3085 + pTempDMMRes = pCtxt->pDMMList;
3086 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
3087 + while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
3088 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
3089 + pTempDMMRes2 = pTempDMMRes;
3090 + pTempDMMRes = pTempDMMRes->next;
3092 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
3093 + if (pCtxt->pDMMList == pTempDMMRes)
3094 + pCtxt->pDMMList = pTempDMMRes->next;
3096 + if (pTempDMMRes == NULL)
3097 + return DSP_ENOTFOUND;
3098 + else if (pTempDMMRes2->next != NULL)
3099 + pTempDMMRes2->next = pTempDMMRes2->next->next;
3101 + MEM_Free(pDMMRes);
3102 + GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
3103 + return status;
3108 +/* Update DMM resource status */
3109 +DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
3110 + u32 pReqAddr, u32 pMapAddr,
3111 + HANDLE hProcessor)
3113 + struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
3114 + DSP_STATUS status = DSP_SOK;
3116 + DBC_Assert(hDMMRes != NULL);
3117 + pDMMRes->ulMpuAddr = pMpuAddr;
3118 + pDMMRes->ulDSPAddr = pMapAddr;
3119 + pDMMRes->ulDSPResAddr = pReqAddr;
3120 + pDMMRes->dmmSize = ulSize;
3121 + pDMMRes->hProcessor = hProcessor;
3122 + pDMMRes->dmmAllocated = 1;
3124 + return status;
3127 +/* Actual DMM De-Allocation */
3128 +DSP_STATUS DRV_ProcFreeDMMRes(HANDLE hPCtxt)
3130 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3131 + DSP_STATUS status = DSP_SOK;
3132 + struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
3133 + struct DMM_RES_OBJECT *pDMMRes = NULL;
3135 + DBC_Assert(hPCtxt != NULL);
3136 + GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
3137 + while (pDMMList != NULL) {
3138 + pDMMRes = pDMMList;
3139 + pDMMList = pDMMList->next;
3140 + if (pDMMRes->dmmAllocated) {
3141 + status = PROC_UnMap(pDMMRes->hProcessor,
3142 + (void *)pDMMRes->ulDSPResAddr);
3143 + status = PROC_UnReserveMemory(pDMMRes->hProcessor,
3144 + (void *)pDMMRes->ulDSPResAddr);
3145 + pDMMRes->dmmAllocated = 0;
3148 + return status;
3152 +/* Release all DMM resources and its context
3153 +* This is called from .bridge_release. */
3154 +DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
3156 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3157 + DSP_STATUS status = DSP_SOK;
3158 + struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
3159 + struct DMM_RES_OBJECT *pTempDMMRes = NULL;
3161 + DBC_Assert(pCtxt != NULL);
3162 + DRV_ProcFreeDMMRes(pCtxt);
3163 + pTempDMMRes = pCtxt->pDMMList;
3164 + while (pTempDMMRes != NULL) {
3165 + pTempDMMRes2 = pTempDMMRes;
3166 + pTempDMMRes = pTempDMMRes->next;
3167 + MEM_Free(pTempDMMRes2);
3169 + pCtxt->pDMMList = NULL;
3170 + return status;
3173 +DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
3175 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3176 + struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
3177 + DSP_STATUS status = DSP_SOK;
3178 + struct DMM_RES_OBJECT *pTempDMM2 = NULL;
3179 + struct DMM_RES_OBJECT *pTempDMM = NULL;
3181 + DBC_Assert(hPCtxt != NULL);
3182 + pTempDMM = pCtxt->pDMMList;
3183 + while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
3184 + GT_3trace(curTrace, GT_ENTER,
3185 + "DRV_GetDMMResElement: 2 pTempDMM:%x "
3186 + "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
3187 + pTempDMM->ulDSPAddr, pMapAddr);
3188 + pTempDMM2 = pTempDMM;
3189 + pTempDMM = pTempDMM->next;
3191 + if (pTempDMM != NULL) {
3192 + GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
3193 + *pDMMRes = pTempDMM;
3194 + } else {
3195 + status = DSP_ENOTFOUND;
3196 + } GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
3197 + return status;
3200 +/* Update Node allocation status */
3201 +void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
3203 + struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
3204 + DBC_Assert(hNodeRes != NULL);
3205 + pNodeRes->nodeAllocated = status;
3208 +/* Update Node Heap status */
3209 +void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
3211 + struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
3212 + DBC_Assert(hNodeRes != NULL);
3213 + pNodeRes->heapAllocated = status;
3216 +/* Release all Node resources and its context
3217 +* This is called from .bridge_release.
3219 +DSP_STATUS DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
3221 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3222 + DSP_STATUS status = DSP_SOK;
3223 + struct NODE_RES_OBJECT *pTempNode2 = NULL;
3224 + struct NODE_RES_OBJECT *pTempNode = NULL;
3226 + DBC_Assert(hPCtxt != NULL);
3227 + DRV_ProcFreeNodeRes(pCtxt);
3228 + pTempNode = pCtxt->pNodeList;
3229 + while (pTempNode != NULL) {
3230 + pTempNode2 = pTempNode;
3231 + pTempNode = pTempNode->next;
3232 + MEM_Free(pTempNode2);
3234 + pCtxt->pNodeList = NULL;
3235 + return status;
3238 +/* Getting the node resource element */
3240 +DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
3242 + struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
3243 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3244 + DSP_STATUS status = DSP_SOK;
3245 + struct NODE_RES_OBJECT *pTempNode2 = NULL;
3246 + struct NODE_RES_OBJECT *pTempNode = NULL;
3248 + DBC_Assert(hPCtxt != NULL);
3249 + pTempNode = pCtxt->pNodeList;
3250 + GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
3251 + while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
3252 + pTempNode2 = pTempNode;
3253 + pTempNode = pTempNode->next;
3255 + if (pTempNode != NULL)
3256 + *nodeRes = pTempNode;
3257 + else
3258 + status = DSP_ENOTFOUND;
3260 + return status;
3265 +/* Allocate the STRM resource element
3266 +* This is called after the actual resource is allocated
3268 +DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
3269 + HANDLE hPCtxt)
3271 + struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
3272 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3273 + DSP_STATUS status = DSP_SOK;
3274 + struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
3275 + DBC_Assert(hPCtxt != NULL);
3277 + *pSTRMRes = (struct STRM_RES_OBJECT *)
3278 + MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
3279 + if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
3280 + GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
3281 + status = DSP_EHANDLE;
3283 + if (DSP_SUCCEEDED(status)) {
3284 + (*pSTRMRes)->hStream = hStreamHandle;
3285 + if (pCtxt->pSTRMList != NULL) {
3286 + GT_0trace(curTrace, GT_ENTER,
3287 + "DRV_InsertiSTRMResElement: 3");
3288 + pTempSTRMRes = pCtxt->pSTRMList;
3289 + while (pTempSTRMRes->next != NULL)
3290 + pTempSTRMRes = pTempSTRMRes->next;
3292 + pTempSTRMRes->next = *pSTRMRes;
3293 + } else {
3294 + pCtxt->pSTRMList = *pSTRMRes;
3295 + GT_0trace(curTrace, GT_ENTER,
3296 + "DRV_InsertSTRMResElement: 4");
3299 + return status;
3304 +/* Release Stream resource element context
3305 +* This function called after the actual resource is freed
3307 +DSP_STATUS DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
3309 + struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
3310 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3311 + DSP_STATUS status = DSP_SOK;
3312 + struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
3313 + struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
3315 + DBC_Assert(hPCtxt != NULL);
3316 + while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
3317 + pTempSTRMRes2 = pTempSTRMRes;
3318 + pTempSTRMRes = pTempSTRMRes->next;
3320 + if (pCtxt->pSTRMList == pTempSTRMRes)
3321 + pCtxt->pSTRMList = pTempSTRMRes->next;
3323 + if (pTempSTRMRes == NULL)
3324 + status = DSP_ENOTFOUND;
3325 + else if (pTempSTRMRes2->next != NULL)
3326 + pTempSTRMRes2->next = pTempSTRMRes2->next->next;
3328 + MEM_Free(pSTRMRes);
3329 + return status;
3333 +/* Actual Stream De-Allocation */
3334 +DSP_STATUS DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
3336 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3337 + DSP_STATUS status = DSP_SOK;
3338 + DSP_STATUS status1 = DSP_SOK;
3339 + u8 **apBuffer = NULL;
3340 + struct STRM_RES_OBJECT *pSTRMList = NULL;
3341 + struct STRM_RES_OBJECT *pSTRMRes = NULL;
3342 + u8 *pBufPtr;
3343 + u32 ulBytes;
3344 + u32 dwArg;
3345 + s32 ulBufSize;
3348 + DBC_Assert(hPCtxt != NULL);
3349 + pSTRMList = pCtxt->pSTRMList;
3350 + while (pSTRMList != NULL) {
3351 + pSTRMRes = pSTRMList;
3352 + pSTRMList = pSTRMList->next;
3353 + if (pSTRMRes->uNumBufs != 0) {
3354 + apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
3355 + sizeof(u8 *)), MEM_NONPAGED);
3356 + status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
3357 + pSTRMRes->uNumBufs);
3358 + MEM_Free(apBuffer);
3360 + status = STRM_Close(pSTRMRes->hStream);
3361 + if (DSP_FAILED(status)) {
3362 + if (status == DSP_EPENDING) {
3363 + status = STRM_Reclaim(pSTRMRes->hStream,
3364 + &pBufPtr, &ulBytes,
3365 + (u32 *)&ulBufSize, &dwArg);
3366 + if (DSP_SUCCEEDED(status))
3367 + status = STRM_Close(pSTRMRes->hStream);
3372 + return status1;
3375 +/* Release all Stream resources and its context
3376 +* This is called from .bridge_release.
3378 +DSP_STATUS DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
3380 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3381 + DSP_STATUS status = DSP_SOK;
3382 + struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
3383 + struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
3385 + DBC_Assert(hPCtxt != NULL);
3386 + DRV_ProcFreeSTRMRes(pCtxt);
3387 + pTempSTRMRes = pCtxt->pSTRMList;
3388 + while (pTempSTRMRes != NULL) {
3389 + pTempSTRMRes2 = pTempSTRMRes;
3390 + pTempSTRMRes = pTempSTRMRes->next;
3391 + MEM_Free(pTempSTRMRes2);
3393 + pCtxt->pSTRMList = NULL;
3394 + return status;
3398 +/* Getting the stream resource element */
3399 +DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
3401 + struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
3402 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
3403 + DSP_STATUS status = DSP_SOK;
3404 + struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
3405 + struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
3407 + DBC_Assert(hPCtxt != NULL);
3408 + while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
3409 + GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
3410 + pTempSTRM2 = pTempSTRM;
3411 + pTempSTRM = pTempSTRM->next;
3413 + if (pTempSTRM != NULL) {
3414 + GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
3415 + *STRMRes = pTempSTRM;
3416 + } else {
3417 + GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
3418 + status = DSP_ENOTFOUND;
3420 + GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
3421 + return status;
3424 +/* Updating the stream resource element */
3425 +DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
3427 + DSP_STATUS status = DSP_SOK;
3428 + struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
3430 + DBC_Assert(hPCtxt != NULL);
3431 + (*STRMRes)->uNumBufs = uNumBufs;
3432 + return status;
3434 +/* Displaying the resources allocated by a process */
3435 +DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
3437 + struct PROCESS_CONTEXT *pCtxt = NULL;
3438 + struct NODE_RES_OBJECT *pNodeRes = NULL;
3439 + struct DMM_RES_OBJECT *pDMMRes = NULL;
3440 + struct STRM_RES_OBJECT *pSTRMRes = NULL;
3441 + struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
3442 + u32 tempCount = 1;
3443 + HANDLE hDrvObject = NULL;
3444 + void *pBuf = pBuf1;
3445 + u8 pTempBuf[250];
3446 + u32 tempStrLen = 0, tempStrLen2 = 0;
3447 + DSP_STATUS status = DSP_SOK;
3449 + CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
3450 + DRV_GetProcCtxtList(&pCtxt, hDrvObject);
3451 + GT_0trace(curTrace, GT_ENTER, "*********************"
3452 + "DRV_ProcDisplayResourceInfo:*\n");
3453 + while (pCtxt != NULL) {
3454 + tempStrLen2 = sprintf((char *)pTempBuf,
3455 + "-------------------------------------"
3456 + "-----------------------------------\n");
3457 + tempStrLen2 += 2;
3458 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3459 + tempStrLen += tempStrLen2;
3460 + if (pCtxt->resState == PROC_RES_ALLOCATED) {
3461 + tempStrLen2 = sprintf((char *)pTempBuf,
3462 + "GPP Process Resource State: "
3463 + "pCtxt->resState = PROC_RES_ALLOCATED, "
3464 + " Process ID: %d\n", pCtxt->pid);
3465 + tempStrLen2 += 2;
3466 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3467 + tempStrLen += tempStrLen2;
3468 + } else {
3469 + tempStrLen2 = sprintf((char *)pTempBuf,
3470 + "GPP Resource State: pCtxt->resState"
3471 + " = PROC_RES_DEALLOCATED, Process ID:%d\n",
3472 + pCtxt->pid);
3473 + tempStrLen2 += 2;
3474 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3475 + tempStrLen += tempStrLen2;
3477 + pNodeRes = pCtxt->pNodeList;
3478 + tempCount = 1;
3479 + while (pNodeRes != NULL) {
3480 + GT_2trace(curTrace, GT_ENTER,
3481 + "DRV_ProcDisplayResourceInfo: #:%d "
3482 + "pCtxt->pNodeList->hNode:%x\n",
3483 + tempCount, pNodeRes->hNode);
3484 + tempStrLen2 = sprintf((char *)pTempBuf,
3485 + "Node Resource Information: Node #"
3486 + " %d Node Handle hNode:0X%x\n",
3487 + tempCount, (u32)pNodeRes->hNode);
3488 + pNodeRes = pNodeRes->next;
3489 + tempStrLen2 += 2;
3490 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3491 + tempStrLen += tempStrLen2;
3492 + tempCount++;
3494 + tempCount = 1;
3495 + pDSPHEAPRes = pCtxt->pDSPHEAPList;
3496 + while (pDSPHEAPRes != NULL) {
3497 + GT_2trace(curTrace, GT_ENTER,
3498 + "DRV_ProcDisplayResourceInfo: #:%d "
3499 + "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
3500 + tempCount, pDSPHEAPRes->ulMpuAddr);
3501 + tempStrLen2 = sprintf((char *)pTempBuf,
3502 + "DSP Heap Resource Info: HEAP # %d"
3503 + " Mapped GPP Address: 0x%x, size: 0x%x\n",
3504 + tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
3505 + (u32)pDSPHEAPRes->heapSize);
3506 + pDSPHEAPRes = pDSPHEAPRes->next;
3507 + tempStrLen2 += 2;
3508 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3509 + tempStrLen += tempStrLen2;
3510 + tempCount++;
3512 + tempCount = 1;
3513 + pDMMRes = pCtxt->pDMMList;
3514 + while (pDMMRes != NULL) {
3515 + GT_2trace(curTrace, GT_ENTER,
3516 + "DRV_ProcDisplayResourceInfo: #:%d "
3517 + " pCtxt->pDMMList->ulMpuAddr:%x\n",
3518 + tempCount,
3519 + pDMMRes->ulMpuAddr);
3520 + tempStrLen2 = sprintf((char *)pTempBuf,
3521 + "DMM Resource Info: DMM # %d Mapped"
3522 + " GPP Address: 0x%x, size: 0x%x\n",
3523 + tempCount, (u32)pDMMRes->ulMpuAddr,
3524 + (u32)pDMMRes->dmmSize);
3525 + pDMMRes = pDMMRes->next;
3526 + tempStrLen2 += 2;
3527 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3528 + tempStrLen += tempStrLen2;
3529 + tempCount++;
3531 + tempCount = 1;
3532 + pSTRMRes = pCtxt->pSTRMList;
3533 + while (pSTRMRes != NULL) {
3534 + GT_2trace(curTrace, GT_ENTER,
3535 + "DRV_ProcDisplayResourceInfo: #:%d "
3536 + "pCtxt->pSTRMList->hStream:%x\n", tempCount,
3537 + pSTRMRes->hStream);
3538 + tempStrLen2 = sprintf((char *)pTempBuf,
3539 + "Stream Resource info: STRM # %d "
3540 + "Stream Handle: 0x%x \n",
3541 + tempCount, (u32)pSTRMRes->hStream);
3542 + pSTRMRes = pSTRMRes->next;
3543 + tempStrLen2 += 2;
3544 + memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
3545 + tempStrLen += tempStrLen2;
3546 + tempCount++;
3548 + pCtxt = pCtxt->next;
3550 + *pSize = tempStrLen;
3551 + status = PrintProcessInformation();
3552 + GT_0trace(curTrace, GT_ENTER, "*********************"
3553 + "DRV_ProcDisplayResourceInfo:**\n");
3554 + return status;
3558 + * ======== PrintProcessInformation ========
3559 + * Purpose:
3560 + * This function prints the Process's information stored in
3561 + * the process context list. Some of the information that
3562 + * it displays is Process's state, Node, Stream, DMM, and
3563 + * Heap information.
3564 + */
3565 +static DSP_STATUS PrintProcessInformation(void)
3567 + struct DRV_OBJECT *hDrvObject = NULL;
3568 + struct PROCESS_CONTEXT *pCtxtList = NULL;
3569 + struct NODE_RES_OBJECT *pNodeRes = NULL;
3570 + struct DMM_RES_OBJECT *pDMMRes = NULL;
3571 + struct STRM_RES_OBJECT *pSTRMRes = NULL;
3572 + struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
3573 + DSP_STATUS status = DSP_SOK;
3574 + u32 tempCount;
3575 + u32 procID;
3577 + /* Get the Process context list */
3578 + CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
3579 + DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
3580 + GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
3581 + " for DSP bridge ##\n");
3582 + GT_0trace(curTrace, GT_4CLASS, " \n ###The processes"
3583 + " information is as follows ### \n") ;
3584 + GT_0trace(curTrace, GT_4CLASS, " ====================="
3585 + "============ \n");
3586 + /* Go through the entries in the Process context list */
3587 + while (pCtxtList != NULL) {
3588 + GT_1trace(curTrace, GT_4CLASS, "\nThe process"
3589 + " id is %d\n", pCtxtList->pid);
3590 + GT_0trace(curTrace, GT_4CLASS, " -------------------"
3591 + "---------\n");
3592 + if (pCtxtList->resState == PROC_RES_ALLOCATED) {
3593 + GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
3594 + " is in Allocated state\n");
3595 + } else {
3596 + GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
3597 + " is in DeAllocated state\n");
3599 + GT_1trace(curTrace, GT_4CLASS, "\nThe hProcessor"
3600 + " handle is: 0X%x\n",
3601 + (u32)pCtxtList->hProcessor);
3602 + if (pCtxtList->hProcessor != NULL) {
3603 + PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
3604 + if (procID == DSP_UNIT) {
3605 + GT_0trace(curTrace, GT_4CLASS,
3606 + "\nProcess connected to"
3607 + " DSP Processor\n");
3608 + } else if (procID == IVA_UNIT) {
3609 + GT_0trace(curTrace, GT_4CLASS,
3610 + "\nProcess connected to"
3611 + " IVA Processor\n");
3612 + } else {
3613 + GT_0trace(curTrace, GT_7CLASS,
3614 + "\n***ERROR:Invalid Processor Id***\n");
3617 + pNodeRes = pCtxtList->pNodeList;
3618 + tempCount = 1;
3619 + while (pNodeRes != NULL) {
3620 + if (tempCount == 1)
3621 + GT_0trace(curTrace, GT_4CLASS,
3622 + "\n***The Nodes allocated by"
3623 + " this Process are***\n");
3624 + GT_2trace(curTrace, GT_4CLASS,
3625 + "Node # %d Node Handle hNode:0x%x\n",
3626 + tempCount, (u32)pNodeRes->hNode);
3627 + pNodeRes = pNodeRes->next;
3628 + tempCount++;
3630 + if (tempCount == 1)
3631 + GT_0trace(curTrace, GT_4CLASS,
3632 + "\n ***There are no Nodes"
3633 + " allocated by this Process***\n");
3634 + tempCount = 1;
3635 + pDSPHEAPRes = pCtxtList->pDSPHEAPList;
3636 + while (pDSPHEAPRes != NULL) {
3637 + if (tempCount == 1)
3638 + GT_0trace(curTrace, GT_4CLASS,
3639 + "\n***The Heaps allocated by"
3640 + " this Process are***\n");
3641 + GT_3trace(curTrace, GT_4CLASS,
3642 + "DSP Heap Resource Info: HEAP # %d "
3643 + "Mapped GPP Address:0x%x, Size: 0x%lx\n",
3644 + tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
3645 + pDSPHEAPRes->heapSize);
3646 + pDSPHEAPRes = pDSPHEAPRes->next;
3647 + tempCount++;
3649 + if (tempCount == 1)
3650 + GT_0trace(curTrace, GT_4CLASS,
3651 + "\n ***There are no Heaps allocated"
3652 + " by this Process***\n");
3653 + tempCount = 1;
3654 + pDMMRes = pCtxtList->pDMMList;
3655 + while (pDMMRes != NULL) {
3656 + if (tempCount == 1)
3657 + GT_0trace(curTrace, GT_4CLASS,
3658 + "\n ***The DMM resources allocated by"
3659 + " this Process are***\n");
3660 + GT_3trace(curTrace, GT_4CLASS,
3661 + "DMM Resource Info: DMM # %d "
3662 + "Mapped GPP Address:0X%lx, Size: 0X%lx\n",
3663 + tempCount, pDMMRes->ulMpuAddr,
3664 + pDMMRes->dmmSize);
3665 + pDMMRes = pDMMRes->next;
3666 + tempCount++;
3668 + if (tempCount == 1)
3669 + GT_0trace(curTrace, GT_4CLASS,
3670 + "\n ***There are no DMM resources"
3671 + " allocated by this Process***\n");
3672 + tempCount = 1;
3673 + pSTRMRes = pCtxtList->pSTRMList;
3674 + while (pSTRMRes != NULL) {
3675 + if (tempCount == 1)
3676 + GT_0trace(curTrace, GT_4CLASS,
3677 + "\n***The Stream resources allocated by"
3678 + " this Process are***\n");
3679 + GT_2trace(curTrace, GT_4CLASS,
3680 + "Stream Resource info: STRM # %d"
3681 + "Stream Handle:0X%x\n", tempCount,
3682 + (u32)pSTRMRes->hStream);
3683 + pSTRMRes = pSTRMRes->next;
3684 + tempCount++;
3686 + if (tempCount == 1)
3687 + GT_0trace(curTrace, GT_4CLASS,
3688 + "\n ***There are no Stream resources"
3689 + "allocated by this Process***\n");
3690 + pCtxtList = pCtxtList->next;
3692 + return status;
3695 +/* GPP PROCESS CLEANUP CODE END */
3696 +#endif
3699 + * ======== = DRV_Create ======== =
3700 + * Purpose:
3701 + * DRV Object gets created only once during Driver Loading.
3702 + */
3703 +DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
3705 + DSP_STATUS status = DSP_SOK;
3706 + struct DRV_OBJECT *pDRVObject = NULL;
3708 + DBC_Require(phDRVObject != NULL);
3709 + DBC_Require(cRefs > 0);
3710 + GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
3711 + " phDRVObject 0x%x\n", phDRVObject);
3712 + MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
3713 + if (pDRVObject) {
3714 + /* Create and Initialize List of device objects */
3715 + pDRVObject->devList = LST_Create();
3716 + if (pDRVObject->devList) {
3717 + /* Create and Initialize List of device Extension */
3718 + pDRVObject->devNodeString = LST_Create();
3719 + if (!(pDRVObject->devNodeString)) {
3720 + status = DSP_EFAIL;
3721 + GT_0trace(curTrace, GT_7CLASS,
3722 + "Failed to Create DRV_EXT list ");
3723 + MEM_FreeObject(pDRVObject);
3725 + } else {
3726 + status = DSP_EFAIL;
3727 + GT_0trace(curTrace, GT_7CLASS,
3728 + "Failed to Create Dev List ");
3729 + MEM_FreeObject(pDRVObject);
3731 + } else {
3732 + status = DSP_EFAIL;
3733 + GT_0trace(curTrace, GT_7CLASS,
3734 + "Failed to Allocate Memory for DRV Obj");
3736 + if (DSP_SUCCEEDED(status)) {
3737 + /* Store the DRV Object in the Registry */
3738 + if (DSP_SUCCEEDED
3739 + (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
3740 + GT_1trace(curTrace, GT_1CLASS,
3741 + "DRV Obj Created pDrvObject 0x%x\n ",
3742 + pDRVObject);
3743 + *phDRVObject = pDRVObject;
3744 + } else {
3745 + /* Free the DRV Object */
3746 + status = DSP_EFAIL;
3747 + MEM_Free(pDRVObject);
3748 + GT_0trace(curTrace, GT_7CLASS,
3749 + "Failed to update the Registry with "
3750 + "DRV Object ");
3753 + GT_2trace(curTrace, GT_ENTER,
3754 + "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
3755 + "0x%x\n", phDRVObject, status);
3756 + DBC_Ensure(DSP_FAILED(status) ||
3757 + MEM_IsValidHandle(pDRVObject, SIGNATURE));
3758 + return status;
3762 + * ======== DRV_Exit ========
3763 + * Purpose:
3764 + * Discontinue usage of the DRV module.
3765 + */
3766 +void DRV_Exit(void)
3768 + DBC_Require(cRefs > 0);
3770 + GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
3772 + cRefs--;
3774 + DBC_Ensure(cRefs >= 0);
3778 + * ======== = DRV_Destroy ======== =
3779 + * purpose:
3780 + * Invoked during bridge de-initialization
3781 + */
3782 +DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
3784 + DSP_STATUS status = DSP_SOK;
3785 + struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
3787 + DBC_Require(cRefs > 0);
3788 + DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
3790 + GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
3791 + " hDRVObject 0x%x\n", hDRVObject);
3792 + /*
3793 + * Delete the List if it exists.Should not come here
3794 + * as the DRV_RemoveDevObject and the Last DRV_RequestResources
3795 + * removes the list if the lists are empty.
3796 + */
3797 + if (pDRVObject->devList) {
3798 + /* Could assert if the list is not empty */
3799 + LST_Delete(pDRVObject->devList);
3801 + if (pDRVObject->devNodeString) {
3802 + /* Could assert if the list is not empty */
3803 + LST_Delete(pDRVObject->devNodeString);
3805 + MEM_FreeObject(pDRVObject);
3806 + /* Update the DRV Object in Registry to be 0 */
3807 + (void)CFG_SetObject(0, REG_DRV_OBJECT);
3808 + GT_2trace(curTrace, GT_ENTER,
3809 + "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
3810 + "0x%x\n", hDRVObject, status);
3811 + DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
3812 + return status;
3816 + * ======== DRV_GetDevObject ========
3817 + * Purpose:
3818 + * Given a index, returns a handle to DevObject from the list.
3819 + */
3820 +DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
3821 + struct DEV_OBJECT **phDevObject)
3823 + DSP_STATUS status = DSP_SOK;
3824 +#if GT_TRACE /* pDrvObject is used only for Assertions and debug messages.*/
3825 + struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
3826 +#endif
3827 + struct DEV_OBJECT *pDevObject;
3828 + u32 i;
3829 + DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
3830 + DBC_Require(phDevObject != NULL);
3831 + DBC_Require(uIndex >= 0);
3832 + DBC_Require(cRefs > 0);
3833 + DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
3834 + GT_3trace(curTrace, GT_ENTER,
3835 + "Entered DRV_GetDevObject, args:\n\tuIndex: "
3836 + "0x%x\n\thDrvObject: 0x%x\n\tphDevObject: 0x%x\n",
3837 + uIndex, hDrvObject, phDevObject);
3838 + pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
3839 + for (i = 0; i < uIndex; i++) {
3840 + pDevObject =
3841 + (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
3843 + if (pDevObject) {
3844 + *phDevObject = (struct DEV_OBJECT *) pDevObject;
3845 + status = DSP_SOK;
3846 + } else {
3847 + *phDevObject = NULL;
3848 + status = DSP_EFAIL;
3849 + GT_0trace(curTrace, GT_7CLASS,
3850 + "DRV: Could not get the DevObject\n");
3852 + GT_2trace(curTrace, GT_ENTER,
3853 + "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
3854 + "hDevObject: 0x%x\n", status, *phDevObject);
3855 + return status;
3859 + * ======== DRV_GetFirstDevObject ========
3860 + * Purpose:
3861 + * Retrieve the first Device Object handle from an internal linked list of
3862 + * of DEV_OBJECTs maintained by DRV.
3863 + */
3864 +u32 DRV_GetFirstDevObject(void)
3866 + u32 dwDevObject = 0;
3867 + struct DRV_OBJECT *pDrvObject;
3869 + if (DSP_SUCCEEDED
3870 + (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
3871 + if ((pDrvObject->devList != NULL) &&
3872 + !LST_IsEmpty(pDrvObject->devList)) {
3873 + dwDevObject = (u32) LST_First(pDrvObject->devList);
3877 + return dwDevObject;
3881 + * ======== DRV_GetFirstDevNodeString ========
3882 + * Purpose:
3883 + * Retrieve the first Device Extension from an internal linked list of
3884 + * of Pointer to DevNode Strings maintained by DRV.
3885 + */
3886 +u32 DRV_GetFirstDevExtension(void)
3888 + u32 dwDevExtension = 0;
3889 + struct DRV_OBJECT *pDrvObject;
3891 + if (DSP_SUCCEEDED
3892 + (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
3894 + if ((pDrvObject->devNodeString != NULL) &&
3895 + !LST_IsEmpty(pDrvObject->devNodeString)) {
3896 + dwDevExtension = (u32)LST_First(pDrvObject->
3897 + devNodeString);
3901 + return dwDevExtension;
3905 + * ======== DRV_GetNextDevObject ========
3906 + * Purpose:
3907 + * Retrieve the next Device Object handle from an internal linked list of
3908 + * of DEV_OBJECTs maintained by DRV, after having previously called
3909 + * DRV_GetFirstDevObject() and zero or more DRV_GetNext.
3910 + */
3911 +u32 DRV_GetNextDevObject(u32 hDevObject)
3913 + u32 dwNextDevObject = 0;
3914 + struct DRV_OBJECT *pDrvObject;
3916 + DBC_Require(hDevObject != 0);
3918 + if (DSP_SUCCEEDED
3919 + (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
3921 + if ((pDrvObject->devList != NULL) &&
3922 + !LST_IsEmpty(pDrvObject->devList)) {
3923 + dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
3924 + (struct LST_ELEM *)hDevObject);
3927 + return dwNextDevObject;
3931 + * ======== DRV_GetNextDevExtension ========
3932 + * Purpose:
3933 + * Retrieve the next Device Extension from an internal linked list of
3934 + * of pointer to DevNodeString maintained by DRV, after having previously
3935 + * called DRV_GetFirstDevExtension() and zero or more
3936 + * DRV_GetNextDevExtension().
3937 + */
3938 +u32 DRV_GetNextDevExtension(u32 hDevExtension)
3940 + u32 dwDevExtension = 0;
3941 + struct DRV_OBJECT *pDrvObject;
3943 + DBC_Require(hDevExtension != 0);
3945 + if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
3946 + REG_DRV_OBJECT))) {
3947 + if ((pDrvObject->devNodeString != NULL) &&
3948 + !LST_IsEmpty(pDrvObject->devNodeString)) {
3949 + dwDevExtension = (u32)LST_Next(pDrvObject->
3950 + devNodeString,
3951 + (struct LST_ELEM *)hDevExtension);
3955 + return dwDevExtension;
3959 + * ======== DRV_Init ========
3960 + * Purpose:
3961 + * Initialize DRV module private state.
3962 + */
3963 +DSP_STATUS DRV_Init(void)
3965 + s32 fRetval = 1; /* function return value */
3967 + DBC_Require(cRefs >= 0);
3969 + if (fRetval)
3970 + cRefs++;
3972 + GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry crefs 0x%x \n",
3973 + cRefs);
3975 + DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
3977 + return fRetval;
3981 + * ======== DRV_InsertDevObject ========
3982 + * Purpose:
3983 + * Insert a DevObject into the list of Manager object.
3984 + */
3985 +DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
3986 + struct DEV_OBJECT *hDevObject)
3988 + DSP_STATUS status = DSP_SOK;
3989 + struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
3991 + DBC_Require(cRefs > 0);
3992 + DBC_Require(hDevObject != NULL);
3993 + DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
3994 + DBC_Assert(pDRVObject->devList);
3996 + GT_2trace(curTrace, GT_ENTER,
3997 + "Entering DRV_InsertProcObject hDRVObject "
3998 + "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
4000 + LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
4002 + GT_1trace(curTrace, GT_ENTER,
4003 + "Exiting InsertDevObject status 0x%x\n", status);
4005 + DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
4007 + return status;
4011 + * ======== DRV_RemoveDevObject ========
4012 + * Purpose:
4013 + * Search for and remove a DeviceObject from the given list of DRV
4014 + * objects.
4015 + */
4016 +DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
4017 + struct DEV_OBJECT *hDevObject)
4019 + DSP_STATUS status = DSP_EFAIL;
4020 + struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
4021 + struct LST_ELEM *pCurElem;
4023 + DBC_Require(cRefs > 0);
4024 + DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
4025 + DBC_Require(hDevObject != NULL);
4027 + DBC_Require(pDRVObject->devList != NULL);
4028 + DBC_Require(!LST_IsEmpty(pDRVObject->devList));
4030 + GT_2trace(curTrace, GT_ENTER,
4031 + "Entering DRV_RemoveDevObject hDevObject "
4032 + "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
4033 + /* Search list for pProcObject: */
4034 + for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
4035 + pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
4036 + /* If found, remove it. */
4037 + if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
4038 + LST_RemoveElem(pDRVObject->devList, pCurElem);
4039 + status = DSP_SOK;
4040 + break;
4043 + /* Remove list if empty. */
4044 + if (LST_IsEmpty(pDRVObject->devList)) {
4045 + LST_Delete(pDRVObject->devList);
4046 + pDRVObject->devList = NULL;
4048 + DBC_Ensure((pDRVObject->devList == NULL) ||
4049 + !LST_IsEmpty(pDRVObject->devList));
4050 + GT_1trace(curTrace, GT_ENTER,
4051 + "DRV_RemoveDevObject returning 0x%x\n", status);
4052 + return status;
4056 + * ======== DRV_RequestResources ========
4057 + * Purpose:
4058 + * Requests resources from the OS.
4059 + */
4060 +DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
4062 + DSP_STATUS status = DSP_SOK;
4063 + struct DRV_OBJECT *pDRVObject;
4064 + struct DRV_EXT *pszdevNode;
4066 + DBC_Require(dwContext != 0);
4067 + DBC_Require(pDevNodeString != NULL);
4068 + GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
4069 + /*
4070 + * Allocate memory to hold the string. This will live untill
4071 + * it is freed in the Release resources. Update the driver object
4072 + * list.
4073 + */
4074 + if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
4075 + REG_DRV_OBJECT))) {
4076 + pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
4077 + if (pszdevNode) {
4078 + LST_InitElem(&pszdevNode->link);
4079 + CSL_Strcpyn((char *) pszdevNode->szString,
4080 + (char *)dwContext, MAXREGPATHLENGTH);
4081 + /* Update the Driver Object List */
4082 + *pDevNodeString = (u32)pszdevNode->szString;
4083 + LST_PutTail(pDRVObject->devNodeString,
4084 + (struct LST_ELEM *)pszdevNode);
4085 + } else {
4086 + GT_0trace(curTrace, GT_7CLASS,
4087 + "Failed to Allocate Memory devNodeString ");
4088 + status = DSP_EFAIL;
4089 + *pDevNodeString = 0;
4091 + } else {
4092 + status = DSP_EFAIL;
4093 + GT_0trace(curTrace, GT_7CLASS,
4094 + "Failed to get Driver Object from Registry");
4095 + *pDevNodeString = 0;
4098 + if (!(CSL_Strcmp((char *) dwContext, "TIOMAP1510"))) {
4099 + GT_0trace(curTrace, GT_1CLASS,
4100 + " Allocating resources for UMA \n");
4101 + status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
4102 + } else {
4103 + status = DSP_EFAIL;
4104 + GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
4107 + if (DSP_FAILED(status)) {
4108 + GT_0trace(curTrace, GT_7CLASS,
4109 + "Failed to reserve bridge resources ");
4111 + DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != 0 &&
4112 + !LST_IsEmpty(pDRVObject->devNodeString)) ||
4113 + (DSP_FAILED(status) && *pDevNodeString == 0));
4115 + return status;
4119 + * ======== DRV_ReleaseResources ========
4120 + * Purpose:
4121 + * Releases resources from the OS.
4122 + */
4123 +DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
4125 + DSP_STATUS status = DSP_SOK;
4126 + struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
4127 + struct DRV_EXT *pszdevNode;
4129 + GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
4131 + if (!(CSL_Strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
4132 + "TIOMAP1510"))) {
4133 + GT_0trace(curTrace, GT_1CLASS,
4134 + " Releasing DSP-Bridge resources \n");
4135 + status = RequestBridgeResources(dwContext, DRV_RELEASE);
4136 + } else {
4137 + GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
4140 + if (DSP_SUCCEEDED(status)) {
4141 + GT_0trace(curTrace, GT_1CLASS,
4142 + "Failed to relese bridge resources\n");
4145 + /*
4146 + * Irrespective of the status go ahead and clean it
4147 + * The following will over write the status.
4148 + */
4149 + for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
4150 + pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
4151 + DRV_GetNextDevExtension((u32)pszdevNode)) {
4152 + if ((u32)pszdevNode == dwContext) {
4153 + /* Found it */
4154 + /* Delete from the Driver object list */
4155 + LST_RemoveElem(pDRVObject->devNodeString,
4156 + (struct LST_ELEM *)pszdevNode);
4157 + MEM_Free((void *) pszdevNode);
4158 + break;
4160 + /* Delete the List if it is empty */
4161 + if (LST_IsEmpty(pDRVObject->devNodeString)) {
4162 + LST_Delete(pDRVObject->devNodeString);
4163 + pDRVObject->devNodeString = NULL;
4166 + return status;
4170 + * ======== RequestBridgeResources ========
4171 + * Purpose:
4172 + * Reserves shared memory for bridge.
4173 + */
4174 +static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
4176 + DSP_STATUS status = DSP_SOK;
4177 + struct CFG_HOSTRES *pResources;
4178 + u32 dwBuffSize;
4180 + struct DRV_EXT *driverExt;
4181 + u32 shm_size;
4183 + DBC_Require(dwContext != 0);
4185 + GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
4187 + if (!bRequest) {
4188 + driverExt = (struct DRV_EXT *)dwContext;
4189 + /* Releasing resources by deleting the registry key */
4190 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4191 + pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
4192 + if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
4193 + CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
4194 + status = CFG_E_RESOURCENOTAVAIL;
4195 + GT_0trace(curTrace, GT_1CLASS,
4196 + "REG_GetValue Failed \n");
4197 + } else {
4198 + GT_0trace(curTrace, GT_1CLASS,
4199 + "REG_GetValue Succeeded \n");
4202 + if (pResources != NULL) {
4203 + dwBuffSize = sizeof(shm_size);
4204 + status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
4205 + (u8 *)&shm_size, &dwBuffSize);
4206 + if (DSP_SUCCEEDED(status)) {
4207 + if ((pResources->dwMemBase[1]) &&
4208 + (pResources->dwMemPhys[1])) {
4209 + MEM_FreePhysMem((void *)pResources->
4210 + dwMemBase[1], pResources->dwMemPhys[1],
4211 + shm_size);
4213 + } else {
4214 + GT_1trace(curTrace, GT_7CLASS,
4215 + "Error getting SHM size from registry: "
4216 + "%x. Not calling MEM_FreePhysMem\n",
4217 + status);
4219 + pResources->dwMemBase[1] = 0;
4220 + pResources->dwMemPhys[1] = 0;
4222 + if (pResources->dwPrmBase)
4223 + iounmap((void *)pResources->dwPrmBase);
4224 + if (pResources->dwCmBase)
4225 + iounmap((void *)pResources->dwCmBase);
4226 + if (pResources->dwMboxBase)
4227 + iounmap((void *)pResources->dwMboxBase);
4228 + if (pResources->dwMemBase[0])
4229 + iounmap((void *)pResources->dwMemBase[0]);
4230 + if (pResources->dwMemBase[2])
4231 + iounmap((void *)pResources->dwMemBase[2]);
4232 + if (pResources->dwMemBase[3])
4233 + iounmap((void *)pResources->dwMemBase[3]);
4234 + if (pResources->dwMemBase[4])
4235 + iounmap((void *)pResources->dwMemBase[4]);
4236 + if (pResources->dwWdTimerDspBase)
4237 + iounmap((void *)pResources->dwWdTimerDspBase);
4238 + if (pResources->dwDmmuBase)
4239 + iounmap((void *)pResources->dwDmmuBase);
4240 + if (pResources->dwPerBase)
4241 + iounmap((void *)pResources->dwPerBase);
4243 + if (pResources->dwSysCtrlBase) {
4244 + iounmap((void *)pResources->dwSysCtrlBase);
4245 + /* don't set pResources->dwSysCtrlBase to null
4246 + * as it is used in BOARD_Stop */
4248 + pResources->dwPrmBase = (u32) NULL;
4249 + pResources->dwCmBase = (u32) NULL;
4250 + pResources->dwMboxBase = (u32) NULL;
4251 + pResources->dwMemBase[0] = (u32) NULL;
4252 + pResources->dwMemBase[2] = (u32) NULL;
4253 + pResources->dwMemBase[3] = (u32) NULL;
4254 + pResources->dwMemBase[4] = (u32) NULL;
4255 + pResources->dwWdTimerDspBase = (u32) NULL;
4256 + pResources->dwDmmuBase = (u32) NULL;
4258 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4259 + status = REG_SetValue(NULL, (char *)driverExt->szString,
4260 + CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
4261 + (u32)dwBuffSize);
4262 + /* Set all the other entries to NULL */
4263 + MEM_Free(pResources);
4265 + GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
4266 + return status;
4268 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4269 + pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
4270 + if (pResources != NULL) {
4271 + /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
4272 + pResources->wNumMemWindows = 2;
4273 + /* First window is for DSP internal memory */
4275 + pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
4276 + OMAP_IVA2_PRM_SIZE);
4277 + pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
4278 + OMAP_IVA2_CM_SIZE);
4279 + pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
4280 + OMAP_MBOX_SIZE);
4281 + pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
4282 + OMAP_SYSC_SIZE);
4283 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
4284 + pResources->dwMemBase[0]);
4285 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
4286 + pResources->dwMemBase[3]);
4287 + GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
4288 + pResources->dwPrmBase);
4289 + GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
4290 + pResources->dwCmBase);
4291 + GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
4292 + pResources->dwWdTimerDspBase);
4293 + GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
4294 + pResources->dwMboxBase);
4295 + GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
4296 + pResources->dwDmmuBase);
4298 + /* for 24xx base port is not mapping the mamory for DSP
4299 + * internal memory TODO Do a ioremap here */
4300 + /* Second window is for DSP external memory shared with MPU */
4301 + if (DSP_SUCCEEDED(status)) {
4302 + /* for Linux, these are hard-coded values */
4303 + pResources->dwBusType = 0;
4304 + pResources->bIRQRegisters = 0;
4305 + pResources->bIRQAttrib = 0;
4306 + pResources->dwOffsetForMonitor = 0;
4307 + pResources->dwChnlOffset = 0;
4308 + /* CHNL_MAXCHANNELS */
4309 + pResources->dwNumChnls = CHNL_MAXCHANNELS;
4310 + pResources->dwChnlBufSize = 0x400;
4311 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4312 + status = REG_SetValue(NULL, (char *) dwContext,
4313 + CURRENTCONFIG, REG_BINARY,
4314 + (u8 *)pResources,
4315 + sizeof(struct CFG_HOSTRES));
4316 + if (DSP_SUCCEEDED(status)) {
4317 + GT_0trace(curTrace, GT_1CLASS,
4318 + " Successfully set the registry "
4319 + "value for CURRENTCONFIG\n");
4320 + } else {
4321 + GT_0trace(curTrace, GT_7CLASS,
4322 + " Failed to set the registry "
4323 + "value for CURRENTCONFIG\n");
4326 + MEM_Free(pResources);
4328 + /* End Mem alloc */
4329 + return status;
4333 + * ======== RequestBridgeResourcesDSP ========
4334 + * Purpose:
4335 + * Reserves shared memory for bridge.
4336 + */
4337 +static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
4339 + DSP_STATUS status = DSP_SOK;
4340 + struct CFG_HOSTRES *pResources;
4341 + u32 dwBuffSize;
4342 + u32 dmaAddr;
4343 + u32 shm_size;
4345 + DBC_Require(dwContext != 0);
4347 + GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
4349 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4351 + pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
4353 + if (pResources != NULL) {
4354 + if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
4355 + dwContext, pResources))) {
4356 + /* Call CFG_GetHostResources to get reserve resouces */
4357 + status = RequestBridgeResources(dwContext, bRequest);
4358 + if (DSP_SUCCEEDED(status)) {
4359 + status = CFG_GetHostResources
4360 + ((struct CFG_DEVNODE *) dwContext,
4361 + pResources);
4364 + /* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
4365 + pResources->wNumMemWindows = 4;
4367 + pResources->dwMemBase[0] = 0;
4368 + pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
4369 + OMAP_DSP_MEM1_SIZE);
4370 + pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
4371 + OMAP_DSP_MEM2_SIZE);
4372 + pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
4373 + OMAP_DSP_MEM3_SIZE);
4374 + pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
4375 + OMAP_PER_CM_SIZE);
4376 + pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
4377 + OMAP_DMMU_SIZE);
4378 + pResources->dwWdTimerDspBase = 0;
4380 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
4381 + pResources->dwMemBase[0]);
4382 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
4383 + pResources->dwMemBase[1]);
4384 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
4385 + pResources->dwMemBase[2]);
4386 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
4387 + pResources->dwMemBase[3]);
4388 + GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
4389 + pResources->dwMemBase[4]);
4390 + GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
4391 + pResources->dwPrmBase);
4392 + GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
4393 + pResources->dwCmBase);
4394 + GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
4395 + pResources->dwWdTimerDspBase);
4396 + GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
4397 + pResources->dwMboxBase);
4398 + GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
4399 + pResources->dwDmmuBase);
4400 + dwBuffSize = sizeof(shm_size);
4401 + status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
4402 + (u8 *)&shm_size, &dwBuffSize);
4403 + if (DSP_SUCCEEDED(status)) {
4404 + /* Allocate Physically contiguous,
4405 + * non-cacheable memory */
4406 + pResources->dwMemBase[1] =
4407 + (u32)MEM_AllocPhysMem(shm_size, 0x100000,
4408 + &dmaAddr);
4409 + if (pResources->dwMemBase[1] == 0) {
4410 + status = DSP_EMEMORY;
4411 + GT_0trace(curTrace, GT_7CLASS,
4412 + "SHM reservation Failed\n");
4413 + } else {
4414 + pResources->dwMemLength[1] = shm_size;
4415 + pResources->dwMemPhys[1] = dmaAddr;
4417 + GT_3trace(curTrace, GT_1CLASS,
4418 + "Bridge SHM address 0x%x dmaAddr"
4419 + " %x size %x\n",
4420 + pResources->dwMemBase[1],
4421 + dmaAddr, shm_size);
4424 + if (DSP_SUCCEEDED(status)) {
4425 + /* for Linux, these are hard-coded values */
4426 + pResources->dwBusType = 0;
4427 + pResources->bIRQRegisters = 0;
4428 + pResources->bIRQAttrib = 0;
4429 + pResources->dwOffsetForMonitor = 0;
4430 + pResources->dwChnlOffset = 0;
4431 + /* CHNL_MAXCHANNELS */
4432 + pResources->dwNumChnls = CHNL_MAXCHANNELS;
4433 + pResources->dwChnlBufSize = 0x400;
4434 + dwBuffSize = sizeof(struct CFG_HOSTRES);
4435 + status = REG_SetValue(NULL, (char *)dwContext,
4436 + CURRENTCONFIG, REG_BINARY,
4437 + (u8 *)pResources,
4438 + sizeof(struct CFG_HOSTRES));
4439 + if (DSP_SUCCEEDED(status)) {
4440 + GT_0trace(curTrace, GT_1CLASS,
4441 + " Successfully set the registry"
4442 + " value for CURRENTCONFIG\n");
4443 + } else {
4444 + GT_0trace(curTrace, GT_7CLASS,
4445 + " Failed to set the registry value"
4446 + " for CURRENTCONFIG\n");
4449 + MEM_Free(pResources);
4451 + /* End Mem alloc */
4452 + return status;
4454 Index: lk/drivers/dsp/bridge/rmgr/drv_interface.c
4455 ===================================================================
4456 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
4457 +++ lk/drivers/dsp/bridge/rmgr/drv_interface.c 2008-08-18 10:38:37.000000000 +0300
4458 @@ -0,0 +1,780 @@
4460 + * linux/drivers/dsp/bridge/rmgr/drv_interface.c
4462 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
4464 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
4466 + * This package is free software; you can redistribute it and/or modify
4467 + * it under the terms of the GNU General Public License version 2 as
4468 + * published by the Free Software Foundation.
4470 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
4471 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
4472 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
4473 + */
4476 + * ======== linux_driver.c ========
4477 + * Description:
4478 + * DSP/BIOS Bridge driver interface.
4480 + * Public Functions:
4481 + * driver_init
4482 + * driver_exit
4483 + * driver_open
4484 + * driver_release
4485 + * driver_ioctl
4486 + * driver_mmap
4488 + *! Revision History
4489 + *! ================
4490 + *! 21-Apr-2004 map Deprecated use of MODULE_PARM for kernel versions
4491 + *! greater than 2.5, use module_param.
4492 + *! 08-Mar-2004 sb Added the dsp_debug argument, which keeps the DSP in self
4493 + *! loop after image load and waits in a loop for DSP to start
4494 + *! 16-Feb-2004 vp Deprecated the usage of MOD_INC_USE_COUNT and
4495 + *! MOD_DEC_USE_COUNT
4496 + *! for kernel versions greater than 2.5
4497 + *! 20-May-2003 vp Added unregister functions for the DPM.
4498 + *! 24-Mar-2003 sb Pass pid instead of driverContext to DSP_Close
4499 + *! 24-Mar-2003 vp Added Power Management support.
4500 + *! 21-Mar-2003 sb Configure SHM size using insmod argument shm_size
4501 + *! 10-Feb-2003 vp Updated based on code review comments
4502 + *! 18-Oct-2002 sb Created initial version
4503 + */
4505 +/* ----------------------------------- Host OS */
4507 +#include <host_os.h>
4508 +#include <linux/platform_device.h>
4509 +#include <linux/pm.h>
4511 +#ifdef MODULE
4512 +#include <linux/module.h>
4513 +#endif
4515 +#include <linux/device.h>
4516 +#include <linux/init.h>
4517 +#include <linux/moduleparam.h>
4518 +#include <linux/cdev.h>
4519 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4520 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
4521 +#include <asm/arch/resource.h>
4522 +#include <asm/arch/prcm_34xx.h>
4523 +#endif
4524 +#endif
4526 +/* ----------------------------------- DSP/BIOS Bridge */
4527 +#include <std.h>
4528 +#include <dbdefs.h>
4529 +#include <errbase.h>
4531 +/* ----------------------------------- Trace & Debug */
4532 +#include <gt.h>
4533 +#include <dbc.h>
4535 +/* ----------------------------------- OS Adaptation Layer */
4536 +#include <services.h>
4537 +#include <sync.h>
4538 +#include <reg.h>
4539 +#include <csl.h>
4540 +#include <prcs.h>
4542 +/* ----------------------------------- Platform Manager */
4543 +#include <wcdioctl.h>
4544 +#include <_dcd.h>
4545 +#include <dspdrv.h>
4546 +#include <dbreg.h>
4548 +/* ----------------------------------- Resource Manager */
4549 +#include <pwr.h>
4551 +/* ----------------------------------- This */
4552 +#include <drv_interface.h>
4554 +#ifndef RES_CLEANUP_DISABLE
4555 +#include <cfg.h>
4556 +#include <resourcecleanup.h>
4557 +#include <chnl.h>
4558 +#include <proc.h>
4559 +#include <cfg.h>
4560 +#include <dev.h>
4561 +#include <drvdefs.h>
4562 +#include <drv.h>
4563 +#include <dbreg.h>
4564 +#endif
4566 +#define BRIDGE_NAME "C6410"
4567 +/* ----------------------------------- Globals */
4568 +#define DRIVER_NAME "DspBridge"
4569 +#define DRIVER_MAJOR 0 /* Linux assigns our Major device number */
4570 +#define DRIVER_MINOR 0 /* Linux assigns our Major device number */
4571 +s32 dsp_debug;
4573 +/* This is a test variable used by Bridge to test different sleep states */
4574 +static s32 dsp_test_sleepstate;
4575 +struct bridge_dev {
4576 + struct cdev cdev;
4579 +static struct bridge_dev *bridge_device;
4581 +static struct class *bridge_class;
4583 +static u32 driverContext;
4584 +static char *GT_str;
4585 +static s32 driver_major = DRIVER_MAJOR;
4586 +static s32 driver_minor = DRIVER_MINOR;
4587 +static char *base_img;
4588 +char *iva_img;
4589 +static char *num_procs = "C55=1";
4590 +static s32 shm_size = 0x400000; /* 4 MB */
4591 +static u32 phys_mempool_base = 0x87000000;
4592 +static u32 phys_mempool_size = 0x600000;
4593 +#if !defined(CONFIG_ARCH_OMAP2430) && !defined(CONFIG_ARCH_OMAP3430)
4594 +static int tc_wordswapon = 1; /* Default value is always TRUE */
4595 +#else
4596 +static int tc_wordswapon = 0; /* Default value is always TRUE */
4597 +#endif
4601 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4602 +struct omap34xx_bridge_suspend_data {
4603 + int suspended;
4604 + wait_queue_head_t suspend_wq;
4607 +static struct omap34xx_bridge_suspend_data bridge_suspend_data;
4609 +int omap34xxbridge_suspend_lockout(struct omap34xx_bridge_suspend_data *s,
4610 + struct file *f)
4612 + if ((s)->suspended) {
4613 + if ((f)->f_flags & O_NONBLOCK)
4614 + return DSP_EDPMSUSPEND;
4615 + wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
4617 + return 0;
4620 +#endif
4622 +#ifdef DEBUG
4623 +module_param(GT_str, charp, 0);
4624 +MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
4626 +module_param(dsp_debug, int, 0);
4627 +MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
4628 +#endif
4630 +module_param(driver_major, int, 0); /* Driver's major number */
4631 +MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
4633 +module_param(driver_minor, int, 0); /* Driver's major number */
4634 +MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
4636 +module_param(dsp_test_sleepstate, int, 0);
4637 +MODULE_PARM_DESC(dsp_test_sleepstate, "DSP Sleep state = 0");
4639 +module_param(base_img, charp, 0);
4640 +MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
4642 +module_param(shm_size, int, 0);
4643 +MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
4645 +module_param(phys_mempool_base, uint, 0);
4646 +MODULE_PARM_DESC(phys_mempool_base,
4647 + "Physical memory pool base passed to driver");
4649 +module_param(phys_mempool_size, uint, 0);
4650 +MODULE_PARM_DESC(phys_mempool_size,
4651 + "Physical memory pool size passed to driver");
4652 +module_param(tc_wordswapon, int, 0);
4653 +MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
4655 +MODULE_AUTHOR("Texas Instruments");
4656 +MODULE_LICENSE("GPL");
4658 +static char *driver_name = DRIVER_NAME;
4659 +static struct GT_Mask driverTrace;
4661 +static struct file_operations bridge_fops = {
4662 + .open = bridge_open,
4663 + .release = bridge_release,
4664 + .ioctl = bridge_ioctl,
4665 + .mmap = bridge_mmap,
4668 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4669 +u32 timeOut = 1000;
4671 +static int bridge_suspend(struct platform_device *pdev, pm_message_t state);
4672 +static int bridge_resume(struct platform_device *pdev);
4673 +#endif
4675 +static void bridge_free(struct device *dev);
4677 +static int omap34xx_bridge_probe(struct platform_device *dev);
4679 +static int omap34xx_bridge_probe(struct platform_device *dev)
4681 + return 0;
4684 +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
4685 +static struct platform_device omap_dspbridge_dev = {
4686 + .name = BRIDGE_NAME,
4687 + .id = -1,
4688 + .num_resources = 0,
4689 + .dev = {
4690 + .release = bridge_free,
4691 + },
4692 + .resource = NULL,
4696 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4697 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
4698 +/* The number of OPPs supported in the system */
4699 +s32 dsp_max_opps = CO_VDD1_OPP5-2;
4700 +u32 vdd1_dsp_freq[6][4] = {
4702 + {0, 0, 0, 0},
4704 + {0, 90000, 0, 86000},
4706 + {0, 180000, 80000, 170000},
4708 + {0, 360000, 160000, 340000},
4710 + {0, 396000, 325000, 376000},
4712 + {0, 430000, 355000, 430000},
4715 +/* The handle for setting constraints */
4716 +struct constraint_handle *dsp_constraint_handle;
4717 +struct constraint_handle *mpu_constraint_handle;
4719 +static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
4720 + void *ptr)
4722 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4723 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
4724 + PWR_PM_PostScale(PRCM_VDD1, level);
4725 +#endif
4726 +#endif
4727 + return 0;
4731 +static struct notifier_block omap34xxbridge_post_scale = {
4732 + .notifier_call = dspbridge_post_scale,
4733 + NULL,
4735 +static struct constraint_id cnstr_id_vdd1 = {
4736 + .type = RES_OPP_CO,
4737 + .data = (void *)"vdd1_opp",
4739 +#endif
4740 +#endif
4742 +static struct platform_driver bridge_driver_ldm = {
4743 + .driver = {
4744 + .owner = THIS_MODULE,
4745 + .name = BRIDGE_NAME,
4746 + },
4747 + .probe = omap34xx_bridge_probe,
4748 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4749 + .suspend = bridge_suspend,
4750 + .resume = bridge_resume,
4751 +#endif
4752 + .shutdown = NULL,
4753 + .remove = NULL,
4757 +#endif
4759 +/* Initialization routine. Executed when the driver is loaded (as a kernel
4760 + * module), or when the system is booted (when included as part of the kernel
4761 + * image). */
4762 +static int __init bridge_init(void)
4764 + int status;
4765 + u32 initStatus;
4766 + u32 temp;
4767 + dev_t dev = 0 ;
4768 + int result;
4770 + /* use 2.6 device model */
4771 + if (driver_major) {
4772 + dev = MKDEV(driver_major, driver_minor);
4773 + result = register_chrdev_region(dev, 1, driver_name);
4774 + } else {
4775 + result = alloc_chrdev_region(&dev, driver_minor, 1,
4776 + driver_name);
4777 + driver_major = MAJOR(dev);
4780 + if (result < 0) {
4781 + GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
4782 + "Can't get Major %d \n", driver_major);
4783 + return result;
4786 + bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
4787 + if (!bridge_device) {
4788 + result = -ENOMEM;
4789 + unregister_chrdev_region(dev, 1);
4790 + return result;
4792 + memset(bridge_device, 0, sizeof(struct bridge_dev));
4793 + cdev_init(&bridge_device->cdev, &bridge_fops);
4794 + bridge_device->cdev.owner = THIS_MODULE;
4795 + bridge_device->cdev.ops = &bridge_fops;
4797 + status = cdev_add(&bridge_device->cdev, dev, 1);
4799 + if (status) {
4800 + GT_0trace(driverTrace, GT_7CLASS,
4801 + "Failed to add the bridge device \n");
4802 + return status;
4805 + /* udev support */
4806 + bridge_class = class_create(THIS_MODULE, "ti_bridge");
4808 + if (IS_ERR(bridge_class))
4809 + GT_0trace(driverTrace, GT_7CLASS,
4810 + "Error creating bridge class \n");
4812 + device_create(bridge_class, NULL, MKDEV(driver_major,
4813 + driver_minor), NULL, "DspBridge");
4815 + GT_init();
4816 + GT_create(&driverTrace, "LD");
4818 +#ifdef DEBUG
4819 + if (GT_str)
4820 + GT_set(GT_str);
4822 +#else
4823 +#if (defined DDSP_DEBUG_PRODUCT) && GT_TRACE
4824 + GT_set("**=67");
4825 +#endif
4826 +#endif
4829 + GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
4830 + status = platform_driver_register(&bridge_driver_ldm);
4831 + if (!status)
4832 + status = platform_device_register(&omap_dspbridge_dev);
4834 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4835 + /* Initialize the wait queue */
4836 + if (!status) {
4837 + bridge_suspend_data.suspended = 0;
4838 + init_waitqueue_head(&bridge_suspend_data.suspend_wq);
4840 +#endif
4842 + SERVICES_Init();
4844 + /* Autostart flag. This should be set to true if the DSP image should
4845 + * be loaded and run during bridge module initialization */
4847 + if (base_img) {
4848 + temp = true;
4849 + REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
4850 + sizeof(temp));
4851 + REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
4852 + CSL_Strlen(base_img) + 1);
4853 + } else {
4854 + temp = false;
4855 + REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
4856 + sizeof(temp));
4857 + REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
4859 + REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
4860 + CSL_Strlen(num_procs) + 1);
4862 + if (shm_size >= 0x10000) { /* 64 KB */
4863 + initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
4864 + (u8 *)&shm_size, sizeof(shm_size));
4865 + } else {
4866 + initStatus = DSP_EINVALIDARG;
4867 + status = -1;
4868 + GT_0trace(driverTrace, GT_7CLASS,
4869 + "SHM size must be atleast 64 KB\n");
4871 + GT_1trace(driverTrace, GT_7CLASS,
4872 + "requested shm_size = 0x%x\n", shm_size);
4874 + if (phys_mempool_base > 0x0) {
4875 + initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
4876 + REG_DWORD, (u8 *)&phys_mempool_base,
4877 + sizeof(phys_mempool_base));
4879 + GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
4880 + phys_mempool_base);
4882 + if (phys_mempool_size > 0x0) {
4883 + initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
4884 + REG_DWORD, (u8 *)&phys_mempool_size,
4885 + sizeof(phys_mempool_size));
4887 + GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x \n",
4888 + phys_mempool_base);
4889 + if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
4890 + MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
4891 + if (tc_wordswapon) {
4892 + GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
4893 + REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
4894 + (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
4895 + } else {
4896 + GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
4897 + REG_SetValue(NULL, NULL, TCWORDSWAP,
4898 + REG_DWORD, (u8 *)&tc_wordswapon,
4899 + sizeof(tc_wordswapon));
4901 + if (DSP_SUCCEEDED(initStatus)) {
4902 + driverContext = DSP_Init(&initStatus);
4903 + if (DSP_FAILED(initStatus)) {
4904 + status = -1;
4905 + GT_0trace(driverTrace, GT_7CLASS,
4906 + "DSP/BIOS Bridge initialization Failed\n");
4907 + } else {
4908 + GT_0trace(driverTrace, GT_5CLASS,
4909 + "DSP/BIOS Bridge driver loaded\n");
4911 + #ifndef CONFIG_DISABLE_BRIDGE_PM
4912 + #ifndef CONFIG_DISABLE_BRIDGE_DVFS
4913 + /* Register for the constraints */
4914 + dsp_constraint_handle = constraint_get("dspbridge",
4915 + &cnstr_id_vdd1);
4916 + constraint_register_post_notification(dsp_constraint_handle,
4917 + &omap34xxbridge_post_scale,
4918 + CO_VDD1_OPP5 + 1);
4919 + mpu_constraint_handle = constraint_get("mpubridge",
4920 + &cnstr_id_vdd1);
4921 + constraint_register_post_notification(mpu_constraint_handle,
4922 + &omap34xxbridge_post_scale,
4923 + CO_VDD1_OPP5 + 1);
4924 +#endif
4925 +#endif
4928 + DBC_Assert(status == 0);
4929 + DBC_Assert(DSP_SUCCEEDED(initStatus));
4930 + GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
4931 + return status;
4934 +/* This function is invoked during unlinking of the bridge module from the
4935 + * kernel. Bridge resources are freed in this function. */
4936 +static void __exit bridge_exit(void)
4938 + dev_t devno;
4939 + bool ret;
4940 + GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
4942 +#ifndef CONFIG_DISABLE_BRIDGE_PM
4943 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
4944 + /* remove the constraints */
4945 + if (dsp_constraint_handle != NULL) {
4946 + GT_0trace(driverTrace, GT_7CLASS,
4947 + "bridge_exit: remove constraints\n");
4948 + constraint_remove(dsp_constraint_handle);
4949 + constraint_unregister_post_notification(dsp_constraint_handle,
4950 + &omap34xxbridge_post_scale,
4951 + CO_VDD1_OPP5 + 1);
4952 + constraint_put(dsp_constraint_handle);
4953 + dsp_constraint_handle = NULL;
4954 + } else {
4955 + GT_0trace(driverTrace, GT_7CLASS,
4956 + "dsp_constraint_handle is NULL\n");
4959 + if (mpu_constraint_handle != NULL) {
4960 + GT_0trace(driverTrace, GT_7CLASS,
4961 + "bridge_exit: remove constraints\n");
4962 + constraint_remove(mpu_constraint_handle);
4963 + constraint_unregister_post_notification(mpu_constraint_handle,
4964 + &omap34xxbridge_post_scale,
4965 + CO_VDD1_OPP5 + 1);
4966 + constraint_put(mpu_constraint_handle);
4967 + mpu_constraint_handle = NULL;
4968 + } else {
4969 + GT_0trace(driverTrace, GT_7CLASS,
4970 + "mpu_constraint_handle is NULL\n");
4973 +#endif /*#ifndef CONFIG_DISABLE_BRIDGE_DVFS*/
4974 +#endif /*#ifndef CONFIG_DISABLE_BRIDGE_PM*/
4975 + /* unregister bridge driver */
4976 + platform_device_unregister(&omap_dspbridge_dev);
4977 + platform_driver_unregister(&bridge_driver_ldm);
4979 + if (driverContext) {
4980 + ret = DSP_Deinit(driverContext);
4981 + driverContext = 0;
4983 + DBC_Assert(ret == true);
4985 + SERVICES_Exit();
4986 + GT_exit();
4988 + devno = MKDEV(driver_major, driver_minor);
4989 + if (bridge_device) {
4990 + cdev_del(&bridge_device->cdev);
4991 + kfree(bridge_device);
4993 + unregister_chrdev_region(devno, 1);
4994 + if (bridge_class) {
4995 + /* remove the device from sysfs */
4996 + device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
4997 + class_destroy(bridge_class);
5002 +/* This function is called when an application opens handle to the
5003 + * bridge driver. */
5005 +int bridge_open(struct inode *ip, struct file *filp)
5007 + int status = 0;
5008 +#ifndef RES_CLEANUP_DISABLE
5009 + HANDLE hProcess;
5010 + DSP_STATUS dsp_status = DSP_SOK;
5011 + HANDLE hDrvObject = NULL;
5012 + struct PROCESS_CONTEXT *pPctxt = NULL;
5013 + struct PROCESS_CONTEXT *pTmp = NULL;
5014 + struct PROCESS_CONTEXT *pCtxtclosed = NULL;
5015 + struct PROCESS_CONTEXT *pCtxttraverse = NULL;
5016 + struct task_struct *tsk = NULL;
5017 + GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
5018 + dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
5020 + /* Checking weather task structure for all process existing
5021 + * in the process context list If not removing those processes*/
5022 + if (DSP_FAILED(dsp_status))
5023 + goto func_cont;
5025 + DRV_GetProcCtxtList(&pCtxtclosed, hDrvObject);
5026 + while (pCtxtclosed != NULL) {
5027 + tsk = find_task_by_vpid(pCtxtclosed->pid);
5029 + if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
5031 + GT_1trace(driverTrace, GT_5CLASS,
5032 + "***Task structure not existing for "
5033 + "process***%d\n", pCtxtclosed->pid);
5034 + DRV_RemoveAllResources(pCtxtclosed);
5035 + if (pCtxtclosed->hProcessor != NULL) {
5036 + DRV_GetProcCtxtList(&pCtxttraverse,
5037 + hDrvObject);
5038 + if (pCtxttraverse->next == NULL) {
5039 + PROC_Detach(pCtxtclosed->hProcessor);
5040 + } else {
5041 + if ((pCtxtclosed->pid ==
5042 + pCtxttraverse->pid) &&
5043 + (pCtxttraverse->next != NULL)) {
5044 + pCtxttraverse =
5045 + pCtxttraverse->next;
5047 + while ((pCtxttraverse != NULL) &&
5048 + (pCtxtclosed->hProcessor
5049 + != pCtxttraverse->hProcessor)) {
5050 + pCtxttraverse =
5051 + pCtxttraverse->next;
5052 + if ((pCtxttraverse != NULL) &&
5053 + (pCtxtclosed->pid ==
5054 + pCtxttraverse->pid)) {
5055 + pCtxttraverse =
5056 + pCtxttraverse->next;
5059 + if (pCtxttraverse == NULL) {
5060 + PROC_Detach
5061 + (pCtxtclosed->hProcessor);
5065 + pTmp = pCtxtclosed->next;
5066 + DRV_RemoveProcContext(hDrvObject, pCtxtclosed,
5067 + (void *)pCtxtclosed->pid);
5068 + } else {
5069 + pTmp = pCtxtclosed->next;
5071 + pCtxtclosed = pTmp;
5073 +func_cont:
5074 + dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
5075 + if (DSP_SUCCEEDED(dsp_status))
5076 + dsp_status = DRV_InsertProcContext(hDrvObject, &pPctxt);
5078 + if (pPctxt != NULL) {
5079 + PRCS_GetCurrentHandle(&hProcess);
5080 + DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
5081 + DRV_ProcSetPID(pPctxt, (s32) hProcess);
5083 +#endif
5085 + GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
5086 + return status;
5089 +/* This function is called when an application closes handle to the bridge
5090 + * driver. */
5091 +int bridge_release(struct inode *ip, struct file *filp)
5093 + int status;
5094 + HANDLE pid;
5096 + GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
5098 + status = PRCS_GetCurrentHandle(&pid);
5100 + if (DSP_SUCCEEDED(status))
5101 + status = DSP_Close((u32) pid);
5104 + (status == true) ? (status = 0) : (status = -1);
5106 + GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
5108 + return status;
5111 +static void bridge_free(struct device *dev)
5113 + /* nothing to Free */
5117 +/* This function provides IO interface to the bridge driver. */
5118 +int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
5119 + unsigned long args)
5121 + int status;
5122 + u32 retval = DSP_SOK;
5123 + union Trapped_Args pBufIn;
5125 + DBC_Require(filp != 0);
5126 +#ifndef CONFIG_DISABLE_BRIDGE_PM
5127 + status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
5128 + if (status != 0)
5129 + return status;
5131 +#endif
5133 + GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
5135 + /* Deduct one for the CMD_BASE. */
5136 + code = (code - 1);
5138 + status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
5139 + sizeof(union Trapped_Args));
5141 + if (status >= 0) {
5142 + status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
5144 + if (DSP_SUCCEEDED(status)) {
5145 + status = retval;
5146 + } else {
5147 + GT_1trace(driverTrace, GT_7CLASS,
5148 + "IOCTL Failed, code : 0x%x\n", code);
5149 + status = -1;
5154 + GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
5156 + return status;
5159 +/* This function maps kernel space memory to user space memory. */
5160 +int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
5162 +#if GT_TRACE
5163 + u32 offset = vma->vm_pgoff << PAGE_SHIFT;
5164 +#endif
5165 + u32 status;
5167 + DBC_Assert(vma->vm_start < vma->vm_end);
5169 + vma->vm_flags |= VM_RESERVED | VM_IO;
5170 + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
5172 + GT_6trace(driverTrace, GT_3CLASS,
5173 + "vm filp %p offset %lx start %lx end %lx"
5174 + " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
5175 + vma->vm_end, vma->vm_page_prot, vma->vm_flags);
5177 + status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
5178 + vma->vm_end - vma->vm_start, vma->vm_page_prot);
5179 + if (status != 0)
5180 + status = -EAGAIN;
5182 + return status;
5185 +#ifndef RES_CLEANUP_DISABLE
5186 +/* To remove all process resources before removing the process from the
5187 + * process context list*/
5188 +DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
5190 + DSP_STATUS status = DSP_SOK;
5191 + struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
5192 + if (pCtxt != NULL) {
5193 + DRV_RemoveAllSTRMResElements(pCtxt);
5194 + DRV_RemoveAllNodeResElements(pCtxt);
5195 + DRV_RemoveAllDMMResElements(pCtxt);
5196 + DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
5198 + return status;
5200 +#endif
5202 +#ifndef CONFIG_DISABLE_BRIDGE_PM
5204 +static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
5206 + u32 status = DSP_EFAIL;
5207 + u32 command = PWR_EMERGENCYDEEPSLEEP;
5209 + status = PWR_SleepDSP(command, timeOut);
5210 + if (DSP_SUCCEEDED(status)) {
5211 + bridge_suspend_data.suspended = 1;
5212 + return 0;
5213 + } else {
5214 + return -1;
5218 +static int bridge_resume(struct platform_device *pdev)
5220 + u32 status = DSP_EFAIL;
5222 + status = PWR_WakeDSP(timeOut);
5224 + if (DSP_SUCCEEDED(status)) {
5225 + bridge_suspend_data.suspended = 0;
5226 + wake_up(&bridge_suspend_data.suspend_wq);
5228 + return 0;
5229 + } else {
5230 + return -1;
5234 +#endif
5235 +/* Bridge driver initialization and de-initialization functions */
5236 +module_init(bridge_init);
5237 +module_exit(bridge_exit);
5239 Index: lk/drivers/dsp/bridge/rmgr/drv_interface.h
5240 ===================================================================
5241 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5242 +++ lk/drivers/dsp/bridge/rmgr/drv_interface.h 2008-08-18 10:38:37.000000000 +0300
5243 @@ -0,0 +1,40 @@
5245 + * linux/drivers/dsp/bridge/rmgr/drv_interface.h
5247 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5249 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
5251 + * This package is free software; you can redistribute it and/or modify
5252 + * it under the terms of the GNU General Public License version 2 as
5253 + * published by the Free Software Foundation.
5255 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
5256 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
5257 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5258 + */
5262 + * ======== drv_interface.h ========
5264 + *! Revision History
5265 + *! ================
5266 + *! 24-Mar-2003 vp Added hooks for Power Management Test
5267 + *! 18-Feb-2003 vp Code review updates
5268 + *! 18-Oct-2002 sb Created initial version
5270 + */
5272 +#ifndef _DRV_INTERFACE_H_
5273 +#define _DRV_INTERFACE_H_
5275 +/* Prototypes for all functions in this bridge */
5276 +static int __init bridge_init(void); /* Initialize bridge */
5277 +static void __exit bridge_exit(void); /* Opposite of initialize */
5278 +static int bridge_open(struct inode *, struct file *); /* Open */
5279 +static int bridge_release(struct inode *, struct file *); /* Release */
5280 +static int bridge_ioctl(struct inode *, struct file *, unsigned int,
5281 + unsigned long);
5282 +static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
5283 +#endif /* ifndef _DRV_INTERFACE_H_ */
5284 Index: lk/drivers/dsp/bridge/rmgr/dspdrv.c
5285 ===================================================================
5286 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5287 +++ lk/drivers/dsp/bridge/rmgr/dspdrv.c 2008-08-18 10:38:37.000000000 +0300
5288 @@ -0,0 +1,276 @@
5290 + * linux/drivers/dsp/bridge/rmgr/dspdrv.c
5292 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5294 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
5296 + * This package is free software; you can redistribute it and/or modify
5297 + * it under the terms of the GNU General Public License version 2 as
5298 + * published by the Free Software Foundation.
5300 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
5301 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
5302 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5303 + */
5307 + * ======== dspdrv.c ========
5308 + * Description:
5309 + * Interface to allocate and free bridge resources.
5311 + *! Revision History
5312 + *! ================
5313 + *! 12-Apr-2004 hp: Compile IVA only for 24xx.
5314 + *! 09-Feb-2004 vp: Updated to support IVA.
5315 + *! 10-Feb-2003 vp: Code review updates.
5316 + *! 18-oct-2002 vp: Ported to the Linux platform.
5317 + *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
5318 + *! before calling MGR_Destroy.
5319 + *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
5320 + *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
5321 + *! sllowing the class driver to load irrespective of
5322 + *! the image load.
5323 + *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
5324 + *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
5325 + *! Failure in WCD_InitComplete2 will cause the
5326 + *! DSP_Init to fail.
5327 + *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
5328 + *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
5329 + *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
5330 + *! DevObjects. Static variables removed. Returns
5331 + *! the Driver Object in DSP_Init.
5332 + *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
5333 + *! the list of Device objects.
5334 + *! 07-Jul-2000 rr: RM implementaion started.
5335 + *! 24-May-2000 ag: Cleaned up debug msgs.
5336 + *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
5337 + *! 03-Feb-2000 rr: GT Changes.
5338 + *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
5339 + *! DSP_Deinit checks return values.dwCode in
5340 + *! DSP_IO_CONTROL is decoded(not hard coded)
5341 + *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
5342 + *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
5343 + *! 29-Dec-1999 rr: Code Cleaned up
5344 + *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
5345 + *! 06-Dec-1999 rr: ArrayofInstalledNode, index and ArrayofInstalledDev
5346 + *! is Global.DevObject stores this pointer as hDevNode.
5347 + *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
5348 + *! Comments changed.Deinit handled.Code cleaned up.
5349 + *! DSP_IOControl, Close, Deinit returns bool values.
5350 + *! Calls WCD_InitComplete2 for Board AutoStart.
5351 + *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
5352 + *! Global Arrays keeps track of installed devices.
5353 + *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
5354 + *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
5355 + *! for multiple mini driver support.PCCARD flag
5356 + *! checking to include PCMCIA related stuff.
5357 + *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
5358 + *! return value initalized to S_OK upfront in the
5359 + *! Process Attach.
5360 + *! 15-Oct-1999 rr: DSP_DeInit handles the return values
5361 + *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
5362 + *! DRV_Request Resources is used instead of the
5363 + *! RegisterMiniDriver as it sounds close to what we are doing.
5364 + *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
5365 + *! neccessaryPCMCIA fxns are here. Soon they will move out
5366 + *! either to a seperate file for bus specific inits.
5367 + *! 10-Sep-1999 rr: GT Enabled. Considerably changed the driver structure as
5368 + *! - This is the Class driver. After successfully initialized
5369 + *! the Class driver will attempt to load the Mini driver.
5370 + *! - Need to seperate the PCMCIA stuff based on bus type.
5371 + *! - Changed the name of the file to wcdce.c
5372 + *! - Made the Media Handle as Global again
5373 + *!
5374 + *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
5375 + *! Modified the DSP_Init, now three windows are opened.
5376 + *! Split the driver into PDD so that hardware dependent
5377 + *! functions will reside in PDD.
5378 + *! 16-Jul-1999 ag Adapted from rkw's CAC Bullet card driver.
5379 + *!
5380 + */
5382 +/* ----------------------------------- Host OS */
5383 +#include <host_os.h>
5385 +/* ----------------------------------- DSP/BIOS Bridge */
5386 +#include <std.h>
5387 +#include <dbdefs.h>
5388 +#include <errbase.h>
5390 +/* ----------------------------------- Trace & Debug */
5391 +#include <dbc.h>
5392 +#include <gt.h>
5394 +/* ----------------------------------- OS Adaptation Layer */
5395 +#include <cfg.h>
5396 +#include <csl.h>
5397 +#include <mem.h>
5398 +#include <reg.h>
5400 +/* ----------------------------------- Platform Manager */
5401 +#include <drv.h>
5402 +#include <dev.h>
5403 +#include <_dcd.h>
5405 +/* ----------------------------------- Resource Manager */
5406 +#include <mgr.h>
5408 +/* ----------------------------------- Others */
5409 +#include <dbreg.h>
5411 +/* ----------------------------------- This */
5412 +#include <dspdrv.h>
5414 +/* ----------------------------------- Globals */
5415 +struct GT_Mask curTrace;
5418 + * ======== DSP_Init ========
5419 + * Allocates bridge resources. Loads a base image onto DSP, if specified.
5420 + */
5421 +u32 DSP_Init(OUT u32 *initStatus)
5423 + char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
5424 + DSP_STATUS status = DSP_EFAIL;
5425 + struct DRV_OBJECT *drvObject = NULL;
5426 + u32 index = 0;
5427 + u32 deviceNode;
5428 + u32 deviceNodeString;
5430 + GT_create(&curTrace, "DD");
5432 + GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
5434 + if (DSP_FAILED(WCD_Init())) {
5435 + GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
5436 + goto func_cont;
5437 + } /* End WCD_Exit */
5438 + if (DSP_FAILED(DRV_Create(&drvObject))) {
5439 + GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
5440 + WCD_Exit();
5441 + goto func_cont;
5442 + } /* End DRV_Create */
5443 + GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
5445 + /* Request Resources */
5446 + if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
5447 + &deviceNodeString))) {
5448 + /* Attempt to Start the Device */
5449 + if (DSP_SUCCEEDED(DEV_StartDevice(
5450 + (struct CFG_DEVNODE *)deviceNodeString))) {
5451 + /* Retreive the DevObject from the Registry */
5452 + GT_2trace(curTrace, GT_1CLASS,
5453 + "DSP_Init Succeeded for Device1:"
5454 + "%d: value: %x\n", index, deviceNodeString);
5455 + status = DSP_SOK;
5456 + } else {
5457 + GT_0trace(curTrace, GT_7CLASS,
5458 + "DSP_Init:DEV_StartDevice Failed\n");
5459 + (void)DRV_ReleaseResources
5460 + ((u32) deviceNodeString, drvObject);
5461 + status = DSP_EFAIL;
5463 + } else {
5464 + GT_0trace(curTrace, GT_7CLASS,
5465 + "DSP_Init:DRV_RequestResources Failed \r\n");
5466 + status = DSP_EFAIL;
5467 + } /* DRV_RequestResources */
5468 + index++;
5470 + /* Unwind whatever was loaded */
5471 + if (DSP_FAILED(status)) {
5472 + /* irrespective of the status of DEV_RemoveDevice we conitinue
5473 + * unloading. Get the Driver Object iterate through and remove.
5474 + * Reset the status to E_FAIL to avoid going through
5475 + * WCD_InitComplete2. */
5476 + status = DSP_EFAIL;
5477 + for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
5478 + deviceNode = DRV_GetNextDevExtension(deviceNode)) {
5479 + (void)DEV_RemoveDevice
5480 + ((struct CFG_DEVNODE *)deviceNode);
5481 + (void)DRV_ReleaseResources((u32)deviceNode,
5482 + drvObject);
5484 + /* Remove the Driver Object */
5485 + (void)DRV_Destroy(drvObject);
5486 + drvObject = 0;
5487 + WCD_Exit();
5488 + GT_0trace(curTrace, GT_7CLASS,
5489 + "DSP_Init:Logical device Failed to Load\n");
5490 + } /* Unwinding the loaded drivers */
5491 +func_cont:
5492 + /* Attempt to Start the Board */
5493 + if (DSP_SUCCEEDED(status)) {
5494 + /* BRD_AutoStart could fail if the dsp execuetable is not the
5495 + * correct one. We should not propagate that error
5496 + * into the device loader. */
5497 + (void)WCD_InitComplete2();
5498 + GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
5499 + } else {
5500 + GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
5501 + } /* End WCD_InitComplete2 */
5502 + DBC_Ensure((DSP_SUCCEEDED(status) && drvObject > 0) ||
5503 + (DSP_FAILED(status) && drvObject == 0));
5504 + *initStatus = status;
5505 + /* Return the Driver Object */
5506 + return (u32)drvObject;
5510 + * ======== DSP_Deinit ========
5511 + * Frees the resources allocated for bridge.
5512 + */
5513 +bool DSP_Deinit(u32 deviceContext)
5515 + bool retVal = true;
5516 + u32 deviceNode;
5517 + struct MGR_OBJECT *mgrObject = NULL;
5519 + GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
5521 + while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
5522 + (void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
5524 + (void)DRV_ReleaseResources((u32)deviceNode,
5525 + (struct DRV_OBJECT *)deviceContext);
5528 + (void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
5530 + /* Get the Manager Object from Registry
5531 + * MGR Destroy will unload the DCD dll */
5532 + if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
5533 + (void)MGR_Destroy(mgrObject);
5535 + WCD_Exit();
5537 + return retVal;
5541 + * ======== DSP_Close ========
5542 + * The Calling Process handle is passed to DEV_CleanupProcesState
5543 + * for cleaning up of any resources used by the application
5544 + */
5545 +bool DSP_Close(u32 dwOpenContext)
5547 + bool retVal = false;
5549 + DBC_Require(dwOpenContext != 0);
5551 + GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
5553 +#ifdef RES_CLEANUP_DISABLE
5555 + if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
5556 + GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
5557 + retVal = true;
5558 + } else {
5559 + GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
5561 +#endif
5563 + return retVal;
5565 Index: lk/drivers/dsp/bridge/rmgr/mgr.c
5566 ===================================================================
5567 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
5568 +++ lk/drivers/dsp/bridge/rmgr/mgr.c 2008-08-18 10:38:37.000000000 +0300
5569 @@ -0,0 +1,491 @@
5571 + * linux/drivers/dsp/bridge/rmgr/mgr.c
5573 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5575 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
5577 + * This package is free software; you can redistribute it and/or modify
5578 + * it under the terms of the GNU General Public License version 2 as
5579 + * published by the Free Software Foundation.
5581 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
5582 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
5583 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
5584 + */
5588 + * ======== mgr.c ========
5589 + * Description:
5590 + * Implementation of Manager interface to the device object at the
5591 + * driver level. This queries the NDB data base and retrieves the
5592 + * data about Node and Processor.
5595 + *! Revision History:
5596 + *! ================
5597 + *! 12-Feb-2003 vp: Code review updates.
5598 + *! 18-Oct-2002 vp: Ported to Linux platform
5599 + *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
5600 + *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
5601 + *! 22-Nov-2000 kc: Added MGR_GetPerfData.
5602 + *! 03-Nov-2000 rr: Updated after code review.
5603 + *! 25-Sep-2000 rr: Updated to Version 0.9
5604 + *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
5605 + *! as it is taken care by MEM_AllocObject. stdwin.h added
5606 + *! for retail build to succeed.
5607 + *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
5608 + *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
5609 + *! 20-Jun-2000 rr: Created.
5610 + */
5612 +/* ----------------------------------- DSP/BIOS Bridge */
5613 +#include <std.h>
5614 +#include <dbdefs.h>
5615 +#include <errbase.h>
5617 +/* ----------------------------------- Trace & Debug */
5618 +#include <dbc.h>
5619 +#include <gt.h>
5621 +/* ----------------------------------- OS Adaptation Layer */
5622 +#include <cfg.h>
5623 +#include <mem.h>
5624 +#include <sync.h>
5626 +/* ----------------------------------- Others */
5627 +#include <dbdcd.h>
5628 +#include <dbreg.h>
5629 +#include <drv.h>
5630 +#include <dev.h>
5632 +/* ----------------------------------- This */
5633 +#include <mgr.h>
5635 +/* ----------------------------------- Defines, Data Structures, Typedefs */
5636 +#define ZLDLLNAME ""
5637 +#define SIGNATURE 0x5f52474d /* "MGR_" (in reverse) */
5639 +struct MGR_OBJECT {
5640 + u32 dwSignature;
5641 + struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
5644 +/* ----------------------------------- Globals */
5645 +#if GT_TRACE
5646 +static struct GT_Mask MGR_DebugMask = { NULL, NULL };
5647 +#endif
5649 +static u32 cRefs;
5652 + * ========= MGR_Create =========
5653 + * Purpose:
5654 + * MGR Object gets created only once during driver Loading.
5655 + */
5656 +DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
5657 + struct CFG_DEVNODE *hDevNode)
5659 + DSP_STATUS status = DSP_SOK;
5660 + struct MGR_OBJECT *pMgrObject = NULL;
5662 + DBC_Require(phMgrObject != NULL);
5663 + DBC_Require(cRefs > 0);
5664 + GT_1trace(MGR_DebugMask, GT_ENTER,
5665 + "Entering MGR_Create phMgrObject 0x%x\n ",
5666 + phMgrObject);
5667 + MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
5668 + if (pMgrObject) {
5669 + if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
5670 + &pMgrObject->hDcdMgr))) {
5671 + /* If succeeded store the handle in the MGR Object */
5672 + if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
5673 + REG_MGR_OBJECT))) {
5674 + *phMgrObject = pMgrObject;
5675 + GT_0trace(MGR_DebugMask, GT_1CLASS,
5676 + "MGR_Create:MGR Created\r\n");
5677 + } else {
5678 + status = DSP_EFAIL;
5679 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5680 + "MGR_Create:CFG_SetObject "
5681 + "Failed\r\n");
5682 + DCD_DestroyManager(pMgrObject->hDcdMgr);
5683 + MEM_FreeObject(pMgrObject);
5685 + } else {
5686 + /* failed to Create DCD Manager */
5687 + status = DSP_EFAIL;
5688 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5689 + "MGR_Create:DCD_ManagerCreate Failed\r\n");
5690 + MEM_FreeObject(pMgrObject);
5692 + } else {
5693 + status = DSP_EMEMORY;
5694 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5695 + "MGR_Create DSP_FAILED to allocate memory \n");
5697 + GT_2trace(MGR_DebugMask, GT_ENTER,
5698 + "Exiting MGR_Create: phMgrObject: 0x%x\t"
5699 + "status: 0x%x\n", phMgrObject, status);
5700 + DBC_Ensure(DSP_FAILED(status) ||
5701 + MEM_IsValidHandle(pMgrObject, SIGNATURE));
5702 + return status;
5706 + * ========= MGR_Destroy =========
5707 + * This function is invoked during bridge driver unloading.Frees MGR object.
5708 + */
5709 +DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
5711 + DSP_STATUS status = DSP_SOK;
5712 + struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
5714 + DBC_Require(cRefs > 0);
5715 + DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
5717 + GT_1trace(MGR_DebugMask, GT_ENTER,
5718 + "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
5719 + /* Free resources */
5720 + if (hMgrObject->hDcdMgr)
5721 + DCD_DestroyManager(hMgrObject->hDcdMgr);
5723 + MEM_FreeObject(pMgrObject);
5724 + /* Update the Registry with NULL for MGR Object */
5725 + (void)CFG_SetObject(0, REG_MGR_OBJECT);
5727 + GT_2trace(MGR_DebugMask, GT_ENTER,
5728 + "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
5729 + "status: 0x%x\n", hMgrObject, status);
5731 + DBC_Ensure(DSP_FAILED(status) ||
5732 + !MEM_IsValidHandle(hMgrObject, SIGNATURE));
5734 + return status;
5738 + * ======== MGR_EnumNodeInfo ========
5739 + * Enumerate and get configuration information about nodes configured
5740 + * in the node database.
5741 + */
5742 +DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
5743 + u32 uNDBPropsSize, OUT u32 *puNumNodes)
5745 + DSP_STATUS status = DSP_SOK;
5746 + DSP_STATUS status1 = DSP_SOK;
5747 + struct DSP_UUID Uuid, uTempUuid;
5748 + u32 uTempIndex = 0;
5749 + u32 uNodeIndex = 0;
5750 + struct DCD_GENERICOBJ GenObj;
5751 + struct MGR_OBJECT *pMgrObject = NULL;
5753 + DBC_Require(pNDBProps != NULL);
5754 + DBC_Require(puNumNodes != NULL);
5755 + DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
5756 + DBC_Require(cRefs > 0);
5758 + GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
5759 + "args:\n\t uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
5760 + "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
5761 + uNDBPropsSize, puNumNodes);
5762 + *puNumNodes = 0;
5763 + /* Get The Manager Object from the Registry */
5764 + if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
5765 + REG_MGR_OBJECT))) {
5766 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5767 + "Manager_EnumNodeInfo:Failed To Get"
5768 + " MGR Object from Registry\r\n");
5769 + goto func_cont;
5771 + DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
5772 + /* Forever loop till we hit failed or no more items in the
5773 + * Enumeration. We will exit the loop other than DSP_SOK; */
5774 + while (status == DSP_SOK) {
5775 + status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
5776 + &uTempUuid);
5777 + if (status == DSP_SOK) {
5778 + uNodeIndex++;
5779 + if (uNode == (uNodeIndex - 1))
5780 + Uuid = uTempUuid;
5784 + if (DSP_SUCCEEDED(status)) {
5785 + if (uNode > (uNodeIndex - 1)) {
5786 + status = DSP_EINVALIDARG;
5787 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5788 + "Manager_EnumNodeInfo: uNode"
5789 + " is Invalid \r\n");
5790 + } else {
5791 + status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
5792 + (struct DSP_UUID *)&Uuid,
5793 + DSP_DCDNODETYPE, &GenObj);
5794 + if (DSP_SUCCEEDED(status1)) {
5795 + /* Get the Obj def */
5796 + *pNDBProps = GenObj.objData.nodeObj.ndbProps;
5797 + *puNumNodes = uNodeIndex;
5798 + status = DSP_SOK;
5799 + } else {
5800 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5801 + "Manager_EnumNodeInfo: "
5802 + "Failed to Get Node Info \r\n");
5803 + status = DSP_EFAIL;
5806 + } else {
5807 + /* This could be changed during enum, EFAIL ... */
5808 + GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
5809 + "Enumeration failure\r\n");
5810 + status = DSP_EFAIL;
5812 +func_cont:
5813 + GT_4trace(MGR_DebugMask, GT_ENTER,
5814 + "Exiting Manager_EnumNodeInfo, args:\n\t"
5815 + "uNode: 0x%x\n\tpNDBProps: 0x%x\n\tuNDBPropsSize:"
5816 + " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
5817 + uNDBPropsSize, *puNumNodes);
5818 + DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
5819 + (DSP_FAILED(status) && *puNumNodes == 0));
5821 + return status;
5825 + * ======== MGR_EnumProcessorInfo ========
5826 + * Enumerate and get configuration information about available
5827 + * DSP processors.
5828 + */
5829 +DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
5830 + OUT struct DSP_PROCESSORINFO *pProcessorInfo,
5831 + u32 uProcessorInfoSize, OUT u32 *puNumProcs)
5833 + DSP_STATUS status = DSP_SOK;
5834 + DSP_STATUS status1 = DSP_SOK;
5835 + DSP_STATUS status2 = DSP_SOK;
5836 + struct DSP_UUID uTempUuid;
5837 + u32 uTempIndex = 0;
5838 + u32 uProcIndex = 0;
5839 + struct DCD_GENERICOBJ GenObj;
5840 + struct MGR_OBJECT *pMgrObject = NULL;
5841 + struct MGR_PROCESSOREXTINFO *pExtInfo;
5842 + struct DEV_OBJECT *hDevObject;
5843 + struct DRV_OBJECT *hDrvObject;
5844 + s32 devType;
5845 + struct CFG_DEVNODE *devNode;
5846 + struct CFG_DSPRES chipResources;
5847 + bool procDetect = false;
5849 + DBC_Require(pProcessorInfo != NULL);
5850 + DBC_Require(puNumProcs != NULL);
5851 + DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
5852 + DBC_Require(cRefs > 0);
5854 + GT_4trace(MGR_DebugMask, GT_ENTER,
5855 + "Entered Manager_EnumProcessorInfo, "
5856 + "args:\n\tuProcessor: 0x%x\n\tpProcessorInfo: 0x%x\n\t"
5857 + "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
5858 + pProcessorInfo, uProcessorInfoSize, puNumProcs);
5859 + *puNumProcs = 0;
5860 + status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
5861 + if (DSP_SUCCEEDED(status)) {
5862 + status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
5863 + if (DSP_SUCCEEDED(status)) {
5864 + status = DEV_GetDevType(hDevObject, (u32 *) &devType);
5865 + status = DEV_GetDevNode(hDevObject, &devNode);
5866 + if (devType == DSP_UNIT) {
5867 + status = CFG_GetDSPResources(devNode,
5868 + &chipResources);
5869 + } else {
5870 + status = DSP_EFAIL;
5871 + GT_1trace(MGR_DebugMask, GT_7CLASS,
5872 + "Unsupported dev type gotten"
5873 + "from device object %d\n", devType);
5875 + if (DSP_SUCCEEDED(status)) {
5876 + pProcessorInfo->uProcessorType =
5877 + chipResources.uChipType;
5881 + if (DSP_FAILED(status))
5882 + goto func_end;
5884 + /* Get The Manager Object from the Registry */
5885 + if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
5886 + REG_MGR_OBJECT))) {
5887 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5888 + "Manager_EnumProcessorInfo: "
5889 + "Failed To Get MGR Object from Registry\r\n");
5890 + goto func_end;
5892 + DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
5893 + /* Forever loop till we hit no more items in the
5894 + * Enumeration. We will exit the loop other than DSP_SOK; */
5895 + while (status1 == DSP_SOK) {
5896 + status1 = DCD_EnumerateObject(uTempIndex++,
5897 + DSP_DCDPROCESSORTYPE,
5898 + &uTempUuid);
5899 + if (status1 != DSP_SOK)
5900 + break;
5902 + uProcIndex++;
5903 + /* Get the Object properties to find the Device/Processor
5904 + * Type */
5905 + if (procDetect != false)
5906 + continue;
5908 + status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
5909 + (struct DSP_UUID *)&uTempUuid,
5910 + DSP_DCDPROCESSORTYPE,
5911 + &GenObj);
5912 + if (DSP_SUCCEEDED(status2)) {
5913 + /* Get the Obj def */
5914 + if (uProcessorInfoSize <
5915 + sizeof(struct MGR_PROCESSOREXTINFO)) {
5916 + *pProcessorInfo = GenObj.objData.procObj;
5917 + } else {
5918 + /* extended info */
5919 + pExtInfo = (struct MGR_PROCESSOREXTINFO *)
5920 + pProcessorInfo;
5921 + *pExtInfo = GenObj.objData.extProcObj;
5923 + GT_1trace(MGR_DebugMask, GT_7CLASS,
5924 + "Manager_EnumProcessorInfo: Got"
5925 + " Proctype from DCD %x \r\n",
5926 + pProcessorInfo->uProcessorType);
5927 + /* See if we got the needed processor */
5928 + if (devType == DSP_UNIT) {
5929 + if (pProcessorInfo->uProcessorType ==
5930 + DSPPROCTYPE_C64)
5931 + procDetect = true;
5932 + } else if (devType == IVA_UNIT) {
5933 + if (pProcessorInfo->uProcessorType ==
5934 + IVAPROCTYPE_ARM7)
5935 + procDetect = true;
5937 + /* User applciatiuons aonly check for chip type, so
5938 + * this clumsy overwrite */
5939 + pProcessorInfo->uProcessorType =
5940 + chipResources.uChipType;
5941 + } else {
5942 + GT_1trace(MGR_DebugMask, GT_7CLASS,
5943 + "Manager_EnumProcessorInfo: "
5944 + "Failed to Get DCD Processor Info %x \r\n",
5945 + status2);
5946 + status = DSP_EFAIL;
5949 + *puNumProcs = uProcIndex;
5950 + if (procDetect == false) {
5951 + GT_0trace(MGR_DebugMask, GT_7CLASS,
5952 + "Manager_EnumProcessorInfo: Failed"
5953 + " to get Proc info from DCD , so use CFG registry\n");
5954 + pProcessorInfo->uProcessorType = chipResources.uChipType;
5956 +func_end:
5957 + return status;
5961 + * ======== MGR_Exit ========
5962 + * Decrement reference count, and free resources when reference count is
5963 + * 0.
5964 + */
5965 +void CDECL MGR_Exit(void)
5967 + DBC_Require(cRefs > 0);
5968 + cRefs--;
5969 + if (cRefs == 0)
5970 + DCD_Exit();
5972 + GT_1trace(MGR_DebugMask, GT_5CLASS,
5973 + "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
5974 + DBC_Ensure(cRefs >= 0);
5978 + * ======== MGR_GetDCDHandle ========
5979 + * Retrieves the MGR handle. Accessor Function.
5980 + */
5981 +DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
5982 + OUT u32 *phDCDHandle)
5984 + DSP_STATUS status = DSP_EFAIL;
5985 + struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
5987 + DBC_Require(cRefs > 0);
5988 + DBC_Require(phDCDHandle != NULL);
5990 + *phDCDHandle = (u32)NULL;
5991 + if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
5992 + *phDCDHandle = (u32) pMgrObject->hDcdMgr;
5993 + status = DSP_SOK;
5995 + DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
5996 + (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
5998 + return status;
6002 + * ======== MGR_Init ========
6003 + * Initialize MGR's private state, keeping a reference count on each call.
6004 + */
6005 +bool CDECL MGR_Init(void)
6007 + bool fRetval = true;
6008 + bool fInitDCD = false;
6010 + DBC_Require(cRefs >= 0);
6012 + if (cRefs == 0) {
6014 + /* Set the Trace mask */
6015 + DBC_Assert(!MGR_DebugMask.flags);
6017 + GT_create(&MGR_DebugMask, "MG"); /* "MG" for Manager */
6018 + fInitDCD = DCD_Init(); /* DCD Module */
6020 + if (!fInitDCD) {
6021 + fRetval = false;
6022 + GT_0trace(MGR_DebugMask, GT_6CLASS,
6023 + "MGR_Init failed\n");
6027 + if (fRetval)
6028 + cRefs++;
6031 + GT_1trace(MGR_DebugMask, GT_5CLASS,
6032 + "Entered MGR_Init, ref count: 0x%x\n", cRefs);
6033 + DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
6035 + return fRetval;
6039 + * ======== MGR_WaitForBridgeEvents ========
6040 + * Block on any Bridge event(s)
6041 + */
6042 +DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
6043 + u32 uCount, OUT u32 *puIndex, u32 uTimeout)
6045 + DSP_STATUS status;
6046 + struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
6047 + u32 i;
6049 + DBC_Require(uCount < MAX_EVENTS);
6051 + for (i = 0; i < uCount; i++)
6052 + hSyncEvents[i] = aNotifications[i]->handle;
6054 + status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
6055 + puIndex);
6057 + return status;
6061 Index: lk/drivers/dsp/bridge/rmgr/nldr.c
6062 ===================================================================
6063 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
6064 +++ lk/drivers/dsp/bridge/rmgr/nldr.c 2008-08-18 10:38:37.000000000 +0300
6065 @@ -0,0 +1,1966 @@
6067 + * linux/drivers/dsp/bridge/rmgr/linux/nldr/nldr.c
6069 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
6071 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
6073 + * This package is free software; you can redistribute it and/or modify
6074 + * it under the terms of the GNU General Public License version 2 as
6075 + * published by the Free Software Foundation.
6077 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
6078 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
6079 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
6080 + */
6084 + * ======== nldr.c ========
6085 + * Description:
6086 + * DSP/BIOS Bridge dynamic + overlay Node loader.
6088 + * Public Functions:
6089 + * NLDR_Allocate
6090 + * NLDR_Create
6091 + * NLDR_Delete
6092 + * NLDR_Exit
6093 + * NLDR_Free
6094 + * NLDR_GetFxnAddr
6095 + * NLDR_Init
6096 + * NLDR_Load
6097 + * NLDR_Unload
6099 + * Notes:
6101 + *! Revision History
6102 + *! ================
6103 + *! 07-Apr-2003 map Removed references to dead DLDR module
6104 + *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
6105 + *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
6106 + *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
6107 + *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
6108 + *! sections > 1024 bytes.
6109 + *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
6110 + *! libs for symbols
6111 + *! 27-Sep-2002 map Added RemoteFree to convert size to words for
6112 + *! correct deallocation
6113 + *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
6114 + *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
6115 + *! 05-Aug-2002 jeh Created.
6116 + */
6118 +#include <host_os.h>
6120 +#include <std.h>
6121 +#include <dbdefs.h>
6122 +#include <errbase.h>
6124 +#include <dbc.h>
6125 +#include <gt.h>
6126 +#ifdef DEBUG
6127 +#include <dbg.h>
6128 +#endif
6130 +/* OS adaptation layer */
6131 +#include <csl.h>
6132 +#include <mem.h>
6134 +/* Platform manager */
6135 +#include <cod.h>
6136 +#include <dev.h>
6138 +/* Resource manager */
6139 +#include <dbll.h>
6140 +#include <dbdcd.h>
6141 +#include <rmm.h>
6142 +#include <uuidutil.h>
6144 +#include <nldr.h>
6146 +#define NLDR_SIGNATURE 0x52444c4e /* "RDLN" */
6147 +#define NLDR_NODESIGNATURE 0x4e444c4e /* "NDLN" */
6149 +/* Name of section containing dynamic load mem */
6150 +#define DYNMEMSECT ".dspbridge_mem"
6152 +/* Name of section containing dependent library information */
6153 +#define DEPLIBSECT ".dspbridge_deplibs"
6155 +/* Max depth of recursion for loading node's dependent libraries */
6156 +#define MAXDEPTH 5
6158 +/* Max number of persistent libraries kept by a node */
6159 +#define MAXLIBS 5
6162 + * Defines for extracting packed dynamic load memory requirements from two
6163 + * masks.
6164 + * These defines must match node.cdb and dynm.cdb
6165 + * Format of data/code mask is:
6166 + * uuuuuuuu|fueeeeee|fudddddd|fucccccc|
6167 + * where
6168 + * u = unused
6169 + * cccccc = prefered/required dynamic mem segid for create phase data/code
6170 + * dddddd = prefered/required dynamic mem segid for delete phase data/code
6171 + * eeeeee = prefered/req. dynamic mem segid for execute phase data/code
6172 + * f = flag indicating if memory is preferred or required:
6173 + * f = 1 if required, f = 0 if preferred.
6175 + * The 6 bits of the segid are interpreted as follows:
6177 + * If the 6th bit (bit 5) is not set, then this specifies a memory segment
6178 + * between 0 and 31 (a maximum of 32 dynamic loading memory segments).
6179 + * If the 6th bit (bit 5) is set, segid has the following interpretation:
6180 + * segid = 32 - Any internal memory segment can be used.
6181 + * segid = 33 - Any external memory segment can be used.
6182 + * segid = 63 - Any memory segment can be used (in this case the
6183 + * required/preferred flag is irrelevant).
6185 + */
6186 +/* Maximum allowed dynamic loading memory segments */
6187 +#define MAXMEMSEGS 32
6189 +#define MAXSEGID 3 /* Largest possible (real) segid */
6190 +#define MEMINTERNALID 32 /* Segid meaning use internal mem */
6191 +#define MEMEXTERNALID 33 /* Segid meaning use external mem */
6192 +#define NULLID 63 /* Segid meaning no memory req/pref */
6193 +#define FLAGBIT 7 /* 7th bit is pref./req. flag */
6194 +#define SEGMASK 0x3f /* Bits 0 - 5 */
6196 +#define CREATEBIT 0 /* Create segid starts at bit 0 */
6197 +#define DELETEBIT 8 /* Delete segid starts at bit 8 */
6198 +#define EXECUTEBIT 16 /* Execute segid starts at bit 16 */
6201 + * Masks that define memory type. Must match defines in dynm.cdb.
6202 + */
6203 +#define DYNM_CODE 0x2
6204 +#define DYNM_DATA 0x4
6205 +#define DYNM_CODEDATA (DYNM_CODE | DYNM_DATA)
6206 +#define DYNM_INTERNAL 0x8
6207 +#define DYNM_EXTERNAL 0x10
6210 + * Defines for packing memory requirement/preference flags for code and
6211 + * data of each of the node's phases into one mask.
6212 + * The bit is set if the segid is required for loading code/data of the
6213 + * given phase. The bit is not set, if the segid is preferred only.
6215 + * These defines are also used as indeces into a segid array for the node.
6216 + * eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
6217 + * create phase data is required or preferred to be loaded into.
6218 + */
6219 +#define CREATEDATAFLAGBIT 0
6220 +#define CREATECODEFLAGBIT 1
6221 +#define EXECUTEDATAFLAGBIT 2
6222 +#define EXECUTECODEFLAGBIT 3
6223 +#define DELETEDATAFLAGBIT 4
6224 +#define DELETECODEFLAGBIT 5
6225 +#define MAXFLAGS 6
6227 +#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
6228 + hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
6229 + (segid) == MEMINTERNALID)
6231 +#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
6232 + hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
6233 + (segid) == MEMEXTERNALID)
6235 +#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
6236 + (((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
6238 +#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
6240 + /*
6241 + * These names may be embedded in overlay sections to identify which
6242 + * node phase the section should be overlayed.
6243 + */
6244 +#define PCREATE "create"
6245 +#define PDELETE "delete"
6246 +#define PEXECUTE "execute"
6248 +#define IsEqualUUID(uuid1, uuid2) (\
6249 + ((uuid1).ulData1 == (uuid2).ulData1) && \
6250 + ((uuid1).usData2 == (uuid2).usData2) && \
6251 + ((uuid1).usData3 == (uuid2).usData3) && \
6252 + ((uuid1).ucData4 == (uuid2).ucData4) && \
6253 + ((uuid1).ucData5 == (uuid2).ucData5) && \
6254 + (CSL_Strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
6256 + /*
6257 + * ======== MemInfo ========
6258 + * Format of dynamic loading memory segment info in coff file.
6259 + * Must match dynm.h55.
6260 + */
6261 +struct MemInfo {
6262 + u32 segid; /* Dynamic loading memory segment number */
6263 + u32 base;
6264 + u32 len;
6265 + u32 type; /* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
6269 + * ======== LibNode ========
6270 + * For maintaining a tree of library dependencies.
6271 + */
6272 +struct LibNode {
6273 + struct DBLL_LibraryObj *lib; /* The library */
6274 + u16 nDepLibs; /* Number of dependent libraries */
6275 + struct LibNode *pDepLibs; /* Dependent libraries of lib */
6279 + * ======== OvlySect ========
6280 + * Information needed to overlay a section.
6281 + */
6282 +struct OvlySect {
6283 + struct OvlySect *pNextSect;
6284 + u32 loadAddr; /* Load address of section */
6285 + u32 runAddr; /* Run address of section */
6286 + u32 size; /* Size of section */
6287 + u16 page; /* DBL_CODE, DBL_DATA */
6291 + * ======== OvlyNode ========
6292 + * For maintaining a list of overlay nodes, with sections that need to be
6293 + * overlayed for each of the nodes phases.
6294 + */
6295 +struct OvlyNode {
6296 + struct DSP_UUID uuid;
6297 + char *pNodeName;
6298 + struct OvlySect *pCreateSects;
6299 + struct OvlySect *pDeleteSects;
6300 + struct OvlySect *pExecuteSects;
6301 + struct OvlySect *pOtherSects;
6302 + u16 nCreateSects;
6303 + u16 nDeleteSects;
6304 + u16 nExecuteSects;
6305 + u16 nOtherSects;
6306 + u16 createRef;
6307 + u16 deleteRef;
6308 + u16 executeRef;
6309 + u16 otherRef;
6313 + * ======== NLDR_OBJECT ========
6314 + * Overlay loader object.
6315 + */
6316 +struct NLDR_OBJECT {
6317 + u32 dwSignature; /* For object validation */
6318 + struct DEV_OBJECT *hDevObject; /* Device object */
6319 + struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
6320 + struct DBLL_TarObj *dbll; /* The DBL loader */
6321 + struct DBLL_LibraryObj *baseLib; /* Base image library */
6322 + struct RMM_TargetObj *rmm; /* Remote memory manager for DSP */
6323 + struct DBLL_Fxns dbllFxns; /* Loader function table */
6324 + struct DBLL_Attrs dbllAttrs; /* attrs to pass to loader functions */
6325 + NLDR_OVLYFXN ovlyFxn; /* "write" for overlay nodes */
6326 + NLDR_WRITEFXN writeFxn; /* "write" for dynamic nodes */
6327 + struct OvlyNode *ovlyTable; /* Table of overlay nodes */
6328 + u16 nOvlyNodes; /* Number of overlay nodes in base */
6329 + u16 nNode; /* Index for tracking overlay nodes */
6330 + u16 nSegs; /* Number of dynamic load mem segs */
6331 + u32 *segTable; /* memtypes of dynamic memory segs
6332 + * indexed by segid
6333 + */
6334 + u16 usDSPMauSize; /* Size of DSP MAU */
6335 + u16 usDSPWordSize; /* Size of DSP word */
6339 + * ======== NLDR_NODEOBJECT ========
6340 + * Dynamic node object. This object is created when a node is allocated.
6341 + */
6342 +struct NLDR_NODEOBJECT {
6343 + u32 dwSignature; /* For object validation */
6344 + struct NLDR_OBJECT *pNldr; /* Dynamic loader handle */
6345 + void *pPrivRef; /* Handle to pass to DBL_WriteFxn */
6346 + struct DSP_UUID uuid; /* Node's UUID */
6347 + bool fDynamic; /* Dynamically loaded node? */
6348 + bool fOverlay; /* Overlay node? */
6349 + bool *pfPhaseSplit; /* Multiple phase libraries? */
6350 + struct LibNode root; /* Library containing node phase */
6351 + struct LibNode createLib; /* Library containing create phase lib */
6352 + struct LibNode executeLib; /* Library containing execute phase lib */
6353 + struct LibNode deleteLib; /* Library containing delete phase lib */
6354 + struct LibNode persLib[MAXLIBS]; /* libs remain loaded until Delete */
6355 + s32 nPersLib; /* Number of persistent libraries */
6356 + /* Path in lib dependency tree */
6357 + struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
6358 + enum NLDR_PHASE phase; /* Node phase currently being loaded */
6360 + /*
6361 + * Dynamic loading memory segments for data and code of each phase.
6362 + */
6363 + u16 segId[MAXFLAGS];
6365 + /*
6366 + * Mask indicating whether each mem segment specified in segId[]
6367 + * is preferred or required.
6368 + * For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
6369 + * then it is required to load execute phase data into the memory
6370 + * specified by segId[EXECUTEDATAFLAGBIT].
6371 + */
6372 + u32 codeDataFlagMask;
6375 +/* Dynamic loader function table */
6376 +static struct DBLL_Fxns dbllFxns = {
6377 + (DBLL_CloseFxn) DBLL_close,
6378 + (DBLL_CreateFxn) DBLL_create,
6379 + (DBLL_DeleteFxn) DBLL_delete,
6380 + (DBLL_ExitFxn) DBLL_exit,
6381 + (DBLL_GetAttrsFxn) DBLL_getAttrs,
6382 + (DBLL_GetAddrFxn) DBLL_getAddr,
6383 + (DBLL_GetCAddrFxn) DBLL_getCAddr,
6384 + (DBLL_GetSectFxn) DBLL_getSect,
6385 + (DBLL_InitFxn) DBLL_init,
6386 + (DBLL_LoadFxn) DBLL_load,
6387 + (DBLL_LoadSectFxn) DBLL_loadSect,
6388 + (DBLL_OpenFxn) DBLL_open,
6389 + (DBLL_ReadSectFxn) DBLL_readSect,
6390 + (DBLL_SetAttrsFxn) DBLL_setAttrs,
6391 + (DBLL_UnloadFxn) DBLL_unload,
6392 + (DBLL_UnloadSectFxn) DBLL_unloadSect,
6395 +static struct GT_Mask NLDR_debugMask = { NULL, NULL }; /* GT trace variable */
6396 +static u32 cRefs; /* module reference count */
6398 +static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
6399 + u32 addr, u32 nBytes);
6400 +static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
6401 + enum DSP_DCDOBJTYPE objType,
6402 + IN void *handle);
6403 +static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
6404 + struct OvlySect **pList,
6405 + struct DBLL_SectInfo *pSectInfo, bool *pExists,
6406 + u32 addr, u32 nBytes);
6407 +static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
6408 + s32 mtype);
6409 +static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
6410 + u16 nAlloc);
6411 +static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
6412 + char *symName, struct DBLL_Symbol **sym);
6413 +static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
6414 + struct LibNode *root, struct DSP_UUID uuid,
6415 + bool rootPersistent, struct DBLL_LibraryObj **libPath,
6416 + enum NLDR_PHASE phase, u16 depth);
6417 +static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
6418 + enum NLDR_PHASE phase);
6419 +static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
6420 + u32 align, u32 *dspAddr,
6421 + OPTIONAL s32 segmentId, OPTIONAL s32 req,
6422 + bool reserve);
6423 +static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
6424 + u32 size, bool reserve);
6426 +static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
6427 +static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
6428 + enum NLDR_PHASE phase);
6429 +static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
6430 + struct DBLL_LibraryObj *lib);
6431 +static u32 findLcm(u32 a, u32 b);
6432 +static u32 findGcf(u32 a, u32 b);
6435 + * ======== NLDR_Allocate ========
6436 + */
6437 +DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
6438 + IN CONST struct DCD_NODEPROPS *pNodeProps,
6439 + OUT struct NLDR_NODEOBJECT **phNldrNode,
6440 + IN bool *pfPhaseSplit)
6442 + struct NLDR_NODEOBJECT *pNldrNode = NULL;
6443 + DSP_STATUS status = DSP_SOK;
6445 + DBC_Require(cRefs > 0);
6446 + DBC_Require(pNodeProps != NULL);
6447 + DBC_Require(phNldrNode != NULL);
6448 + DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
6450 + GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
6451 + "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
6452 + pfPhaseSplit);
6454 + /* Initialize handle in case of failure */
6455 + *phNldrNode = NULL;
6456 + /* Allocate node object */
6457 + MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
6459 + if (pNldrNode == NULL) {
6460 + GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
6461 + "Memory allocation failed\n");
6462 + status = DSP_EMEMORY;
6463 + } else {
6464 + pNldrNode->pfPhaseSplit = pfPhaseSplit;
6465 + pNldrNode->nPersLib = 0;
6466 + pNldrNode->pNldr = hNldr;
6467 + pNldrNode->pPrivRef = pPrivRef;
6468 + /* Save node's UUID. */
6469 + pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
6470 + /*
6471 + * Determine if node is a dynamically loaded node from
6472 + * ndbProps.
6473 + */
6474 + if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
6475 + /* Dynamic node */
6476 + pNldrNode->fDynamic = true;
6477 + /*
6478 + * Extract memory requirements from ndbProps masks
6479 + */
6480 + /* Create phase */
6481 + pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
6482 + (pNodeProps->ulDataMemSegMask >> CREATEBIT) &
6483 + SEGMASK;
6484 + pNldrNode->codeDataFlagMask |=
6485 + ((pNodeProps->ulDataMemSegMask >>
6486 + (CREATEBIT + FLAGBIT)) & 1) <<
6487 + CREATEDATAFLAGBIT;
6488 + pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
6489 + (pNodeProps->ulCodeMemSegMask >>
6490 + CREATEBIT) & SEGMASK;
6491 + pNldrNode->codeDataFlagMask |=
6492 + ((pNodeProps->ulCodeMemSegMask >>
6493 + (CREATEBIT + FLAGBIT)) & 1) <<
6494 + CREATECODEFLAGBIT;
6495 + /* Execute phase */
6496 + pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
6497 + (pNodeProps->ulDataMemSegMask >>
6498 + EXECUTEBIT) & SEGMASK;
6499 + pNldrNode->codeDataFlagMask |=
6500 + ((pNodeProps->ulDataMemSegMask >>
6501 + (EXECUTEBIT + FLAGBIT)) & 1) <<
6502 + EXECUTEDATAFLAGBIT;
6503 + pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
6504 + (pNodeProps->ulCodeMemSegMask >>
6505 + EXECUTEBIT) & SEGMASK;
6506 + pNldrNode->codeDataFlagMask |=
6507 + ((pNodeProps->ulCodeMemSegMask >>
6508 + (EXECUTEBIT + FLAGBIT)) & 1) <<
6509 + EXECUTECODEFLAGBIT;
6510 + /* Delete phase */
6511 + pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
6512 + (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
6513 + SEGMASK;
6514 + pNldrNode->codeDataFlagMask |=
6515 + ((pNodeProps->ulDataMemSegMask >>
6516 + (DELETEBIT + FLAGBIT)) & 1) <<
6517 + DELETEDATAFLAGBIT;
6518 + pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
6519 + (pNodeProps->ulCodeMemSegMask >>
6520 + DELETEBIT) & SEGMASK;
6521 + pNldrNode->codeDataFlagMask |=
6522 + ((pNodeProps->ulCodeMemSegMask >>
6523 + (DELETEBIT + FLAGBIT)) & 1) <<
6524 + DELETECODEFLAGBIT;
6525 + } else {
6526 + /* Non-dynamically loaded nodes are part of the
6527 + * base image */
6528 + pNldrNode->root.lib = hNldr->baseLib;
6529 + /* Check for overlay node */
6530 + if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
6531 + pNldrNode->fOverlay = true;
6534 + *phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
6536 + /* Cleanup on failure */
6537 + if (DSP_FAILED(status) && pNldrNode)
6538 + NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
6540 + DBC_Ensure((DSP_SUCCEEDED(status) &&
6541 + MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
6542 + NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
6543 + *phNldrNode == NULL));
6544 + return status;
6548 + * ======== NLDR_Create ========
6549 + */
6550 +DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
6551 + struct DEV_OBJECT *hDevObject,
6552 + IN CONST struct NLDR_ATTRS *pAttrs)
6554 + struct COD_MANAGER *hCodMgr; /* COD manager */
6555 + char *pszCoffBuf = NULL;
6556 + char szZLFile[COD_MAXPATHLENGTH];
6557 + struct NLDR_OBJECT *pNldr = NULL;
6558 + struct DBLL_Attrs saveAttrs;
6559 + struct DBLL_Attrs newAttrs;
6560 + DBLL_Flags flags;
6561 + u32 ulEntry;
6562 + u16 nSegs = 0;
6563 + struct MemInfo *pMemInfo;
6564 + u32 ulLen = 0;
6565 + u32 ulAddr;
6566 + struct RMM_Segment *rmmSegs = NULL;
6567 + u16 i;
6568 + DSP_STATUS status = DSP_SOK;
6569 + DBC_Require(cRefs > 0);
6570 + DBC_Require(phNldr != NULL);
6571 + DBC_Require(hDevObject != NULL);
6572 + DBC_Require(pAttrs != NULL);
6573 + DBC_Require(pAttrs->pfnOvly != NULL);
6574 + DBC_Require(pAttrs->pfnWrite != NULL);
6575 + GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
6576 + phNldr, hDevObject, pAttrs);
6577 + /* Allocate dynamic loader object */
6578 + MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
6579 + if (pNldr) {
6580 + pNldr->hDevObject = hDevObject;
6581 + /* warning, lazy status checking alert! */
6582 + status = DEV_GetCodMgr(hDevObject, &hCodMgr);
6583 + DBC_Assert(DSP_SUCCEEDED(status));
6584 + status = COD_GetLoader(hCodMgr, &pNldr->dbll);
6585 + DBC_Assert(DSP_SUCCEEDED(status));
6586 + status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
6587 + DBC_Assert(DSP_SUCCEEDED(status));
6588 + status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
6589 + DBC_Assert(DSP_SUCCEEDED(status));
6590 + status = DSP_SOK;
6591 + /* end lazy status checking */
6592 + pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
6593 + pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
6594 + pNldr->dbllFxns = dbllFxns;
6595 + if (!(pNldr->dbllFxns.initFxn()))
6596 + status = DSP_EMEMORY;
6598 + } else {
6599 + GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
6600 + "Memory allocation failed\n");
6601 + status = DSP_EMEMORY;
6603 + /* Create the DCD Manager */
6604 + if (DSP_SUCCEEDED(status))
6605 + status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
6607 + /* Get dynamic loading memory sections from base lib */
6608 + if (DSP_SUCCEEDED(status)) {
6609 + status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
6610 + &ulAddr, &ulLen);
6611 + if (DSP_SUCCEEDED(status)) {
6612 + pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
6613 + MEM_PAGED);
6614 + if (!pszCoffBuf) {
6615 + GT_0trace(NLDR_debugMask, GT_6CLASS,
6616 + "NLDR_Create: Memory "
6617 + "allocation failed\n");
6618 + status = DSP_EMEMORY;
6620 + } else {
6621 + /* Ok to not have dynamic loading memory */
6622 + status = DSP_SOK;
6623 + ulLen = 0;
6624 + GT_1trace(NLDR_debugMask, GT_6CLASS,
6625 + "NLDR_Create: DBLL_getSect "
6626 + "failed (no dynamic loading mem segments): "
6627 + "0x%lx\n", status);
6630 + if (DSP_SUCCEEDED(status) && ulLen > 0) {
6631 + /* Read section containing dynamic load mem segments */
6632 + status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
6633 + pszCoffBuf, ulLen);
6634 + if (DSP_FAILED(status)) {
6635 + GT_1trace(NLDR_debugMask, GT_6CLASS,
6636 + "NLDR_Create: DBLL_read Section"
6637 + "failed: 0x%lx\n", status);
6640 + if (DSP_SUCCEEDED(status) && ulLen > 0) {
6641 + /* Parse memory segment data */
6642 + nSegs = (u16)(*((u32 *)pszCoffBuf));
6643 + if (nSegs > MAXMEMSEGS) {
6644 + GT_1trace(NLDR_debugMask, GT_6CLASS,
6645 + "NLDR_Create: Invalid number of "
6646 + "dynamic load mem segments: 0x%lx\n", nSegs);
6647 + status = DSP_ECORRUPTFILE;
6650 + /* Parse dynamic load memory segments */
6651 + if (DSP_SUCCEEDED(status) && nSegs > 0) {
6652 + rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
6653 + MEM_PAGED);
6654 + pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
6655 + if (rmmSegs == NULL || pNldr->segTable == NULL) {
6656 + status = DSP_EMEMORY;
6657 + } else {
6658 + pNldr->nSegs = nSegs;
6659 + pMemInfo = (struct MemInfo *)(pszCoffBuf +
6660 + sizeof(u32));
6661 + for (i = 0; i < nSegs; i++) {
6662 + rmmSegs[i].base = (pMemInfo + i)->base;
6663 + rmmSegs[i].length = (pMemInfo + i)->len;
6664 + rmmSegs[i].space = 0;
6665 + pNldr->segTable[i] = (pMemInfo + i)->type;
6666 +#ifdef DEBUG
6667 + DBG_Trace(DBG_LEVEL7,
6668 + "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
6669 + "Length: 0x%x\n", i, rmmSegs[i].base,
6670 + rmmSegs[i].length);
6671 +#endif
6675 + /* Create Remote memory manager */
6676 + if (DSP_SUCCEEDED(status))
6677 + status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
6679 + if (DSP_SUCCEEDED(status)) {
6680 + /* set the alloc, free, write functions for loader */
6681 + pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
6682 + newAttrs = saveAttrs;
6683 + newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
6684 + newAttrs.free = (DBLL_FreeFxn) RemoteFree;
6685 + newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
6686 + newAttrs.symHandle = pNldr;
6687 + newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
6688 + pNldr->ovlyFxn = pAttrs->pfnOvly;
6689 + pNldr->writeFxn = pAttrs->pfnWrite;
6690 + pNldr->dbllAttrs = newAttrs;
6692 + if (rmmSegs)
6693 + MEM_Free(rmmSegs);
6695 + if (pszCoffBuf)
6696 + MEM_Free(pszCoffBuf);
6698 + /* Get overlay nodes */
6699 + if (DSP_SUCCEEDED(status)) {
6700 + status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
6701 + /* lazy check */
6702 + DBC_Assert(DSP_SUCCEEDED(status));
6703 + /* First count number of overlay nodes */
6704 + status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
6705 + (void *) pNldr);
6706 + /* Now build table of overlay nodes */
6707 + if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
6708 + /* Allocate table for overlay nodes */
6709 + pNldr->ovlyTable =
6710 + MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
6711 + MEM_PAGED);
6712 + /* Put overlay nodes in the table */
6713 + pNldr->nNode = 0;
6714 + status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
6715 + AddOvlyNode,
6716 + (void *) pNldr);
6719 + /* Do a fake reload of the base image to get overlay section info */
6720 + if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
6721 + saveAttrs.write = fakeOvlyWrite;
6722 + saveAttrs.logWrite = AddOvlyInfo;
6723 + saveAttrs.logWriteHandle = pNldr;
6724 + flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
6725 + status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
6726 + &saveAttrs, &ulEntry);
6728 + if (DSP_SUCCEEDED(status)) {
6729 + *phNldr = (struct NLDR_OBJECT *) pNldr;
6730 + } else {
6731 + if (pNldr)
6732 + NLDR_Delete((struct NLDR_OBJECT *) pNldr);
6734 + *phNldr = NULL;
6736 + /* FIXME:Temp. Fix. Must be removed */
6737 + DBC_Ensure((DSP_SUCCEEDED(status) &&
6738 + MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
6739 + NLDR_SIGNATURE))
6740 + || (DSP_FAILED(status) && (*phNldr == NULL)));
6741 + return status;
6745 + * ======== NLDR_Delete ========
6746 + */
6747 +void NLDR_Delete(struct NLDR_OBJECT *hNldr)
6749 + struct OvlySect *pSect;
6750 + struct OvlySect *pNext;
6751 + u16 i;
6752 + DBC_Require(cRefs > 0);
6753 + DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
6754 + GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
6755 + hNldr->dbllFxns.exitFxn();
6756 + if (hNldr->rmm)
6757 + RMM_delete(hNldr->rmm);
6759 + if (hNldr->segTable)
6760 + MEM_Free(hNldr->segTable);
6762 + if (hNldr->hDcdMgr)
6763 + DCD_DestroyManager(hNldr->hDcdMgr);
6765 + /* Free overlay node information */
6766 + if (hNldr->ovlyTable) {
6767 + for (i = 0; i < hNldr->nOvlyNodes; i++) {
6768 + pSect = hNldr->ovlyTable[i].pCreateSects;
6769 + while (pSect) {
6770 + pNext = pSect->pNextSect;
6771 + MEM_Free(pSect);
6772 + pSect = pNext;
6774 + pSect = hNldr->ovlyTable[i].pDeleteSects;
6775 + while (pSect) {
6776 + pNext = pSect->pNextSect;
6777 + MEM_Free(pSect);
6778 + pSect = pNext;
6780 + pSect = hNldr->ovlyTable[i].pExecuteSects;
6781 + while (pSect) {
6782 + pNext = pSect->pNextSect;
6783 + MEM_Free(pSect);
6784 + pSect = pNext;
6786 + pSect = hNldr->ovlyTable[i].pOtherSects;
6787 + while (pSect) {
6788 + pNext = pSect->pNextSect;
6789 + MEM_Free(pSect);
6790 + pSect = pNext;
6793 + MEM_Free(hNldr->ovlyTable);
6795 + MEM_FreeObject(hNldr);
6796 + DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
6800 + * ======== NLDR_Exit ========
6801 + * Discontinue usage of NLDR module.
6802 + */
6803 +void NLDR_Exit(void)
6805 + DBC_Require(cRefs > 0);
6807 + cRefs--;
6809 + GT_1trace(NLDR_debugMask, GT_5CLASS,
6810 + "Entered NLDR_Exit, ref count: 0x%x\n", cRefs);
6812 + if (cRefs == 0) {
6813 + RMM_exit();
6814 + NLDR_debugMask.flags = 0;
6817 + DBC_Ensure(cRefs >= 0);
6821 + * ======== NLDR_Free ========
6822 + */
6823 +void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
6825 + DBC_Require(cRefs > 0);
6826 + DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
6828 + GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
6830 + MEM_FreeObject(hNldrNode);
6834 + * ======== NLDR_GetFxnAddr ========
6835 + */
6836 +DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
6837 + u32 *pulAddr)
6839 + struct DBLL_Symbol *pSym;
6840 + struct NLDR_OBJECT *hNldr;
6841 + DSP_STATUS status = DSP_SOK;
6842 + bool status1 = false;
6843 + s32 i = 0;
6844 + struct LibNode root = { NULL, 0, NULL };
6845 + DBC_Require(cRefs > 0);
6846 + DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
6847 + DBC_Require(pulAddr != NULL);
6848 + DBC_Require(pstrFxn != NULL);
6849 + GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
6850 + hNldrNode, pstrFxn, pulAddr);
6852 + hNldr = hNldrNode->pNldr;
6853 + /* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
6854 + if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
6855 + switch (hNldrNode->phase) {
6856 + case NLDR_CREATE:
6857 + root = hNldrNode->createLib;
6858 + break;
6859 + case NLDR_EXECUTE:
6860 + root = hNldrNode->executeLib;
6861 + break;
6862 + case NLDR_DELETE:
6863 + root = hNldrNode->deleteLib;
6864 + break;
6865 + default:
6866 + DBC_Assert(false);
6867 + break;
6869 + } else {
6870 + /* for Overlay nodes or non-split Dynamic nodes */
6871 + root = hNldrNode->root;
6873 + status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
6874 + if (!status1)
6875 + status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
6877 + /* If symbol not found, check dependent libraries */
6878 + if (!status1) {
6879 + for (i = 0; i < root.nDepLibs; i++) {
6880 + status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
6881 + lib, pstrFxn, &pSym);
6882 + if (!status1) {
6883 + status1 = hNldr->dbllFxns.getCAddrFxn(root.
6884 + pDepLibs[i].lib, pstrFxn, &pSym);
6886 + if (status1) {
6887 + /* Symbol found */
6888 + break;
6892 + /* Check persistent libraries */
6893 + if (!status1) {
6894 + for (i = 0; i < hNldrNode->nPersLib; i++) {
6895 + status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
6896 + persLib[i].lib, pstrFxn, &pSym);
6897 + if (!status1) {
6898 + status1 =
6899 + hNldr->dbllFxns.getCAddrFxn(hNldrNode->
6900 + persLib[i].lib, pstrFxn, &pSym);
6902 + if (status1) {
6903 + /* Symbol found */
6904 + break;
6909 + if (status1) {
6910 + *pulAddr = pSym->value;
6911 + } else {
6912 + GT_1trace(NLDR_debugMask, GT_6CLASS,
6913 + "NLDR_GetFxnAddr: Symbol not found: "
6914 + "%s\n", pstrFxn);
6915 + status = DSP_ESYMBOL;
6918 + return status;
6922 + * ======== NLDR_GetRmmManager ========
6923 + * Given a NLDR object, retrieve RMM Manager Handle
6924 + */
6925 +DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
6926 + OUT struct RMM_TargetObj **phRmmMgr)
6928 + DSP_STATUS status = DSP_SOK;
6929 + struct NLDR_OBJECT *pNldrObject = hNldrObject;
6930 + DBC_Require(phRmmMgr != NULL);
6931 + GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
6932 + hNldrObject, phRmmMgr);
6933 + if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
6934 + *phRmmMgr = pNldrObject->rmm;
6935 + } else {
6936 + *phRmmMgr = NULL;
6937 + status = DSP_EHANDLE;
6938 + GT_0trace(NLDR_debugMask, GT_7CLASS,
6939 + "NLDR_GetRmmManager:Invalid handle");
6942 + GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
6943 + "0x%x\n\tphRmmMgr: 0x%x\n", status, *phRmmMgr);
6945 + DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
6946 + (*phRmmMgr == NULL)));
6948 + return status;
6952 + * ======== NLDR_Init ========
6953 + * Initialize the NLDR module.
6954 + */
6955 +bool NLDR_Init(void)
6957 + DBC_Require(cRefs >= 0);
6959 + if (cRefs == 0) {
6960 + DBC_Assert(!NLDR_debugMask.flags);
6961 + GT_create(&NLDR_debugMask, "DL"); /* "DL" for DLdr */
6963 + RMM_init();
6966 + cRefs++;
6968 + GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
6969 + cRefs);
6971 + DBC_Ensure(cRefs > 0);
6972 + return true;
6976 + * ======== NLDR_Load ========
6977 + */
6978 +DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
6980 + struct NLDR_OBJECT *hNldr;
6981 + struct DSP_UUID libUUID;
6982 + DSP_STATUS status = DSP_SOK;
6984 + DBC_Require(cRefs > 0);
6985 + DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
6987 + hNldr = hNldrNode->pNldr;
6989 + GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
6990 + hNldrNode, phase);
6992 + if (hNldrNode->fDynamic) {
6993 + hNldrNode->phase = phase;
6995 + libUUID = hNldrNode->uuid;
6997 + /* At this point, we may not know if node is split into
6998 + * different libraries. So we'll go ahead and load the
6999 + * library, and then save the pointer to the appropriate
7000 + * location after we know. */
7002 + status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
7003 + hNldrNode->libPath, phase, 0);
7005 + if (DSP_SUCCEEDED(status)) {
7006 + if (*hNldrNode->pfPhaseSplit) {
7007 + switch (phase) {
7008 + case NLDR_CREATE:
7009 + hNldrNode->createLib = hNldrNode->root;
7010 + break;
7012 + case NLDR_EXECUTE:
7013 + hNldrNode->executeLib = hNldrNode->root;
7014 + break;
7016 + case NLDR_DELETE:
7017 + hNldrNode->deleteLib = hNldrNode->root;
7018 + break;
7020 + default:
7021 + DBC_Assert(false);
7022 + break;
7026 + } else {
7027 + if (hNldrNode->fOverlay)
7028 + status = LoadOvly(hNldrNode, phase);
7032 + return status;
7036 + * ======== NLDR_Unload ========
7037 + */
7038 +DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
7040 + DSP_STATUS status = DSP_SOK;
7041 + struct LibNode *pRootLib = NULL;
7042 + s32 i = 0;
7044 + DBC_Require(cRefs > 0);
7045 + DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
7046 + GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
7047 + hNldrNode, phase);
7048 + if (hNldrNode != NULL) {
7049 + if (hNldrNode->fDynamic) {
7050 + if (*hNldrNode->pfPhaseSplit) {
7051 + switch (phase) {
7052 + case NLDR_CREATE:
7053 + pRootLib = &hNldrNode->createLib;
7054 + break;
7055 + case NLDR_EXECUTE:
7056 + pRootLib = &hNldrNode->executeLib;
7057 + break;
7058 + case NLDR_DELETE:
7059 + pRootLib = &hNldrNode->deleteLib;
7060 + /* Unload persistent libraries */
7061 + for (i = 0; i < hNldrNode->nPersLib;
7062 + i++) {
7063 + UnloadLib(hNldrNode,
7064 + &hNldrNode->persLib[i]);
7066 + hNldrNode->nPersLib = 0;
7067 + break;
7068 + default:
7069 + DBC_Assert(false);
7070 + break;
7072 + } else {
7073 + /* Unload main library */
7074 + pRootLib = &hNldrNode->root;
7076 + UnloadLib(hNldrNode, pRootLib);
7077 + } else {
7078 + if (hNldrNode->fOverlay)
7079 + UnloadOvly(hNldrNode, phase);
7083 + return status;
7087 + * ======== AddOvlyInfo ========
7088 + */
7089 +static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
7090 + u32 addr, u32 nBytes)
7092 + char *pNodeName;
7093 + char *pSectName = (char *)sectInfo->name;
7094 + bool fExists = false;
7095 + char seps = ':';
7096 + char *pch;
7097 + u16 i;
7098 + struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
7099 + DSP_STATUS status = DSP_SOK;
7101 + /* Is this an overlay section (load address != run address)? */
7102 + if (sectInfo->loadAddr == sectInfo->runAddr)
7103 + goto func_end;
7105 + /* Find the node it belongs to */
7106 + for (i = 0; i < hNldr->nOvlyNodes; i++) {
7107 + pNodeName = hNldr->ovlyTable[i].pNodeName;
7108 + if (CSL_Strncmp(pNodeName, pSectName + 1,
7109 + CSL_Strlen(pNodeName)) == 0) {
7110 + /* Found the node */
7111 + break;
7114 + if (!(i < hNldr->nOvlyNodes))
7115 + goto func_end;
7117 + /* Determine which phase this section belongs to */
7118 + for (pch = pSectName + 1; *pch && *pch != seps; pch++)
7119 + ;;
7121 + if (*pch) {
7122 + pch++; /* Skip over the ':' */
7123 + if (CSL_Strncmp(pch, PCREATE, CSL_Strlen(PCREATE)) == 0) {
7124 + status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
7125 + pCreateSects, sectInfo, &fExists, addr, nBytes);
7126 + if (DSP_SUCCEEDED(status) && !fExists)
7127 + hNldr->ovlyTable[i].nCreateSects++;
7129 + } else
7130 + if (CSL_Strncmp(pch, PDELETE, CSL_Strlen(PDELETE)) == 0) {
7131 + status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
7132 + pDeleteSects, sectInfo, &fExists,
7133 + addr, nBytes);
7134 + if (DSP_SUCCEEDED(status) && !fExists)
7135 + hNldr->ovlyTable[i].nDeleteSects++;
7137 + } else
7138 + if (CSL_Strncmp(pch, PEXECUTE, CSL_Strlen(PEXECUTE)) == 0) {
7139 + status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
7140 + pExecuteSects, sectInfo, &fExists,
7141 + addr, nBytes);
7142 + if (DSP_SUCCEEDED(status) && !fExists)
7143 + hNldr->ovlyTable[i].nExecuteSects++;
7145 + } else {
7146 + /* Put in "other" sectins */
7147 + status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
7148 + pOtherSects, sectInfo, &fExists,
7149 + addr, nBytes);
7150 + if (DSP_SUCCEEDED(status) && !fExists)
7151 + hNldr->ovlyTable[i].nOtherSects++;
7155 +func_end:
7156 + return status;
7160 + * ======== AddOvlyNode =========
7161 + * Callback function passed to DCD_GetObjects.
7162 + */
7163 +static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
7164 + enum DSP_DCDOBJTYPE objType,
7165 + IN void *handle)
7167 + struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
7168 + char *pNodeName = NULL;
7169 + char *pBuf = NULL;
7170 + u32 uLen;
7171 + struct DCD_GENERICOBJ objDef;
7172 + DSP_STATUS status = DSP_SOK;
7174 + if (objType != DSP_DCDNODETYPE)
7175 + goto func_end;
7177 + status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
7178 + if (DSP_FAILED(status))
7179 + goto func_end;
7181 + /* If overlay node, add to the list */
7182 + if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
7183 + if (hNldr->ovlyTable == NULL) {
7184 + hNldr->nOvlyNodes++;
7185 + } else {
7186 + /* Add node to table */
7187 + hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
7188 + uLen = CSL_Strlen(objDef.objData.nodeObj.ndbProps.
7189 + acName);
7190 + pNodeName = objDef.objData.nodeObj.ndbProps.acName;
7191 + pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
7192 + if (pBuf == NULL) {
7193 + status = DSP_EMEMORY;
7194 + } else {
7195 + CSL_Strcpyn(pBuf, pNodeName, uLen);
7196 + hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
7197 + hNldr->nNode++;
7201 + /* These were allocated in DCD_GetObjectDef */
7202 + if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
7203 + MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
7205 + if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
7206 + MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
7208 + if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
7209 + MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
7211 + if (objDef.objData.nodeObj.pstrIAlgName)
7212 + MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
7214 +func_end:
7215 + return status;
7219 + * ======== AddOvlySect ========
7220 + */
7221 +static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
7222 + struct OvlySect **pList,
7223 + struct DBLL_SectInfo *pSectInfo, bool *pExists,
7224 + u32 addr, u32 nBytes)
7226 + struct OvlySect *pNewSect = NULL;
7227 + struct OvlySect *pLastSect;
7228 + struct OvlySect *pSect;
7229 + DSP_STATUS status = DSP_SOK;
7231 + pSect = pLastSect = *pList;
7232 + *pExists = false;
7233 + while (pSect) {
7234 + /*
7235 + * Make sure section has not already been added. Multiple
7236 + * 'write' calls may be made to load the section.
7237 + */
7238 + if (pSect->loadAddr == addr) {
7239 + /* Already added */
7240 + *pExists = true;
7241 + break;
7243 + pLastSect = pSect;
7244 + pSect = pSect->pNextSect;
7247 + if (!pSect) {
7248 + /* New section */
7249 + pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
7250 + if (pNewSect == NULL) {
7251 + status = DSP_EMEMORY;
7252 + } else {
7253 + pNewSect->loadAddr = addr;
7254 + pNewSect->runAddr = pSectInfo->runAddr +
7255 + (addr - pSectInfo->loadAddr);
7256 + pNewSect->size = nBytes;
7257 + pNewSect->page = pSectInfo->type;
7260 + /* Add to the list */
7261 + if (DSP_SUCCEEDED(status)) {
7262 + if (*pList == NULL) {
7263 + /* First in the list */
7264 + *pList = pNewSect;
7265 + } else {
7266 + pLastSect->pNextSect = pNewSect;
7271 + return status;
7275 + * ======== fakeOvlyWrite ========
7276 + */
7277 +static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
7278 + s32 mtype)
7280 + return (s32)nBytes;
7284 + * ======== FreeSects ========
7285 + */
7286 +static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
7287 + u16 nAlloc)
7289 + struct OvlySect *pSect = pPhaseSects;
7290 + u16 i = 0;
7291 + bool fRet;
7293 + while (pSect && i < nAlloc) {
7294 + /* 'Deallocate' */
7295 + /* segid - page not supported yet */
7296 + /* Reserved memory */
7297 + fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
7298 + true);
7299 + DBC_Assert(fRet);
7300 + pSect = pSect->pNextSect;
7301 + i++;
7306 + * ======== GetSymbolValue ========
7307 + * Find symbol in library's base image. If not there, check dependent
7308 + * libraries.
7309 + */
7310 +static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
7311 + char *name, struct DBLL_Symbol **sym)
7313 + struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
7314 + struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
7315 + struct LibNode *root = (struct LibNode *)pArg;
7316 + u16 i;
7317 + bool status = false;
7319 + /* check the base image */
7320 + status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
7321 + if (!status)
7322 + status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
7324 + /*
7325 + * Check in root lib itself. If the library consists of
7326 + * multiple object files linked together, some symbols in the
7327 + * library may need to be resolved.
7328 + */
7329 + if (!status) {
7330 + status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
7331 + if (!status) {
7332 + status =
7333 + hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
7337 + /*
7338 + * Check in root lib's dependent libraries, but not dependent
7339 + * libraries' dependents.
7340 + */
7341 + if (!status) {
7342 + for (i = 0; i < root->nDepLibs; i++) {
7343 + status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
7344 + lib, name, sym);
7345 + if (!status) {
7346 + status = hNldr->dbllFxns.getCAddrFxn(root->
7347 + pDepLibs[i].lib, name, sym);
7349 + if (status) {
7350 + /* Symbol found */
7351 + break;
7355 + /*
7356 + * Check in persistent libraries
7357 + */
7358 + if (!status) {
7359 + for (i = 0; i < hNldrNode->nPersLib; i++) {
7360 + status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
7361 + persLib[i].lib, name, sym);
7362 + if (!status) {
7363 + status = hNldr->dbllFxns.getCAddrFxn
7364 + (hNldrNode->persLib[i].lib, name, sym);
7366 + if (status) {
7367 + /* Symbol found */
7368 + break;
7373 + return status;
7377 + * ======== LoadLib ========
7378 + * Recursively load library and all its dependent libraries. The library
7379 + * we're loading is specified by a uuid.
7380 + */
7381 +static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
7382 + struct LibNode *root, struct DSP_UUID uuid,
7383 + bool rootPersistent, struct DBLL_LibraryObj **libPath,
7384 + enum NLDR_PHASE phase, u16 depth)
7386 + struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
7387 + u16 nLibs = 0; /* Number of dependent libraries */
7388 + u16 nPLibs = 0; /* Number of persistent libraries */
7389 + u16 nLoaded = 0; /* Number of dep. libraries loaded */
7390 + u16 i;
7391 + u32 entry;
7392 + u32 dwBufSize = NLDR_MAXPATHLENGTH;
7393 + DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
7394 + struct DBLL_Attrs newAttrs;
7395 + char *pszFileName = NULL;
7396 + struct DSP_UUID *depLibUUIDs = NULL;
7397 + bool *persistentDepLibs = NULL;
7398 + DSP_STATUS status = DSP_SOK;
7399 + bool fStatus = false;
7400 + struct LibNode *pDepLib;
7402 + if (depth > MAXDEPTH) {
7403 + /* Error */
7404 + DBC_Assert(false);
7406 + root->lib = NULL;
7407 + /* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
7408 + pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
7409 + if (pszFileName == NULL)
7410 + status = DSP_EMEMORY;
7412 + if (DSP_SUCCEEDED(status)) {
7413 + /* Get the name of the library */
7414 + if (depth == 0) {
7415 + status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
7416 + &uuid, pszFileName, &dwBufSize, phase,
7417 + hNldrNode->pfPhaseSplit);
7418 + } else {
7419 + /* Dependent libraries are registered with a phase */
7420 + status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
7421 + &uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
7422 + NULL);
7425 + if (DSP_SUCCEEDED(status)) {
7426 + /* Open the library, don't load symbols */
7427 + status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
7428 + DBLL_NOLOAD, &root->lib);
7430 + /* Done with file name */
7431 + if (pszFileName)
7432 + MEM_Free(pszFileName);
7434 + /* Check to see if library not already loaded */
7435 + if (DSP_SUCCEEDED(status) && rootPersistent) {
7436 + fStatus = findInPersistentLibArray(hNldrNode, root->lib);
7437 + /* Close library */
7438 + if (fStatus) {
7439 + hNldr->dbllFxns.closeFxn(root->lib);
7440 + return DSP_SALREADYLOADED;
7443 + if (DSP_SUCCEEDED(status)) {
7444 + /* Check for circular dependencies. */
7445 + for (i = 0; i < depth; i++) {
7446 + if (root->lib == libPath[i]) {
7447 + /* This condition could be checked by a
7448 + * tool at build time. */
7449 + status = DSP_EDYNLOAD;
7453 + if (DSP_SUCCEEDED(status)) {
7454 + /* Add library to current path in dependency tree */
7455 + libPath[depth] = root->lib;
7456 + depth++;
7457 + /* Get number of dependent libraries */
7458 + status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
7459 + &nLibs, &nPLibs, phase);
7461 + DBC_Assert(nLibs >= nPLibs);
7462 + if (DSP_SUCCEEDED(status)) {
7463 + if (!(*hNldrNode->pfPhaseSplit))
7464 + nPLibs = 0;
7466 + /* nLibs = #of dependent libraries */
7467 + root->nDepLibs = nLibs - nPLibs;
7468 + if (nLibs > 0) {
7469 + depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
7470 + nLibs, MEM_PAGED);
7471 + persistentDepLibs = MEM_Calloc(sizeof(bool) *
7472 + nLibs, MEM_PAGED);
7473 + if (!depLibUUIDs || !persistentDepLibs)
7474 + status = DSP_EMEMORY;
7476 + if (root->nDepLibs > 0) {
7477 + /* Allocate arrays for dependent lib UUIDs,
7478 + * lib nodes */
7479 + root->pDepLibs = MEM_Calloc
7480 + (sizeof(struct LibNode) *
7481 + (root->nDepLibs), MEM_PAGED);
7482 + if (!(root->pDepLibs))
7483 + status = DSP_EMEMORY;
7487 + if (DSP_SUCCEEDED(status)) {
7488 + /* Get the dependent library UUIDs */
7489 + status = DCD_GetDepLibs(hNldrNode->pNldr->
7490 + hDcdMgr, &uuid, nLibs, depLibUUIDs,
7491 + persistentDepLibs, phase);
7496 + /*
7497 + * Recursively load dependent libraries.
7498 + */
7499 + if (DSP_SUCCEEDED(status) && persistentDepLibs) {
7500 + for (i = 0; i < nLibs; i++) {
7501 + /* If root library is NOT persistent, and dep library
7502 + * is, then record it. If root library IS persistent,
7503 + * the deplib is already included */
7504 + if (!rootPersistent && persistentDepLibs[i] &&
7505 + *hNldrNode->pfPhaseSplit) {
7506 + if ((hNldrNode->nPersLib) > MAXLIBS) {
7507 + status = DSP_EDYNLOAD;
7508 + break;
7511 + /* Allocate library outside of phase */
7512 + pDepLib = &hNldrNode->persLib[hNldrNode->
7513 + nPersLib];
7514 + } else {
7515 + if (rootPersistent)
7516 + persistentDepLibs[i] = true;
7519 + /* Allocate library within phase */
7520 + pDepLib = &root->pDepLibs[nLoaded];
7523 + if (depLibUUIDs) {
7524 + status = LoadLib(hNldrNode, pDepLib,
7525 + depLibUUIDs[i],
7526 + persistentDepLibs[i], libPath,
7527 + phase,
7528 + depth);
7529 + } else {
7530 + status = DSP_EMEMORY;
7533 + if (DSP_SUCCEEDED(status)) {
7534 + if ((status != DSP_SALREADYLOADED) &&
7535 + !rootPersistent && persistentDepLibs[i] &&
7536 + *hNldrNode->pfPhaseSplit) {
7537 + (hNldrNode->nPersLib)++;
7538 + } else {
7539 + if (!persistentDepLibs[i] ||
7540 + !(*hNldrNode->pfPhaseSplit)) {
7541 + nLoaded++;
7544 + } else {
7545 + break;
7550 + /* Now we can load the root library */
7551 + if (DSP_SUCCEEDED(status)) {
7552 + newAttrs = hNldr->dbllAttrs;
7553 + newAttrs.symArg = root;
7554 + newAttrs.rmmHandle = hNldrNode;
7555 + newAttrs.wHandle = hNldrNode->pPrivRef;
7556 + newAttrs.baseImage = false;
7558 + status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
7559 + &entry);
7562 + /*
7563 + * In case of failure, unload any dependent libraries that
7564 + * were loaded, and close the root library.
7565 + * (Persistent libraries are unloaded from the very top)
7566 + */
7567 + if (DSP_FAILED(status)) {
7568 + if (phase != NLDR_EXECUTE) {
7569 + for (i = 0; i < hNldrNode->nPersLib; i++)
7570 + UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
7572 + hNldrNode->nPersLib = 0;
7574 + for (i = 0; i < nLoaded; i++)
7575 + UnloadLib(hNldrNode, &root->pDepLibs[i]);
7577 + if (root->lib)
7578 + hNldr->dbllFxns.closeFxn(root->lib);
7582 + /* Going up one node in the dependency tree */
7583 + depth--;
7585 + if (depLibUUIDs) {
7586 + MEM_Free(depLibUUIDs);
7587 + depLibUUIDs = NULL;
7590 + if (persistentDepLibs) {
7591 + MEM_Free(persistentDepLibs);
7592 + persistentDepLibs = NULL;
7595 + return status;
7599 + * ======== LoadOvly ========
7600 + */
7601 +static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
7602 + enum NLDR_PHASE phase)
7604 + struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
7605 + struct OvlyNode *pONode = NULL;
7606 + struct OvlySect *pPhaseSects = NULL;
7607 + struct OvlySect *pOtherSects = NULL;
7608 + u16 i;
7609 + u16 nAlloc = 0;
7610 + u16 nOtherAlloc = 0;
7611 + u16 *pRefCount = NULL;
7612 + u16 *pOtherRef = NULL;
7613 + u32 nBytes;
7614 + struct OvlySect *pSect;
7615 + DSP_STATUS status = DSP_SOK;
7617 + /* Find the node in the table */
7618 + for (i = 0; i < hNldr->nOvlyNodes; i++) {
7619 + if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
7620 + /* Found it */
7621 + pONode = &(hNldr->ovlyTable[i]);
7622 + break;
7626 + DBC_Assert(i < hNldr->nOvlyNodes);
7627 + switch (phase) {
7628 + case NLDR_CREATE:
7629 + pRefCount = &(pONode->createRef);
7630 + pOtherRef = &(pONode->otherRef);
7631 + pPhaseSects = pONode->pCreateSects;
7632 + pOtherSects = pONode->pOtherSects;
7633 + break;
7635 + case NLDR_EXECUTE:
7636 + pRefCount = &(pONode->executeRef);
7637 + pPhaseSects = pONode->pExecuteSects;
7638 + break;
7640 + case NLDR_DELETE:
7641 + pRefCount = &(pONode->deleteRef);
7642 + pPhaseSects = pONode->pDeleteSects;
7643 + break;
7645 + default:
7646 + DBC_Assert(false);
7647 + break;
7650 + DBC_Assert(pRefCount != NULL);
7651 + if (DSP_FAILED(status))
7652 + goto func_end;
7654 + if (pRefCount == NULL)
7655 + goto func_end;
7657 + if (*pRefCount != 0)
7658 + goto func_end;
7660 + /* 'Allocate' memory for overlay sections of this phase */
7661 + pSect = pPhaseSects;
7662 + while (pSect) {
7663 + /* allocate */ /* page not supported yet */
7664 + /* reserve */ /* align */
7665 + status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
7666 + &(pSect->runAddr), true);
7667 + if (DSP_SUCCEEDED(status)) {
7668 + pSect = pSect->pNextSect;
7669 + nAlloc++;
7670 + } else {
7671 + break;
7674 + if (pOtherRef && *pOtherRef == 0) {
7675 + /* 'Allocate' memory for other overlay sections
7676 + * (create phase) */
7677 + if (DSP_SUCCEEDED(status)) {
7678 + pSect = pOtherSects;
7679 + while (pSect) {
7680 + /* page not supported */ /* align */
7681 + /* reserve */
7682 + status = RMM_alloc(hNldr->rmm, 0, pSect->size,
7683 + 0, &(pSect->runAddr), true);
7684 + if (DSP_SUCCEEDED(status)) {
7685 + pSect = pSect->pNextSect;
7686 + nOtherAlloc++;
7687 + } else {
7688 + break;
7693 + if (*pRefCount == 0) {
7694 + if (DSP_SUCCEEDED(status)) {
7695 + /* Load sections for this phase */
7696 + pSect = pPhaseSects;
7697 + while (pSect && DSP_SUCCEEDED(status)) {
7698 + nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
7699 + pSect->runAddr, pSect->loadAddr,
7700 + pSect->size, pSect->page);
7701 + if (nBytes != pSect->size)
7702 + status = DSP_EFAIL;
7704 + pSect = pSect->pNextSect;
7708 + if (pOtherRef && *pOtherRef == 0) {
7709 + if (DSP_SUCCEEDED(status)) {
7710 + /* Load other sections (create phase) */
7711 + pSect = pOtherSects;
7712 + while (pSect && DSP_SUCCEEDED(status)) {
7713 + nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
7714 + pSect->runAddr, pSect->loadAddr,
7715 + pSect->size, pSect->page);
7716 + if (nBytes != pSect->size)
7717 + status = DSP_EFAIL;
7719 + pSect = pSect->pNextSect;
7723 + if (DSP_FAILED(status)) {
7724 + /* 'Deallocate' memory */
7725 + FreeSects(hNldr, pPhaseSects, nAlloc);
7726 + FreeSects(hNldr, pOtherSects, nOtherAlloc);
7728 +func_end:
7729 + if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
7730 + *pRefCount += 1;
7731 + if (pOtherRef)
7732 + *pOtherRef += 1;
7736 + return status;
7740 + * ======== RemoteAlloc ========
7741 + */
7742 +static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
7743 + u32 align, u32 *dspAddr,
7744 + OPTIONAL s32 segmentId, OPTIONAL s32 req,
7745 + bool reserve)
7747 + struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
7748 + struct NLDR_OBJECT *hNldr;
7749 + struct RMM_TargetObj *rmm;
7750 + u16 memPhaseBit = MAXFLAGS;
7751 + u16 segid = 0;
7752 + u16 i;
7753 + u16 memType;
7754 + u32 nWords;
7755 + struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
7756 + bool fReq = false;
7757 + DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
7758 + DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
7759 + DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
7760 + space == DBLL_BSS);
7761 + hNldr = hNode->pNldr;
7762 + rmm = hNldr->rmm;
7763 + /* Convert size to DSP words */
7764 + nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
7765 + /* Modify memory 'align' to account for DSP cache line size */
7766 + align = findLcm(GEM_CACHE_LINE_SIZE, align);
7767 + GT_1trace(NLDR_debugMask, GT_7CLASS,
7768 + "RemoteAlloc: memory align to 0x%x \n", align);
7769 + if (segmentId != -1) {
7770 + pRmmAddr->segid = segmentId;
7771 + segid = segmentId;
7772 + fReq = req;
7773 + } else {
7774 + switch (hNode->phase) {
7775 + case NLDR_CREATE:
7776 + memPhaseBit = CREATEDATAFLAGBIT;
7777 + break;
7778 + case NLDR_DELETE:
7779 + memPhaseBit = DELETEDATAFLAGBIT;
7780 + break;
7781 + case NLDR_EXECUTE:
7782 + memPhaseBit = EXECUTEDATAFLAGBIT;
7783 + break;
7784 + default:
7785 + DBC_Assert(false);
7786 + break;
7788 + if (space == DBLL_CODE)
7789 + memPhaseBit++;
7791 + if (memPhaseBit < MAXFLAGS)
7792 + segid = hNode->segId[memPhaseBit];
7794 + /* Determine if there is a memory loading requirement */
7795 + if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
7796 + fReq = true;
7799 + memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
7801 + /* Find an appropriate segment based on space */
7802 + if (segid == NULLID) {
7803 + /* No memory requirements of preferences */
7804 + DBC_Assert(!fReq);
7805 + goto func_cont;
7807 + if (segid <= MAXSEGID) {
7808 + DBC_Assert(segid < hNldr->nSegs);
7809 + /* Attempt to allocate from segid first. */
7810 + pRmmAddr->segid = segid;
7811 + status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
7812 + if (DSP_FAILED(status)) {
7813 + GT_1trace(NLDR_debugMask, GT_6CLASS,
7814 + "RemoteAlloc:Unable allocate "
7815 + "from segment %d.\n", segid);
7817 + } else {
7818 + /* segid > MAXSEGID ==> Internal or external memory */
7819 + DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
7820 + /* Check for any internal or external memory segment,
7821 + * depending on segid.*/
7822 + memType |= segid == MEMINTERNALID ?
7823 + DYNM_INTERNAL : DYNM_EXTERNAL;
7824 + for (i = 0; i < hNldr->nSegs; i++) {
7825 + if ((hNldr->segTable[i] & memType) != memType)
7826 + continue;
7828 + status = RMM_alloc(rmm, i, nWords, align, dspAddr,
7829 + false);
7830 + if (DSP_SUCCEEDED(status)) {
7831 + /* Save segid for freeing later */
7832 + pRmmAddr->segid = i;
7833 + break;
7837 +func_cont:
7838 + /* Haven't found memory yet, attempt to find any segment that works */
7839 + if (status == DSP_EMEMORY && !fReq) {
7840 + GT_0trace(NLDR_debugMask, GT_6CLASS,
7841 + "RemoteAlloc: Preferred segment "
7842 + "unavailable, trying another segment.\n");
7843 + for (i = 0; i < hNldr->nSegs; i++) {
7844 + /* All bits of memType must be set */
7845 + if ((hNldr->segTable[i] & memType) != memType)
7846 + continue;
7848 + status = RMM_alloc(rmm, i, nWords, align, dspAddr,
7849 + false);
7850 + if (DSP_SUCCEEDED(status)) {
7851 + /* Save segid */
7852 + pRmmAddr->segid = i;
7853 + break;
7858 + return status;
7861 +static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
7862 + u32 size, bool reserve)
7864 + struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
7865 + struct RMM_TargetObj *rmm;
7866 + u32 nWords;
7867 + DSP_STATUS status = DSP_EMEMORY; /* Set to fail */
7869 + DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
7871 + rmm = hNldr->rmm;
7873 + /* Convert size to DSP words */
7874 + nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
7876 + if (RMM_free(rmm, space, dspAddr, nWords, reserve))
7877 + status = DSP_SOK;
7879 + return status;
7883 + * ======== UnloadLib ========
7884 + */
7885 +static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
7887 + struct DBLL_Attrs newAttrs;
7888 + struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
7889 + u16 i;
7891 + DBC_Assert(root != NULL);
7893 + /* Unload dependent libraries */
7894 + for (i = 0; i < root->nDepLibs; i++)
7895 + UnloadLib(hNldrNode, &root->pDepLibs[i]);
7897 + root->nDepLibs = 0;
7899 + newAttrs = hNldr->dbllAttrs;
7900 + newAttrs.rmmHandle = hNldr->rmm;
7901 + newAttrs.wHandle = hNldrNode->pPrivRef;
7902 + newAttrs.baseImage = false;
7903 + newAttrs.symArg = root;
7905 + if (root->lib) {
7906 + /* Unload the root library */
7907 + hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
7908 + hNldr->dbllFxns.closeFxn(root->lib);
7911 + /* Free dependent library list */
7912 + if (root->pDepLibs) {
7913 + MEM_Free(root->pDepLibs);
7914 + root->pDepLibs = NULL;
7919 + * ======== UnloadOvly ========
7920 + */
7921 +static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
7923 + struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
7924 + struct OvlyNode *pONode = NULL;
7925 + struct OvlySect *pPhaseSects = NULL;
7926 + struct OvlySect *pOtherSects = NULL;
7927 + u16 i;
7928 + u16 nAlloc = 0;
7929 + u16 nOtherAlloc = 0;
7930 + u16 *pRefCount = NULL;
7931 + u16 *pOtherRef = NULL;
7932 + DSP_STATUS status = DSP_SOK;
7934 + /* Find the node in the table */
7935 + for (i = 0; i < hNldr->nOvlyNodes; i++) {
7936 + if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
7937 + /* Found it */
7938 + pONode = &(hNldr->ovlyTable[i]);
7939 + break;
7943 + DBC_Assert(i < hNldr->nOvlyNodes);
7944 + switch (phase) {
7945 + case NLDR_CREATE:
7946 + pRefCount = &(pONode->createRef);
7947 + pPhaseSects = pONode->pCreateSects;
7948 + nAlloc = pONode->nCreateSects;
7949 + break;
7950 + case NLDR_EXECUTE:
7951 + pRefCount = &(pONode->executeRef);
7952 + pPhaseSects = pONode->pExecuteSects;
7953 + nAlloc = pONode->nExecuteSects;
7954 + break;
7955 + case NLDR_DELETE:
7956 + pRefCount = &(pONode->deleteRef);
7957 + pOtherRef = &(pONode->otherRef);
7958 + pPhaseSects = pONode->pDeleteSects;
7959 + /* 'Other' overlay sections are unloaded in the delete phase */
7960 + pOtherSects = pONode->pOtherSects;
7961 + nAlloc = pONode->nDeleteSects;
7962 + nOtherAlloc = pONode->nOtherSects;
7963 + break;
7964 + default:
7965 + DBC_Assert(false);
7966 + break;
7968 + if (DSP_SUCCEEDED(status)) {
7969 + DBC_Assert(pRefCount && (*pRefCount > 0));
7970 + if (pRefCount && (*pRefCount > 0)) {
7971 + *pRefCount -= 1;
7972 + if (pOtherRef) {
7973 + DBC_Assert(*pOtherRef > 0);
7974 + *pOtherRef -= 1;
7978 + if (pRefCount && (*pRefCount == 0)) {
7979 + /* 'Deallocate' memory */
7980 + FreeSects(hNldr, pPhaseSects, nAlloc);
7982 + if (pOtherRef && *pOtherRef == 0)
7983 + FreeSects(hNldr, pOtherSects, nOtherAlloc);
7988 + * ======== findInPersistentLibArray ========
7989 + */
7990 +static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
7991 + struct DBLL_LibraryObj *lib)
7993 + s32 i = 0;
7995 + for (i = 0; i < hNldrNode->nPersLib; i++) {
7996 + if (lib == hNldrNode->persLib[i].lib)
7997 + return true;
8001 + return false;
8005 + * ================ Find LCM (Least Common Multiplier ===
8006 + */
8007 +static u32 findLcm(u32 a, u32 b)
8009 + u32 retVal;
8011 + retVal = a * b / findGcf(a, b);
8013 + return retVal;
8017 + * ================ Find GCF (Greatest Common Factor ) ===
8018 + */
8019 +static u32 findGcf(u32 a, u32 b)
8021 + u32 c;
8023 + /* Get the GCF (Greatest common factor between the numbers,
8024 + * using Euclidian Algo */
8025 + while ((c = (a % b))) {
8026 + a = b;
8027 + b = c;
8029 + return b;
8032 Index: lk/drivers/dsp/bridge/rmgr/node.c
8033 ===================================================================
8034 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
8035 +++ lk/drivers/dsp/bridge/rmgr/node.c 2008-08-18 10:38:37.000000000 +0300
8036 @@ -0,0 +1,3365 @@
8038 + * linux/drivers/dsp/bridge/rmgr/node.c
8040 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
8042 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
8044 + * This package is free software; you can redistribute it and/or modify
8045 + * it under the terms of the GNU General Public License version 2 as
8046 + * published by the Free Software Foundation.
8048 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
8049 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
8050 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
8051 + */
8055 + * ======== node.c ========
8057 + * Description:
8058 + * DSP/BIOS Bridge Node Manager.
8060 + * Public Functions:
8061 + * NODE_Allocate
8062 + * NODE_AllocMsgBuf
8063 + * NODE_ChangePriority
8064 + * NODE_Connect
8065 + * NODE_Create
8066 + * NODE_CreateMgr
8067 + * NODE_Delete
8068 + * NODE_DeleteMgr
8069 + * NODE_EnumNodes
8070 + * NODE_Exit
8071 + * NODE_FreeMsgBuf
8072 + * NODE_GetAttr
8073 + * NODE_GetChannelId
8074 + * NODE_GetMessage
8075 + * NODE_GetStrmMgr
8076 + * NODE_Init
8077 + * NODE_OnExit
8078 + * NODE_Pause
8079 + * NODE_PutMessage
8080 + * NODE_RegisterNotify
8081 + * NODE_Run
8082 + * NODE_Terminate
8084 + *! Revision History:
8085 + *! =================
8086 + *! 12-Apr-2004 hp Compile IVA only for 24xx
8087 + *! 09-Feb-2004 vp Updated to support IVA.
8088 + *! 07-Apr-2003 map Eliminated references to old DLDR
8089 + *! 26-Mar-2003 vp Commented the call to DSP deep sleep in Node_Delete
8090 + *! function.
8091 + *! 18-Feb-2003 vp Code review updates.
8092 + *! 06-Feb-2003 kc Fixed FreeStream to release streams correctly.
8093 + *! 23-Jan-2003 map Removed call to DISP_DoCinit within Write()
8094 + *! 03-Jan-2003 map Only unload code after phase has executed if
8095 + *! overlay or split dynload phases
8096 + *! 18-Oct-2002 vp Ported to Linux platform.
8097 + *! 06-Nov-2002 map Fixed NODE_Run on NODE_PAUSED bug
8098 + *! 12-Oct-2002 map Fixed DeleteNode bug in NODE_Create
8099 + *! 11-Sep-2002 rr DeleteNode frees the memory for strmConnect and dcd obj
8100 + *! 29-Aug-2002 map Modified Ovly and Write to use ARM-side copy
8101 + *! 22-May-2002 sg Changed use of cbData for PWR calls.
8102 + *! 17-May-2002 jeh Removed LoadLoaderFxns(). Get address of RMS_cinit()
8103 + *! function. Call DISP_DoCinit() from Write(), if .cinit.
8104 + *! 13-May-2002 sg Added timeout to wake/sleep calls.
8105 + *! 02-May-2002 sg Added wake/sleep of DSP to support "nap" mode.
8106 + *! 18-Apr-2002 jeh Use dynamic loader if compile flag is set.
8107 + *! 13-Feb-2002 jeh Get uSysStackSize from DSP_NDBPROPS.
8108 + *! 07-Jan-2002 ag STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
8109 + *! 17-Dec-2001 ag STRMMODE_RDMA(DDMA) enabled.
8110 + *! 12-Dec-2001 ag Check for valid stream mode in NODE_Connect().
8111 + *! 04-Dec-2001 jeh Check for node sufficiently connected in NODE_Create().
8112 + *! 15-Nov-2001 jeh Removed DBC_Require(pNode->hXlator != NULL) from
8113 + *! NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
8114 + *! 11-Sep-2001 ag Zero-copy messaging support.
8115 + *! 28-Aug-2001 jeh Overlay/dynamic loader infrastructure added. Removed
8116 + *! NODE_GetDispatcher, excess node states.
8117 + *! 07-Aug-2001 jeh Removed critical section for dispatcher.
8118 + *! 26-Jul-2001 jeh Get ZL dll name through CFG.
8119 + *! 05-Jun-2001 jeh Assume DSP_STRMATTRS.uBufsize in GPP bytes.
8120 + *! 11-May-2001 jeh Some code review cleanup.
8121 + *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
8122 + *! 15-Dec-2000 sg Convert IALG_Fxn address from byte addr to word addr.
8123 + *! 04-Dec-2000 jeh Call MSG Get and Put functions.
8124 + *! 04-Dec-2000 ag Added SM support for node messaging.
8125 + *! 10-Nov-2000 rr: NODE_MIN/MAX Priority is defined in dspdefs.h.
8126 + *! 27-Oct-2000 jeh Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
8127 + *! 11-Oct-2000 jeh Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
8128 + *! NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
8129 + *! 19-Jun-2000 jeh Created.
8130 + */
8132 +/* ----------------------------------- Host OS */
8133 +#include <host_os.h>
8135 +/* ----------------------------------- DSP/BIOS Bridge */
8136 +#include <std.h>
8137 +#include <dbdefs.h>
8138 +#include <errbase.h>
8140 +/* ----------------------------------- Trace & Debug */
8141 +#include <dbc.h>
8142 +#include <gt.h>
8144 +/* ----------------------------------- OS Adaptation Layer */
8145 +#include <cfg.h>
8146 +#include <csl.h>
8147 +#include <list.h>
8148 +#include <mem.h>
8149 +#include <proc.h>
8150 +#include <strm.h>
8151 +#include <sync.h>
8152 +#include <ntfy.h>
8154 +/* ----------------------------------- Platform Manager */
8155 +#include <cmm.h>
8156 +#include <cod.h>
8157 +#include <dev.h>
8158 +#include <msg.h>
8160 +/* ----------------------------------- Resource Manager */
8161 +#include <dbdcd.h>
8162 +#include <disp.h>
8163 +#include <rms_sh.h>
8165 +/* ----------------------------------- Link Driver */
8166 +#include <wmd.h>
8167 +#include <wmdioctl.h>
8169 +/* ----------------------------------- Others */
8170 +#include <gb.h>
8171 +#ifdef DEBUG
8172 +#include <uuidutil.h>
8173 +#include <dbg.h>
8174 +#endif
8176 +/* ----------------------------------- This */
8177 +#include <nodepriv.h>
8178 +#include <node.h>
8180 +/* Static/Dynamic Loader includes */
8181 +#include <dbll.h>
8182 +#include <nldr.h>
8184 +#ifndef RES_CLEANUP_DISABLE
8185 +#include <drv.h>
8186 +#include <drvdefs.h>
8187 +#include <prcs.h>
8188 +#include <dbreg.h>
8189 +#include <resourcecleanup.h>
8190 +#endif
8192 +#ifndef CONFIG_DISABLE_BRIDGE_PM
8193 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
8194 +#include <asm/arch/resource.h>
8195 +#endif
8196 +#endif
8198 +#define NODE_SIGNATURE 0x45444f4e /* "EDON" */
8199 +#define NODEMGR_SIGNATURE 0x52474d4e /* "RGMN" */
8201 +#define HOSTPREFIX "/host"
8202 +#define PIPEPREFIX "/dbpipe"
8204 +#define MaxInputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
8205 +#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
8207 +#define NODE_GetPriority(h) ((h)->nPriority)
8208 +#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
8209 +#define NODE_SetState(hNode, state) ((hNode)->nState = state)
8211 +#define MAXPIPES 100 /* Max # of /pipe connections (CSL limit) */
8212 +#define MAXDEVSUFFIXLEN 2 /* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
8214 +#define PIPENAMELEN (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
8215 +#define HOSTNAMELEN (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
8217 +#define MAXDEVNAMELEN 32 /* DSP_NDBPROPS.acName size */
8218 +#define CREATEPHASE 1
8219 +#define EXECUTEPHASE 2
8220 +#define DELETEPHASE 3
8222 +/* Define default STRM parameters */
8224 + * TBD: Put in header file, make global DSP_STRMATTRS with defaults,
8225 + * or make defaults configurable.
8226 + */
8227 +#define DEFAULTBUFSIZE 32
8228 +#define DEFAULTNBUFS 2
8229 +#define DEFAULTSEGID 0
8230 +#define DEFAULTALIGNMENT 0
8231 +#define DEFAULTTIMEOUT 10000
8233 +#define RMSQUERYSERVER 0
8234 +#define RMSCONFIGURESERVER 1
8235 +#define RMSCREATENODE 2
8236 +#define RMSEXECUTENODE 3
8237 +#define RMSDELETENODE 4
8238 +#define RMSCHANGENODEPRIORITY 5
8239 +#define RMSREADMEMORY 6
8240 +#define RMSWRITEMEMORY 7
8241 +#define RMSCOPY 8
8242 +#define MAXTIMEOUT 2000
8244 +#define NUMRMSFXNS 9
8246 +#define PWR_TIMEOUT 500 /* default PWR timeout in msec */
8248 +#define STACKSEGLABEL "L1DSRAM_HEAP" /* Label for DSP Stack Segment Address */
8251 + * ======== NODE_MGR ========
8252 + */
8253 +struct NODE_MGR {
8254 + u32 dwSignature; /* For object validation */
8255 + struct DEV_OBJECT *hDevObject; /* Device object */
8256 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
8257 + struct DCD_MANAGER *hDcdMgr; /* Proc/Node data manager */
8258 + struct DISP_OBJECT *hDisp; /* Node dispatcher */
8259 + struct LST_LIST *nodeList; /* List of all allocated nodes */
8260 + u32 uNumNodes; /* Number of nodes in nodeList */
8261 + u32 uNumCreated; /* Number of nodes *created* on DSP */
8262 + struct GB_TMap *pipeMap; /* Pipe connection bit map */
8263 + struct GB_TMap *pipeDoneMap; /* Pipes that are half free */
8264 + struct GB_TMap *chnlMap; /* Channel allocation bit map */
8265 + struct GB_TMap *dmaChnlMap; /* DMA Channel allocation bit map */
8266 + struct GB_TMap *zChnlMap; /* Zero-Copy Channel alloc bit map */
8267 + struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
8268 + struct SYNC_CSOBJECT *hSync; /* For critical sections */
8269 + struct SYNC_CSOBJECT *hAllocSync; /* For NODE_Alloc critical sections */
8270 + u32 ulFxnAddrs[NUMRMSFXNS]; /* RMS function addresses */
8271 + struct MSG_MGR *hMsg;
8273 + /* Processor properties needed by Node Dispatcher */
8274 + u32 ulNumChnls; /* Total number of channels */
8275 + u32 ulChnlOffset; /* Offset of chnl ids rsvd for RMS */
8276 + u32 ulChnlBufSize; /* Buffer size for data to RMS */
8277 + DSP_PROCFAMILY procFamily; /* eg, 5000 */
8278 + DSP_PROCTYPE procType; /* eg, 5510 */
8279 + u32 uDSPWordSize; /* Size of DSP word on host bytes */
8280 + u32 uDSPDataMauSize; /* Size of DSP data MAU */
8281 + u32 uDSPMauSize; /* Size of MAU */
8282 + s32 nMinPri; /* Minimum runtime priority for node */
8283 + s32 nMaxPri; /* Maximum runtime priority for node */
8285 + struct STRM_MGR *hStrmMgr; /* STRM manager */
8287 + /* Loader properties */
8288 + struct NLDR_OBJECT *hNldr; /* Handle to loader */
8289 + struct NLDR_FXNS nldrFxns; /* Handle to loader functions */
8290 + bool fLoaderInit; /* Loader Init function succeeded? */
8294 + * ======== CONNECTTYPE ========
8295 + */
8296 +enum CONNECTTYPE {
8297 + NOTCONNECTED = 0,
8298 + NODECONNECT,
8299 + HOSTCONNECT,
8300 + DEVICECONNECT,
8301 +} ;
8304 + * ======== STREAM ========
8305 + */
8306 +struct STREAM {
8307 + enum CONNECTTYPE type; /* Type of stream connection */
8308 + u32 devId; /* pipe or channel id */
8312 + * ======== NODE_OBJECT ========
8313 + */
8314 +struct NODE_OBJECT {
8315 + struct LST_ELEM listElem;
8316 + u32 dwSignature; /* For object validation */
8317 + struct NODE_MGR *hNodeMgr; /* The manager of this node */
8318 + struct PROC_OBJECT *hProcessor; /* Back pointer to processor */
8319 + struct DSP_UUID nodeId; /* Node's ID */
8320 + s32 nPriority; /* Node's current priority */
8321 + u32 uTimeout; /* Timeout for blocking NODE calls */
8322 + u32 uHeapSize; /* Heap Size */
8323 + u32 uDSPHeapVirtAddr; /* Heap Size */
8324 + u32 uGPPHeapVirtAddr; /* Heap Size */
8325 + enum NODE_TYPE nType; /* Type of node: message, task, etc */
8326 + enum NODE_STATE nState; /* NODE_ALLOCATED, NODE_CREATED, ... */
8327 + u32 uNumInputs; /* Current number of inputs */
8328 + u32 uNumOutputs; /* Current number of outputs */
8329 + u32 uMaxInputIndex; /* Current max input stream index */
8330 + u32 uMaxOutputIndex; /* Current max output stream index */
8331 + struct STREAM *inputs; /* Node's input streams */
8332 + struct STREAM *outputs; /* Node's output streams */
8333 + struct NODE_CREATEARGS createArgs; /* Args for node create function */
8334 + NODE_ENV nodeEnv; /* Environment returned by RMS */
8335 + struct DCD_GENERICOBJ dcdProps; /* Node properties from DCD */
8336 + struct DSP_CBDATA *pArgs; /* Optional args to pass to node */
8337 + struct NTFY_OBJECT *hNtfy; /* Manages registered notifications */
8338 + char *pstrDevName; /* device name, if device node */
8339 + struct SYNC_OBJECT *hSyncDone; /* Synchronize NODE_Terminate */
8340 + s32 nExitStatus; /* execute function return status */
8342 + /* Information needed for NODE_GetAttr() */
8343 + DSP_HNODE hDeviceOwner; /* If dev node, task that owns it */
8344 + u32 uNumGPPInputs; /* Current # of from GPP streams */
8345 + u32 uNumGPPOutputs; /* Current # of to GPP streams */
8346 + /* Current stream connections */
8347 + struct DSP_STREAMCONNECT *streamConnect;
8349 + /* Message queue */
8350 + struct MSG_QUEUE *hMsgQueue;
8352 + /* These fields used for SM messaging */
8353 + struct CMM_XLATOROBJECT *hXlator; /* Node's SM address translator */
8355 + /* Handle to pass to dynamic loader */
8356 + struct NLDR_NODEOBJECT *hNldrNode;
8357 + bool fLoaded; /* Code is (dynamically) loaded */
8358 + bool fPhaseSplit; /* Phases split in many libs or ovly */
8360 +} ;
8362 +/* Default buffer attributes */
8363 +struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
8364 + 0, /* cbStruct */
8365 + 1, /* uSegment */
8366 + 0, /* uAlignment */
8369 +static void DeleteNode(struct NODE_OBJECT *hNode);
8370 +static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
8371 +static void FillStreamConnect(struct NODE_OBJECT *hNode1,
8372 + struct NODE_OBJECT *hNode2, u32 uStream1,
8373 + u32 uStream2);
8374 +static void FillStreamDef(struct NODE_OBJECT *hNode,
8375 + struct NODE_STRMDEF *pstrmDef,
8376 + struct DSP_STRMATTR *pAttrs);
8377 +static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
8378 +static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
8379 + u32 uPhase);
8380 +static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
8381 + struct NODE_OBJECT *hNode,
8382 + CONST struct DSP_UUID *pNodeId,
8383 + struct DCD_GENERICOBJ *pdcdProps);
8384 +static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
8385 + struct DEV_OBJECT *hDevObject);
8386 +static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
8387 +static CDECL u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
8388 + u32 ulNumBytes, u32 nMemSpace);
8389 +static CDECL u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
8390 + u32 ulNumBytes, u32 nMemSpace);
8391 +#if GT_TRACE
8392 +static struct GT_Mask NODE_debugMask = { NULL, NULL }; /* GT trace variable */
8393 +#endif
8395 +static u32 cRefs; /* module reference count */
8397 +/* Dynamic loader functions. */
8398 +static struct NLDR_FXNS nldrFxns = {
8399 + NLDR_Allocate,
8400 + NLDR_Create,
8401 + NLDR_Delete,
8402 + NLDR_Exit,
8403 + NLDR_Free,
8404 + NLDR_GetFxnAddr,
8405 + NLDR_Init,
8406 + NLDR_Load,
8407 + NLDR_Unload,
8410 +#ifndef CONFIG_DISABLE_BRIDGE_PM
8411 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
8412 +extern struct constraint_handle *mpu_constraint_handle;
8413 +/*The maximum number of OPPs that DSP bridge can request */
8414 +extern s32 dsp_max_opps;
8415 +#endif
8416 +#endif
8418 +enum NODE_STATE NODE_GetState(HANDLE hNode)
8420 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
8421 + return pNode->nState;
8425 + * ======== NODE_Allocate ========
8426 + * Purpose:
8427 + * Allocate GPP resources to manage a node on the DSP.
8428 + */
8429 +DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
8430 + IN CONST struct DSP_UUID *pNodeId,
8431 + OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
8432 + OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
8433 + OUT struct NODE_OBJECT **phNode)
8435 + struct NODE_MGR *hNodeMgr;
8436 + struct DEV_OBJECT *hDevObject;
8437 + struct NODE_OBJECT *pNode = NULL;
8438 + enum NODE_TYPE nodeType = NODE_TASK;
8439 + struct NODE_MSGARGS *pmsgArgs;
8440 + struct NODE_TASKARGS *ptaskArgs;
8441 + u32 uNumStreams;
8442 + struct WMD_DRV_INTERFACE *pIntfFxns;
8443 + DSP_STATUS status = DSP_SOK;
8444 + struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
8445 + u32 procId;
8446 + char *label;
8447 + u32 pulValue;
8448 + u32 dynextBase;
8449 + u32 offSet = 0;
8450 + u32 ulStackSegAddr, ulStackSegVal;
8451 + u32 ulGppMemBase;
8452 + struct CFG_HOSTRES hostRes;
8453 + u32 pMappedAddr = 0;
8454 + u32 mapAttrs = 0x0;
8456 +#ifndef RES_CLEANUP_DISABLE
8458 + HANDLE hDrvObject;
8459 + HANDLE nodeRes;
8460 + HANDLE hProcess;
8461 + struct PROCESS_CONTEXT *pPctxt = NULL;
8462 + DSP_STATUS res_status = DSP_SOK;
8464 +#endif
8466 + DBC_Require(cRefs > 0);
8467 + DBC_Require(hProcessor != NULL);
8468 + DBC_Require(phNode != NULL);
8469 + DBC_Require(pNodeId != NULL);
8471 + GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
8472 + "0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
8473 + "0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
8474 + phNode);
8476 + *phNode = NULL;
8478 + status = PROC_GetProcessorId(hProcessor, &procId);
8480 + status = PROC_GetDevObject(hProcessor, &hDevObject);
8481 + if (DSP_SUCCEEDED(status)) {
8482 + status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
8483 + if (hNodeMgr == NULL)
8484 + status = DSP_EFAIL;
8487 + if (procId != DSP_UNIT)
8488 + goto func_cont;
8490 + if (DSP_FAILED(status))
8491 + goto func_cont;
8493 + /* Assuming that 0 is not a valid function address */
8494 + if (hNodeMgr->ulFxnAddrs[0] == 0) {
8495 + /* No RMS on target - we currently can't handle this */
8496 + GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
8497 + "image. Node allocation fails.\n");
8498 + status = DSP_EFAIL;
8499 + } else {
8500 + /* Validate pAttrIn fields, if non-NULL */
8501 + if (pAttrIn) {
8502 + /* Check if pAttrIn->iPriority is within range */
8503 + if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
8504 + pAttrIn->iPriority > hNodeMgr->nMaxPri)
8505 + status = DSP_ERANGE;
8508 +func_cont:
8509 + /* Allocate node object and fill in */
8510 + if (DSP_FAILED(status))
8511 + goto func_cont2;
8513 + MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
8514 + if (pNode == NULL) {
8515 + status = DSP_EMEMORY;
8516 + goto func_cont1;
8518 + pNode->hNodeMgr = hNodeMgr;
8519 + /* This critical section protects GetNodeProps */
8520 + status = SYNC_EnterCS(hNodeMgr->hAllocSync);
8521 + if (procId != DSP_UNIT)
8522 + goto func_cont3;
8524 + /* Get DSP_NDBPROPS from node database */
8525 + status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
8526 + &(pNode->dcdProps));
8527 + if (DSP_FAILED(status))
8528 + goto func_cont3;
8530 + pNode->nodeId = *pNodeId;
8531 + pNode->hProcessor = hProcessor;
8532 + pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
8533 + pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
8534 + pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
8536 + /* Currently only C64 DSP builds support Node Dynamic * heaps */
8537 + /* Allocate memory for node heap */
8538 + pNode->createArgs.asa.taskArgs.uHeapSize = 0;
8539 + pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
8540 + pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
8541 + pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
8542 + if (!pAttrIn)
8543 + goto func_cont3;
8545 + /* Check if we have a user allocated node heap */
8546 + if (!(pAttrIn->pGPPVirtAddr))
8547 + goto func_cont3;
8549 + /* check for page aligned Heap size */
8550 + if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
8551 + GT_1trace(NODE_debugMask, GT_7CLASS,
8552 + "NODE_Allocate: node heap page size"
8553 + " not aligned to 4K page, size=0x%x \n",
8554 + pAttrIn->uHeapSize);
8555 + status = DSP_EINVALIDARG;
8556 + } else {
8557 + pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
8558 + pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
8559 + (u32)pAttrIn->pGPPVirtAddr;
8561 + if (DSP_FAILED(status))
8562 + goto func_cont3;
8564 + status = PROC_ReserveMemory(hProcessor,
8565 + pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
8566 + (void **)&(pNode->createArgs.asa.taskArgs.
8567 + uDSPHeapResAddr));
8568 + if (DSP_FAILED(status)) {
8569 + GT_1trace(NODE_debugMask, GT_5CLASS,
8570 + "NODE_Allocate:Failed to reserve "
8571 + "memory for Heap: 0x%x\n", status);
8572 + } else {
8573 + GT_1trace(NODE_debugMask, GT_5CLASS,
8574 + "NODE_Allocate: DSPProcessor_Reserve"
8575 + " Memory successful: 0x%x\n", status);
8577 + if (DSP_FAILED(status))
8578 + goto func_cont3;
8580 + mapAttrs |= DSP_MAPLITTLEENDIAN;
8581 + mapAttrs |= DSP_MAPELEMSIZE32;
8582 + mapAttrs |= DSP_MAPVIRTUALADDR;
8583 + status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
8584 + pNode->createArgs.asa.taskArgs.uHeapSize,
8585 + (void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
8586 + (void **)&pMappedAddr, mapAttrs);
8587 + if (DSP_FAILED(status)) {
8588 + GT_1trace(NODE_debugMask, GT_5CLASS,
8589 + "NODE_Allocate: Failed to map memory"
8590 + " for Heap: 0x%x\n", status);
8591 + } else {
8592 + pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
8593 + (u32) pMappedAddr;
8594 + GT_1trace(NODE_debugMask, GT_5CLASS,
8595 + "NODE_Allocate:DSPProcessor_Map"
8596 + " successful: 0x%x\n", status);
8599 +func_cont3:
8600 + (void)SYNC_LeaveCS(hNodeMgr->hAllocSync);
8601 +func_cont1:
8602 + if (pAttrIn != NULL) {
8603 + /* Overrides of NBD properties */
8604 + pNode->uTimeout = pAttrIn->uTimeout;
8605 + pNode->nPriority = pAttrIn->iPriority;
8607 +func_cont2:
8608 + /* Create object to manage notifications */
8609 + if (DSP_SUCCEEDED(status))
8610 + status = NTFY_Create(&pNode->hNtfy);
8612 + if (DSP_SUCCEEDED(status)) {
8613 + nodeType = NODE_GetType(pNode);
8614 + /* Allocate DSP_STREAMCONNECT array for device, task, and
8615 + * dais socket nodes. */
8616 + if (nodeType != NODE_MESSAGE) {
8617 + uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
8618 + pNode->streamConnect = MEM_Calloc(uNumStreams *
8619 + sizeof(struct DSP_STREAMCONNECT),
8620 + MEM_PAGED);
8621 + if (uNumStreams > 0 && pNode->streamConnect == NULL)
8622 + status = DSP_EMEMORY;
8625 + if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
8626 + nodeType == NODE_DAISSOCKET)) {
8627 + /* Allocate arrays for maintainig stream connections */
8628 + pNode->inputs =
8629 + MEM_Calloc(MaxInputs(pNode) *
8630 + sizeof(struct STREAM), MEM_PAGED);
8631 + pNode->outputs =
8632 + MEM_Calloc(MaxOutputs(pNode) *
8633 + sizeof(struct STREAM), MEM_PAGED);
8634 + ptaskArgs = &(pNode->createArgs.asa.taskArgs);
8635 + ptaskArgs->strmInDef =
8636 + MEM_Calloc(MaxInputs(pNode) *
8637 + sizeof(struct NODE_STRMDEF),
8638 + MEM_PAGED);
8639 + ptaskArgs->strmOutDef =
8640 + MEM_Calloc(MaxOutputs(pNode) *
8641 + sizeof(struct NODE_STRMDEF),
8642 + MEM_PAGED);
8643 + if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
8644 + ptaskArgs->strmInDef == NULL)) ||
8645 + (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
8646 + ptaskArgs->strmOutDef == NULL)))
8647 + status = DSP_EMEMORY;
8650 + if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
8651 + /* Create an event that will be posted when RMS_EXIT is
8652 + * received. */
8653 + status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
8654 + if (DSP_SUCCEEDED(status)) {
8655 + /*Get the shared mem mgr for this nodes dev object */
8656 + status = CMM_GetHandle(hProcessor, &hCmmMgr);
8657 + if (DSP_FAILED(status)) {
8658 + GT_1trace(NODE_debugMask, GT_5CLASS,
8659 + "NODE_Allocate: Failed to"
8660 + " get CMM Mgr handle: 0x%x\n", status);
8661 + } else {
8662 + /* Allocate a SM addr translator for this node
8663 + * w/ deflt attr */
8664 + status = CMM_XlatorCreate(&pNode->hXlator,
8665 + hCmmMgr, NULL);
8666 + if (DSP_FAILED(status)) {
8667 + GT_1trace(NODE_debugMask, GT_5CLASS,
8668 + "NODE_Allocate: Failed"
8669 + " to create SM translator: 0x%x\n",
8670 + status);
8674 + if (DSP_SUCCEEDED(status)) {
8675 + /* Fill in message args */
8676 + if ((pArgs != NULL) && (pArgs->cbData > 0)) {
8677 + pmsgArgs = &(pNode->createArgs.asa.msgArgs);
8678 + pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
8679 + MEM_PAGED);
8680 + if (pmsgArgs->pData == NULL) {
8681 + status = DSP_EMEMORY;
8682 + } else {
8683 + pmsgArgs->uArgLength = pArgs->cbData;
8684 + memcpy(pmsgArgs->pData, pArgs->cData,
8685 + pArgs->cbData);
8691 + if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
8692 + /* Create a message queue for this node */
8693 + pIntfFxns = hNodeMgr->pIntfFxns;
8694 + status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
8695 + &pNode->hMsgQueue, 0,
8696 + pNode->createArgs.asa.msgArgs.uMaxMessages,
8697 + pNode);
8700 + if (DSP_SUCCEEDED(status)) {
8701 + /* Create object for dynamic loading */
8703 + status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
8704 + (void *) pNode,
8705 + &pNode->dcdProps.objData.nodeObj,
8706 + &pNode->hNldrNode,
8707 + &pNode->fPhaseSplit);
8708 + if (DSP_FAILED(status)) {
8709 + GT_1trace(NODE_debugMask, GT_5CLASS,
8710 + "NODE_Allocate: Failed to "
8711 + "allocate NLDR node: 0x%x\n", status);
8715 + /* Comapare value read from Node Properties and check if it is same as
8716 + * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
8717 + * GPP Address, Read the value in that address and override the
8718 + * uStackSeg value in task args */
8719 + if (DSP_SUCCEEDED(status) &&
8720 + (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
8721 + NULL) {
8722 + label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
8723 + CSL_Strcpyn(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
8725 + if (CSL_Strcmp((char *)pNode->dcdProps.objData.nodeObj.
8726 + ndbProps.uStackSegName, label) == 0) {
8727 + status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
8728 + hNldrNode, "DYNEXT_BEG", &dynextBase);
8729 + if (DSP_FAILED(status)) {
8730 + GT_1trace(NODE_debugMask, GT_5CLASS,
8731 + "NODE_Allocate: Failed to get Address for "
8732 + "DYNEXT_BEG: 0x%x\n", status);
8735 + status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
8736 + hNldrNode, "L1DSRAM_HEAP", &pulValue);
8738 + if (DSP_FAILED(status)) {
8739 + GT_1trace(NODE_debugMask, GT_5CLASS,
8740 + "NODE_Allocate: Failed to get Address for "
8741 + "L1DSRAM_HEAP: 0x%x\n", status);
8744 + status = CFG_GetHostResources((struct CFG_DEVNODE *)
8745 + DRV_GetFirstDevExtension(), &hostRes);
8747 + if (DSP_FAILED(status)) {
8748 + GT_1trace(NODE_debugMask, GT_5CLASS,
8749 + "NODE_Allocate: Failed to get host resource "
8750 + "0x%x\n", status);
8753 + ulGppMemBase = hostRes.dwMemBase[1];
8754 + offSet = pulValue - dynextBase;
8755 + ulStackSegAddr = ulGppMemBase + offSet;
8756 + ulStackSegVal = (u32)*((REG_UWORD32 *)
8757 + ((u32)(ulStackSegAddr)));
8759 + GT_1trace(NODE_debugMask, GT_5CLASS,
8760 + "StackSegVal =0x%x\n", ulStackSegVal);
8761 + GT_1trace(NODE_debugMask, GT_5CLASS,
8762 + "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
8764 + pNode->createArgs.asa.taskArgs.uStackSeg =
8765 + ulStackSegVal;
8769 + if (label)
8770 + MEM_Free(label);
8775 + if (DSP_SUCCEEDED(status)) {
8776 + /* Add the node to the node manager's list of allocated
8777 + * nodes. */
8778 + LST_InitElem((struct LST_ELEM *)pNode);
8779 + NODE_SetState(pNode, NODE_ALLOCATED);
8781 + status = SYNC_EnterCS(hNodeMgr->hSync);
8783 + if (DSP_SUCCEEDED(status)) {
8784 + LST_PutTail(hNodeMgr->nodeList,
8785 + (struct LST_ELEM *) pNode);
8786 + ++(hNodeMgr->uNumNodes);
8789 + /* Exit critical section */
8790 + (void) SYNC_LeaveCS(hNodeMgr->hSync);
8792 + /* Preset this to assume phases are split
8793 + * (for overlay and dll) */
8794 + pNode->fPhaseSplit = true;
8796 + if (DSP_SUCCEEDED(status))
8797 + *phNode = pNode;
8800 + /* Notify all clients registered for DSP_NODESTATECHANGE. */
8801 + PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
8802 + } else {
8803 + /* Cleanup */
8804 + if (pNode)
8805 + DeleteNode(pNode);
8809 +#ifndef RES_CLEANUP_DISABLE
8810 + if (DSP_SUCCEEDED(status)) {
8811 + PRCS_GetCurrentHandle(&hProcess);
8812 + res_status = CFG_GetObject((u32 *)&hDrvObject,
8813 + REG_DRV_OBJECT);
8814 + if (DSP_SUCCEEDED(res_status)) {
8815 + DRV_GetProcContext(hProcess, hDrvObject, &pPctxt,
8816 + *phNode, 0);
8817 + if (pPctxt == NULL) {
8818 + DRV_InsertProcContext(hDrvObject, &pPctxt);
8819 + if (pPctxt != NULL) {
8820 + DRV_ProcUpdatestate(pPctxt,
8821 + PROC_RES_ALLOCATED);
8822 + DRV_ProcSetPID(pPctxt, (s32) hProcess);
8823 + pPctxt->hProcessor =
8824 + (DSP_HPROCESSOR)hProcessor;
8829 + if (DSP_SUCCEEDED(status)) {
8830 + PRCS_GetCurrentHandle(&hProcess);
8831 + res_status = CFG_GetObject((u32 *)&hDrvObject,
8832 + REG_DRV_OBJECT);
8833 + if (DSP_SUCCEEDED(res_status)) {
8834 + DRV_GetProcContext(hProcess, hDrvObject, &pPctxt,
8835 + *phNode, 0);
8836 + if (pPctxt != NULL) {
8837 + DRV_InsertNodeResElement(*phNode, &nodeRes,
8838 + pPctxt);
8839 + DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
8840 + DRV_ProcNodeUpdateStatus(nodeRes, true);
8844 +#endif
8845 + DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
8846 + (DSP_SUCCEEDED(status)
8847 + && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
8848 + return status;
8852 + * ======== NODE_AllocMsgBuf ========
8853 + * Purpose:
8854 + * Allocates buffer for zero copy messaging.
8855 + */
8856 +DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
8857 + OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
8858 + OUT u8 **pBuffer)
8860 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
8861 + DSP_STATUS status = DSP_SOK;
8862 + bool bVirtAddr = false;
8863 + bool bSetInfo;
8864 + u32 procId;
8866 + DBC_Require(cRefs > 0);
8867 + DBC_Require(pBuffer != NULL);
8869 + DBC_Require(uSize > 0);
8871 + GT_4trace(NODE_debugMask, GT_ENTER,
8872 + "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
8873 + " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
8874 + pBuffer);
8876 + if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
8877 + status = DSP_EHANDLE;
8879 + if (NODE_GetType(pNode) == NODE_DEVICE)
8880 + status = DSP_ENODETYPE;
8882 + if (DSP_FAILED(status))
8883 + goto func_end;
8885 + if (pAttr == NULL)
8886 + pAttr = &NODE_DFLTBUFATTRS; /* set defaults */
8888 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
8889 + if (procId != DSP_UNIT) {
8890 + DBC_Assert(NULL);
8891 + goto func_end;
8893 + /* If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
8894 + * virt address, so set this info in this node's translator
8895 + * object for future ref. If MEM_GETVIRTUALSEGID then retrieve
8896 + * virtual address from node's translator. */
8897 + if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
8898 + (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
8899 + bVirtAddr = true;
8900 + bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
8901 + true : false;
8902 + pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
8903 + /* Set/get this node's translators virtual address base/size */
8904 + status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
8905 + pAttr->uSegment, bSetInfo);
8906 + if (DSP_FAILED(status)) {
8907 + GT_1trace(NODE_debugMask, GT_7CLASS,
8908 + "NODE_AllocMsgBuf "
8909 + "failed: 0x%lx\n", status);
8912 + if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
8913 + if (pAttr->uSegment != 1) {
8914 + /* Node supports single SM segment only. */
8915 + status = DSP_EBADSEGID;
8917 + /* Arbitrary SM buffer alignment not supported for host side
8918 + * allocs, but guaranteed for the following alignment
8919 + * values. */
8920 + switch (pAttr->uAlignment) {
8921 + case 0:
8922 + case 1:
8923 + case 2:
8924 + case 4:
8925 + break;
8926 + default:
8927 + /* alignment value not suportted */
8928 + status = DSP_EALIGNMENT;
8929 + break;
8931 + if (DSP_SUCCEEDED(status)) {
8932 + /* allocate physical buffer from segId in node's
8933 + * translator */
8934 + (void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
8935 + uSize);
8936 + if (*pBuffer == NULL) {
8937 + GT_0trace(NODE_debugMask, GT_7CLASS,
8938 + "NODE_AllocMsgBuf: "
8939 + "ERROR: Out of shared memory.\n");
8940 + status = DSP_EMEMORY;
8944 +func_end:
8945 + return status;
8949 + * ======== NODE_ChangePriority ========
8950 + * Purpose:
8951 + * Change the priority of a node in the allocated state, or that is
8952 + * currently running or paused on the target.
8953 + */
8954 +DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
8956 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
8957 + struct NODE_MGR *hNodeMgr = NULL;
8958 + enum NODE_TYPE nodeType;
8959 + enum NODE_STATE state;
8960 + DSP_STATUS status = DSP_SOK;
8961 + u32 procId;
8963 + DBC_Require(cRefs > 0);
8965 + GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
8966 + "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
8968 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
8969 + GT_1trace(NODE_debugMask, GT_7CLASS,
8970 + "Invalid NODE Handle: 0x%x\n", hNode);
8971 + status = DSP_EHANDLE;
8972 + } else {
8973 + hNodeMgr = hNode->hNodeMgr;
8974 + nodeType = NODE_GetType(hNode);
8975 + if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
8976 + status = DSP_ENODETYPE;
8977 + else if (nPriority < hNodeMgr->nMinPri ||
8978 + nPriority > hNodeMgr->nMaxPri)
8979 + status = DSP_ERANGE;
8981 + if (DSP_FAILED(status))
8982 + goto func_end;
8984 + /* Enter critical section */
8985 + status = SYNC_EnterCS(hNodeMgr->hSync);
8986 + if (DSP_FAILED(status))
8987 + goto func_cont;
8989 + state = NODE_GetState(hNode);
8990 + if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
8991 + NODE_SetPriority(hNode, nPriority);
8992 + } else {
8993 + if (state != NODE_RUNNING) {
8994 + status = DSP_EWRONGSTATE;
8995 + goto func_cont;
8997 + if (DSP_SUCCEEDED(status)) {
8998 + status = PROC_GetProcessorId(pNode->hProcessor,
8999 + &procId);
9000 + if (procId == DSP_UNIT) {
9001 + status = DISP_NodeChangePriority(hNodeMgr->
9002 + hDisp, hNode,
9003 + hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
9004 + hNode->nodeEnv, nPriority);
9006 + if (DSP_SUCCEEDED(status))
9007 + NODE_SetPriority(hNode, nPriority);
9011 +func_cont:
9012 + /* Leave critical section */
9013 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
9014 +func_end:
9015 + return status;
9019 + * ======== NODE_Connect ========
9020 + * Purpose:
9021 + * Connect two nodes on the DSP, or a node on the DSP to the GPP.
9022 + */
9023 +DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
9024 + struct NODE_OBJECT *hNode2,
9025 + u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
9026 + OPTIONAL IN struct DSP_CBDATA *pConnParam)
9028 + struct NODE_MGR *hNodeMgr;
9029 + char *pstrDevName = NULL;
9030 + char *pstrDevName1;
9031 + char *pstrDevName2;
9032 + enum NODE_TYPE node1Type = NODE_TASK;
9033 + enum NODE_TYPE node2Type = NODE_TASK;
9034 + struct NODE_STRMDEF *pstrmDef;
9035 + struct NODE_STRMDEF *pInput = NULL;
9036 + struct NODE_STRMDEF *pOutput = NULL;
9037 + struct NODE_OBJECT *hDevNode;
9038 + struct NODE_OBJECT *hNode;
9039 + struct STREAM *pStream;
9040 + GB_BitNum pipeId = GB_NOBITS;
9041 + GB_BitNum chnlId = GB_NOBITS;
9042 + CHNL_MODE uMode;
9043 + u32 dwLength;
9044 + DSP_STATUS status = DSP_SOK;
9045 + DBC_Require(cRefs > 0);
9046 + GT_5trace(NODE_debugMask, GT_ENTER,
9047 + "NODE_Connect: hNode1: 0x%x\tuStream1:"
9048 + " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
9049 + uStream1, hNode2, uStream2, pAttrs);
9050 + if (DSP_SUCCEEDED(status)) {
9051 + if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
9052 + !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
9053 + (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
9054 + !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
9055 + status = DSP_EHANDLE;
9057 + if (DSP_SUCCEEDED(status)) {
9058 + /* The two nodes must be on the same processor */
9059 + if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
9060 + hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
9061 + hNode1->hNodeMgr != hNode2->hNodeMgr)
9062 + status = DSP_EFAIL;
9063 + /* Cannot connect a node to itself */
9064 + if (hNode1 == hNode2)
9065 + status = DSP_EFAIL;
9068 + if (DSP_SUCCEEDED(status)) {
9069 + /* NODE_GetType() will return NODE_GPP if hNode =
9070 + * DSP_HGPPNODE. */
9071 + node1Type = NODE_GetType(hNode1);
9072 + node2Type = NODE_GetType(hNode2);
9073 + /* Check stream indices ranges */
9074 + if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
9075 + uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
9076 + node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
9077 + status = DSP_EVALUE;
9079 + if (DSP_SUCCEEDED(status)) {
9080 + /*
9081 + * Only the following types of connections are allowed:
9082 + * task/dais socket < == > task/dais socket
9083 + * task/dais socket < == > device
9084 + * task/dais socket < == > GPP
9086 + * ie, no message nodes, and at least one task or dais
9087 + * socket node.
9088 + */
9089 + if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
9090 + (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
9091 + node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
9092 + status = DSP_EFAIL;
9094 + /*
9095 + * Check stream mode. Default is STRMMODE_PROCCOPY.
9096 + */
9097 + if (DSP_SUCCEEDED(status) && pAttrs) {
9098 + if (pAttrs->lMode != STRMMODE_PROCCOPY)
9099 + status = DSP_ESTRMMODE; /* illegal stream mode */
9102 + if (DSP_FAILED(status))
9103 + goto func_end;
9105 + if (node1Type != NODE_GPP) {
9106 + hNodeMgr = hNode1->hNodeMgr;
9107 + } else {
9108 + DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
9109 + hNodeMgr = hNode2->hNodeMgr;
9111 + /* Enter critical section */
9112 + status = SYNC_EnterCS(hNodeMgr->hSync);
9113 + if (DSP_FAILED(status))
9114 + goto func_cont;
9116 + /* Nodes must be in the allocated state */
9117 + if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
9118 + status = DSP_EWRONGSTATE;
9120 + if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
9121 + status = DSP_EWRONGSTATE;
9123 + if (DSP_SUCCEEDED(status)) {
9124 + /* Check that stream indices for task and dais socket nodes
9125 + * are not already be used. (Device nodes checked later) */
9126 + if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
9127 + pOutput = &(hNode1->createArgs.asa.taskArgs.
9128 + strmOutDef[uStream1]);
9129 + if (pOutput->szDevice != NULL)
9130 + status = DSP_EALREADYCONNECTED;
9133 + if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
9134 + pInput = &(hNode2->createArgs.asa.taskArgs.
9135 + strmInDef[uStream2]);
9136 + if (pInput->szDevice != NULL)
9137 + status = DSP_EALREADYCONNECTED;
9141 + /* Connecting two task nodes? */
9142 + if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
9143 + node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
9144 + node2Type == NODE_DAISSOCKET))) {
9145 + /* Find available pipe */
9146 + pipeId = GB_findandset(hNodeMgr->pipeMap);
9147 + if (pipeId == GB_NOBITS) {
9148 + status = DSP_ENOMORECONNECTIONS;
9149 + } else {
9150 + hNode1->outputs[uStream1].type = NODECONNECT;
9151 + hNode2->inputs[uStream2].type = NODECONNECT;
9152 + hNode1->outputs[uStream1].devId = pipeId;
9153 + hNode2->inputs[uStream2].devId = pipeId;
9154 + pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
9155 + MEM_PAGED);
9156 + pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
9157 + MEM_PAGED);
9158 + if (pOutput->szDevice == NULL ||
9159 + pInput->szDevice == NULL) {
9160 + /* Undo the connection */
9161 + if (pOutput->szDevice)
9162 + MEM_Free(pOutput->szDevice);
9164 + if (pInput->szDevice)
9165 + MEM_Free(pInput->szDevice);
9167 + pOutput->szDevice = NULL;
9168 + pInput->szDevice = NULL;
9169 + GB_clear(hNodeMgr->pipeMap, pipeId);
9170 + status = DSP_EMEMORY;
9171 + } else {
9172 + /* Copy "/dbpipe<pipId>" name to device names */
9173 + pstrDevName1 = pOutput->szDevice;
9174 + CSL_Strcpyn(pstrDevName1, PIPEPREFIX,
9175 + sizeof(PIPEPREFIX));
9176 + pstrDevName1 += CSL_Strlen(pstrDevName1);
9177 + CSL_NumToAscii(pstrDevName1, pipeId);
9178 + pstrDevName1 = pOutput->szDevice;
9179 + pstrDevName2 = pInput->szDevice;
9180 + CSL_Strcpyn(pstrDevName2, pstrDevName1,
9181 + PIPENAMELEN);
9185 + /* Connecting task node to host? */
9186 + if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
9187 + node2Type == NODE_GPP)) {
9188 + if (node1Type == NODE_GPP) {
9189 + uMode = CHNL_MODETODSP;
9190 + } else {
9191 + DBC_Assert(node2Type == NODE_GPP);
9192 + uMode = CHNL_MODEFROMDSP;
9194 + /* Reserve a channel id. We need to put the name "/host<id>"
9195 + * in the node's createArgs, but the host
9196 + * side channel will not be opened until DSPStream_Open is
9197 + * called for this node. */
9198 + if (pAttrs) {
9199 + if (pAttrs->lMode == STRMMODE_RDMA) {
9200 + chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
9201 + /* dma chans are 2nd transport chnl set
9202 + * ids(e.g. 16-31)*/
9203 + (chnlId != GB_NOBITS) ?
9204 + (chnlId = chnlId + hNodeMgr->ulNumChnls) :
9205 + chnlId;
9206 + } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
9207 + chnlId = GB_findandset(hNodeMgr->zChnlMap);
9208 + /* zero-copy chans are 3nd transport set
9209 + * (e.g. 32-47) */
9210 + (chnlId != GB_NOBITS) ? (chnlId = chnlId +
9211 + (2 * hNodeMgr->ulNumChnls)) : chnlId;
9212 + } else { /* must be PROCCOPY */
9213 + DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
9214 + chnlId = GB_findandset(hNodeMgr->chnlMap);
9215 + /* e.g. 0-15 */
9217 + } else {
9218 + /* default to PROCCOPY */
9219 + chnlId = GB_findandset(hNodeMgr->chnlMap);
9221 + if (chnlId == GB_NOBITS) {
9222 + status = DSP_ENOMORECONNECTIONS;
9223 + goto func_cont2;
9225 + pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
9226 + if (pstrDevName != NULL)
9227 + goto func_cont2;
9229 + if (pAttrs) {
9230 + if (pAttrs->lMode == STRMMODE_RDMA) {
9231 + GB_clear(hNodeMgr->dmaChnlMap, chnlId -
9232 + hNodeMgr->ulNumChnls);
9233 + } else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
9234 + GB_clear(hNodeMgr->zChnlMap, chnlId -
9235 + (2*hNodeMgr->ulNumChnls));
9236 + } else {
9237 + DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
9238 + GB_clear(hNodeMgr->chnlMap, chnlId);
9240 + } else {
9241 + GB_clear(hNodeMgr->chnlMap, chnlId);
9243 + status = DSP_EMEMORY;
9244 +func_cont2:
9245 + if (DSP_SUCCEEDED(status)) {
9246 + if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
9247 + hNode2->inputs[uStream2].type = HOSTCONNECT;
9248 + hNode2->inputs[uStream2].devId = chnlId;
9249 + pInput->szDevice = pstrDevName;
9250 + } else {
9251 + hNode1->outputs[uStream1].type = HOSTCONNECT;
9252 + hNode1->outputs[uStream1].devId = chnlId;
9253 + pOutput->szDevice = pstrDevName;
9255 + CSL_Strcpyn(pstrDevName, HOSTPREFIX,
9256 + sizeof(HOSTPREFIX));
9257 + pstrDevName += CSL_Strlen(pstrDevName);
9258 + CSL_NumToAscii(pstrDevName, chnlId);
9261 + /* Connecting task node to device node? */
9262 + if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
9263 + (node2Type == NODE_DEVICE))) {
9264 + if (node2Type == NODE_DEVICE) {
9265 + /* node1 == > device */
9266 + hDevNode = hNode2;
9267 + hNode = hNode1;
9268 + pStream = &(hNode1->outputs[uStream1]);
9269 + pstrmDef = pOutput;
9270 + } else {
9271 + /* device == > node2 */
9272 + hDevNode = hNode1;
9273 + hNode = hNode2;
9274 + pStream = &(hNode2->inputs[uStream2]);
9275 + pstrmDef = pInput;
9277 + /* Set up create args */
9278 + pStream->type = DEVICECONNECT;
9279 + dwLength = CSL_Strlen(hDevNode->pstrDevName);
9280 + if (pConnParam != NULL) {
9281 + pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
9282 + (u32) pConnParam->cbData,
9283 + MEM_PAGED);
9284 + } else {
9285 + pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
9286 + MEM_PAGED);
9288 + if (pstrmDef->szDevice == NULL) {
9289 + status = DSP_EMEMORY;
9290 + } else {
9291 + /* Copy device name */
9292 + CSL_Strcpyn(pstrmDef->szDevice, hDevNode->pstrDevName,
9293 + dwLength);
9294 + if (pConnParam != NULL) {
9295 + CSL_Strncat(pstrmDef->szDevice,
9296 + (char *)pConnParam->cData,
9297 + (u32)pConnParam->cbData);
9299 + hDevNode->hDeviceOwner = hNode;
9302 + if (DSP_SUCCEEDED(status)) {
9303 + /* Fill in create args */
9304 + if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
9305 + hNode1->createArgs.asa.taskArgs.uNumOutputs++;
9306 + FillStreamDef(hNode1, pOutput, pAttrs);
9308 + if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
9309 + hNode2->createArgs.asa.taskArgs.uNumInputs++;
9310 + FillStreamDef(hNode2, pInput, pAttrs);
9312 + /* Update hNode1 and hNode2 streamConnect */
9313 + if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
9314 + hNode1->uNumOutputs++;
9315 + if (uStream1 > hNode1->uMaxOutputIndex)
9316 + hNode1->uMaxOutputIndex = uStream1;
9319 + if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
9320 + hNode2->uNumInputs++;
9321 + if (uStream2 > hNode2->uMaxInputIndex)
9322 + hNode2->uMaxInputIndex = uStream2;
9325 + FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
9327 +func_cont:
9328 + /* end of SYNC_EnterCS */
9329 + /* Exit critical section */
9330 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
9331 +func_end:
9332 + return status;
9336 + * ======== NODE_Create ========
9337 + * Purpose:
9338 + * Create a node on the DSP by remotely calling the node's create function.
9339 + */
9340 +DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
9342 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
9343 + struct NODE_MGR *hNodeMgr;
9344 + struct WMD_DRV_INTERFACE *pIntfFxns;
9345 + u32 ulCreateFxn;
9346 + enum NODE_TYPE nodeType;
9347 + DSP_STATUS status = DSP_SOK;
9348 + DSP_STATUS status1 = DSP_SOK;
9349 + bool bJustWokeDSP = false;
9350 + struct DSP_CBDATA cbData;
9351 + u32 procId = 255;
9353 + DBC_Require(cRefs > 0);
9354 + GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
9355 + hNode);
9356 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
9357 + status = DSP_EHANDLE;
9358 + goto func_end;
9360 + /* create struct DSP_CBDATA struct for PWR calls */
9361 + cbData.cbData = PWR_TIMEOUT;
9362 + nodeType = NODE_GetType(hNode);
9363 + hNodeMgr = hNode->hNodeMgr;
9364 + pIntfFxns = hNodeMgr->pIntfFxns;
9365 + /* Get access to node dispatcher */
9366 + status = SYNC_EnterCS(hNodeMgr->hSync);
9367 + if (DSP_FAILED(status))
9368 + goto func_cont;
9370 + /* Check node state */
9371 + if (NODE_GetState(hNode) != NODE_ALLOCATED)
9372 + status = DSP_EWRONGSTATE;
9374 + if (DSP_SUCCEEDED(status))
9375 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
9377 + if (DSP_FAILED(status))
9378 + goto func_cont2;
9380 + if (procId != DSP_UNIT)
9381 + goto func_cont2;
9383 + /* Make sure streams are properly connected */
9384 + if ((hNode->uNumInputs && hNode->uMaxInputIndex >
9385 + hNode->uNumInputs - 1) ||
9386 + (hNode->uNumOutputs && hNode->uMaxOutputIndex >
9387 + hNode->uNumOutputs - 1))
9388 + status = DSP_ENOTCONNECTED;
9390 + if (DSP_SUCCEEDED(status)) {
9391 + /* If node's create function is not loaded, load it */
9392 +#ifndef CONFIG_DISABLE_BRIDGE_PM
9393 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
9394 + /* Boost the OPP level to max level that DSP can be requested */
9395 + if (constraint_set(mpu_constraint_handle,
9396 + dsp_max_opps) != 0)
9397 + GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
9398 + "Constraint set of %d failed\n", dsp_max_opps);
9399 + else
9400 + GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
9401 + "Constraint set of %d passed\n",
9402 + dsp_max_opps);
9403 +#endif
9404 +#endif
9405 + status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
9406 + NLDR_CREATE);
9407 + /* Get address of node's create function */
9408 + if (DSP_SUCCEEDED(status)) {
9409 + hNode->fLoaded = true;
9410 + if (nodeType != NODE_DEVICE) {
9411 + status = GetFxnAddress(hNode, &ulCreateFxn,
9412 + CREATEPHASE);
9414 + } else {
9415 + GT_1trace(NODE_debugMask, GT_ENTER,
9416 + "NODE_Create: failed to load"
9417 + " create code: 0x%x\n", status);
9419 +#ifndef CONFIG_DISABLE_BRIDGE_PM
9420 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
9421 + /* Request the lowest OPP level*/
9422 + if (constraint_set(mpu_constraint_handle,
9423 + (CO_VDD1_OPP1)) != 0) {
9424 + GT_1trace(NODE_debugMask, GT_4CLASS,
9425 + "NODE_Create: Constraint set of %d "
9426 + "failed\n", CO_VDD1_OPP1);
9427 + } else {
9428 + GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
9429 + "Constraint set of %d passed\n", CO_VDD1_OPP1);
9431 +#endif
9432 +#endif
9433 + /* Get address of iAlg functions, if socket node */
9434 + if (DSP_SUCCEEDED(status)) {
9435 + if (nodeType == NODE_DAISSOCKET) {
9436 + status = hNodeMgr->nldrFxns.pfnGetFxnAddr
9437 + (hNode->hNldrNode, hNode->dcdProps.
9438 + objData.nodeObj.pstrIAlgName,
9439 + &hNode->createArgs.asa.taskArgs.
9440 + ulDaisArg);
9444 + if (DSP_SUCCEEDED(status)) {
9445 + if (nodeType != NODE_DEVICE) {
9446 + status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
9447 + hNodeMgr->ulFxnAddrs[RMSCREATENODE],
9448 + ulCreateFxn, &(hNode->createArgs),
9449 + &(hNode->nodeEnv));
9450 + if (DSP_SUCCEEDED(status)) {
9451 + /* Set the message queue id to the node env
9452 + * pointer */
9453 + pIntfFxns = hNodeMgr->pIntfFxns;
9454 + (*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
9455 + hNode->nodeEnv);
9459 + /* Phase II/Overlays: Create, execute, delete phases possibly in
9460 + * different files/sections. */
9461 + if (hNode->fLoaded && hNode->fPhaseSplit) {
9462 + /* If create code was dynamically loaded, we can now unload
9463 + * it. */
9464 + status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
9465 + NLDR_CREATE);
9466 + hNode->fLoaded = false;
9468 + if (DSP_FAILED(status1)) {
9469 + GT_1trace(NODE_debugMask, GT_5CLASS,
9470 + "NODE_Create: Failed to unload "
9471 + "create code: 0x%x\n", status1);
9473 +func_cont2:
9474 + /* Update node state and node manager state */
9475 + if (DSP_SUCCEEDED(status)) {
9476 + NODE_SetState(hNode, NODE_CREATED);
9477 + hNodeMgr->uNumCreated++;
9478 + goto func_cont;
9480 + if (status != DSP_EWRONGSTATE) {
9481 + /* Put back in NODE_ALLOCATED state if error occurred */
9482 + NODE_SetState(hNode, NODE_ALLOCATED);
9484 + if (procId == DSP_UNIT) {
9485 + /* If node create failed, see if should sleep DSP now */
9486 + if (bJustWokeDSP == true) {
9487 + /* Check to see if partial create happened on DSP */
9488 + if (hNode->nodeEnv == (u32)NULL) {
9489 + /* No environment allocated on DSP, re-sleep
9490 + * DSP now */
9491 + PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
9492 + &cbData);
9493 + } else {
9494 + /* Increment count, sleep later when node fully
9495 + * deleted */
9496 + hNodeMgr->uNumCreated++;
9500 +func_cont:
9501 + /* Free access to node dispatcher */
9502 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
9503 +func_end:
9504 + if (DSP_SUCCEEDED(status)) {
9505 + PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
9506 + NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
9509 + return status;
9513 + * ======== NODE_CreateMgr ========
9514 + * Purpose:
9515 + * Create a NODE Manager object.
9516 + */
9517 +DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
9518 + struct DEV_OBJECT *hDevObject)
9520 + u32 i;
9521 + struct NODE_MGR *pNodeMgr = NULL;
9522 + struct DISP_ATTRS dispAttrs;
9523 + char *szZLFile = "";
9524 + struct NLDR_ATTRS nldrAttrs;
9525 + DSP_STATUS status = DSP_SOK;
9526 + u32 devType;
9527 + DBC_Require(cRefs > 0);
9528 + DBC_Require(phNodeMgr != NULL);
9529 + DBC_Require(hDevObject != NULL);
9530 + GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
9531 + "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
9532 + *phNodeMgr = NULL;
9533 + /* Allocate Node manager object */
9534 + MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
9535 + if (pNodeMgr) {
9536 + pNodeMgr->hDevObject = hDevObject;
9537 + pNodeMgr->nodeList = LST_Create();
9538 + pNodeMgr->pipeMap = GB_create(MAXPIPES);
9539 + pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
9540 + if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
9541 + pNodeMgr->pipeDoneMap == NULL) {
9542 + status = DSP_EMEMORY;
9543 + GT_0trace(NODE_debugMask, GT_6CLASS,
9544 + "NODE_CreateMgr: Memory "
9545 + "allocation failed\n");
9546 + } else {
9547 + status = NTFY_Create(&pNodeMgr->hNtfy);
9549 + pNodeMgr->uNumCreated = 0;
9550 + } else {
9551 + GT_0trace(NODE_debugMask, GT_6CLASS,
9552 + "NODE_CreateMgr: Memory allocation failed\n");
9553 + status = DSP_EMEMORY;
9555 + /* get devNodeType */
9556 + if (DSP_SUCCEEDED(status))
9557 + status = DEV_GetDevType(hDevObject, &devType);
9559 + /* Create the DCD Manager */
9560 + if (DSP_SUCCEEDED(status)) {
9561 + status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
9562 + if (DSP_SUCCEEDED(status))
9563 + status = GetProcProps(pNodeMgr, hDevObject);
9566 + /* Create NODE Dispatcher */
9567 + if (DSP_SUCCEEDED(status)) {
9568 + dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
9569 + dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
9570 + dispAttrs.procFamily = pNodeMgr->procFamily;
9571 + dispAttrs.procType = pNodeMgr->procType;
9572 + status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
9574 + /* Create a STRM Manager */
9575 + if (DSP_SUCCEEDED(status))
9576 + status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
9578 + if (DSP_SUCCEEDED(status)) {
9579 + DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
9580 + /* Get MSG queue manager */
9581 + DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
9582 + status = SYNC_InitializeCS(&pNodeMgr->hSync);
9583 + if (DSP_FAILED(status))
9584 + status = DSP_EMEMORY;
9586 + if (DSP_SUCCEEDED(status)) {
9587 + status = SYNC_InitializeCS(&pNodeMgr->hAllocSync);
9588 + if (DSP_FAILED(status))
9589 + status = DSP_EMEMORY;
9593 + if (DSP_SUCCEEDED(status)) {
9594 + pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
9595 + /* dma chnl map. ulNumChnls is # per transport */
9596 + pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
9597 + pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
9598 + if ((pNodeMgr->chnlMap == NULL) ||
9599 + (pNodeMgr->dmaChnlMap == NULL) ||
9600 + (pNodeMgr->zChnlMap == NULL)) {
9601 + status = DSP_EMEMORY;
9602 + } else {
9603 + /* Block out reserved channels */
9604 + for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
9605 + GB_set(pNodeMgr->chnlMap, i);
9607 + /* Block out channels reserved for RMS */
9608 + GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
9609 + GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
9612 + if (DSP_SUCCEEDED(status)) {
9613 + /* NO RM Server on the IVA */
9614 + if (devType != IVA_UNIT) {
9615 + /* Get addresses of any RMS functions loaded */
9616 + status = GetRMSFxns(pNodeMgr);
9617 + if (DSP_FAILED(status)) {
9618 + GT_1trace(NODE_debugMask, GT_6CLASS,
9619 + "NODE_CreateMgr: Failed to"
9620 + " get RMS functions: status = 0x%x", status);
9625 + /* Get loader functions and create loader */
9626 + if (DSP_SUCCEEDED(status)) {
9627 + GT_0trace(NODE_debugMask, GT_1CLASS,
9628 + "NODE_CreateMgr: using dynamic loader\n");
9629 + pNodeMgr->nldrFxns = nldrFxns; /* Dynamic loader functions */
9631 + if (DSP_SUCCEEDED(status)) {
9632 + nldrAttrs.pfnOvly = Ovly;
9633 + nldrAttrs.pfnWrite = Write;
9634 + nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
9635 + nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
9636 + pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
9637 + status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
9638 + hDevObject, &nldrAttrs);
9639 + if (DSP_FAILED(status)) {
9640 + GT_1trace(NODE_debugMask, GT_6CLASS,
9641 + "NODE_CreateMgr: Failed to "
9642 + "create loader: status = 0x%x\n", status);
9645 + if (DSP_SUCCEEDED(status))
9646 + *phNodeMgr = pNodeMgr;
9647 + else
9648 + DeleteNodeMgr(pNodeMgr);
9650 + DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
9651 + (DSP_SUCCEEDED(status) &&
9652 + MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
9654 + return status;
9658 + * ======== NODE_Delete ========
9659 + * Purpose:
9660 + * Delete a node on the DSP by remotely calling the node's delete function.
9661 + * Loads the node's delete function if necessary. Free GPP side resources
9662 + * after node's delete function returns.
9663 + */
9664 +DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
9666 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
9667 + struct NODE_MGR *hNodeMgr;
9668 + struct PROC_OBJECT *hProcessor;
9669 + struct DISP_OBJECT *hDisp;
9670 + u32 ulDeleteFxn;
9671 + enum NODE_TYPE nodeType;
9672 + enum NODE_STATE state;
9673 + DSP_STATUS status = DSP_SOK;
9674 + DSP_STATUS status1 = DSP_SOK;
9675 + struct DSP_CBDATA cbData;
9676 + u32 procId;
9677 + struct WMD_DRV_INTERFACE *pIntfFxns;
9679 +#ifndef RES_CLEANUP_DISABLE
9680 + HANDLE hProcess;
9681 + HANDLE nodeRes;
9682 + HANDLE hDrvObject;
9683 + struct PROCESS_CONTEXT *pCtxt = NULL;
9684 + DSP_STATUS res_status = DSP_SOK;
9685 +#endif
9687 + DBC_Require(cRefs > 0);
9688 + GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
9689 + hNode);
9690 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
9691 + status = DSP_EHANDLE;
9692 + goto func_end;
9694 + /* create struct DSP_CBDATA struct for PWR call */
9695 + cbData.cbData = PWR_TIMEOUT;
9696 + hNodeMgr = hNode->hNodeMgr;
9697 + hProcessor = hNode->hProcessor;
9698 + hDisp = hNodeMgr->hDisp;
9699 + nodeType = NODE_GetType(hNode);
9700 + pIntfFxns = hNodeMgr->pIntfFxns;
9701 + /* Enter critical section */
9702 + status = SYNC_EnterCS(hNodeMgr->hSync);
9703 + if (DSP_FAILED(status))
9704 + goto func_end;
9706 + state = NODE_GetState(hNode);
9707 + /* Execute delete phase code for non-device node in all cases
9708 + * except when the node was only allocated. Delete phase must be
9709 + * executed even if create phase was executed, but failed.
9710 + * If the node environment pointer is non-NULL, the delete phase
9711 + * code must be executed. */
9712 + if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
9713 + nodeType != NODE_DEVICE) {
9714 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
9715 + if (DSP_FAILED(status))
9716 + goto func_cont1;
9718 + if (procId == DSP_UNIT || procId == IVA_UNIT) {
9719 + /* If node has terminated, execute phase code will
9720 + * have already been unloaded in NODE_OnExit(). If the
9721 + * node is PAUSED, the execute phase is loaded, and it
9722 + * is now ok to unload it. If the node is running, we
9723 + * will unload the execute phase only after deleting
9724 + * the node. */
9725 + if (state == NODE_PAUSED && hNode->fLoaded &&
9726 + hNode->fPhaseSplit) {
9727 + /* Ok to unload execute code as long as node
9728 + * is not * running */
9729 + status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
9730 + hNldrNode, NLDR_EXECUTE);
9731 + hNode->fLoaded = false;
9732 + NODE_SetState(hNode, NODE_DONE);
9734 + /* Load delete phase code if not loaded or if haven't
9735 + * * unloaded EXECUTE phase */
9736 + if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
9737 + hNode->fPhaseSplit) {
9738 + status = hNodeMgr->nldrFxns.pfnLoad(hNode->
9739 + hNldrNode, NLDR_DELETE);
9740 + if (DSP_SUCCEEDED(status)) {
9741 + hNode->fLoaded = true;
9742 + } else {
9743 + GT_1trace(NODE_debugMask, GT_ENTER,
9744 + "NODE_Delete: failed to "
9745 + "load delete code: 0x%x\n",
9746 + status);
9750 +func_cont1:
9751 + if (DSP_SUCCEEDED(status)) {
9752 + /* Unblock a thread trying to terminate the node */
9753 + (void)SYNC_SetEvent(hNode->hSyncDone);
9754 + if (procId == DSP_UNIT) {
9755 + /* ulDeleteFxn = address of node's delete
9756 + * function */
9757 + status = GetFxnAddress(hNode, &ulDeleteFxn,
9758 + DELETEPHASE);
9759 + } else if (procId == IVA_UNIT)
9760 + ulDeleteFxn = (u32)hNode->nodeEnv;
9761 + if (DSP_SUCCEEDED(status)) {
9762 + status = DISP_NodeDelete(hDisp, hNode,
9763 + hNodeMgr->ulFxnAddrs[RMSDELETENODE],
9764 + ulDeleteFxn, hNode->nodeEnv);
9765 + /* Unload execute, if not unloaded, and delete
9766 + * function */
9767 + if (state == NODE_RUNNING &&
9768 + hNode->fPhaseSplit) {
9769 + status1 = hNodeMgr->nldrFxns.pfnUnload(
9770 + hNode->hNldrNode, NLDR_EXECUTE);
9772 + if (DSP_FAILED(status1)) {
9773 + GT_1trace(NODE_debugMask, GT_ENTER,
9774 + "NODE_Delete: failed to"
9775 + "unload execute code: 0x%x\n",
9776 + status1);
9778 + status1 = hNodeMgr->nldrFxns.pfnUnload(
9779 + hNode->hNldrNode, NLDR_DELETE);
9780 + hNode->fLoaded = false;
9781 + if (DSP_FAILED(status1)) {
9782 + GT_1trace(NODE_debugMask, GT_ENTER,
9783 + "NODE_Delete: failed to"
9784 + "unload delete code: 0x%x\n",
9785 + status1);
9790 + /* Free host side resources even if a failure occurred */
9791 + /* Remove node from hNodeMgr->nodeList */
9792 + LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
9793 + hNodeMgr->uNumNodes--;
9794 + /* Decrement count of nodes created on DSP */
9795 + if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
9796 + (hNode->nodeEnv != (u32) NULL))) {
9797 + hNodeMgr->uNumCreated--;
9798 + /* This is not acceptable since in deep sleep, all the
9799 + * peripherals are switched off We just need to put DSP
9800 + * CPU in idle mode */
9802 + /* Free host-side resources allocated by NODE_Create()
9803 + * DeleteNode() fails if SM buffers not freed by client! */
9804 +#ifndef RES_CLEANUP_DISABLE
9805 + if (DSP_FAILED(status))
9806 + goto func_cont;
9808 + /* Update the node and stream resource status */
9809 + PRCS_GetCurrentHandle(&hProcess);
9810 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
9811 + if (DSP_FAILED(res_status))
9812 + goto func_cont;
9814 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, hNode, 0);
9815 + if (pCtxt == NULL)
9816 + goto func_cont;
9818 + if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
9819 + GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
9820 + DRV_ProcNodeUpdateStatus(nodeRes, false);
9822 +#endif
9823 +func_cont:
9824 + GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
9825 + DeleteNode(hNode);
9826 +#ifndef RES_CLEANUP_DISABLE
9827 + if (DSP_SUCCEEDED(status)) {
9828 + GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
9829 + if (pCtxt != NULL)
9830 + DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
9833 +#endif
9834 + GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
9835 + /* Exit critical section */
9836 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
9837 + PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
9838 +func_end:
9839 + return status;
9843 + * ======== NODE_DeleteMgr ========
9844 + * Purpose:
9845 + * Delete the NODE Manager.
9846 + */
9847 +DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
9849 + DSP_STATUS status = DSP_SOK;
9851 + DBC_Require(cRefs > 0);
9852 + DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
9854 + GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
9855 + hNodeMgr);
9856 + DeleteNodeMgr(hNodeMgr);
9858 + return status;
9862 + * ======== NODE_EnumNodes ========
9863 + * Purpose:
9864 + * Enumerate currently allocated nodes.
9865 + */
9866 +DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
9867 + u32 uNodeTabSize, OUT u32 *puNumNodes,
9868 + OUT u32 *puAllocated)
9870 + struct NODE_OBJECT *hNode;
9871 + u32 i;
9872 + DSP_STATUS status = DSP_SOK;
9873 + DBC_Require(cRefs > 0);
9874 + DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
9875 + DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
9876 + DBC_Require(puNumNodes != NULL);
9877 + DBC_Require(puAllocated != NULL);
9878 + GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
9879 + "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
9880 + "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
9881 + puAllocated);
9882 + /* Enter critical section */
9883 + status = SYNC_EnterCS(hNodeMgr->hSync);
9884 + if (DSP_SUCCEEDED(status)) {
9885 + if (hNodeMgr->uNumNodes > uNodeTabSize) {
9886 + *puAllocated = hNodeMgr->uNumNodes;
9887 + *puNumNodes = 0;
9888 + status = DSP_ESIZE;
9889 + } else {
9890 + hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
9891 + nodeList);
9892 + for (i = 0; i < hNodeMgr->uNumNodes; i++) {
9893 + DBC_Assert(MEM_IsValidHandle(hNode,
9894 + NODE_SIGNATURE));
9895 + aNodeTab[i] = hNode;
9896 + hNode = (struct NODE_OBJECT *)LST_Next
9897 + (hNodeMgr->nodeList,
9898 + (struct LST_ELEM *)hNode);
9900 + *puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
9903 + /* end of SYNC_EnterCS */
9904 + /* Exit critical section */
9905 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
9906 + return status;
9910 + * ======== NODE_Exit ========
9911 + * Purpose:
9912 + * Discontinue usage of NODE module.
9913 + */
9914 +void NODE_Exit(void)
9916 + DBC_Require(cRefs > 0);
9918 + cRefs--;
9920 + GT_1trace(NODE_debugMask, GT_5CLASS,
9921 + "Entered NODE_Exit, ref count: 0x%x\n", cRefs);
9923 + DBC_Ensure(cRefs >= 0);
9927 + * ======== NODE_FreeMsgBuf ========
9928 + * Purpose:
9929 + * Frees the message buffer.
9930 + */
9931 +DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
9932 + OPTIONAL struct DSP_BUFFERATTR *pAttr)
9934 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
9935 + DSP_STATUS status = DSP_SOK;
9936 + u32 procId;
9937 + DBC_Require(cRefs > 0);
9938 + DBC_Require(pBuffer != NULL);
9939 + DBC_Require(pNode != NULL);
9940 + DBC_Require(pNode->hXlator != NULL);
9941 + GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
9942 + "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
9943 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
9944 + status = DSP_EHANDLE;
9946 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
9947 + if (procId == DSP_UNIT) {
9948 + if (DSP_SUCCEEDED(status)) {
9949 + if (pAttr == NULL) {
9950 + /* set defaults */
9951 + pAttr = &NODE_DFLTBUFATTRS;
9953 + /* Node supports single SM segment only */
9954 + if (pAttr->uSegment != 1)
9955 + status = DSP_EBADSEGID;
9957 + /* pBuffer is clients Va. */
9958 + status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
9959 + if (DSP_FAILED(status))
9960 + status = DSP_EFAIL;
9961 + else
9962 + status = DSP_SOK;
9965 + } else {
9966 + DBC_Assert(NULL); /* BUG */
9968 + return status;
9972 + * ======== NODE_GetAttr ========
9973 + * Purpose:
9974 + * Copy the current attributes of the specified node into a DSP_NODEATTR
9975 + * structure.
9976 + */
9977 +DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
9978 + OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
9980 + struct NODE_MGR *hNodeMgr;
9981 + DSP_STATUS status = DSP_SOK;
9982 + DBC_Require(cRefs > 0);
9983 + DBC_Require(pAttr != NULL);
9984 + DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
9985 + GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
9986 + "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
9987 + uAttrSize);
9988 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
9989 + status = DSP_EHANDLE;
9990 + } else {
9991 + hNodeMgr = hNode->hNodeMgr;
9992 + /* Enter hNodeMgr critical section (since we're accessing
9993 + * data that could be changed by NODE_ChangePriority() and
9994 + * NODE_Connect(). */
9995 + status = SYNC_EnterCS(hNodeMgr->hSync);
9996 + if (DSP_SUCCEEDED(status)) {
9997 + pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
9998 + /* DSP_NODEATTRIN */
9999 + pAttr->inNodeAttrIn.cbStruct =
10000 + sizeof(struct DSP_NODEATTRIN);
10001 + pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
10002 + pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
10003 + pAttr->inNodeAttrIn.uHeapSize =
10004 + hNode->createArgs.asa.taskArgs.uHeapSize;
10005 + pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
10006 + hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
10007 + pAttr->uInputs = hNode->uNumGPPInputs;
10008 + pAttr->uOutputs = hNode->uNumGPPOutputs;
10009 + /* DSP_NODEINFO */
10010 + GetNodeInfo(hNode, &(pAttr->iNodeInfo));
10012 + /* end of SYNC_EnterCS */
10013 + /* Exit critical section */
10014 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10016 + return status;
10020 + * ======== NODE_GetChannelId ========
10021 + * Purpose:
10022 + * Get the channel index reserved for a stream connection between the
10023 + * host and a node.
10024 + */
10025 +DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
10026 + OUT u32 *pulId)
10028 + enum NODE_TYPE nodeType;
10029 + DSP_STATUS status = DSP_EVALUE;
10030 + DBC_Require(cRefs > 0);
10031 + DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
10032 + DBC_Require(pulId != NULL);
10033 + GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
10034 + "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
10035 + uIndex, pulId);
10036 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10037 + status = DSP_EHANDLE;
10038 + return status;
10040 + nodeType = NODE_GetType(hNode);
10041 + if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
10042 + status = DSP_ENODETYPE;
10043 + return status;
10045 + if (uDir == DSP_TONODE) {
10046 + if (uIndex < MaxInputs(hNode)) {
10047 + if (hNode->inputs[uIndex].type == HOSTCONNECT) {
10048 + *pulId = hNode->inputs[uIndex].devId;
10049 + status = DSP_SOK;
10052 + } else {
10053 + DBC_Assert(uDir == DSP_FROMNODE);
10054 + if (uIndex < MaxOutputs(hNode)) {
10055 + if (hNode->outputs[uIndex].type == HOSTCONNECT) {
10056 + *pulId = hNode->outputs[uIndex].devId;
10057 + status = DSP_SOK;
10061 + return status;
10065 + * ======== NODE_GetMessage ========
10066 + * Purpose:
10067 + * Retrieve a message from a node on the DSP.
10068 + */
10069 +DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
10070 + u32 uTimeout)
10072 + struct NODE_MGR *hNodeMgr;
10073 + enum NODE_TYPE nodeType;
10074 + struct WMD_DRV_INTERFACE *pIntfFxns;
10075 + DSP_STATUS status = DSP_SOK;
10076 + void *pTmpBuf;
10077 + DBC_Require(cRefs > 0);
10078 + DBC_Require(pMsg != NULL);
10079 + GT_3trace(NODE_debugMask, GT_ENTER,
10080 + "NODE_GetMessage: hNode: 0x%x\tpMsg: "
10081 + "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
10082 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10083 + status = DSP_EHANDLE;
10084 + goto func_end;
10086 + hNodeMgr = hNode->hNodeMgr;
10087 + nodeType = NODE_GetType(hNode);
10088 + if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
10089 + nodeType != NODE_DAISSOCKET) {
10090 + status = DSP_ENODETYPE;
10091 + goto func_end;
10093 + /* This function will block unless a message is available. Since
10094 + * DSPNode_RegisterNotify() allows notification when a message
10095 + * is available, the system can be designed so that
10096 + * DSPNode_GetMessage() is only called when a message is
10097 + * available. */
10098 + pIntfFxns = hNodeMgr->pIntfFxns;
10099 + status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
10100 + /* Check if message contains SM descriptor */
10101 + if (DSP_FAILED(status) || !(pMsg->dwCmd & DSP_RMSBUFDESC))
10102 + goto func_end;
10104 + /* Translate DSP byte addr to GPP Va. */
10105 + pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
10106 + (void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
10107 + CMM_DSPPA2PA);
10108 + if (pTmpBuf != NULL) {
10109 + /* now convert this GPP Pa to Va */
10110 + pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
10111 + CMM_PA2VA);
10112 + if (pTmpBuf != NULL) {
10113 + /* Adjust SM size in msg */
10114 + pMsg->dwArg1 = (u32) pTmpBuf;
10115 + pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
10116 + } else {
10117 + GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
10118 + "Failed SM translation!\n");
10119 + status = DSP_ETRANSLATE;
10121 + } else {
10122 + GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
10123 + "SM Pa/Pa translation!\n");
10124 + status = DSP_ETRANSLATE;
10126 +func_end:
10127 + return status;
10131 + * ======== NODE_GetNldrObj ========
10132 + */
10133 +DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
10134 + struct NLDR_OBJECT **phNldrObj)
10136 + DSP_STATUS status = DSP_SOK;
10137 + struct NODE_MGR *pNodeMgr = hNodeMgr;
10138 + DBC_Require(phNldrObj != NULL);
10139 + GT_2trace(NODE_debugMask, GT_ENTER,
10140 + "Entered NODE_GetNldrObj, hNodeMgr: "
10141 + "0x%x\n\tphNldrObj: 0x%x\n", hNodeMgr, phNldrObj);
10142 + if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
10143 + status = DSP_EHANDLE;
10144 + else
10145 + *phNldrObj = pNodeMgr->hNldr;
10147 + GT_2trace(NODE_debugMask, GT_ENTER,
10148 + "Exit NODE_GetNldrObj: status 0x%x\n\t"
10149 + "phNldrObj: 0x%x\n", status, *phNldrObj);
10150 + DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
10151 + (*phNldrObj == NULL)));
10152 + return status;
10156 + * ======== NODE_GetStrmMgr ========
10157 + * Purpose:
10158 + * Returns the Stream manager.
10159 + */
10160 +DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
10161 + struct STRM_MGR **phStrmMgr)
10163 + DSP_STATUS status = DSP_SOK;
10165 + DBC_Require(cRefs > 0);
10167 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
10168 + status = DSP_EHANDLE;
10169 + else
10170 + *phStrmMgr = hNode->hNodeMgr->hStrmMgr;
10172 + return status;
10176 + * ======== NODE_GetLoadType ========
10177 + */
10178 +enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
10181 + DBC_Require(cRefs > 0);
10182 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
10184 + return hNode->dcdProps.objData.nodeObj.usLoadType;
10188 + * ======== NODE_GetTimeout ========
10189 + * Purpose:
10190 + * Returns the timeout value for this node.
10191 + */
10192 +u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
10194 + DBC_Require(cRefs > 0);
10195 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
10197 + return hNode->uTimeout;
10201 + * ======== NODE_GetType ========
10202 + * Purpose:
10203 + * Returns the node type.
10204 + */
10205 +enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
10207 + enum NODE_TYPE nodeType;
10209 + if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
10210 + nodeType = NODE_GPP;
10211 + else
10212 + nodeType = hNode->nType;
10214 + return nodeType;
10218 + * ======== NODE_Init ========
10219 + * Purpose:
10220 + * Initialize the NODE module.
10221 + */
10222 +bool NODE_Init(void)
10224 + bool fRetVal = true;
10226 + DBC_Require(cRefs >= 0);
10228 + if (cRefs == 0) {
10229 + DBC_Assert(!NODE_debugMask.flags);
10230 + GT_create(&NODE_debugMask, "NO"); /* "NO" for NOde */
10233 + if (fRetVal)
10234 + cRefs++;
10236 + GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
10237 + cRefs);
10239 + DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
10240 + return fRetVal;
10244 + * ======== NODE_OnExit ========
10245 + * Purpose:
10246 + * Gets called when RMS_EXIT is received for a node.
10247 + */
10248 +CDECL void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
10250 + DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
10251 + /* Set node state to done */
10252 + NODE_SetState(hNode, NODE_DONE);
10253 + hNode->nExitStatus = nStatus;
10254 + if (hNode->fLoaded && hNode->fPhaseSplit) {
10255 + (void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
10256 + NLDR_EXECUTE);
10257 + hNode->fLoaded = false;
10259 + /* Unblock call to NODE_Terminate */
10260 + (void) SYNC_SetEvent(hNode->hSyncDone);
10261 + /* Notify clients */
10262 + PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
10263 + NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
10267 + * ======== NODE_Pause ========
10268 + * Purpose:
10269 + * Suspend execution of a node currently running on the DSP.
10270 + */
10271 +DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
10273 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
10274 + enum NODE_TYPE nodeType;
10275 + enum NODE_STATE state;
10276 + struct NODE_MGR *hNodeMgr;
10277 + DSP_STATUS status = DSP_SOK;
10278 + u32 procId;
10280 + DBC_Require(cRefs > 0);
10282 + GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
10284 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10285 + status = DSP_EHANDLE;
10286 + } else {
10287 + nodeType = NODE_GetType(hNode);
10288 + if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
10289 + status = DSP_ENODETYPE;
10293 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
10295 + if (procId == IVA_UNIT)
10296 + status = DSP_ENOTIMPL;
10298 + if (DSP_SUCCEEDED(status)) {
10299 + hNodeMgr = hNode->hNodeMgr;
10301 + /* Enter critical section */
10302 + status = SYNC_EnterCS(hNodeMgr->hSync);
10304 + if (DSP_SUCCEEDED(status)) {
10305 + state = NODE_GetState(hNode);
10306 + /* Check node state */
10307 + if (state != NODE_RUNNING)
10308 + status = DSP_EWRONGSTATE;
10310 + if (DSP_SUCCEEDED(status)) {
10311 + status = DISP_NodeChangePriority(hNodeMgr->
10312 + hDisp, hNode,
10313 + hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
10314 + hNode->nodeEnv, NODE_SUSPENDEDPRI);
10317 + /* Update state */
10318 + if (DSP_SUCCEEDED(status)) {
10319 + NODE_SetState(hNode, NODE_PAUSED);
10320 + } else {
10321 + GT_1trace(NODE_debugMask, GT_6CLASS,
10322 + "NODE_Pause: Failed. hNode:"
10323 + " 0x%x\n", hNode);
10326 + /* End of SYNC_EnterCS */
10327 + /* Leave critical section */
10328 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10329 + if (DSP_SUCCEEDED(status)) {
10330 + PROC_NotifyClients(hNode->hProcessor,
10331 + DSP_NODESTATECHANGE);
10332 + NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
10335 + return status;
10339 + * ======== NODE_PutMessage ========
10340 + * Purpose:
10341 + * Send a message to a message node, task node, or XDAIS socket node. This
10342 + * function will block until the message stream can accommodate the
10343 + * message, or a timeout occurs.
10344 + */
10345 +DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
10346 + IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
10348 + struct NODE_MGR *hNodeMgr = NULL;
10349 + enum NODE_TYPE nodeType;
10350 + struct WMD_DRV_INTERFACE *pIntfFxns;
10351 + enum NODE_STATE state;
10352 + DSP_STATUS status = DSP_SOK;
10353 + void *pTmpBuf;
10354 + struct DSP_MSG newMsg;
10356 + DBC_Require(cRefs > 0);
10357 + DBC_Require(pMsg != NULL);
10358 + GT_3trace(NODE_debugMask, GT_ENTER,
10359 + "NODE_PutMessage: hNode: 0x%x\tpMsg: "
10360 + "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
10361 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
10362 + status = DSP_EHANDLE;
10363 + else {
10364 + hNodeMgr = hNode->hNodeMgr;
10365 + nodeType = NODE_GetType(hNode);
10366 + if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
10367 + nodeType != NODE_DAISSOCKET)
10368 + status = DSP_ENODETYPE;
10370 + if (DSP_SUCCEEDED(status)) {
10371 + /* Check node state. Can't send messages to a node after
10372 + * we've sent the RMS_EXIT command. There is still the
10373 + * possibility that NODE_Terminate can be called after we've
10374 + * checked the state. Could add another SYNC object to
10375 + * prevent this (can't use hNodeMgr->hSync, since we don't
10376 + * want to block other NODE functions). However, the node may
10377 + * still exit on its own, before this message is sent. */
10378 + status = SYNC_EnterCS(hNodeMgr->hSync);
10379 + if (DSP_SUCCEEDED(status)) {
10380 + state = NODE_GetState(hNode);
10381 + if (state == NODE_TERMINATING || state == NODE_DONE)
10382 + status = DSP_EWRONGSTATE;
10385 + /* end of SYNC_EnterCS */
10386 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10388 + if (DSP_FAILED(status))
10389 + goto func_end;
10391 + /* assign pMsg values to new msg */
10392 + newMsg = *pMsg;
10393 + /* Now, check if message contains a SM buffer descriptor */
10394 + if (pMsg->dwCmd & DSP_RMSBUFDESC) {
10395 + /* Translate GPP Va to DSP physical buf Ptr. */
10396 + pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
10397 + (void *)newMsg.dwArg1, CMM_VA2DSPPA);
10398 + if (pTmpBuf != NULL) {
10399 + /* got translation, convert to MAUs in msg */
10400 + if (hNode->hNodeMgr->uDSPWordSize != 0) {
10401 + newMsg.dwArg1 =
10402 + (u32)pTmpBuf /
10403 + hNode->hNodeMgr->uDSPWordSize;
10404 + /* MAUs */
10405 + newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
10406 + } else {
10407 + GT_0trace(NODE_debugMask, GT_7CLASS,
10408 + "NODE_PutMessage: "
10409 + "uDSPWordSize is zero!\n");
10410 + status = DSP_EFAIL; /* bad DSPWordSize */
10412 + } else { /* failed to translate buffer address */
10413 + GT_0trace(NODE_debugMask, GT_7CLASS,
10414 + "NODE_PutMessage: Failed to"
10415 + " translate SM address\n");
10416 + status = DSP_ETRANSLATE;
10419 + if (DSP_SUCCEEDED(status)) {
10420 + pIntfFxns = hNodeMgr->pIntfFxns;
10421 + status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
10422 + &newMsg, uTimeout);
10424 +func_end:
10425 + return status;
10429 + * ======== NODE_RegisterNotify ========
10430 + * Purpose:
10431 + * Register to be notified on specific events for this node.
10432 + */
10433 +DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
10434 + u32 uNotifyType,
10435 + struct DSP_NOTIFICATION *hNotification)
10437 + struct WMD_DRV_INTERFACE *pIntfFxns;
10438 + DSP_STATUS status = DSP_SOK;
10440 + DBC_Require(cRefs > 0);
10441 + DBC_Require(hNotification != NULL);
10443 + GT_4trace(NODE_debugMask, GT_ENTER,
10444 + "NODE_RegisterNotify: hNode: 0x%x\t"
10445 + "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
10446 + hNode, uEventMask, uNotifyType, hNotification);
10448 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10449 + status = DSP_EHANDLE;
10450 + } else {
10451 + /* Check if event mask is a valid node related event */
10452 + if (uEventMask & ~(DSP_NODESTATECHANGE |
10453 + DSP_NODEMESSAGEREADY))
10454 + status = DSP_EVALUE;
10456 + /* Check if notify type is valid */
10457 + if (uNotifyType != DSP_SIGNALEVENT)
10458 + status = DSP_EVALUE;
10460 + /* Only one Notification can be registered at a
10461 + * time - Limitation */
10462 + if (uEventMask == (DSP_NODESTATECHANGE |
10463 + DSP_NODEMESSAGEREADY))
10464 + status = DSP_EVALUE;
10466 + if (DSP_SUCCEEDED(status)) {
10467 + if (uEventMask == DSP_NODESTATECHANGE) {
10468 + status = NTFY_Register(hNode->hNtfy, hNotification,
10469 + uEventMask & DSP_NODESTATECHANGE, uNotifyType);
10470 + } else {
10471 + /* Send Message part of event mask to MSG */
10472 + pIntfFxns = hNode->hNodeMgr->pIntfFxns;
10473 + status = (*pIntfFxns->pfnMsgRegisterNotify)
10474 + (hNode->hMsgQueue,
10475 + uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
10476 + hNotification);
10480 + return status;
10484 + * ======== NODE_Run ========
10485 + * Purpose:
10486 + * Start execution of a node's execute phase, or resume execution of a node
10487 + * that has been suspended (via NODE_NodePause()) on the DSP. Load the
10488 + * node's execute function if necessary.
10489 + */
10490 +DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
10492 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
10493 + struct NODE_MGR *hNodeMgr;
10494 + enum NODE_TYPE nodeType;
10495 + enum NODE_STATE state;
10496 + u32 ulExecuteFxn;
10497 + u32 ulFxnAddr;
10498 + DSP_STATUS status = DSP_SOK;
10499 + u32 procId;
10500 + struct WMD_DRV_INTERFACE *pIntfFxns;
10502 + DBC_Require(cRefs > 0);
10503 + GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
10504 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10505 + status = DSP_EHANDLE;
10506 + } else {
10507 + nodeType = NODE_GetType(hNode);
10508 + if (nodeType == NODE_DEVICE)
10509 + status = DSP_ENODETYPE;
10511 + if (DSP_FAILED(status))
10512 + goto func_end;
10514 + hNodeMgr = hNode->hNodeMgr;
10515 + pIntfFxns = hNodeMgr->pIntfFxns;
10516 + /* Enter critical section */
10517 + status = SYNC_EnterCS(hNodeMgr->hSync);
10518 + if (DSP_FAILED(status))
10519 + goto func_cont;
10521 + state = NODE_GetState(hNode);
10522 + if (state != NODE_CREATED && state != NODE_PAUSED)
10523 + status = DSP_EWRONGSTATE;
10525 + if (DSP_SUCCEEDED(status))
10526 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
10528 + if (DSP_FAILED(status))
10529 + goto func_cont1;
10531 + if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
10532 + goto func_cont1;
10534 + if (state == NODE_CREATED) {
10535 + /* If node's execute function is not loaded, load it */
10536 + if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
10537 + status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
10538 + NLDR_EXECUTE);
10539 + if (DSP_SUCCEEDED(status)) {
10540 + hNode->fLoaded = true;
10541 + } else {
10542 + GT_1trace(NODE_debugMask, GT_ENTER,
10543 + "NODE_Run: failed to load "
10544 + "execute code:0x%x\n", status);
10547 + if (DSP_SUCCEEDED(status)) {
10548 + /* Get address of node's execute function */
10549 + if (procId == IVA_UNIT)
10550 + ulExecuteFxn = (u32) hNode->nodeEnv;
10551 + else {
10552 + status = GetFxnAddress(hNode, &ulExecuteFxn,
10553 + EXECUTEPHASE);
10556 + if (DSP_SUCCEEDED(status)) {
10557 + ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
10558 + status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
10559 + ulExecuteFxn, hNode->nodeEnv);
10561 + } else if (state == NODE_PAUSED) {
10562 + ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
10563 + status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
10564 + ulFxnAddr, hNode->nodeEnv,
10565 + NODE_GetPriority(hNode));
10566 + } else {
10567 + /* We should never get here */
10568 + DBC_Assert(false);
10570 +func_cont1:
10571 + /* Update node state. */
10572 + if (DSP_SUCCEEDED(status))
10573 + NODE_SetState(hNode, NODE_RUNNING);
10574 + else /* Set state back to previous value */
10575 + NODE_SetState(hNode, state);
10576 + /*End of SYNC_EnterCS */
10577 + /* Exit critical section */
10578 +func_cont:
10579 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10580 + if (DSP_SUCCEEDED(status)) {
10581 + PROC_NotifyClients(hNode->hProcessor,
10582 + DSP_NODESTATECHANGE);
10583 + NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
10585 +func_end:
10586 + return status;
10590 + * ======== NODE_Terminate ========
10591 + * Purpose:
10592 + * Signal a node running on the DSP that it should exit its execute phase
10593 + * function.
10594 + */
10595 +DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
10597 + struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
10598 + struct NODE_MGR *hNodeMgr = NULL;
10599 + enum NODE_TYPE nodeType;
10600 + struct WMD_DRV_INTERFACE *pIntfFxns;
10601 + enum NODE_STATE state;
10602 + struct DSP_MSG msg, killmsg;
10603 + DSP_STATUS status = DSP_SOK;
10604 + u32 procId, killTimeOut;
10605 + struct DEH_MGR *hDehMgr;
10607 + DBC_Require(cRefs > 0);
10608 + DBC_Require(pStatus != NULL);
10610 + GT_1trace(NODE_debugMask, GT_ENTER,
10611 + "NODE_Terminate: hNode: 0x%x\n", hNode);
10613 + status = PROC_GetProcessorId(pNode->hProcessor, &procId);
10615 + if (DSP_SUCCEEDED(status)) {
10616 + hNodeMgr = hNode->hNodeMgr;
10618 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
10619 + status = DSP_EHANDLE;
10620 + else {
10621 + nodeType = NODE_GetType(hNode);
10622 + if (nodeType != NODE_TASK && nodeType !=
10623 + NODE_DAISSOCKET)
10624 + status = DSP_ENODETYPE;
10627 + if (DSP_SUCCEEDED(status)) {
10628 + /* Check node state */
10629 + status = SYNC_EnterCS(hNodeMgr->hSync);
10630 + if (DSP_SUCCEEDED(status)) {
10631 + state = NODE_GetState(hNode);
10632 + if (state != NODE_RUNNING) {
10633 + status = DSP_EWRONGSTATE;
10634 + /* Set the exit status if node terminated on
10635 + * its own. */
10636 + if (state == NODE_DONE)
10637 + *pStatus = hNode->nExitStatus;
10639 + } else {
10640 + NODE_SetState(hNode, NODE_TERMINATING);
10643 + /* end of SYNC_EnterCS */
10644 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10646 + if (DSP_SUCCEEDED(status)) {
10647 + /*
10648 + * Send exit message. Do not change state to NODE_DONE
10649 + * here. That will be done in callback.
10650 + */
10651 + GT_1trace(NODE_debugMask, GT_5CLASS,
10652 + "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
10653 + msg.dwCmd = RMS_EXIT;
10654 + msg.dwArg1 = hNode->nodeEnv;
10655 + killmsg.dwCmd = RMS_KILLTASK;
10656 + killmsg.dwArg1 = hNode->nodeEnv;
10657 + pIntfFxns = hNodeMgr->pIntfFxns;
10659 + if (hNode->uTimeout > MAXTIMEOUT)
10660 + killTimeOut = MAXTIMEOUT;
10661 + else
10662 + killTimeOut = (hNode->uTimeout)*2;
10664 + status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
10665 + hNode->uTimeout);
10666 + if (DSP_SUCCEEDED(status)) {
10667 + /* Wait on synchronization object that will be
10668 + * posted in the callback on receiving RMS_EXIT
10669 + * message, or by NODE_Delete. Check for valid hNode,
10670 + * in case posted by NODE_Delete(). */
10671 + status = SYNC_WaitOnEvent(hNode->hSyncDone,
10672 + killTimeOut/2);
10673 + if (DSP_FAILED(status)) {
10674 + if (status == DSP_ETIMEOUT) {
10675 + status = (*pIntfFxns->pfnMsgPut)
10676 + (hNode->hMsgQueue, &killmsg,
10677 + hNode->uTimeout);
10678 + if (DSP_SUCCEEDED(status)) {
10679 + status = SYNC_WaitOnEvent
10680 + (hNode->hSyncDone,
10681 + killTimeOut/2);
10682 + if (DSP_FAILED(status)) {
10683 + /* Here it goes the part
10684 + * of the simulation of
10685 + * the DSP exception */
10686 + DEV_GetDehMgr(hNodeMgr->
10687 + hDevObject, &hDehMgr);
10688 + if (hDehMgr) {
10689 + (*pIntfFxns->
10690 + pfnDehNotify)(hDehMgr,
10691 + DSP_SYSERROR,
10692 + DSP_EXCEPTIONABORT);
10693 + status = DSP_EFAIL;
10695 + } else
10696 + status = DSP_SOK;
10698 + } else
10699 + status = DSP_EFAIL;
10700 + } else /* Convert SYNC status to DSP status */
10701 + status = DSP_SOK;
10704 + if (DSP_SUCCEEDED(status)) {
10705 + /* Enter CS before getting exit status, in case node was
10706 + * deleted. */
10707 + status = SYNC_EnterCS(hNodeMgr->hSync);
10708 + /* Make sure node wasn't deleted while we blocked */
10709 + if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
10710 + status = DSP_EFAIL;
10711 + } else {
10712 + *pStatus = hNode->nExitStatus;
10713 + GT_1trace(NODE_debugMask, GT_ENTER,
10714 + "NODE_Terminate: env = 0x%x "
10715 + "succeeded.\n", hNode->nodeEnv);
10717 + (void)SYNC_LeaveCS(hNodeMgr->hSync);
10718 + } /*End of SYNC_EnterCS */
10720 + return status;
10724 + * ======== DeleteNode ========
10725 + * Purpose:
10726 + * Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
10727 + */
10728 +static void DeleteNode(struct NODE_OBJECT *hNode)
10730 + struct NODE_MGR *hNodeMgr;
10731 + struct CMM_XLATOROBJECT *hXlator;
10732 + struct WMD_DRV_INTERFACE *pIntfFxns;
10733 + u32 i;
10734 + enum NODE_TYPE nodeType;
10735 + struct STREAM stream;
10736 + struct NODE_MSGARGS msgArgs;
10737 + struct NODE_TASKARGS taskArgs;
10738 + DSP_STATUS status;
10739 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
10740 + hNodeMgr = hNode->hNodeMgr;
10741 + hXlator = hNode->hXlator;
10742 + nodeType = NODE_GetType(hNode);
10743 + if (nodeType != NODE_DEVICE) {
10744 + msgArgs = hNode->createArgs.asa.msgArgs;
10745 + if (msgArgs.pData)
10746 + MEM_Free(msgArgs.pData);
10748 + /* Free MSG queue */
10749 + if (hNode->hMsgQueue) {
10750 + pIntfFxns = hNodeMgr->pIntfFxns;
10751 + (*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
10753 + if (hNode->hSyncDone)
10754 + (void) SYNC_CloseEvent(hNode->hSyncDone);
10756 + /* Free all stream info */
10757 + if (hNode->inputs) {
10758 + for (i = 0; i < MaxInputs(hNode); i++) {
10759 + stream = hNode->inputs[i];
10760 + FreeStream(hNodeMgr, stream);
10762 + MEM_Free(hNode->inputs);
10764 + if (hNode->outputs) {
10765 + for (i = 0; i < MaxOutputs(hNode); i++) {
10766 + stream = hNode->outputs[i];
10767 + FreeStream(hNodeMgr, stream);
10769 + MEM_Free(hNode->outputs);
10771 + taskArgs = hNode->createArgs.asa.taskArgs;
10772 + if (taskArgs.strmInDef) {
10773 + for (i = 0; i < MaxInputs(hNode); i++) {
10774 + if (taskArgs.strmInDef[i].szDevice) {
10775 + MEM_Free(taskArgs.strmInDef[i].
10776 + szDevice);
10779 + MEM_Free(taskArgs.strmInDef);
10780 + taskArgs.strmInDef = NULL;
10782 + if (taskArgs.strmOutDef) {
10783 + for (i = 0; i < MaxOutputs(hNode); i++) {
10784 + if (taskArgs.strmOutDef[i].szDevice) {
10785 + MEM_Free(taskArgs.strmOutDef[i].
10786 + szDevice);
10789 + MEM_Free(taskArgs.strmOutDef);
10790 + taskArgs.strmOutDef = NULL;
10792 + if (taskArgs.uDSPHeapResAddr) {
10793 + status = PROC_UnMap(hNode->hProcessor,
10794 + (void *)taskArgs.uDSPHeapAddr);
10795 + if (DSP_SUCCEEDED(status)) {
10796 + GT_0trace(NODE_debugMask, GT_5CLASS,
10797 + "DSPProcessor_UnMap succeeded.\n");
10798 + } else {
10799 + GT_1trace(NODE_debugMask, GT_5CLASS,
10800 + "DSPProcessor_UnMap failed."
10801 + " Status = 0x%x\n", (u32)status);
10803 + status = PROC_UnReserveMemory(hNode->hProcessor,
10804 + (void *)taskArgs.uDSPHeapResAddr);
10805 + if (DSP_SUCCEEDED(status)) {
10806 + GT_0trace(NODE_debugMask, GT_5CLASS,
10807 + "DSPProcessor_UnReserveMemory "
10808 + "succeeded.\n");
10809 + } else {
10810 + GT_1trace(NODE_debugMask, GT_5CLASS,
10811 + "DSPProcessor_UnReserveMemory "
10812 + "failed. Status = 0x%x\n",
10813 + (u32)status);
10817 + if (nodeType != NODE_MESSAGE) {
10818 + if (hNode->streamConnect)
10819 + MEM_Free(hNode->streamConnect);
10822 + if (hNode->pstrDevName)
10823 + MEM_Free(hNode->pstrDevName);
10825 + if (hNode->hNtfy)
10826 + NTFY_Delete(hNode->hNtfy);
10828 + /* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
10829 + if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn)
10830 + MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
10832 + if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn)
10833 + MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
10835 + if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn)
10836 + MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
10838 + if (hNode->dcdProps.objData.nodeObj.pstrIAlgName)
10839 + MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
10841 + /* Free all SM address translator resources */
10842 + if (hXlator)
10843 + (void) CMM_XlatorDelete(hXlator, TRUE); /* force free */
10845 + if (hNode->hNldrNode)
10846 + hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
10848 + MEM_FreeObject(hNode);
10852 + * ======== DeleteNodeMgr ========
10853 + * Purpose:
10854 + * Frees the node manager.
10855 + */
10856 +static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
10858 + struct NODE_OBJECT *hNode;
10860 + if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
10861 + /* Free resources */
10862 + if (hNodeMgr->hDcdMgr)
10863 + DCD_DestroyManager(hNodeMgr->hDcdMgr);
10865 + /* Remove any elements remaining in lists */
10866 + if (hNodeMgr->nodeList) {
10867 + while ((hNode =
10868 + (struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
10869 + nodeList)))
10870 + DeleteNode(hNode);
10872 + DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
10873 + LST_Delete(hNodeMgr->nodeList);
10875 + if (hNodeMgr->hNtfy)
10876 + NTFY_Delete(hNodeMgr->hNtfy);
10878 + if (hNodeMgr->pipeMap)
10879 + GB_delete(hNodeMgr->pipeMap);
10881 + if (hNodeMgr->pipeDoneMap)
10882 + GB_delete(hNodeMgr->pipeDoneMap);
10884 + if (hNodeMgr->chnlMap)
10885 + GB_delete(hNodeMgr->chnlMap);
10887 + if (hNodeMgr->dmaChnlMap)
10888 + GB_delete(hNodeMgr->dmaChnlMap);
10890 + if (hNodeMgr->zChnlMap)
10891 + GB_delete(hNodeMgr->zChnlMap);
10893 + if (hNodeMgr->hDisp)
10894 + DISP_Delete(hNodeMgr->hDisp);
10896 + if (hNodeMgr->hSync)
10897 + SYNC_DeleteCS(hNodeMgr->hSync);
10899 + if (hNodeMgr->hSync)
10900 + SYNC_DeleteCS(hNodeMgr->hAllocSync);
10902 + if (hNodeMgr->hStrmMgr)
10903 + STRM_Delete(hNodeMgr->hStrmMgr);
10905 + /* Delete the loader */
10906 + if (hNodeMgr->hNldr)
10907 + hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
10909 + if (hNodeMgr->fLoaderInit)
10910 + hNodeMgr->nldrFxns.pfnExit();
10912 + MEM_FreeObject(hNodeMgr);
10917 + * ======== FillStreamConnect ========
10918 + * Purpose:
10919 + * Fills stream information.
10920 + */
10921 +static void FillStreamConnect(struct NODE_OBJECT *hNode1,
10922 + struct NODE_OBJECT *hNode2,
10923 + u32 uStream1, u32 uStream2)
10925 + u32 uStrmIndex;
10926 + struct DSP_STREAMCONNECT *pStrm1 = NULL;
10927 + struct DSP_STREAMCONNECT *pStrm2 = NULL;
10928 + enum NODE_TYPE node1Type = NODE_TASK;
10929 + enum NODE_TYPE node2Type = NODE_TASK;
10931 + node1Type = NODE_GetType(hNode1);
10932 + node2Type = NODE_GetType(hNode2);
10933 + if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
10935 + if (node1Type != NODE_DEVICE) {
10936 + uStrmIndex = hNode1->uNumInputs +
10937 + hNode1->uNumOutputs - 1;
10938 + pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
10939 + pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
10940 + pStrm1->uThisNodeStreamIndex = uStream1;
10943 + if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
10944 + /* NODE == > NODE */
10945 + if (node1Type != NODE_DEVICE) {
10946 + pStrm1->hConnectedNode = hNode2;
10947 + pStrm1->uiConnectedNodeID = hNode2->nodeId;
10948 + pStrm1->uConnectedNodeStreamIndex = uStream2;
10949 + pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
10951 + if (node2Type != NODE_DEVICE) {
10952 + uStrmIndex = hNode2->uNumInputs +
10953 + hNode2->uNumOutputs - 1;
10954 + pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
10955 + pStrm2->cbStruct =
10956 + sizeof(struct DSP_STREAMCONNECT);
10957 + pStrm2->uThisNodeStreamIndex = uStream2;
10958 + pStrm2->hConnectedNode = hNode1;
10959 + pStrm2->uiConnectedNodeID = hNode1->nodeId;
10960 + pStrm2->uConnectedNodeStreamIndex = uStream1;
10961 + pStrm2->lType = CONNECTTYPE_NODEINPUT;
10963 + } else if (node1Type != NODE_DEVICE)
10964 + pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
10965 + } else {
10966 + /* GPP == > NODE */
10967 + DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
10968 + uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
10969 + pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
10970 + pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
10971 + pStrm2->uThisNodeStreamIndex = uStream2;
10972 + pStrm2->lType = CONNECTTYPE_GPPINPUT;
10977 + * ======== FillStreamDef ========
10978 + * Purpose:
10979 + * Fills Stream attributes.
10980 + */
10981 +static void FillStreamDef(struct NODE_OBJECT *hNode,
10982 + struct NODE_STRMDEF *pstrmDef,
10983 + struct DSP_STRMATTR *pAttrs)
10985 + struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
10987 + if (pAttrs != NULL) {
10988 + pstrmDef->uNumBufs = pAttrs->uNumBufs;
10989 + pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
10990 + uDSPDataMauSize;
10991 + pstrmDef->uSegid = pAttrs->uSegid;
10992 + pstrmDef->uAlignment = pAttrs->uAlignment;
10993 + pstrmDef->uTimeout = pAttrs->uTimeout;
10994 + } else {
10995 + pstrmDef->uNumBufs = DEFAULTNBUFS;
10996 + pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
10997 + uDSPDataMauSize;
10998 + pstrmDef->uSegid = DEFAULTSEGID;
10999 + pstrmDef->uAlignment = DEFAULTALIGNMENT;
11000 + pstrmDef->uTimeout = DEFAULTTIMEOUT;
11005 + * ======== FreeStream ========
11006 + * Purpose:
11007 + * Updates the channel mask and frees the pipe id.
11008 + */
11009 +static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
11011 + /* Free up the pipe id unless other node has not yet been deleted. */
11012 + if (stream.type == NODECONNECT) {
11013 + if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
11014 + /* The other node has already been deleted */
11015 + GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
11016 + GB_clear(hNodeMgr->pipeMap, stream.devId);
11017 + } else {
11018 + /* The other node has not been deleted yet */
11019 + GB_set(hNodeMgr->pipeDoneMap, stream.devId);
11021 + } else if (stream.type == HOSTCONNECT) {
11022 + if (stream.devId < hNodeMgr->ulNumChnls) {
11023 + GB_clear(hNodeMgr->chnlMap, stream.devId);
11024 + } else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
11025 + /* dsp-dma */
11026 + GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
11027 + (1 * hNodeMgr->ulNumChnls));
11028 + } else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
11029 + /* zero-copy */
11030 + GB_clear(hNodeMgr->zChnlMap, stream.devId -
11031 + (2 * hNodeMgr->ulNumChnls));
11037 + * ======== GetFxnAddress ========
11038 + * Purpose:
11039 + * Retrieves the address for create, execute or delete phase for a node.
11040 + */
11041 +static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
11042 + u32 uPhase)
11044 + char *pstrFxnName = NULL;
11045 + struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
11046 + DSP_STATUS status = DSP_SOK;
11047 + DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
11048 + NODE_GetType(hNode) == NODE_DAISSOCKET ||
11049 + NODE_GetType(hNode) == NODE_MESSAGE);
11051 + switch (uPhase) {
11052 + case CREATEPHASE:
11053 + pstrFxnName = hNode->dcdProps.objData.nodeObj.
11054 + pstrCreatePhaseFxn;
11055 + break;
11056 + case EXECUTEPHASE:
11057 + pstrFxnName = hNode->dcdProps.objData.nodeObj.
11058 + pstrExecutePhaseFxn;
11059 + break;
11060 + case DELETEPHASE:
11061 + pstrFxnName = hNode->dcdProps.objData.nodeObj.
11062 + pstrDeletePhaseFxn;
11063 + break;
11064 + default:
11065 + /* Should never get here */
11066 + DBC_Assert(false);
11067 + break;
11070 + status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
11071 + pulFxnAddr);
11073 + return status;
11077 + * ======== GetNodeInfo ========
11078 + * Purpose:
11079 + * Retrieves the node information.
11080 + */
11081 +void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
11083 + u32 i;
11085 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
11086 + DBC_Require(pNodeInfo != NULL);
11088 + pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
11089 + pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
11090 + ndbProps;
11091 + pNodeInfo->uExecutionPriority = hNode->nPriority;
11092 + pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
11093 + pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
11094 + pNodeInfo->uNodeEnv = hNode->nodeEnv;
11096 + pNodeInfo->nsExecutionState = NODE_GetState(hNode);
11098 + /* Copy stream connect data */
11099 + for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
11100 + pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
11105 + * ======== GetNodeProps ========
11106 + * Purpose:
11107 + * Retrieve node properties.
11108 + */
11109 +static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
11110 + struct NODE_OBJECT *hNode,
11111 + CONST struct DSP_UUID *pNodeId,
11112 + struct DCD_GENERICOBJ *pdcdProps)
11114 + u32 uLen;
11115 + struct NODE_MSGARGS *pMsgArgs;
11116 + struct NODE_TASKARGS *pTaskArgs;
11117 + enum NODE_TYPE nodeType = NODE_TASK;
11118 + struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
11119 + DSP_STATUS status = DSP_SOK;
11120 +#ifdef DEBUG
11121 + char szUuid[MAXUUIDLEN];
11122 +#endif
11124 + status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
11125 + DSP_DCDNODETYPE, pdcdProps);
11127 + if (DSP_SUCCEEDED(status)) {
11128 + hNode->nType = nodeType = pndbProps->uNodeType;
11130 +#ifdef DEBUG
11131 + /* Create UUID value to set in registry. */
11132 + UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
11133 + MAXUUIDLEN);
11134 + DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
11135 +#endif
11137 + /* Fill in message args that come from NDB */
11138 + if (nodeType != NODE_DEVICE) {
11139 + pMsgArgs = &(hNode->createArgs.asa.msgArgs);
11140 + pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
11141 + pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
11142 + uMsgNotifyType;
11143 + pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
11144 +#ifdef DEBUG
11145 + DBG_Trace(DBG_LEVEL7,
11146 + "** (node) Max Number of Messages: 0x%x\n",
11147 + pMsgArgs->uMaxMessages);
11148 +#endif
11149 + } else {
11150 + /* Copy device name */
11151 + uLen = CSL_Strlen(pndbProps->acName);
11152 + DBC_Assert(uLen < MAXDEVNAMELEN);
11153 + hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
11154 + if (hNode->pstrDevName == NULL) {
11155 + status = DSP_EMEMORY;
11156 + } else {
11157 + CSL_Strcpyn(hNode->pstrDevName,
11158 + pndbProps->acName, uLen);
11162 + if (DSP_SUCCEEDED(status)) {
11163 + /* Fill in create args that come from NDB */
11164 + if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
11165 + pTaskArgs = &(hNode->createArgs.asa.taskArgs);
11166 + pTaskArgs->nPriority = pndbProps->iPriority;
11167 + pTaskArgs->uStackSize = pndbProps->uStackSize;
11168 + pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
11169 + pTaskArgs->uStackSeg = pndbProps->uStackSeg;
11170 +#ifdef DEBUG
11171 + DBG_Trace(DBG_LEVEL7,
11172 + "** (node) Priority: 0x%x\n" "** (node) Stack"
11173 + " Size: 0x%x words\n" "** (node) System Stack"
11174 + " Size: 0x%x words\n" "** (node) Stack"
11175 + " Segment: 0x%x\n\n",
11176 + "** (node) profile count : 0x%x \n \n",
11177 + pTaskArgs->nPriority, pTaskArgs->uStackSize,
11178 + pTaskArgs->uSysStackSize,
11179 + pTaskArgs->uStackSeg,
11180 + pndbProps->uCountProfiles);
11181 +#endif
11185 + return status;
11189 + * ======== GetProcProps ========
11190 + * Purpose:
11191 + * Retrieve the processor properties.
11192 + */
11193 +static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
11194 + struct DEV_OBJECT *hDevObject)
11196 + struct CFG_DEVNODE *hDevNode;
11197 + struct CFG_HOSTRES hostRes;
11198 + DSP_STATUS status = DSP_SOK;
11200 + status = DEV_GetDevNode(hDevObject, &hDevNode);
11201 + if (DSP_SUCCEEDED(status))
11202 + status = CFG_GetHostResources(hDevNode, &hostRes);
11204 + if (DSP_SUCCEEDED(status)) {
11205 + hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
11206 + hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
11207 + hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
11209 + /*
11210 + * PROC will add an API to get DSP_PROCESSORINFO.
11211 + * Fill in default values for now.
11212 + */
11213 + /* TODO -- Instead of hard coding, take from registry */
11214 + hNodeMgr->procFamily = 6000;
11215 + hNodeMgr->procType = 6410;
11216 + hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
11217 + hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
11218 + hNodeMgr->uDSPWordSize = DSPWORDSIZE;
11219 + hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
11220 + hNodeMgr->uDSPMauSize = 1;
11223 + return status;
11229 + * ======== NODE_GetUUIDProps ========
11230 + * Purpose:
11231 + * Fetch Node UUID properties from DCD/DOF file.
11232 + */
11233 +DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
11234 + IN CONST struct DSP_UUID *pNodeId,
11235 + OUT struct DSP_NDBPROPS *pNodeProps)
11237 + struct NODE_MGR *hNodeMgr = NULL;
11238 + struct DEV_OBJECT *hDevObject;
11239 + DSP_STATUS status = DSP_SOK;
11240 + struct DCD_NODEPROPS dcdNodeProps;
11242 + DBC_Require(cRefs > 0);
11243 + DBC_Require(hProcessor != NULL);
11244 + DBC_Require(pNodeId != NULL);
11246 + GT_3trace(NODE_debugMask, GT_ENTER,
11247 + "NODE_GetUUIDProps: " "\thProcessor: "
11248 + "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
11249 + pNodeId, pNodeProps);
11251 + status = PROC_GetDevObject(hProcessor, &hDevObject);
11252 + if (DSP_SUCCEEDED(status)) {
11253 + status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
11254 + if (hNodeMgr == NULL)
11255 + status = DSP_EFAIL;
11258 + if (DSP_SUCCEEDED(status)) {
11259 + dcdNodeProps.pstrCreatePhaseFxn = NULL;
11260 + dcdNodeProps.pstrExecutePhaseFxn = NULL;
11261 + dcdNodeProps.pstrDeletePhaseFxn = NULL;
11262 + dcdNodeProps.pstrIAlgName = NULL;
11264 + status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
11265 + (struct DSP_UUID *) pNodeId,
11266 + DSP_DCDNODETYPE,
11267 + (struct DCD_GENERICOBJ *) &dcdNodeProps);
11268 + if (DSP_SUCCEEDED(status)) {
11269 + *pNodeProps = dcdNodeProps.ndbProps;
11270 + if (dcdNodeProps.pstrCreatePhaseFxn)
11271 + MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
11273 + if (dcdNodeProps.pstrExecutePhaseFxn)
11274 + MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
11276 + if (dcdNodeProps.pstrDeletePhaseFxn)
11277 + MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
11279 + if (dcdNodeProps.pstrIAlgName)
11280 + MEM_Free(dcdNodeProps.pstrIAlgName);
11284 + return status;
11288 + * ======== GetRMSFxns ========
11289 + * Purpose:
11290 + * Retrieve the RMS functions.
11291 + */
11292 +static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
11294 + s32 i;
11295 + struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
11296 + DSP_STATUS status = DSP_SOK;
11298 + static char *pszFxns[NUMRMSFXNS] = {
11299 + "RMS_queryServer", /* RMSQUERYSERVER */
11300 + "RMS_configureServer", /* RMSCONFIGURESERVER */
11301 + "RMS_createNode", /* RMSCREATENODE */
11302 + "RMS_executeNode", /* RMSEXECUTENODE */
11303 + "RMS_deleteNode", /* RMSDELETENODE */
11304 + "RMS_changeNodePriority", /* RMSCHANGENODEPRIORITY */
11305 + "RMS_readMemory", /* RMSREADMEMORY */
11306 + "RMS_writeMemory", /* RMSWRITEMEMORY */
11307 + "RMS_copy", /* RMSCOPY */
11308 + };
11310 + for (i = 0; i < NUMRMSFXNS; i++) {
11311 + status = DEV_GetSymbol(hDev, pszFxns[i],
11312 + &(hNodeMgr->ulFxnAddrs[i]));
11313 + if (DSP_FAILED(status)) {
11314 + if (status == COD_E_SYMBOLNOTFOUND) {
11315 + /*
11316 + * May be loaded dynamically (in the future),
11317 + * but return an error for now.
11318 + */
11319 + GT_1trace(NODE_debugMask, GT_6CLASS,
11320 + "RMS function: %s "
11321 + "currently not loaded\n", pszFxns[i]);
11322 + } else {
11323 + GT_2trace(NODE_debugMask, GT_6CLASS,
11324 + "GetRMSFxns: Symbol not "
11325 + "found: %s\tstatus = 0x%x\n",
11326 + pszFxns[i], status);
11327 + break;
11332 + return status;
11336 + * ======== Ovly ========
11337 + * Purpose:
11338 + * Called during overlay.Sends command to RMS to copy a block of data.
11339 + */
11340 +static CDECL u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
11341 + u32 ulNumBytes, u32 nMemSpace)
11343 + struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
11344 + struct NODE_MGR *hNodeMgr;
11345 + u32 ulBytes = 0;
11346 + u32 ulSize;
11347 + u32 ulTimeout;
11348 + DSP_STATUS status = DSP_SOK;
11349 + struct WMD_DEV_CONTEXT *hWmdContext;
11350 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
11352 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
11354 + hNodeMgr = hNode->hNodeMgr;
11356 + ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
11357 + ulTimeout = hNode->uTimeout;
11359 + /* Call new MemCopy function */
11360 + pIntfFxns = hNodeMgr->pIntfFxns;
11361 + status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
11362 + status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
11363 + ulDspLoadAddr, ulNumBytes, (u32) nMemSpace);
11365 + if (DSP_SUCCEEDED(status))
11366 + ulBytes = ulNumBytes;
11368 + return ulBytes;
11372 + * ======== Write ========
11373 + */
11374 +static CDECL u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
11375 + u32 ulNumBytes, u32 nMemSpace)
11377 + struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
11378 + struct NODE_MGR *hNodeMgr;
11379 + u16 memType;
11380 + u32 ulTimeout;
11381 + DSP_STATUS status = DSP_SOK;
11382 + struct WMD_DEV_CONTEXT *hWmdContext;
11383 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
11385 + DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
11386 + DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
11388 + hNodeMgr = hNode->hNodeMgr;
11390 + ulTimeout = hNode->uTimeout;
11391 + memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
11393 + /* Call new MemWrite function */
11394 + pIntfFxns = hNodeMgr->pIntfFxns;
11395 + status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
11396 + status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
11397 + ulNumBytes, memType);
11399 + return ulNumBytes;
11402 Index: lk/drivers/dsp/bridge/rmgr/proc.c
11403 ===================================================================
11404 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
11405 +++ lk/drivers/dsp/bridge/rmgr/proc.c 2008-08-18 10:38:37.000000000 +0300
11406 @@ -0,0 +1,1958 @@
11408 + * linux/drivers/dsp/bridge/rmgr/proc.c
11410 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
11412 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
11414 + * This package is free software; you can redistribute it and/or modify
11415 + * it under the terms of the GNU General Public License version 2 as
11416 + * published by the Free Software Foundation.
11418 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
11419 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
11420 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
11421 + */
11425 + * ======== proc.c ========
11426 + * Description:
11427 + * Processor interface at the driver level.
11429 + * Public Functions:
11430 + * PROC_Attach
11431 + * PROC_Ctrl
11432 + * PROC_Detach
11433 + * PROC_EnumNodes
11434 + * PROC_GetResourceInfo
11435 + * PROC_Exit
11436 + * PROC_FlushMemory
11437 + * PROC_GetState
11438 + * PROC_GetProcessorId
11439 + * PROC_GetTrace
11440 + * PROC_Init
11441 + * PROC_Load
11442 + * PROC_Map
11443 + * PROC_NotifyClients
11444 + * PROC_RegisterNotify
11445 + * PROC_ReserveMemory
11446 + * PROC_Start
11447 + * PROC_UnMap
11448 + * PROC_UnReserveMemory
11449 + * PROC_InvalidateMemory
11451 + *! Revision History
11452 + *! ======== ========
11453 + *! 04-Apr-2007 sh Added PROC_InvalidateMemory API
11454 + *! 19-Apr-2004 sb Aligned DMM definitions with Symbian
11455 + *! Used MEM_FlushCache instead of OS specific API
11456 + *! Integrated Alan's code review updates
11457 + *! 08-Mar-2004 sb Added the Dynamic Memory Mapping feature
11458 + *! 08-Mar-2004 vp Added g_pszLastCoff member to PROC_OBJECT.
11459 + *! This is required for multiprocessor environment.
11460 + *! 09-Feb-2004 vp Added PROC_GetProcessorID function
11461 + *! 22-Apr-2003 vp Fixed issue with the string that stores coff file name
11462 + *! 03-Apr-2003 sb Fix DEH deregistering bug
11463 + *! 26-Mar-2003 vp Commented the call to DSP deep sleep in PROC_Start function.
11464 + *! 18-Feb-2003 vp Code review updates.
11465 + *! 18-Oct-2002 vp Ported to Linux platform.
11466 + *! 22-May-2002 sg Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
11467 + *! 14-May-2002 sg Use CSL_Atoi() instead of atoi().
11468 + *! 13-May-2002 sg Propagate PWR return codes upwards.
11469 + *! 07-May-2002 sg Added check for, and call to PWR functions in PROC_Ctrl.
11470 + *! 02-May-2002 sg Added "nap" mode: put DSP to sleep once booted.
11471 + *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
11472 + *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
11473 + *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
11474 + *! DEH module.
11475 + *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
11476 + *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
11477 + *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
11478 + *! to facilitate the external loading.
11479 + *! 14-Aug-2001 ag DCD_AutoRegister() now called before IOOnLoaded() fxn.
11480 + *! 21-Jun-2001 rr: MSG_Create is done only the first time.
11481 + *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
11482 + *! error other than E_NOTIMPL.
11483 + *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
11484 + *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
11485 + *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
11486 + *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
11487 + *! if DEV_Create2 fails; ie, no non-RMS targets can be
11488 + *! loaded.
11489 + *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
11490 + *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
11491 + *! 29-Nov-2000 rr: Incorporated code review changes.
11492 + *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
11493 + *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
11494 + *! WMD_BRD_STOP is always followed by DEV_Destroy2.
11495 + *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
11496 + *! different way.
11497 + *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
11498 + *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
11499 + *! WMD fxns are checked for WSX_STATUS.
11500 + *! PROC_Attach does not alter the state of the BRD.
11501 + *! PROC_Run removed.
11502 + *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
11503 + *! invalid
11504 + *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
11505 + *! ver 0.8 API.
11506 + *! 06-Jul-2000 rr: Created.
11507 + */
11509 +/* ------------------------------------ Host OS */
11510 +#include <host_os.h>
11512 +/* ----------------------------------- DSP/BIOS Bridge */
11513 +#include <std.h>
11514 +#include <dbdefs.h>
11515 +#include <errbase.h>
11517 +/* ----------------------------------- Trace & Debug */
11518 +#include <dbc.h>
11519 +#include <gt.h>
11521 +/* ----------------------------------- OS Adaptation Layer */
11522 +#include <cfg.h>
11523 +#include <csl.h>
11524 +#include <list.h>
11525 +#include <mem.h>
11526 +#include <ntfy.h>
11527 +#include <prcs.h>
11529 +/* ----------------------------------- Mini Driver */
11530 +#include <wmd.h>
11532 +/* ----------------------------------- Platform Manager */
11533 +#include <cod.h>
11534 +#include <dev.h>
11535 +#include <drv.h>
11536 +#include <procpriv.h>
11537 +#include <dmm.h>
11539 +/* ----------------------------------- Resource Manager */
11540 +#include <mgr.h>
11541 +#include <node.h>
11542 +#include <nldr.h>
11543 +#include <rmm.h>
11545 +/* ----------------------------------- Others */
11546 +#include <dbdcd.h>
11547 +#include <dbreg.h>
11548 +#include <msg.h>
11549 +#include <pwr.h>
11550 +#include <wmdioctl.h>
11552 +/* ----------------------------------- This */
11553 +#include <proc.h>
11555 +#ifndef RES_CLEANUP_DISABLE
11556 +#include <resourcecleanup.h>
11557 +#endif
11558 +#ifndef CONFIG_DISABLE_BRIDGE_PM
11559 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
11560 +#include <asm/arch/resource.h>
11561 +#endif
11562 +#endif
11563 +/* ----------------------------------- Defines, Data Structures, Typedefs */
11564 +#define PROC_SIGNATURE 0x434F5250 /* "PROC" (in reverse). */
11565 +#define MAXCMDLINELEN 255
11566 +#define PROC_ENVPROCID "PROC_ID=%d"
11567 +#define MAXPROCIDLEN (8 + 5)
11568 +#define PROC_DFLT_TIMEOUT 10000 /* Time out in milliseconds */
11569 +#define PWR_TIMEOUT 500 /* Sleep/wake timout in msec */
11570 +#define EXTEND "_EXT_END" /* Extmem end addr in DSP binary */
11572 +extern char *iva_img;
11573 +/* The PROC_OBJECT structure. */
11574 +struct PROC_OBJECT {
11575 + struct LST_ELEM link; /* Link to next PROC_OBJECT */
11576 + u32 dwSignature; /* Used for object validation */
11577 + struct DEV_OBJECT *hDevObject; /* Device this PROC represents */
11578 + HANDLE hProcess; /* Process owning this Processor */
11579 + struct MGR_OBJECT *hMgrObject; /* Manager Object Handle */
11580 + u32 uAttachCount; /* Processor attach count */
11581 + u32 uProcessor; /* Processor number */
11582 + u32 uTimeout; /* Time out count */
11583 + enum DSP_PROCSTATE sState; /* Processor state */
11584 + u32 ulUnit; /* DDSP unit number */
11585 + bool bIsAlreadyAttached; /*
11586 + * True if the Device below has
11587 + * GPP Client attached
11588 + */
11589 + struct NTFY_OBJECT *hNtfy; /* Manages notifications */
11590 + struct WMD_DEV_CONTEXT *hWmdContext; /* WMD Context Handle */
11591 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
11592 + char *g_pszLastCoff;
11593 +} ;
11595 +/* ----------------------------------- Globals */
11596 +#if GT_TRACE
11597 +static struct GT_Mask PROC_DebugMask = { NULL, NULL }; /* WCD MGR Mask */
11598 +#endif
11600 +static u32 cRefs;
11602 +#ifndef CONFIG_DISABLE_BRIDGE_PM
11603 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
11604 +extern struct constraint_handle *mpu_constraint_handle;
11605 +#endif
11606 +#endif
11608 +/* ----------------------------------- Function Prototypes */
11609 +static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
11610 +static s32 GetEnvpCount(char **envp);
11611 +static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
11612 + char *szVar);
11616 + * ======== PROC_Attach ========
11617 + * Purpose:
11618 + * Prepare for communication with a particular DSP processor, and return
11619 + * a handle to the processor object.
11620 + */
11621 +DSP_STATUS
11622 +PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
11623 + OUT DSP_HPROCESSOR *phProcessor)
11625 + DSP_STATUS status = DSP_SOK;
11626 + struct DEV_OBJECT *hDevObject;
11627 + struct PROC_OBJECT *pProcObject = NULL;
11628 + struct MGR_OBJECT *hMgrObject = NULL;
11629 + struct DRV_OBJECT *hDrvObject = NULL;
11630 + u32 devType;
11632 +#ifndef RES_CLEANUP_DISABLE
11633 + HANDLE hDRVObject;
11634 + HANDLE hProcess;
11635 + DSP_STATUS res_status = DSP_SOK;
11636 + struct PROCESS_CONTEXT *pPctxt = NULL;
11637 +#endif
11639 + DBC_Require(cRefs > 0);
11640 + DBC_Require(phProcessor != NULL);
11642 + GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
11643 + "uProcessor: 0x%x\n\tpAttrIn: 0x%x\n\tphProcessor:"
11644 + "0x%x\n", uProcessor, pAttrIn, phProcessor);
11645 + /* Get the Driver and Manager Object Handles */
11646 + status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
11647 + if (DSP_SUCCEEDED(status)) {
11648 + status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
11649 + if (DSP_FAILED(status)) {
11650 + /* don't propogate CFG errors from this PROC function */
11651 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11652 + "PROC_Attach: DSP_FAILED to get"
11653 + "the Manager Object.\n", status);
11655 + } else {
11656 + /* don't propogate CFG errors from this PROC function */
11657 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11658 + "PROC_Attach: failed to get the"
11659 + " DriverObject, 0x%x!\n", status);
11661 + if (DSP_SUCCEEDED(status)) {
11662 + /* Get the Device Object */
11663 + status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
11664 + if (DSP_FAILED(status)) {
11665 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11666 + "PROC_Attach: failed to get"
11667 + " DevObject, 0x%x!\n", status);
11670 + if (DSP_SUCCEEDED(status)) {
11671 + status = DEV_GetDevType(hDevObject, &devType);
11672 + if (DSP_FAILED(status)) {
11673 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11674 + "PROC_Attach: failed to get"
11675 + " DevType, 0x%x!\n", status);
11678 + if (DSP_FAILED(status))
11679 + goto func_end;
11681 + /* If we made it this far, create the Proceesor object: */
11682 + MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
11683 + /* Fill out the Processor Object: */
11684 + if (pProcObject == NULL) {
11685 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11686 + "PROC_Attach:Out of memeory \n");
11687 + status = DSP_EFAIL;
11688 + goto func_end;
11690 + pProcObject->hDevObject = hDevObject;
11691 + pProcObject->hMgrObject = hMgrObject;
11692 + pProcObject->uProcessor = devType;
11693 + /* Get Caller Process and store it */
11694 + (void)PRCS_GetCurrentHandle(&pProcObject->hProcess);
11695 + if (pAttrIn)
11696 + pProcObject->uTimeout = pAttrIn->uTimeout;
11697 + else
11698 + pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
11700 + status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
11701 + if (DSP_SUCCEEDED(status)) {
11702 + status = DEV_GetWMDContext(hDevObject,
11703 + &pProcObject->hWmdContext);
11704 + if (DSP_FAILED(status)) {
11705 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11706 + "PROC_Attach Could not"
11707 + " get the WMD Context.\n", status);
11708 + MEM_FreeObject(pProcObject);
11710 + } else {
11711 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11712 + "PROC_Attach Could not get"
11713 + " the DEV_ Interface fxns.\n", status);
11714 + MEM_FreeObject(pProcObject);
11716 + if (DSP_FAILED(status))
11717 + goto func_end;
11719 + /* Create the Notification Object */
11720 + /* This is created with no event mask, no notify mask
11721 + * and no valid handle to the notification. They all get
11722 + * filled up when PROC_RegisterNotify is called */
11723 + status = NTFY_Create(&pProcObject->hNtfy);
11724 + if (DSP_SUCCEEDED(status)) {
11725 + /* Insert the Processor Object into the DEV List.
11726 + * Return handle to this Processor Object:
11727 + * Find out if the Device is already attached to a
11728 + * Processor. If so, return AlreadyAttached status */
11729 + LST_InitElem(&pProcObject->link);
11730 + status = DEV_InsertProcObject(pProcObject->hDevObject,
11731 + (u32)pProcObject,
11732 + &pProcObject->bIsAlreadyAttached);
11733 + if (DSP_SUCCEEDED(status)) {
11734 + if (pProcObject->bIsAlreadyAttached) {
11735 + status = DSP_SALREADYATTACHED;
11736 + GT_0trace(PROC_DebugMask, GT_1CLASS,
11737 + "PROC_Attach: Processor "
11738 + "Already Attached!\n");
11740 + } else {
11741 + if (pProcObject->hNtfy)
11742 + NTFY_Delete(pProcObject->hNtfy);
11744 + MEM_FreeObject(pProcObject);
11745 + GT_1trace(PROC_DebugMask, GT_7CLASS,
11746 + "PROC_Attach: failed to insert "
11747 + "Proc Object into DEV, 0x%x!\n", status);
11749 + if (DSP_SUCCEEDED(status)) {
11750 + *phProcessor = (DSP_HPROCESSOR)pProcObject;
11751 + (void)PROC_NotifyClients(pProcObject,
11752 + DSP_PROCESSORATTACH);
11753 + GT_0trace(PROC_DebugMask, GT_1CLASS,
11754 + "PROC_Attach: Processor "
11755 + "Attach Success!\n");
11757 + } else {
11758 + /* Don't leak memory if DSP_FAILED */
11759 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11760 + "PROC_Attach: Could not allocate "
11761 + "storage for notification \n");
11762 + MEM_FreeObject(pProcObject);
11764 +func_end:
11765 +#ifndef RES_CLEANUP_DISABLE
11766 + if (DSP_FAILED(status))
11767 + goto func_cont;
11769 + PRCS_GetCurrentHandle(&hProcess);
11770 + res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
11771 + if (DSP_FAILED(res_status))
11772 + goto func_cont;
11774 + DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
11775 + if (pPctxt == NULL) {
11776 + DRV_InsertProcContext(hDRVObject, &pPctxt);
11777 + if (pPctxt != NULL) {
11778 + DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
11779 + DRV_ProcSetPID(pPctxt, (s32)hProcess);
11782 +func_cont:
11783 + PRCS_GetCurrentHandle(&hProcess);
11784 + res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
11785 + if (DSP_SUCCEEDED(res_status)) {
11786 + DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
11787 + if (pPctxt != NULL)
11788 + pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
11791 +#endif
11792 + DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
11793 + (DSP_SUCCEEDED(status) &&
11794 + MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
11795 + (status == DSP_SALREADYATTACHED &&
11796 + MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
11797 + GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
11798 + "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
11800 + return status;
11803 +static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
11804 + struct DEV_OBJECT *hDevObject,
11805 + u32 size, char *execFile)
11807 + s32 devType;
11808 + s32 len;
11810 + DEV_GetDevType(hDevObject, (u32 *) &devType);
11811 + if (devType == DSP_UNIT) {
11812 + return CFG_GetExecFile(hDevNode, size, execFile);
11813 + } else if (devType == IVA_UNIT) {
11814 + if (iva_img) {
11815 + len = CSL_Strlen(iva_img);
11816 + CSL_Strcpyn(execFile, iva_img, len + 1);
11817 + return DSP_SOK;
11820 + return DSP_EFILE;
11824 + * ======== PROC_AutoStart ======== =
11825 + * Purpose:
11826 + * A Particular device gets loaded with the default image
11827 + * if the AutoStart flag is set.
11828 + * Parameters:
11829 + * hDevObject: Handle to the Device
11830 + * Returns:
11831 + * DSP_SOK: On Successful Loading
11832 + * DSP_EFAIL General Failure
11833 + * Requires:
11834 + * hDevObject != NULL
11835 + * Ensures:
11836 + */
11837 +DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
11838 + struct DEV_OBJECT *hDevObject)
11840 + DSP_STATUS status = DSP_EFAIL;
11841 + u32 dwAutoStart = 0; /* autostart flag */
11842 + struct PROC_OBJECT *pProcObject;
11843 + struct PROC_OBJECT *hProcObject;
11844 + char szExecFile[MAXCMDLINELEN];
11845 + char *argv[2];
11846 + struct MGR_OBJECT *hMgrObject = NULL;
11847 + s32 devType;
11849 + DBC_Require(cRefs > 0);
11850 + DBC_Require(hDevNode != NULL);
11851 + DBC_Require(hDevObject != NULL);
11853 + GT_2trace(PROC_DebugMask, GT_ENTER,
11854 + "Entered PROC_AutoStart, args:\n\t"
11855 + "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
11856 + /* Create a Dummy PROC Object */
11857 + if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
11858 + REG_MGR_OBJECT))) {
11859 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11860 + "PROC_AutoStart: DSP_FAILED to "
11861 + "Get MGR Object\n");
11862 + goto func_end;
11864 + MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
11865 + if (pProcObject == NULL) {
11866 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11867 + "PROC_AutoStart: DSP_FAILED "
11868 + "to Create a dummy Processor\n");
11869 + goto func_end;
11871 + GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
11872 + pProcObject->hDevObject = hDevObject;
11873 + pProcObject->hMgrObject = hMgrObject;
11874 + hProcObject = pProcObject;
11875 + if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
11876 + &pProcObject->pIntfFxns))) {
11877 + if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
11878 + &pProcObject->hWmdContext))) {
11879 + status = DSP_SOK;
11880 + } else {
11881 + MEM_FreeObject(hProcObject);
11882 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11883 + "PROC_AutoStart: Failed "
11884 + "to get WMD Context \n");
11886 + } else {
11887 + MEM_FreeObject(hProcObject);
11888 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11889 + "PROC_AutoStart: Failed to "
11890 + "get IntFxns \n");
11892 + if (DSP_FAILED(status))
11893 + goto func_end;
11895 + /* Stop the Device, put it into standby mode */
11896 + status = PROC_Stop(hProcObject);
11897 + if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
11898 + !dwAutoStart) {
11899 + status = DSP_EFAIL;
11900 + /* DSP_FAILED to Get s32 Fxn or Wmd Context */
11901 + GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
11902 + "CFG_GetAutoStart DSP_FAILED \n");
11903 + goto func_cont;
11905 + /* Get the default executable for this board... */
11906 + DEV_GetDevType(hDevObject, (u32 *)&devType);
11907 + pProcObject->uProcessor = devType;
11908 + if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
11909 + sizeof(szExecFile), szExecFile))) {
11910 + argv[0] = szExecFile;
11911 + argv[1] = NULL;
11912 + /* ...and try to load it: */
11913 + status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
11914 + if (DSP_SUCCEEDED(status)) {
11915 + status = PROC_Start(hProcObject);
11916 + if (DSP_SUCCEEDED(status)) {
11917 + GT_0trace(PROC_DebugMask, GT_1CLASS,
11918 + "PROC_AutoStart: Processor started "
11919 + "running\n");
11920 + } else {
11921 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11922 + "PROC_AutoStart: DSP_FAILED To "
11923 + "Start \n");
11925 + } else {
11926 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11927 + "PROC_AutoStart: DSP_FAILED to Load\n");
11929 + } else {
11930 + status = DSP_EFILE;
11931 + GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
11932 + "No Exec file found \n");
11934 +func_cont:
11935 + MEM_FreeObject(hProcObject);
11936 +func_end:
11937 + GT_1trace(PROC_DebugMask, GT_ENTER,
11938 + "Exiting PROC_AutoStart, status:0x%x\n", status);
11939 + return status;
11943 + * ======== PROC_Ctrl ========
11944 + * Purpose:
11945 + * Pass control information to the GPP device driver managing the
11946 + * DSP processor.
11948 + * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
11949 + * application developer's API.
11950 + * Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
11951 + * Operation. arg can be null.
11952 + */
11953 +DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
11954 + IN struct DSP_CBDATA *arg)
11956 + DSP_STATUS status = DSP_SOK;
11957 + struct PROC_OBJECT *pProcObject = hProcessor;
11958 + u32 timeout = 0;
11960 + DBC_Require(cRefs > 0);
11961 + GT_3trace(PROC_DebugMask, GT_ENTER,
11962 + "Entered PROC_Ctrl, args:\n\thProcessor:"
11963 + " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
11965 + if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
11966 + /* intercept PWR deep sleep command */
11967 + if (dwCmd == WMDIOCTL_DEEPSLEEP) {
11968 + timeout = arg->cbData;
11969 + status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
11971 + /* intercept PWR emergency sleep command */
11972 + else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
11973 + timeout = arg->cbData;
11974 + status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
11975 + } else if (dwCmd == PWR_DEEPSLEEP) {
11976 + /* timeout = arg->cbData; */
11977 + status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
11979 + /* intercept PWR wake commands */
11980 + else if (dwCmd == WMDIOCTL_WAKEUP) {
11981 + timeout = arg->cbData;
11982 + status = PWR_WakeDSP(timeout);
11983 + } else if (dwCmd == PWR_WAKEUP) {
11984 + /* timeout = arg->cbData; */
11985 + status = PWR_WakeDSP(timeout);
11986 + } else
11987 + if (DSP_SUCCEEDED
11988 + ((*pProcObject->pIntfFxns->pfnDevCntrl)
11989 + (pProcObject->hWmdContext, dwCmd, arg))) {
11990 + status = DSP_SOK;
11991 + } else {
11992 + status = DSP_EFAIL;
11993 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11994 + "PROC_Ctrl: Failed \n");
11996 + } else {
11997 + status = DSP_EHANDLE;
11998 + GT_0trace(PROC_DebugMask, GT_7CLASS,
11999 + "PROC_Ctrl: InValid Processor Handle \n");
12001 + GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
12002 + status);
12003 + return status;
12007 + * ======== PROC_Detach ========
12008 + * Purpose:
12009 + * Destroys the Processor Object. Removes the notification from the Dev
12010 + * List.
12011 + */
12012 +DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
12014 + DSP_STATUS status = DSP_SOK;
12015 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12016 +#ifndef RES_CLEANUP_DISABLE
12017 + HANDLE hDRVObject;
12018 + HANDLE hProcess;
12019 + DSP_STATUS res_status = DSP_SOK;
12020 + struct PROCESS_CONTEXT *pPctxt = NULL;
12021 +#endif
12022 + DBC_Require(cRefs > 0);
12023 + GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
12024 + "hProcessor: 0x%x\n", hProcessor);
12026 + if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12027 + /* Notify the Client */
12028 + NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
12029 + /* Remove the notification memory */
12030 + if (pProcObject->hNtfy)
12031 + NTFY_Delete(pProcObject->hNtfy);
12033 + /* Remove the Proc from the DEV List */
12034 + (void)DEV_RemoveProcObject(pProcObject->hDevObject,
12035 + (u32)pProcObject);
12036 + /* Free the Processor Object */
12037 + MEM_FreeObject(pProcObject);
12038 +#ifndef RES_CLEANUP_DISABLE
12039 + PRCS_GetCurrentHandle(&hProcess);
12040 + res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
12041 + /* res_status = CFG_GetObject(REG_DRV_OBJECT, (u32*)&hDRVObject); */
12042 + if (DSP_SUCCEEDED(res_status)) {
12043 + DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
12044 + if (pPctxt != NULL)
12045 + pPctxt->hProcessor = NULL;
12047 +#endif
12048 + } else {
12049 + status = DSP_EHANDLE;
12050 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12051 + "PROC_Detach: InValid Processor Handle \n");
12053 + GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
12054 + status);
12055 + return status;
12059 + * ======== PROC_EnumNodes ========
12060 + * Purpose:
12061 + * Enumerate and get configuration information about nodes allocated
12062 + * on a DSP processor.
12063 + */
12064 +DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
12065 + IN u32 uNodeTabSize, OUT u32 *puNumNodes,
12066 + OUT u32 *puAllocated)
12068 + DSP_STATUS status = DSP_EFAIL;
12069 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12070 + struct NODE_MGR *hNodeMgr = NULL;
12072 + DBC_Require(cRefs > 0);
12073 + DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
12074 + DBC_Require(puNumNodes != NULL);
12075 + DBC_Require(puAllocated != NULL);
12077 + GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
12078 + "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
12079 + " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
12080 + hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
12081 + puAllocated);
12082 + if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12083 + if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
12084 + &hNodeMgr))) {
12085 + if (hNodeMgr) {
12086 + status = NODE_EnumNodes(hNodeMgr, aNodeTab,
12087 + uNodeTabSize,
12088 + puNumNodes,
12089 + puAllocated);
12092 + } else {
12093 + status = DSP_EHANDLE;
12094 + GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
12095 + "InValid Processor Handle \n");
12097 + GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
12098 + "hProcessor: 0x%x\n\taNodeTab: 0x%x\n\tuNodeTabSize: "
12099 + " 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
12100 + "status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
12101 + puNumNodes, puAllocated, status);
12103 + return status;
12107 + * ======== PROC_FlushMemory ========
12108 + * Purpose:
12109 + * Flush cache
12110 + */
12111 +DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
12112 + u32 ulSize, u32 ulFlags)
12114 + /* Keep STATUS here for future additions to this function */
12115 + DSP_STATUS status = DSP_SOK;
12116 + enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
12117 + DBC_Require(cRefs > 0);
12119 + GT_4trace(PROC_DebugMask, GT_ENTER,
12120 + "Entered PROC_FlushMemory, args:\n\t"
12121 + "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
12122 + hProcessor, pMpuAddr, ulSize, ulFlags);
12124 + MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
12126 + GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
12127 + status);
12129 + return status;
12134 + * ======== PROC_InvalidateMemory ========
12135 + * Purpose:
12136 + * Invalidates the memory specified
12137 + */
12138 +DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
12139 + u32 ulSize)
12141 + /* Keep STATUS here for future additions to this function */
12142 + DSP_STATUS status = DSP_SOK;
12143 + enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
12144 + DBC_Require(cRefs > 0);
12145 + GT_3trace(PROC_DebugMask, GT_ENTER,
12146 + "Entered PROC_InvalidateMemory, args:\n\t"
12147 + "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
12148 + pMpuAddr, ulSize);
12149 + MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
12150 + GT_1trace(PROC_DebugMask, GT_ENTER,
12151 + "Leaving PROC_InvalidateMemory [0x%x]", status);
12152 + return status;
12156 + * ======== PROC_GetResourceInfo ========
12157 + * Purpose:
12158 + * Enumerate the resources currently available on a processor.
12159 + */
12160 +DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
12161 + OUT struct DSP_RESOURCEINFO *pResourceInfo,
12162 + u32 uResourceInfoSize)
12164 + DSP_STATUS status = DSP_EFAIL;
12165 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12166 + struct NODE_MGR *hNodeMgr = NULL;
12167 + struct NLDR_OBJECT *hNldr = NULL;
12168 + struct RMM_TargetObj *rmm = NULL;
12169 + struct IO_MGR *hIOMgr = NULL; /* IO manager handle */
12171 + DBC_Require(cRefs > 0);
12172 + DBC_Require(pResourceInfo != NULL);
12173 + DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
12175 + GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
12176 + "hProcessor: 0x%x\n\tuResourceType: 0x%x\n\tpResourceInfo:"
12177 + " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
12178 + uResourceType, pResourceInfo, uResourceInfoSize);
12179 + if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12180 + status = DSP_EHANDLE;
12181 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12182 + "PROC_GetResourceInfo: InValid "
12183 + "Processor Handle \n");
12184 + goto func_end;
12186 + switch (uResourceType) {
12187 + case DSP_RESOURCE_DYNDARAM:
12188 + case DSP_RESOURCE_DYNSARAM:
12189 + case DSP_RESOURCE_DYNEXTERNAL:
12190 + case DSP_RESOURCE_DYNSRAM:
12191 + if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
12192 + &hNodeMgr)))
12193 + goto func_end;
12195 + if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
12196 + if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
12197 + DBC_Assert(rmm != NULL);
12198 + status = DSP_EVALUE;
12199 + if (RMM_stat(rmm,
12200 + (enum DSP_MEMTYPE)uResourceType,
12201 + (struct DSP_MEMSTAT *)&(pResourceInfo->
12202 + result.memStat)))
12203 + status = DSP_SOK;
12206 + break;
12207 + case DSP_RESOURCE_PROCLOAD:
12208 + status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
12209 + status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
12210 + (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
12211 + result.procLoadStat));
12212 + if (DSP_FAILED(status)) {
12213 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12214 + "Error in procLoadStat function 0x%x\n", status);
12216 + break;
12217 + default:
12218 + status = DSP_EFAIL;
12219 + break;
12221 +func_end:
12222 + GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
12223 + "status 0x%x\n", status);
12224 + return status;
12228 + * ======== PROC_Exit ========
12229 + * Purpose:
12230 + * Decrement reference count, and free resources when reference count is
12231 + * 0.
12232 + */
12233 +void CDECL PROC_Exit(void)
12235 + DBC_Require(cRefs > 0);
12237 + cRefs--;
12239 + GT_1trace(PROC_DebugMask, GT_5CLASS,
12240 + "Entered PROC_Exit, ref count:0x%x\n", cRefs);
12241 + DBC_Ensure(cRefs >= 0);
12245 + * ======== PROC_GetDevObject ========
12246 + * Purpose:
12247 + * Return the Dev Object handle for a given Processor.
12249 + */
12250 +DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
12251 + struct DEV_OBJECT **phDevObject)
12253 + DSP_STATUS status = DSP_EFAIL;
12254 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12256 + DBC_Require(cRefs > 0);
12257 + DBC_Require(phDevObject != NULL);
12259 + if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12260 + *phDevObject = pProcObject->hDevObject;
12261 + status = DSP_SOK;
12262 + } else {
12263 + *phDevObject = 0;
12266 + DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject > 0) ||
12267 + (DSP_FAILED(status) && *phDevObject == 0));
12269 + return status;
12273 + * ======== PROC_GetState ========
12274 + * Purpose:
12275 + * Report the state of the specified DSP processor.
12276 + */
12277 +DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
12278 + OUT struct DSP_PROCESSORSTATE *pProcStatus,
12279 + u32 uStateInfoSize)
12281 + DSP_STATUS status = DSP_SOK;
12282 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12283 + BRD_STATUS brdStatus;
12284 + struct DEH_MGR *hDehMgr;
12286 + DBC_Require(cRefs > 0);
12287 + DBC_Require(pProcStatus != NULL);
12288 + DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
12290 + GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
12291 + "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
12292 + " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
12293 + if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12294 + /* First, retrieve BRD state information */
12295 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
12296 + (pProcObject->hWmdContext, &brdStatus))) {
12297 + switch (brdStatus) {
12298 + case BRD_STOPPED:
12299 + pProcStatus->iState = PROC_STOPPED;
12300 + break;
12301 + case BRD_RUNNING:
12302 + pProcStatus->iState = PROC_RUNNING;
12303 + break;
12304 + case BRD_LOADED:
12305 + pProcStatus->iState = PROC_LOADED;
12306 + break;
12307 + default:
12308 + status = DSP_EFAIL;
12309 + break;
12311 + } else {
12312 + status = DSP_EFAIL;
12313 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12314 + "PROC_GetState: General Failure"
12315 + " to read the PROC Status \n");
12317 + /* Next, retrieve error information, if any */
12318 + status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
12319 + if (DSP_SUCCEEDED(status) && hDehMgr) {
12320 + status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
12321 + (hDehMgr, &(pProcStatus->errInfo));
12322 + if (DSP_FAILED(status)) {
12323 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12324 + "PROC_GetState: Failed "
12325 + "retrieve exception info.\n");
12327 + } else {
12328 + status = DSP_EFAIL;
12329 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12330 + "PROC_GetState: Failed to "
12331 + "retrieve DEH handle.\n");
12333 + } else {
12334 + status = DSP_EHANDLE;
12335 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12336 + "PROC_GetState:InValid Processor Handle \n");
12338 + GT_2trace(PROC_DebugMask, GT_ENTER,
12339 + "Exiting PROC_GetState, results:\n\t"
12340 + "status: 0x%x\n\tpProcStatus: 0x%x\n", status, *pProcStatus);
12341 + return status;
12345 + * ======== PROC_GetTrace ========
12346 + * Purpose:
12347 + * Retrieve the current contents of the trace buffer, located on the
12348 + * Processor. Predefined symbols for the trace buffer must have been
12349 + * configured into the DSP executable.
12350 + * Details:
12351 + * We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
12352 + * trace buffer, only. Treat it as an undocumented feature.
12353 + * This call is destructive, meaning the processor is placed in the monitor
12354 + * state as a result of this function.
12355 + */
12356 +DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
12358 + DSP_STATUS status;
12359 + status = DSP_ENOTIMPL;
12360 + return status;
12364 + * ======== PROC_Init ========
12365 + * Purpose:
12366 + * Initialize PROC's private state, keeping a reference count on each call
12367 + */
12368 +bool CDECL PROC_Init(void)
12370 + bool fRetval = true;
12372 + DBC_Require(cRefs >= 0);
12374 + if (cRefs == 0) {
12375 + /* Set the Trace mask */
12376 + DBC_Assert(!PROC_DebugMask.flags);
12377 + GT_create(&PROC_DebugMask, "PR"); /* "PR" for Processor */
12381 + if (fRetval)
12382 + cRefs++;
12384 + GT_1trace(PROC_DebugMask, GT_5CLASS,
12385 + "Entered PROC_Init, ref count:0x%x\n", cRefs);
12386 + DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
12388 + return fRetval;
12392 + * ======== PROC_Load ========
12393 + * Purpose:
12394 + * Reset a processor and load a new base program image.
12395 + * This will be an OEM-only function, and not part of the DSP/BIOS Bridge
12396 + * application developer's API.
12397 + */
12398 +DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
12399 + IN CONST char **aArgv, IN CONST char **aEnvp)
12401 + DSP_STATUS status = DSP_SOK;
12402 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12403 + struct IO_MGR *hIOMgr; /* IO manager handle */
12404 + struct MSG_MGR *hMsgMgr;
12405 + struct COD_MANAGER *hCodMgr; /* Code manager handle */
12406 + char *pargv0; /* temp argv[0] ptr */
12407 + char **newEnvp; /* Updated envp[] array. */
12408 + char szProcID[MAXPROCIDLEN]; /* Size of "PROC_ID=<n>" */
12409 + s32 cEnvp; /* Num elements in envp[]. */
12410 + s32 cNewEnvp; /* " " in newEnvp[] */
12411 + s32 nProcID = 0; /* Anticipate MP version. */
12412 + struct DCD_MANAGER *hDCDHandle;
12413 + struct DMM_OBJECT *hDmmMgr;
12414 + u32 dwExtEnd;
12415 + u32 uProcId;
12416 +#ifdef DEBUG
12417 + BRD_STATUS uBrdState;
12418 +#endif
12419 +#ifdef OPT_LOAD_TIME_INSTRUMENTATION
12420 + struct timeval tv1;
12421 + struct timeval tv2;
12422 +#endif
12423 + DBC_Require(cRefs > 0);
12424 + DBC_Require(iArgc > 0);
12425 + DBC_Require(aArgv != NULL);
12426 +#ifdef OPT_LOAD_TIME_INSTRUMENTATION
12427 + do_gettimeofday(&tv1);
12428 +#endif
12429 + GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
12430 + "hProcessor: 0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
12431 + /* Call the WMD_BRD_Load Fxn */
12432 + if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12433 + status = DSP_EHANDLE;
12434 + GT_0trace(PROC_DebugMask, GT_1CLASS,
12435 + "PROC_Load: Invalid Processor Handle..\n");
12436 + goto func_end;
12438 + if (pProcObject->bIsAlreadyAttached) {
12439 + status = DSP_EATTACHED;
12440 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12441 + "PROC_Load Abort becuase a GPP "
12442 + "Client is already attached status 0x%x \n", status);
12443 + goto func_end;
12445 + if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
12446 + status = DSP_EFAIL;
12447 + GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
12448 + "DEV_GetCodMgr status 0x%x \n", status);
12449 + goto func_end;
12451 + status = PROC_Stop(hProcessor);
12452 + if (DSP_FAILED(status)) {
12453 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12454 + "PROC_Load: DSP_FAILED to Place the"
12455 + " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
12456 + status);
12457 + goto func_end;
12459 + /* Place the board in the monitor state. */
12460 + status = PROC_Monitor(hProcessor);
12461 + if (DSP_FAILED(status)) {
12462 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12463 + "PROC_Load: DSP_FAILED to Place the"
12464 + " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
12465 + status);
12466 + goto func_end;
12468 + /* Save ptr to original argv[0]. */
12469 + pargv0 = (char *)aArgv[0];
12470 + /*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
12471 + cEnvp = GetEnvpCount((char **)aEnvp);
12472 + cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
12473 + newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
12474 + if (newEnvp) {
12475 + status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
12476 + nProcID);
12477 + if (status == -1) {
12478 + GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
12479 + "Proc ID string overflow \n");
12480 + status = DSP_EFAIL;
12481 + } else {
12482 + newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
12483 + cNewEnvp, szProcID);
12484 + /* Get the DCD Handle */
12485 + status = MGR_GetDCDHandle(pProcObject->hMgrObject,
12486 + (u32 *)&hDCDHandle);
12487 + if (DSP_SUCCEEDED(status)) {
12488 + /* Before proceeding with new load,
12489 + * check if a previously registered COFF
12490 + * exists.
12491 + * If yes, unregister nodes in previously
12492 + * registered COFF. If any error occurred,
12493 + * set previously registered COFF to NULL. */
12494 + if (pProcObject->g_pszLastCoff != NULL) {
12495 + status = DCD_AutoUnregister(hDCDHandle,
12496 + pProcObject->g_pszLastCoff);
12497 + /* Regardless of auto unregister status,
12498 + * free previously allocated
12499 + * memory. */
12500 + MEM_Free(pProcObject->g_pszLastCoff);
12501 + pProcObject->g_pszLastCoff = NULL;
12504 + /* On success, do COD_OpenBase() */
12505 + status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
12506 + COD_SYMB);
12507 + if (DSP_FAILED(status)) {
12508 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12509 + "PROC_Load: COD_OpenBase "
12510 + "failed (0x%x)\n", status);
12513 + } else {
12514 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12515 + " PROC_Load:Out of Memory \n");
12516 + status = DSP_EMEMORY;
12518 + if (DSP_SUCCEEDED(status)) {
12519 + /* Auto-register data base */
12520 + /* Get the DCD Handle */
12521 + status = MGR_GetDCDHandle(pProcObject->hMgrObject,
12522 + (u32 *)&hDCDHandle);
12523 + if (DSP_SUCCEEDED(status)) {
12524 + /* Auto register nodes in specified COFF
12525 + * file. If registration did not fail,
12526 + * (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
12527 + * save the name of the COFF file for
12528 + * de-registration in the future. */
12529 + status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
12530 + if (status == DSP_EDCDNOAUTOREGISTER) {
12531 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12532 + "PROC_Load: No Auto "
12533 + "Register section. Proceeding..\n");
12534 + status = DSP_SOK;
12536 + if (DSP_FAILED(status)) {
12537 + status = DSP_EFAIL;
12538 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12539 + "PROC_Load: Failed to "
12540 + "Auto Register..\n");
12541 + } else {
12542 + DBC_Assert(pProcObject->g_pszLastCoff == NULL);
12543 + /* Allocate memory for pszLastCoff */
12544 + pProcObject->g_pszLastCoff = MEM_Calloc(
12545 + (CSL_Strlen((char *)aArgv[0]) + 1),
12546 + MEM_PAGED);
12547 + /* If memory allocated, save COFF file name*/
12548 + if (pProcObject->g_pszLastCoff) {
12549 + CSL_Strcpyn(pProcObject->g_pszLastCoff,
12550 + (char *)aArgv[0],
12551 + (CSL_Strlen((char *)aArgv[0])
12552 + + 1));
12557 + /* Update shared memory address and size */
12558 + if (DSP_SUCCEEDED(status)) {
12559 + /* Create the message manager. This must be done
12560 + * before calling the IOOnLoaded function. */
12561 + DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
12562 + if (!hMsgMgr) {
12563 + status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
12564 + (MSG_ONEXIT)NODE_OnExit);
12565 + DBC_Assert(DSP_SUCCEEDED(status));
12566 + DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
12568 + if (status == DSP_ENOTIMPL) {
12569 + /* It's OK not to have a message manager */
12570 + status = DSP_SOK;
12573 + if (DSP_SUCCEEDED(status)) {
12574 + /* Set the Device object's message manager */
12575 + status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
12576 + DBC_Assert(DSP_SUCCEEDED(status));
12577 + status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
12578 + if (status == DSP_ENOTIMPL) {
12579 + /* Ok not to implement this function */
12580 + status = DSP_SOK;
12581 + } else {
12582 + if (DSP_FAILED(status)) {
12583 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12584 + "PROC_Load: Failed to get shared "
12585 + "memory or message buffer address "
12586 + "from COFF status 0x%x\n", status);
12587 + status = DSP_EFAIL;
12590 + } else {
12591 + status = DSP_EFAIL;
12592 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12593 + "PROC_Load: DSP_FAILED in "
12594 + "MSG_Create status 0x%x\n", status);
12596 + if (DSP_SUCCEEDED(status)) {
12597 + /* Now, attempt to load an exec: */
12599 +#ifndef CONFIG_DISABLE_BRIDGE_PM
12600 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
12601 + /* Boost the OPP level to Maximum level supported by baseport*/
12602 + if (constraint_set(mpu_constraint_handle, CO_VDD1_OPP5) != 0)
12603 + GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
12604 + "Constraint set of %d failed\n", CO_VDD1_OPP5);
12605 + else
12606 + GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
12607 + "Constraint set of %d passed\n", CO_VDD1_OPP5);
12608 +#endif
12609 +#endif
12610 + status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
12611 + DEV_BrdWriteFxn,
12612 + pProcObject->hDevObject, NULL);
12613 + if (DSP_FAILED(status)) {
12614 + if (status == COD_E_OPENFAILED) {
12615 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12616 + "PROC_Load:Failure to Load the EXE\n");
12618 + if (status == COD_E_SYMBOLNOTFOUND) {
12619 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12620 + "PROC_Load:Could not parse the file\n");
12621 + } else {
12622 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12623 + "PROC_Load: DSP_FAILED in "
12624 + "COD_Load status 0x%x \n", status);
12627 +#ifndef CONFIG_DISABLE_BRIDGE_PM
12628 +#ifndef CONFIG_DISABLE_BRIDGE_DVFS
12629 + /* Requesting the lowest opp supported by baseport*/
12630 + if (constraint_set(mpu_constraint_handle, CO_VDD1_OPP1) != 0)
12631 + GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
12632 + "Constraint setting of %d failed\n",
12633 + CO_VDD1_OPP1);
12634 + else
12635 + GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
12636 + "Constraint setting of %d passed\n",
12637 + CO_VDD1_OPP1);
12638 +#endif
12639 +#endif
12642 + if (DSP_SUCCEEDED(status)) {
12643 + /* Update the Processor status to loaded */
12644 + status = (*pProcObject->pIntfFxns->pfnBrdSetState)
12645 + (pProcObject->hWmdContext, BRD_LOADED);
12646 + if (DSP_SUCCEEDED(status)) {
12647 + pProcObject->sState = PROC_LOADED;
12648 + if (pProcObject->hNtfy) {
12649 + PROC_NotifyClients(pProcObject,
12650 + DSP_PROCESSORSTATECHANGE);
12652 + } else {
12653 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12654 + "PROC_Load, pfnBrdSetState "
12655 + "failed: 0x%x\n", status);
12656 + status = DSP_EFAIL;
12659 + if (DSP_SUCCEEDED(status)) {
12660 + status = PROC_GetProcessorId(hProcessor, &uProcId);
12661 + if (uProcId == DSP_UNIT) {
12662 + /* Use all available DSP address space after EXTMEM
12663 + * for DMM */
12664 + if (DSP_SUCCEEDED(status)) {
12665 + status = COD_GetSymValue(hCodMgr, EXTEND,
12666 + &dwExtEnd);
12667 + if (DSP_FAILED(status)) {
12668 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12669 + "PROC_Load: Failed on "
12670 + "COD_GetSymValue %s.\n",
12671 + EXTEND);
12674 + /* Reset DMM structs and add an initial free chunk*/
12675 + if (DSP_SUCCEEDED(status)) {
12676 + status = DEV_GetDmmMgr(pProcObject->hDevObject,
12677 + &hDmmMgr);
12678 + if (DSP_SUCCEEDED(status)) {
12679 + /* Set dwExtEnd to DMM START u8
12680 + * address */
12681 + dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
12682 + /* DMM memory is from EXT_END */
12683 + status = DMM_CreateTables(hDmmMgr,
12684 + dwExtEnd, DMMPOOLSIZE);
12689 + /* Restore the original argv[0] */
12690 + MEM_Free(newEnvp);
12691 + aArgv[0] = pargv0;
12692 +#ifdef DEBUG
12693 + if (DSP_SUCCEEDED(status)) {
12694 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
12695 + (pProcObject->hWmdContext, &uBrdState))) {
12696 + GT_0trace(PROC_DebugMask, GT_1CLASS,
12697 + "PROC_Load: Processor Loaded\n");
12698 + DBC_Assert(uBrdState == BRD_LOADED);
12701 +#endif
12702 +func_end:
12703 +#ifdef DEBUG
12704 + if (DSP_FAILED(status)) {
12705 + GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
12706 + "Processor Load Failed.\n");
12709 +#endif
12710 + GT_1trace(PROC_DebugMask, GT_ENTER,
12711 + "Exiting PROC_Load, status: 0x%x\n", status);
12712 + DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
12713 + || DSP_FAILED(status));
12714 +#ifdef OPT_LOAD_TIME_INSTRUMENTATION
12715 + do_gettimeofday(&tv2);
12716 + if (tv2.tv_usec < tv1.tv_usec) {
12717 + tv2.tv_usec += 1000000;
12718 + tv2.tv_sec--;
12720 + GT_2trace(PROC_DebugMask, GT_1CLASS,
12721 + "Proc_Load: time to load %d sec and %d usec \n",
12722 + tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
12723 +#endif
12724 + return status;
12728 + * ======== PROC_Map ========
12729 + * Purpose:
12730 + * Maps a MPU buffer to DSP address space.
12731 + */
12732 +DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
12733 + void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
12735 + u32 vaAlign;
12736 + u32 paAlign;
12737 + struct DMM_OBJECT *hDmmMgr;
12738 + u32 sizeAlign;
12739 + DSP_STATUS status = DSP_SOK;
12740 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12742 +#ifndef RES_CLEANUP_DISABLE
12743 + HANDLE hProcess;
12744 + HANDLE pCtxt = NULL;
12745 + HANDLE hDrvObject;
12746 + HANDLE dmmRes;
12747 + DSP_STATUS res_status = DSP_SOK;
12748 +#endif
12750 + GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
12751 + "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
12752 + "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
12753 + pReqAddr, ulMapAttr, ppMapAddr);
12754 + /* Calculate the page-aligned PA, VA and size */
12755 + vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
12756 + paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
12757 + sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
12758 + PG_SIZE_4K);
12760 + GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
12761 + "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
12763 + status = DMM_GetHandle(pProcObject, &hDmmMgr);
12764 + if (DSP_FAILED(status)) {
12765 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12766 + "PROC_Map: Failed to get DMM Mgr "
12767 + "handle: 0x%x\n", status);
12768 + } else {
12769 + status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
12771 + /* Add mapping to the page tables. */
12772 + if (DSP_SUCCEEDED(status)) {
12774 + status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
12775 + (pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
12776 + ulMapAttr);
12778 + if (DSP_SUCCEEDED(status)) {
12779 + /* Mapped address = MSB of VA | LSB of PA */
12780 + *ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
12781 + (PG_SIZE_4K - 1)));
12782 + } else {
12783 + DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
12785 +#ifndef RES_CLEANUP_DISABLE
12786 + if (DSP_SUCCEEDED(status)) {
12787 + /* Update the node and stream resource status */
12788 + PRCS_GetCurrentHandle(&hProcess);
12789 + res_status = CFG_GetObject((u32 *)&hDrvObject,
12790 + REG_DRV_OBJECT);
12791 + if (DSP_SUCCEEDED(res_status)) {
12792 + if (DRV_GetProcContext(hProcess, hDrvObject, &pCtxt,
12793 + NULL, (u32) pMpuAddr) != DSP_ENOTFOUND) {
12794 + DRV_InsertDMMResElement(&dmmRes, pCtxt);
12795 + DRV_UpdateDMMResElement(dmmRes, (u32) pMpuAddr,
12796 + ulSize, (u32) pReqAddr,
12797 + (u32)*ppMapAddr, hProcessor);
12801 +#endif
12802 + GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
12803 + return status;
12807 + * ======== PROC_RegisterNotify ========
12808 + * Purpose:
12809 + * Register to be notified of specific processor events.
12810 + */
12811 +DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
12812 + u32 uNotifyType, struct DSP_NOTIFICATION
12813 + *hNotification)
12815 + DSP_STATUS status = DSP_SOK;
12816 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12817 + struct DEH_MGR *hDehMgr;
12819 + DBC_Require(hNotification != NULL);
12820 + DBC_Require(cRefs > 0);
12822 + GT_4trace(PROC_DebugMask, GT_ENTER,
12823 + "Entered PROC_RegisterNotify, args:\n\t"
12824 + "hProcessor: 0x%x\n\tuEventMask: 0x%x\n\tuNotifyMask:"
12825 + " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
12826 + uNotifyType, hNotification);
12828 + /* Check processor handle */
12829 + if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12830 + status = DSP_EHANDLE;
12831 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12832 + "PROC_RegsiterNotify Invalid "
12833 + "ProcessorHandle 0x%x\n", hProcessor);
12834 + goto func_end;
12836 + /* Check if event mask is a valid processor related event */
12837 + if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
12838 + DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
12839 + DSP_SYSERROR))
12840 + status = DSP_EVALUE;
12842 + /* Check if notify type is valid */
12843 + if (uNotifyType != DSP_SIGNALEVENT)
12844 + status = DSP_EVALUE;
12846 + if (DSP_SUCCEEDED(status)) {
12847 + /* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
12848 + * then register event immediately. */
12849 + if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
12850 + status = NTFY_Register(pProcObject->hNtfy,
12851 + hNotification, uEventMask, uNotifyType);
12852 + /* * Special case alert, special case alert!
12853 + * If we're trying to *deregister* (i.e. uEventMask
12854 + * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
12855 + * we have to deregister with the DEH manager.
12856 + * There's no way to know, based on uEventMask which
12857 + * manager the notification event was registered with,
12858 + * so if we're trying to deregister and NTFY_Register
12859 + * failed, we'll give the deh manager a shot.
12860 + */
12861 + if ((uEventMask == 0) && DSP_FAILED(status)) {
12862 + status = DEV_GetDehMgr(pProcObject->hDevObject,
12863 + &hDehMgr);
12864 + DBC_Assert(pProcObject->pIntfFxns->
12865 + pfnDehRegisterNotify);
12866 + status = (*pProcObject->pIntfFxns->
12867 + pfnDehRegisterNotify)
12868 + (hDehMgr, uEventMask, uNotifyType,
12869 + hNotification);
12871 + } else {
12872 + status = DEV_GetDehMgr(pProcObject->hDevObject,
12873 + &hDehMgr);
12874 + DBC_Assert(pProcObject->pIntfFxns->
12875 + pfnDehRegisterNotify);
12876 + status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
12877 + (hDehMgr, uEventMask, uNotifyType,
12878 + hNotification);
12879 + if (DSP_FAILED(status))
12880 + status = DSP_EFAIL;
12884 +func_end:
12885 + return status;
12889 + * ======== PROC_ReserveMemory ========
12890 + * Purpose:
12891 + * Reserve a virtually contiguous region of DSP address space.
12892 + */
12893 +DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
12894 + void **ppRsvAddr)
12896 + struct DMM_OBJECT *hDmmMgr;
12897 + DSP_STATUS status = DSP_SOK;
12898 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12900 + GT_3trace(PROC_DebugMask, GT_ENTER,
12901 + "Entered PROC_ReserveMemory, args:\n\t"
12902 + "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
12903 + ulSize, ppRsvAddr);
12904 + status = DMM_GetHandle(pProcObject, &hDmmMgr);
12905 + if (DSP_FAILED(status)) {
12906 + GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
12907 + "Failed to get DMM Mgr handle: 0x%x\n", status);
12908 + } else {
12909 + status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
12911 + GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
12912 + status);
12913 + return status;
12917 + * ======== PROC_Start ========
12918 + * Purpose:
12919 + * Start a processor running.
12920 + */
12921 +DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
12923 + DSP_STATUS status = DSP_SOK;
12924 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
12925 + struct COD_MANAGER *hCodMgr; /* Code manager handle */
12926 + u32 dwDspAddr; /* Loaded code's entry point. */
12927 +#ifdef DEBUG
12928 + BRD_STATUS uBrdState;
12929 +#endif
12930 + DBC_Require(cRefs > 0);
12931 + GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
12932 + "hProcessor: 0x%x\n", hProcessor);
12933 + if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
12934 + status = DSP_EHANDLE;
12935 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12936 + "PROC_Start :InValid Handle \n");
12937 + goto func_end;
12939 + /* Call the WMD_BRD_Start */
12940 + if (pProcObject->sState != PROC_LOADED) {
12941 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12942 + "PROC_Start :Wrong state \n");
12943 + status = DSP_EWRONGSTATE;
12944 + goto func_end;
12946 + status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
12947 + if (DSP_FAILED(status)) {
12948 + status = DSP_EFAIL;
12949 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12950 + "Processor Start DSP_FAILED "
12951 + "in Getting DEV_GetCodMgr status 0x%x\n", status);
12952 + goto func_cont;
12954 + status = COD_GetEntry(hCodMgr, &dwDspAddr);
12955 + if (DSP_FAILED(status)) {
12956 + status = DSP_EFAIL;
12957 + GT_1trace(PROC_DebugMask, GT_7CLASS,
12958 + "Processor Start DSP_FAILED in "
12959 + "Getting COD_GetEntry status 0x%x\n", status);
12960 + goto func_cont;
12962 + status = (*pProcObject->pIntfFxns->pfnBrdStart)
12963 + (pProcObject->hWmdContext, dwDspAddr);
12964 + if (DSP_FAILED(status)) {
12965 + status = DSP_EFAIL;
12966 + GT_0trace(PROC_DebugMask, GT_7CLASS,
12967 + "PROC_Start Failed to Start the board\n");
12968 + goto func_cont;
12970 + /* Call DEV_Create2 */
12971 + status = DEV_Create2(pProcObject->hDevObject);
12972 + if (DSP_SUCCEEDED(status)) {
12973 + pProcObject->sState = PROC_RUNNING;
12974 + /* Deep sleep switces off the peripheral clocks.
12975 + * we just put the DSP CPU in idle in the idle loop.
12976 + * so there is no need to send a command to DSP */
12978 + if (pProcObject->hNtfy) {
12979 + PROC_NotifyClients(pProcObject,
12980 + DSP_PROCESSORSTATECHANGE);
12982 + GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
12983 + "Started and running \n");
12984 + } else {
12985 + /* Failed to Create Node Manager and DISP Object
12986 + * Stop the Processor from running. Put it in STOPPED State */
12987 + (void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
12988 + hWmdContext);
12989 + status = DSP_EFAIL;
12990 + pProcObject->sState = PROC_STOPPED;
12991 + GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
12992 + "Failed to Create the Node Manager\n");
12994 +func_cont:
12995 +#ifdef DEBUG
12996 + if (DSP_SUCCEEDED(status)) {
12997 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
12998 + (pProcObject->hWmdContext, &uBrdState))) {
12999 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13000 + "PROC_Start: Processor State is RUNNING \n");
13001 + DBC_Assert(uBrdState != BRD_HIBERNATION);
13004 +#endif
13005 +func_end:
13006 + GT_1trace(PROC_DebugMask, GT_ENTER,
13007 + "Exiting PROC_Start, status 0x%x\n", status);
13008 + DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
13009 + PROC_RUNNING) || DSP_FAILED(status));
13010 + return status;
13014 + * ======== PROC_Stop ========
13015 + * Purpose:
13016 + * Stop a processor running.
13017 + */
13018 +DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
13020 + DSP_STATUS status = DSP_SOK;
13021 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
13022 + struct MSG_MGR *hMsgMgr;
13023 + struct NODE_MGR *hNodeMgr;
13024 + DSP_HNODE hNode;
13025 + u32 uNodeTabSize = 1;
13026 + u32 uNumNodes = 0;
13027 + u32 uNodesAllocated = 0;
13028 +#ifdef DEBUG
13029 + BRD_STATUS uBrdState;
13030 +#endif
13031 + DBC_Require(cRefs > 0);
13032 + GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
13033 + "hProcessor: 0x%x\n", hProcessor);
13034 + if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
13035 + status = DSP_EHANDLE;
13036 + GT_0trace(PROC_DebugMask, GT_7CLASS,
13037 + "PROC_Stop :InValid Handle \n");
13038 + goto func_end;
13040 + /* check if there are any running nodes */
13041 + status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
13042 + if (DSP_SUCCEEDED(status) && hNodeMgr) {
13043 + status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
13044 + &uNumNodes, &uNodesAllocated);
13045 + if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
13046 + GT_1trace(PROC_DebugMask, GT_7CLASS,
13047 + "Can't stop device, Active "
13048 + "nodes = 0x%x \n", uNodesAllocated);
13049 + return DSP_EWRONGSTATE;
13052 + /* Call the WMD_BRD_Stop */
13053 + /* It is OK to stop a device that does n't have nodes OR not started */
13054 + status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
13055 + hWmdContext);
13056 + if (DSP_SUCCEEDED(status)) {
13057 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13058 + "PROC_Stop: Processor Stopped, "
13059 + "i.e in standby mode \n");
13060 + pProcObject->sState = PROC_STOPPED;
13061 + /* Destory the Node Manager, MSG Manager */
13062 + if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
13063 + /* Destroy the MSG by calling MSG_Delete */
13064 + DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
13065 + if (hMsgMgr) {
13066 + MSG_Delete(hMsgMgr);
13067 + DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
13069 +#ifdef DEBUG
13070 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
13071 + pfnBrdStatus)(pProcObject->hWmdContext,
13072 + &uBrdState))) {
13073 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13074 + "PROC_Monitor:Processor Stopped \n");
13075 + DBC_Assert(uBrdState == BRD_STOPPED);
13077 +#endif
13078 + } else {
13079 + GT_0trace(PROC_DebugMask, GT_7CLASS,
13080 + "PROC_Stop Couldn't delete node manager \n");
13082 + } else {
13083 + GT_0trace(PROC_DebugMask, GT_7CLASS,
13084 + "PROC_Stop Failed to Stop the processor/device \n");
13086 +func_end:
13087 + GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status 0x%x\n",
13088 + status);
13090 + return status;
13094 + * ======== PROC_UnMap ========
13095 + * Purpose:
13096 + * Removes a MPU buffer mapping from the DSP address space.
13097 + */
13098 +DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
13100 + DSP_STATUS status = DSP_SOK;
13101 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
13102 + struct DMM_OBJECT *hDmmMgr;
13103 + u32 vaAlign;
13104 + u32 sizeAlign;
13105 +#ifndef RES_CLEANUP_DISABLE
13106 + HANDLE hProcess;
13107 + HANDLE pCtxt = NULL;
13108 + HANDLE hDrvObject;
13109 + HANDLE dmmRes;
13110 + DSP_STATUS res_status = DSP_SOK;
13111 +#endif
13112 + GT_2trace(PROC_DebugMask, GT_ENTER,
13113 + "Entered PROC_UnMap, args:\n\thProcessor:"
13114 + "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
13116 + vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
13118 + status = DMM_GetHandle(hProcessor, &hDmmMgr);
13119 + if (DSP_FAILED(status)) {
13120 + GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
13121 + "Failed to get DMM Mgr handle: 0x%x\n", status);
13122 + } else {
13123 + /* Update DMM structures. Get the size to unmap.
13124 + This function returns error if the VA is not mapped */
13125 + status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
13128 + /* Remove mapping from the page tables. */
13129 + if (DSP_SUCCEEDED(status)) {
13130 + status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
13131 + (pProcObject->hWmdContext, vaAlign, sizeAlign);
13133 +#ifndef RES_CLEANUP_DISABLE
13134 + GT_1trace(PROC_DebugMask, GT_ENTER,
13135 + "PROC_UnMap DRV_GetDMMResElement "
13136 + "pMapAddr:[0x%x]", pMapAddr);
13137 + if (DSP_FAILED(status))
13138 + goto func_end;
13140 + /* Update the node and stream resource status */
13141 + PRCS_GetCurrentHandle(&hProcess);
13142 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
13143 + if (DSP_FAILED(res_status))
13144 + goto func_end;
13146 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, (u32)pMapAddr);
13147 + if (pCtxt != NULL) {
13148 + if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
13149 + DSP_ENOTFOUND)
13150 + DRV_RemoveDMMResElement(dmmRes, pCtxt);
13152 +func_end:
13153 +#endif
13154 + GT_1trace(PROC_DebugMask, GT_ENTER,
13155 + "Leaving PROC_UnMap [0x%x]", status);
13156 + return status;
13160 + * ======== PROC_UnReserveMemory ========
13161 + * Purpose:
13162 + * Frees a previously reserved region of DSP address space.
13163 + */
13164 +DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
13166 + struct DMM_OBJECT *hDmmMgr;
13167 + DSP_STATUS status = DSP_SOK;
13168 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
13170 + GT_2trace(PROC_DebugMask, GT_ENTER,
13171 + "Entered PROC_UnReserveMemory, args:\n\t"
13172 + "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
13174 + status = DMM_GetHandle(pProcObject, &hDmmMgr);
13175 + if (DSP_FAILED(status))
13176 + GT_1trace(PROC_DebugMask, GT_7CLASS,
13177 + "PROC_Map: Failed to get DMM Mgr "
13178 + "handle: 0x%x\n", status);
13179 + else
13180 + status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
13182 + GT_1trace(PROC_DebugMask, GT_ENTER,
13183 + "Leaving PROC_UnReserveMemory [0x%x]",
13184 + status);
13186 + return status;
13190 + * ======== = PROC_Monitor ======== ==
13191 + * Purpose:
13192 + * Place the Processor in Monitor State. This is an internal
13193 + * function and a requirement before Processor is loaded.
13194 + * This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
13195 + * In DEV_Destroy2 we delete the node manager.
13196 + * Parameters:
13197 + * hProcObject: Handle to Processor Object
13198 + * Returns:
13199 + * DSP_SOK: Processor placed in monitor mode.
13200 + * !DSP_SOK: Failed to place processor in monitor mode.
13201 + * Requires:
13202 + * Valid Processor Handle
13203 + * Ensures:
13204 + * Success: ProcObject state is PROC_IDLE
13205 + */
13206 +static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
13208 + DSP_STATUS status = DSP_EFAIL;
13209 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
13210 + struct MSG_MGR *hMsgMgr;
13211 +#ifdef DEBUG
13212 + BRD_STATUS uBrdState;
13213 +#endif
13215 + DBC_Require(cRefs > 0);
13216 + DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
13218 + GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
13219 + "hProcessor: 0x%x\n", hProcObject);
13220 + /* This is needed only when Device is loaded when it is
13221 + * already 'ACTIVE' */
13222 + /* Destory the Node Manager, MSG Manager */
13223 + if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
13224 + /* Destroy the MSG by calling MSG_Delete */
13225 + DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
13226 + if (hMsgMgr) {
13227 + MSG_Delete(hMsgMgr);
13228 + DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
13231 + /* Place the Board in the Monitor State */
13232 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
13233 + (pProcObject->hWmdContext))) {
13234 + status = DSP_SOK;
13235 +#ifdef DEBUG
13236 + if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
13237 + (pProcObject->hWmdContext, &uBrdState))) {
13238 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13239 + "PROC_Monitor:Processor in "
13240 + "Monitor State\n");
13241 + DBC_Assert(uBrdState == BRD_IDLE);
13243 +#endif
13244 + } else {
13245 + /* Monitor Failure */
13246 + GT_0trace(PROC_DebugMask, GT_7CLASS,
13247 + "PROC_Monitor: Processor Could not"
13248 + "be put in Monitor mode \n");
13250 + GT_1trace(PROC_DebugMask, GT_ENTER,
13251 + "Exiting PROC_Monitor, status 0x%x\n",
13252 + status);
13253 +#ifdef DEBUG
13254 + DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
13255 + DSP_FAILED(status));
13256 +#endif
13257 + return status;
13261 + * ======== GetEnvpCount ========
13262 + * Purpose:
13263 + * Return the number of elements in the envp array, including the
13264 + * terminating NULL element.
13265 + */
13266 +static s32 GetEnvpCount(char **envp)
13268 + s32 cRetval = 0;
13269 + if (envp) {
13270 + while (*envp++)
13271 + cRetval++;
13273 + cRetval += 1; /* Include the terminating NULL in the count. */
13276 + return cRetval;
13280 + * ======== PrependEnvp ========
13281 + * Purpose:
13282 + * Prepend an environment variable=value pair to the new envp array, and
13283 + * copy in the existing var=value pairs in the old envp array.
13284 + */
13285 +static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
13286 + char *szVar)
13288 + char **ppEnvp = newEnvp;
13290 + DBC_Require(newEnvp);
13292 + /* Prepend new environ var=value string */
13293 + *newEnvp++ = szVar;
13295 + /* Copy user's environment into our own. */
13296 + while (cEnvp--)
13297 + *newEnvp++ = *envp++;
13299 + /* Ensure NULL terminates the new environment strings array. */
13300 + if (cEnvp == 0)
13301 + *newEnvp = NULL;
13303 + return ppEnvp;
13307 + * ======== PROC_NotifyClients ========
13308 + * Purpose:
13309 + * Notify the processor the events.
13310 + */
13311 +DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
13313 + DSP_STATUS status = DSP_SOK;
13314 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
13316 + DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
13317 + DBC_Require(IsValidProcEvent(uEvents));
13318 + DBC_Require(cRefs > 0);
13320 + NTFY_Notify(pProcObject->hNtfy, uEvents);
13321 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13322 + "PROC_NotifyClients :Signaled. \n");
13324 + return status;
13328 + * ======== PROC_NotifyAllClients ========
13329 + * Purpose:
13330 + * Notify the processor the events. This includes notifying all clients
13331 + * attached to a particulat DSP.
13332 + */
13333 +DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
13335 + DSP_STATUS status = DSP_SOK;
13336 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
13338 + DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
13339 + DBC_Require(IsValidProcEvent(uEvents));
13340 + DBC_Require(cRefs > 0);
13342 + DEV_NotifyClients(pProcObject->hDevObject, uEvents);
13344 + GT_0trace(PROC_DebugMask, GT_1CLASS,
13345 + "PROC_NotifyAllClients :Signaled. \n");
13347 + return status;
13351 + * ======== PROC_GetProcessorId ========
13352 + * Purpose:
13353 + * Retrieves the processor ID.
13354 + */
13355 +DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
13357 + DSP_STATUS status = DSP_SOK;
13358 + struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
13360 + *procID = pProcObject->uProcessor;
13362 + return status;
13365 Index: lk/drivers/dsp/bridge/rmgr/pwr.c
13366 ===================================================================
13367 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13368 +++ lk/drivers/dsp/bridge/rmgr/pwr.c 2008-08-18 10:38:37.000000000 +0300
13369 @@ -0,0 +1,184 @@
13371 + * linux/drivers/dsp/bridge/rmgr/pwr.c
13373 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
13375 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
13377 + * This package is free software; you can redistribute it and/or modify
13378 + * it under the terms of the GNU General Public License version 2 as
13379 + * published by the Free Software Foundation.
13381 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13382 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
13383 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13384 + */
13388 + * ======== PWR.c ========
13389 + * PWR API for controlling DSP power states.
13391 + * Public Functions:
13392 + * PWR_SleepDSP
13393 + * PWR_WakeDSP
13395 + *! Revision History
13396 + *! ================
13397 + *! 18-Feb-2003 vp Code review updates.
13398 + *! 18-Oct-2002 vp Ported to Linux platform.
13399 + *! 22-May-2002 sg Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
13400 + *! 29-Apr-2002 sg Initial.
13401 + */
13403 +/* ----------------------------------- Host OS */
13404 +#include <host_os.h>
13406 +/* ----------------------------------- This */
13407 +#include <pwr.h>
13409 +/* ----------------------------------- Resource Manager */
13410 +#include <devdefs.h>
13411 +#include <drv.h>
13413 +/* ----------------------------------- Platform Manager */
13414 +#include <dev.h>
13416 +/* ----------------------------------- Link Driver */
13417 +#include <wmdioctl.h>
13420 + * ======== PWR_SleepDSP ========
13421 + * Send command to DSP to enter sleep state.
13422 + */
13423 +DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
13425 + struct WMD_DRV_INTERFACE *pIntfFxns;
13426 + struct WMD_DEV_CONTEXT *dwContext;
13427 + DSP_STATUS status = DSP_EFAIL;
13428 + struct DEV_OBJECT *hDevObject = NULL;
13429 + u32 ioctlcode = 0;
13430 + u32 arg = timeout;
13432 + for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
13433 + hDevObject != 0;
13434 + hDevObject =
13435 + (struct DEV_OBJECT *)DRV_GetNextDevObject
13436 + ((u32)hDevObject)) {
13437 + if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
13438 + (struct WMD_DEV_CONTEXT **)&dwContext))) {
13439 + continue;
13441 + if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
13442 + (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
13443 + continue;
13445 + if (sleepCode == PWR_DEEPSLEEP)
13446 + ioctlcode = WMDIOCTL_DEEPSLEEP;
13447 + else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
13448 + ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
13449 + else
13450 + status = DSP_EINVALIDARG;
13452 + if (status != DSP_EINVALIDARG) {
13453 + status = (*pIntfFxns->pfnDevCntrl)(dwContext,
13454 + ioctlcode, (void *)&arg);
13457 + return status;
13461 + * ======== PWR_WakeDSP ========
13462 + * Send command to DSP to wake it from sleep.
13463 + */
13464 +DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
13466 + struct WMD_DRV_INTERFACE *pIntfFxns;
13467 + struct WMD_DEV_CONTEXT *dwContext;
13468 + DSP_STATUS status = DSP_EFAIL;
13469 + struct DEV_OBJECT *hDevObject = NULL;
13470 + u32 arg = timeout;
13472 + for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
13473 + hDevObject != 0;
13474 + hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
13475 + ((u32)hDevObject)) {
13476 + if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
13477 + (struct WMD_DEV_CONTEXT **)&dwContext))) {
13478 + if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
13479 + (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
13480 + status = (*pIntfFxns->pfnDevCntrl)(dwContext,
13481 + WMDIOCTL_WAKEUP, (void *)&arg);
13485 + return status;
13489 + * ======== PWR_PM_PreScale========
13490 + * Sends pre-notification message to DSP.
13491 + */
13492 +DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
13494 + struct WMD_DRV_INTERFACE *pIntfFxns;
13495 + struct WMD_DEV_CONTEXT *dwContext;
13496 + DSP_STATUS status = DSP_EFAIL;
13497 + struct DEV_OBJECT *hDevObject = NULL;
13498 + u32 arg[2];
13500 + arg[0] = voltage_domain;
13501 + arg[1] = level;
13503 + for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
13504 + hDevObject != 0;
13505 + hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
13506 + ((u32)hDevObject)) {
13507 + if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
13508 + (struct WMD_DEV_CONTEXT **)&dwContext))) {
13509 + if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
13510 + (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
13511 + status = (*pIntfFxns->pfnDevCntrl)(dwContext,
13512 + WMDIOCTL_PRESCALE_NOTIFY,
13513 + (void *)&arg);
13517 + return status;
13521 + * ======== PWR_PM_PostScale========
13522 + * Sends post-notification message to DSP.
13523 + */
13524 +DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
13526 + struct WMD_DRV_INTERFACE *pIntfFxns;
13527 + struct WMD_DEV_CONTEXT *dwContext;
13528 + DSP_STATUS status = DSP_EFAIL;
13529 + struct DEV_OBJECT *hDevObject = NULL;
13530 + u32 arg[2];
13532 + arg[0] = voltage_domain;
13533 + arg[1] = level;
13535 + for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
13536 + hDevObject != 0;
13537 + hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
13538 + ((u32)hDevObject)) {
13539 + if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
13540 + (struct WMD_DEV_CONTEXT **)&dwContext))) {
13541 + if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
13542 + (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
13543 + status = (*pIntfFxns->pfnDevCntrl)(dwContext,
13544 + WMDIOCTL_POSTSCALE_NOTIFY,
13545 + (void *)&arg);
13549 + return status;
13554 Index: lk/drivers/dsp/bridge/rmgr/rmm.c
13555 ===================================================================
13556 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
13557 +++ lk/drivers/dsp/bridge/rmgr/rmm.c 2008-08-18 10:38:37.000000000 +0300
13558 @@ -0,0 +1,604 @@
13560 + * linux/drivers/dsp/bridge/rmgr/rmm.c
13562 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
13564 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
13566 + * This package is free software; you can redistribute it and/or modify
13567 + * it under the terms of the GNU General Public License version 2 as
13568 + * published by the Free Software Foundation.
13570 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
13571 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
13572 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
13573 + */
13577 + * ======== rmm.c ========
13578 + * Description:
13580 + * This memory manager provides general heap management and arbitrary
13581 + * alignment for any number of memory segments.
13583 + * Notes:
13585 + * Memory blocks are allocated from the end of the first free memory
13586 + * block large enough to satisfy the request. Alignment requirements
13587 + * are satisfied by "sliding" the block forward until its base satisfies
13588 + * the alignment specification; if this is not possible then the next
13589 + * free block large enough to hold the request is tried.
13591 + * Since alignment can cause the creation of a new free block - the
13592 + * unused memory formed between the start of the original free block
13593 + * and the start of the allocated block - the memory manager must free
13594 + * this memory to prevent a memory leak.
13596 + * Overlay memory is managed by reserving through RMM_alloc, and freeing
13597 + * it through RMM_free. The memory manager prevents DSP code/data that is
13598 + * overlayed from being overwritten as long as the memory it runs at has
13599 + * been allocated, and not yet freed.
13601 + *! Revision History
13602 + *! ================
13603 + *! 18-Feb-2003 vp Code review updates.
13604 + *! 18-Oct-2002 vp Ported to Linux Platform.
13605 + *! 24-Sep-2002 map Updated from Code Review
13606 + *! 25-Jun-2002 jeh Free from segid passed to RMM_free().
13607 + *! 24-Apr-2002 jeh Determine segid based on address in RMM_free(). (No way
13608 + *! to keep track of segid with dynamic loader library.)
13609 + *! 16-Oct-2001 jeh Based on gen tree rm.c. Added support for overlays.
13610 + */
13612 +/* ----------------------------------- DSP/BIOS Bridge */
13613 +#include <std.h>
13614 +#include <dbdefs.h>
13615 +#include <errbase.h>
13617 +/* ----------------------------------- Trace & Debug */
13618 +#include <dbc.h>
13619 +#include <gt.h>
13621 +/* ----------------------------------- OS Adaptation Layer */
13622 +#include <list.h>
13623 +#include <mem.h>
13625 +/* ----------------------------------- This */
13626 +#include <rmm.h>
13628 +#define RMM_TARGSIGNATURE 0x544d4d52 /* "TMMR" */
13631 + * ======== RMM_Header ========
13632 + * This header is used to maintain a list of free memory blocks.
13633 + */
13634 +struct RMM_Header {
13635 + struct RMM_Header *next; /* form a free memory link list */
13636 + u32 size; /* size of the free memory */
13637 + u32 addr; /* DSP address of memory block */
13638 +} ;
13641 + * ======== RMM_OvlySect ========
13642 + * Keeps track of memory occupied by overlay section.
13643 + */
13644 +struct RMM_OvlySect {
13645 + struct LST_ELEM listElem;
13646 + u32 addr; /* Start of memory section */
13647 + u32 size; /* Length (target MAUs) of section */
13648 + s32 page; /* Memory page */
13652 + * ======== RMM_TargetObj ========
13653 + */
13654 +struct RMM_TargetObj {
13655 + u32 dwSignature;
13656 + struct RMM_Segment *segTab;
13657 + struct RMM_Header **freeList;
13658 + u32 numSegs;
13659 + struct LST_LIST *ovlyList; /* List of overlay memory in use */
13662 +#if GT_TRACE
13663 +static struct GT_Mask RMM_debugMask = { NULL, NULL }; /* GT trace variable */
13664 +#endif
13666 +static u32 cRefs; /* module reference count */
13668 +static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
13669 + u32 align, u32 *dspAddr);
13670 +static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
13671 + u32 size);
13674 + * ======== RMM_alloc ========
13675 + */
13676 +DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
13677 + u32 align, u32 *dspAddr, bool reserve)
13679 + struct RMM_OvlySect *sect;
13680 + struct RMM_OvlySect *prevSect = NULL;
13681 + struct RMM_OvlySect *newSect;
13682 + u32 addr;
13683 + DSP_STATUS status = DSP_SOK;
13685 + DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
13686 + DBC_Require(dspAddr != NULL);
13687 + DBC_Require(size > 0);
13688 + DBC_Require(reserve || (target->numSegs > 0));
13689 + DBC_Require(cRefs > 0);
13691 + GT_6trace(RMM_debugMask, GT_ENTER,
13692 + "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
13693 + "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
13694 + reserve);
13695 + if (!reserve) {
13696 + if (!allocBlock(target, segid, size, align, dspAddr)) {
13697 + status = DSP_EMEMORY;
13698 + } else {
13699 + /* Increment the number of allocated blocks in this
13700 + * segment */
13701 + target->segTab[segid].number++;
13703 + goto func_end;
13705 + /* An overlay section - See if block is already in use. If not,
13706 + * insert into the list in ascending address size. */
13707 + addr = *dspAddr;
13708 + sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
13709 + /* Find place to insert new list element. List is sorted from
13710 + * smallest to largest address. */
13711 + while (sect != NULL) {
13712 + if (addr <= sect->addr) {
13713 + /* Check for overlap with sect */
13714 + if ((addr + size > sect->addr) || (prevSect &&
13715 + (prevSect->addr + prevSect->size > addr))) {
13716 + status = DSP_EOVERLAYMEMORY;
13718 + break;
13720 + prevSect = sect;
13721 + sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
13722 + (struct LST_ELEM *)sect);
13724 + if (DSP_SUCCEEDED(status)) {
13725 + /* No overlap - allocate list element for new section. */
13726 + newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
13727 + if (newSect == NULL) {
13728 + status = DSP_EMEMORY;
13729 + } else {
13730 + LST_InitElem((struct LST_ELEM *)newSect);
13731 + newSect->addr = addr;
13732 + newSect->size = size;
13733 + newSect->page = segid;
13734 + if (sect == NULL) {
13735 + /* Put new section at the end of the list */
13736 + LST_PutTail(target->ovlyList,
13737 + (struct LST_ELEM *)newSect);
13738 + } else {
13739 + /* Put new section just before sect */
13740 + LST_InsertBefore(target->ovlyList,
13741 + (struct LST_ELEM *)newSect,
13742 + (struct LST_ELEM *)sect);
13746 +func_end:
13747 + return status;
13751 + * ======== RMM_create ========
13752 + */
13753 +DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
13754 + struct RMM_Segment segTab[], u32 numSegs)
13756 + struct RMM_Header *hptr;
13757 + struct RMM_Segment *sptr, *tmp;
13758 + struct RMM_TargetObj *target;
13759 + s32 i;
13760 + DSP_STATUS status = DSP_SOK;
13762 + DBC_Require(pTarget != NULL);
13763 + DBC_Require(numSegs == 0 || segTab != NULL);
13765 + GT_3trace(RMM_debugMask, GT_ENTER,
13766 + "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
13767 + pTarget, segTab, numSegs);
13769 + /* Allocate DBL target object */
13770 + MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
13772 + if (target == NULL) {
13773 + GT_0trace(RMM_debugMask, GT_6CLASS,
13774 + "RMM_create: Memory allocation failed\n");
13775 + status = DSP_EMEMORY;
13777 + if (DSP_FAILED(status))
13778 + goto func_cont;
13780 + target->numSegs = numSegs;
13781 + if (!(numSegs > 0))
13782 + goto func_cont;
13784 + /* Allocate the memory for freelist from host's memory */
13785 + target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
13786 + MEM_PAGED);
13787 + if (target->freeList == NULL) {
13788 + GT_0trace(RMM_debugMask, GT_6CLASS,
13789 + "RMM_create: Memory allocation failed\n");
13790 + status = DSP_EMEMORY;
13791 + } else {
13792 + /* Allocate headers for each element on the free list */
13793 + for (i = 0; i < (s32) numSegs; i++) {
13794 + target->freeList[i] =
13795 + MEM_Calloc(sizeof(struct RMM_Header),
13796 + MEM_PAGED);
13797 + if (target->freeList[i] == NULL) {
13798 + GT_0trace(RMM_debugMask, GT_6CLASS,
13799 + "RMM_create: Memory "
13800 + "allocation failed\n");
13801 + status = DSP_EMEMORY;
13802 + break;
13805 + /* Allocate memory for initial segment table */
13806 + target->segTab = MEM_Calloc(numSegs *
13807 + sizeof(struct RMM_Segment), MEM_PAGED);
13808 + if (target->segTab == NULL) {
13809 + GT_0trace(RMM_debugMask, GT_6CLASS,
13810 + "RMM_create: Memory allocation failed\n");
13811 + status = DSP_EMEMORY;
13812 + } else {
13813 + /* Initialize segment table and free list */
13814 + sptr = target->segTab;
13815 + for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
13816 + *sptr = *tmp;
13817 + hptr = target->freeList[i];
13818 + hptr->addr = tmp->base;
13819 + hptr->size = tmp->length;
13820 + hptr->next = NULL;
13821 + tmp++;
13822 + sptr++;
13826 +func_cont:
13827 + /* Initialize overlay memory list */
13828 + if (DSP_SUCCEEDED(status)) {
13829 + target->ovlyList = LST_Create();
13830 + if (target->ovlyList == NULL) {
13831 + GT_0trace(RMM_debugMask, GT_6CLASS,
13832 + "RMM_create: Memory allocation failed\n");
13833 + status = DSP_EMEMORY;
13837 + if (DSP_SUCCEEDED(status)) {
13838 + *pTarget = target;
13839 + } else {
13840 + *pTarget = NULL;
13841 + if (target)
13842 + RMM_delete(target);
13846 + DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
13847 + RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
13848 + NULL));
13850 + return status;
13854 + * ======== RMM_delete ========
13855 + */
13856 +void RMM_delete(struct RMM_TargetObj *target)
13858 + struct RMM_OvlySect *pSect;
13859 + struct RMM_Header *hptr;
13860 + struct RMM_Header *next;
13861 + u32 i;
13863 + DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
13865 + GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
13867 + if (target->segTab != NULL)
13868 + MEM_Free(target->segTab);
13870 + if (target->ovlyList) {
13871 + while ((pSect = (struct RMM_OvlySect *)LST_GetHead
13872 + (target->ovlyList))) {
13873 + MEM_Free(pSect);
13875 + DBC_Assert(LST_IsEmpty(target->ovlyList));
13876 + LST_Delete(target->ovlyList);
13879 + if (target->freeList != NULL) {
13880 + /* Free elements on freelist */
13881 + for (i = 0; i < target->numSegs; i++) {
13882 + hptr = next = target->freeList[i];
13883 + while (next) {
13884 + hptr = next;
13885 + next = hptr->next;
13886 + MEM_Free(hptr);
13889 + MEM_Free(target->freeList);
13892 + MEM_FreeObject(target);
13896 + * ======== RMM_exit ========
13897 + */
13898 +void RMM_exit(void)
13900 + DBC_Require(cRefs > 0);
13902 + cRefs--;
13904 + GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
13905 + cRefs);
13907 + if (cRefs == 0)
13908 + MEM_Exit();
13910 + DBC_Ensure(cRefs >= 0);
13914 + * ======== RMM_free ========
13915 + */
13916 +bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
13917 + bool reserved)
13920 + struct RMM_OvlySect *sect;
13921 + bool retVal = true;
13923 + DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
13925 + DBC_Require(reserved || segid < target->numSegs);
13926 + DBC_Require(reserved || (addr >= target->segTab[segid].base &&
13927 + (addr + size) <= (target->segTab[segid].base +
13928 + target->segTab[segid].length)));
13930 + GT_5trace(RMM_debugMask, GT_ENTER,
13931 + "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
13932 + "0x%lx)\n", target, segid, addr, size, reserved);
13933 + /*
13934 + * Free or unreserve memory.
13935 + */
13936 + if (!reserved) {
13937 + retVal = freeBlock(target, segid, addr, size);
13938 + if (retVal)
13939 + target->segTab[segid].number--;
13941 + } else {
13942 + /* Unreserve memory */
13943 + sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
13944 + while (sect != NULL) {
13945 + if (addr == sect->addr) {
13946 + DBC_Assert(size == sect->size);
13947 + /* Remove from list */
13948 + LST_RemoveElem(target->ovlyList,
13949 + (struct LST_ELEM *)sect);
13950 + MEM_Free(sect);
13951 + break;
13953 + sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
13954 + (struct LST_ELEM *)sect);
13956 + if (sect == NULL)
13957 + retVal = false;
13960 + return retVal;
13964 + * ======== RMM_init ========
13965 + */
13966 +bool RMM_init(void)
13968 + bool retVal = true;
13970 + DBC_Require(cRefs >= 0);
13972 + if (cRefs == 0) {
13973 + DBC_Assert(!RMM_debugMask.flags);
13974 + GT_create(&RMM_debugMask, "RM"); /* "RM" for RMm */
13976 + retVal = MEM_Init();
13978 + if (!retVal)
13979 + MEM_Exit();
13983 + if (retVal)
13984 + cRefs++;
13986 + GT_1trace(RMM_debugMask, GT_5CLASS,
13987 + "RMM_init(), ref count: 0x%x\n",
13988 + cRefs);
13990 + DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
13992 + return retVal;
13996 + * ======== RMM_stat ========
13997 + */
13998 +bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
13999 + struct DSP_MEMSTAT *pMemStatBuf)
14001 + struct RMM_Header *head;
14002 + bool retVal = false;
14003 + u32 maxFreeSize = 0;
14004 + u32 totalFreeSize = 0;
14005 + u32 freeBlocks = 0;
14007 + DBC_Require(pMemStatBuf != NULL);
14008 + DBC_Assert(target != NULL);
14010 + if ((u32) segid < target->numSegs) {
14011 + head = target->freeList[segid];
14013 + /* Collect data from freeList */
14014 + while (head != NULL) {
14015 + maxFreeSize = max(maxFreeSize, head->size);
14016 + totalFreeSize += head->size;
14017 + freeBlocks++;
14018 + head = head->next;
14021 + /* ulSize */
14022 + pMemStatBuf->ulSize = target->segTab[segid].length;
14024 + /* ulNumFreeBlocks */
14025 + pMemStatBuf->ulNumFreeBlocks = freeBlocks;
14027 + /* ulTotalFreeSize */
14028 + pMemStatBuf->ulTotalFreeSize = totalFreeSize;
14030 + /* ulLenMaxFreeBlock */
14031 + pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
14033 + /* ulNumAllocBlocks */
14034 + pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
14036 + retVal = true;
14039 + return retVal;
14043 + * ======== balloc ========
14044 + * This allocation function allocates memory from the lowest addresses
14045 + * first.
14046 + */
14047 +static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
14048 + u32 align, u32 *dspAddr)
14050 + struct RMM_Header *head;
14051 + struct RMM_Header *prevhead = NULL;
14052 + struct RMM_Header *next;
14053 + u32 tmpalign;
14054 + u32 alignbytes;
14055 + u32 hsize;
14056 + u32 allocsize;
14057 + u32 addr;
14059 + alignbytes = (align == 0) ? 1 : align;
14060 + prevhead = NULL;
14061 + head = target->freeList[segid];
14063 + do {
14064 + hsize = head->size;
14065 + next = head->next;
14067 + addr = head->addr; /* alloc from the bottom */
14069 + /* align allocation */
14070 + (tmpalign = (u32) addr % alignbytes);
14071 + if (tmpalign != 0)
14072 + tmpalign = alignbytes - tmpalign;
14074 + allocsize = size + tmpalign;
14076 + if (hsize >= allocsize) { /* big enough */
14077 + if (hsize == allocsize && prevhead != NULL) {
14078 + prevhead->next = next;
14079 + MEM_Free(head);
14080 + } else {
14081 + head->size = hsize - allocsize;
14082 + head->addr += allocsize;
14085 + /* free up any hole created by alignment */
14086 + if (tmpalign)
14087 + freeBlock(target, segid, addr, tmpalign);
14089 + *dspAddr = addr + tmpalign;
14090 + return true;
14093 + prevhead = head;
14094 + head = next;
14096 + } while (head != NULL);
14098 + return false;
14102 + * ======== freeBlock ========
14103 + * TO DO: freeBlock() allocates memory, which could result in failure.
14104 + * Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
14105 + * freeBlock() could use an RMM_Header from the pool, freeing as blocks
14106 + * are coalesced.
14107 + */
14108 +static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
14109 + u32 size)
14111 + struct RMM_Header *head;
14112 + struct RMM_Header *thead;
14113 + struct RMM_Header *rhead;
14114 + bool retVal = true;
14116 + /* Create a memory header to hold the newly free'd block. */
14117 + rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
14118 + if (rhead == NULL) {
14119 + retVal = false;
14120 + } else {
14121 + /* search down the free list to find the right place for addr */
14122 + head = target->freeList[segid];
14124 + if (addr >= head->addr) {
14125 + while (head->next != NULL && addr > head->next->addr)
14126 + head = head->next;
14128 + thead = head->next;
14130 + head->next = rhead;
14131 + rhead->next = thead;
14132 + rhead->addr = addr;
14133 + rhead->size = size;
14134 + } else {
14135 + *rhead = *head;
14136 + head->next = rhead;
14137 + head->addr = addr;
14138 + head->size = size;
14139 + thead = rhead->next;
14142 + /* join with upper block, if possible */
14143 + if (thead != NULL && (rhead->addr + rhead->size) ==
14144 + thead->addr) {
14145 + head->next = rhead->next;
14146 + thead->size = size + thead->size;
14147 + thead->addr = addr;
14148 + MEM_Free(rhead);
14149 + rhead = thead;
14152 + /* join with the lower block, if possible */
14153 + if ((head->addr + head->size) == rhead->addr) {
14154 + head->next = rhead->next;
14155 + head->size = head->size + rhead->size;
14156 + MEM_Free(rhead);
14160 + return retVal;
14163 Index: lk/drivers/dsp/bridge/rmgr/strm.c
14164 ===================================================================
14165 --- /dev/null 1970-01-01 00:00:00.000000000 +0000
14166 +++ lk/drivers/dsp/bridge/rmgr/strm.c 2008-08-18 10:38:37.000000000 +0300
14167 @@ -0,0 +1,1053 @@
14169 + * linux/drivers/dsp/bridge/rmgr/strm.c
14171 + * DSP-BIOS Bridge driver support functions for TI OMAP processors.
14173 + * Copyright (C) 2005-2006 Texas Instruments, Inc.
14175 + * This package is free software; you can redistribute it and/or modify
14176 + * it under the terms of the GNU General Public License version 2 as
14177 + * published by the Free Software Foundation.
14179 + * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14180 + * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
14181 + * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
14182 + */
14186 + * ======== strm.c ========
14187 + * Description:
14188 + * DSP/BIOS Bridge Stream Manager.
14190 + * Public Functions:
14191 + * STRM_AllocateBuffer
14192 + * STRM_Close
14193 + * STRM_Create
14194 + * STRM_Delete
14195 + * STRM_Exit
14196 + * STRM_FreeBuffer
14197 + * STRM_GetEventHandle
14198 + * STRM_GetInfo
14199 + * STRM_Idle
14200 + * STRM_Init
14201 + * STRM_Issue
14202 + * STRM_Open
14203 + * STRM_PrepareBuffer
14204 + * STRM_Reclaim
14205 + * STRM_RegisterNotify
14206 + * STRM_Select
14207 + * STRM_UnprepareBuffer
14209 + * Notes:
14211 + *! Revision History:
14212 + *! =================
14213 + *! 18-Feb-2003 vp Code review updates.
14214 + *! 18-Oct-2002 vp Ported to Linux platform.
14215 + *! 13-Mar-2002 map pStrm init'd to NULL in STRM_Open to prevent error
14216 + *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
14217 + *! in DEV and CMM function calls to avoid confusion.
14218 + *! Return DSP_SOK instead of S_OK from API fxns.
14219 + *! 12-Mar-2002 map Changed FAILED(..) to DSP_FAILED(..)
14220 + *! 25-Jan-2002 ag Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
14221 + *! 15-Nov-2001 ag Added STRMMODE & SM for DMA/ZCopy streaming.
14222 + *! Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
14223 + *! Use strm timeout value for dma flush timeout.
14224 + *! 09-May-2001 jeh Code review cleanup.
14225 + *! 06-Feb-2001 kc Updated DBC_Ensure in STRM_Select to check timeout.
14226 + *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
14227 + *! tests to pass.
14228 + *! 25-Sep-2000 jeh Created.
14229 + */
14231 +/* ----------------------------------- Host OS */
14232 +#include <host_os.h>
14234 +/* ----------------------------------- DSP/BIOS Bridge */
14235 +#include <std.h>
14236 +#include <dbdefs.h>
14237 +#include <errbase.h>
14239 +/* ----------------------------------- Trace & Debug */
14240 +#include <dbc.h>
14241 +#include <gt.h>
14243 +/* ----------------------------------- OS Adaptation Layer */
14244 +#include <mem.h>
14245 +#include <sync.h>
14247 +/* ----------------------------------- Mini Driver */
14248 +#include <wmd.h>
14250 +/* ----------------------------------- Resource Manager */
14251 +#include <nodepriv.h>
14253 +/* ----------------------------------- Others */
14254 +#include <cmm.h>
14256 +/* ----------------------------------- This */
14257 +#include <strm.h>
14259 +#ifndef RES_CLEANUP_DISABLE
14260 +#include <cfg.h>
14261 +#include <prcs.h>
14262 +#include <dbreg.h>
14263 +#include <resourcecleanup.h>
14264 +#endif
14266 +/* ----------------------------------- Defines, Data Structures, Typedefs */
14267 +#define STRM_SIGNATURE 0x4d525453 /* "MRTS" */
14268 +#define STRMMGR_SIGNATURE 0x5254534d /* "RTSM" */
14270 +#define DEFAULTTIMEOUT 10000
14271 +#define DEFAULTNUMBUFS 2
14274 + * ======== STRM_MGR ========
14275 + * The STRM_MGR contains device information needed to open the underlying
14276 + * channels of a stream.
14277 + */
14278 +struct STRM_MGR {
14279 + u32 dwSignature;
14280 + struct DEV_OBJECT *hDev; /* Device for this processor */
14281 + struct CHNL_MGR *hChnlMgr; /* Channel manager */
14282 + struct WMD_DRV_INTERFACE *pIntfFxns; /* Function interface to WMD */
14283 + struct SYNC_CSOBJECT *hSync; /* For critical sections */
14284 +} ;
14287 + * ======== STRM_OBJECT ========
14288 + * This object is allocated in STRM_Open().
14289 + */
14290 + struct STRM_OBJECT {
14291 + u32 dwSignature;
14292 + struct STRM_MGR *hStrmMgr;
14293 + struct CHNL_OBJECT *hChnl;
14294 + u32 uDir; /* DSP_TONODE or DSP_FROMNODE */
14295 + u32 uTimeout;
14296 + u32 uNumBufs; /* Max # of bufs allowed in stream */
14297 + u32 uNBufsInStrm; /* Current # of bufs in stream */
14298 + u32 ulNBytes; /* bytes transferred since idled */
14299 + enum DSP_STREAMSTATE strmState; /* STREAM_IDLE, STREAM_READY, ... */
14300 + HANDLE hUserEvent; /* Saved for STRM_GetInfo() */
14301 + enum DSP_STRMMODE lMode; /* STRMMODE_[PROCCOPY][ZEROCOPY]... */
14302 + u32 uDMAChnlId; /* DMA chnl id */
14303 + u32 uDMAPriority; /* DMA priority:DMAPRI_[LOW][HIGH] */
14304 + u32 uSegment; /* >0 is SM segment.=0 is local heap */
14305 + u32 uAlignment; /* Alignment for stream bufs */
14306 + struct CMM_XLATOROBJECT *hXlator; /* Stream's SM address translator */
14307 +} ;
14309 +/* ----------------------------------- Globals */
14310 +#if GT_TRACE
14311 +static struct GT_Mask STRM_debugMask = { NULL, NULL }; /* GT trace variable */
14312 +#endif
14313 +static u32 cRefs; /* module reference count */
14315 +/* ----------------------------------- Function Prototypes */
14316 +static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
14317 +static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
14320 + * ======== STRM_AllocateBuffer ========
14321 + * Purpose:
14322 + * Allocates buffers for a stream.
14323 + */
14324 +DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
14325 + OUT u8 **apBuffer, u32 uNumBufs)
14327 + DSP_STATUS status = DSP_SOK;
14328 + u32 uAllocated = 0;
14329 + u32 i;
14330 + #ifndef RES_CLEANUP_DISABLE
14331 + DSP_STATUS res_status = DSP_SOK;
14332 + HANDLE hProcess;
14333 + HANDLE pCtxt = NULL;
14334 + HANDLE hDrvObject;
14335 + HANDLE hSTRMRes;
14336 + #endif
14337 + DBC_Require(cRefs > 0);
14338 + DBC_Require(apBuffer != NULL);
14340 + GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
14341 + "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
14342 + hStrm, uSize, apBuffer, uNumBufs);
14343 + if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14344 + /*
14345 + * Allocate from segment specified at time of stream open.
14346 + */
14347 + if (uSize == 0)
14348 + status = DSP_ESIZE;
14351 + if (DSP_FAILED(status)) {
14352 + status = DSP_EHANDLE;
14353 + goto func_end;
14355 + for (i = 0; i < uNumBufs; i++) {
14356 + DBC_Assert(hStrm->hXlator != NULL);
14357 + (void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
14358 + if (apBuffer[i] == NULL) {
14359 + GT_0trace(STRM_debugMask, GT_7CLASS,
14360 + "STRM_AllocateBuffer: "
14361 + "DSP_FAILED to alloc shared memory.\n");
14362 + status = DSP_EMEMORY;
14363 + uAllocated = i;
14364 + break;
14367 + if (DSP_FAILED(status))
14368 + STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
14370 +#ifndef RES_CLEANUP_DISABLE
14371 + if (DSP_FAILED(status))
14372 + goto func_end;
14374 + PRCS_GetCurrentHandle(&hProcess);
14375 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
14376 + if (DSP_FAILED(res_status))
14377 + goto func_end;
14379 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
14380 + if (pCtxt != NULL) {
14381 + if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
14382 + DSP_ENOTFOUND) {
14383 + DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
14386 +#endif
14387 +func_end:
14388 + return status;
14392 + * ======== STRM_Close ========
14393 + * Purpose:
14394 + * Close a stream opened with STRM_Open().
14395 + */
14396 +DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
14398 + struct WMD_DRV_INTERFACE *pIntfFxns;
14399 + struct CHNL_INFO chnlInfo;
14400 + DSP_STATUS status = DSP_SOK;
14403 +#ifndef RES_CLEANUP_DISABLE
14404 + HANDLE hProcess;
14405 + HANDLE pCtxt = NULL;
14406 + HANDLE hDrvObject;
14407 + HANDLE hSTRMRes;
14408 + DSP_STATUS res_status = DSP_SOK;
14409 +#endif
14412 + DBC_Require(cRefs > 0);
14414 + GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
14416 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14417 + status = DSP_EHANDLE;
14418 + } else {
14419 + /* Have all buffers been reclaimed? If not, return
14420 + * DSP_EPENDING */
14421 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
14422 + status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
14423 + DBC_Assert(DSP_SUCCEEDED(status));
14425 + if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
14426 + status = DSP_EPENDING;
14427 + } else {
14429 + status = DeleteStrm(hStrm);
14431 + if (DSP_FAILED(status)) {
14432 + /* we already validated the handle. */
14433 + DBC_Assert(status != DSP_EHANDLE);
14435 + /* make sure we return a documented result */
14436 + status = DSP_EFAIL;
14440 +#ifndef RES_CLEANUP_DISABLE
14441 + if (DSP_FAILED(status))
14442 + goto func_end;
14444 + /* Update the node and stream resource status */
14445 + PRCS_GetCurrentHandle(&hProcess);
14446 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
14447 + if (DSP_FAILED(res_status))
14448 + goto func_end;
14450 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
14451 + if (pCtxt != NULL) {
14452 + if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
14453 + DSP_ENOTFOUND) {
14454 + DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
14457 +func_end:
14458 +#endif
14459 + DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
14460 + status == DSP_EPENDING || status == DSP_EFAIL);
14462 + return status;
14466 + * ======== STRM_Create ========
14467 + * Purpose:
14468 + * Create a STRM manager object.
14469 + */
14470 +DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
14472 + struct STRM_MGR *pStrmMgr;
14473 + DSP_STATUS status = DSP_SOK;
14475 + DBC_Require(cRefs > 0);
14476 + DBC_Require(phStrmMgr != NULL);
14477 + DBC_Require(hDev != NULL);
14479 + GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
14480 + "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
14481 + *phStrmMgr = NULL;
14482 + /* Allocate STRM manager object */
14483 + MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
14484 + if (pStrmMgr == NULL) {
14485 + status = DSP_EMEMORY;
14486 + GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
14487 + "MEM_AllocObject() failed!\n ");
14488 + } else {
14489 + pStrmMgr->hDev = hDev;
14491 + /* Get Channel manager and WMD function interface */
14492 + if (DSP_SUCCEEDED(status)) {
14493 + status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
14494 + if (DSP_SUCCEEDED(status)) {
14495 + (void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
14496 + DBC_Assert(pStrmMgr->pIntfFxns != NULL);
14497 + } else {
14498 + GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
14499 + "Failed to get channel manager! status = "
14500 + "0x%x\n", status);
14503 + if (DSP_SUCCEEDED(status))
14504 + status = SYNC_InitializeCS(&pStrmMgr->hSync);
14506 + if (DSP_SUCCEEDED(status))
14507 + *phStrmMgr = pStrmMgr;
14508 + else
14509 + DeleteStrmMgr(pStrmMgr);
14511 + DBC_Ensure(DSP_SUCCEEDED(status) &&
14512 + (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
14513 + (DSP_FAILED(status) && *phStrmMgr == NULL)));
14515 + return status;
14519 + * ======== STRM_Delete ========
14520 + * Purpose:
14521 + * Delete the STRM Manager Object.
14522 + */
14523 +void STRM_Delete(struct STRM_MGR *hStrmMgr)
14525 + DBC_Require(cRefs > 0);
14526 + DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
14528 + GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
14529 + hStrmMgr);
14531 + DeleteStrmMgr(hStrmMgr);
14533 + DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
14537 + * ======== STRM_Exit ========
14538 + * Purpose:
14539 + * Discontinue usage of STRM module.
14540 + */
14541 +void STRM_Exit(void)
14543 + DBC_Require(cRefs > 0);
14545 + cRefs--;
14547 + GT_1trace(STRM_debugMask, GT_5CLASS,
14548 + "Entered STRM_Exit, ref count: 0x%x\n", cRefs);
14550 + DBC_Ensure(cRefs >= 0);
14554 + * ======== STRM_FreeBuffer ========
14555 + * Purpose:
14556 + * Frees the buffers allocated for a stream.
14557 + */
14558 +DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
14559 + u32 uNumBufs)
14561 + DSP_STATUS status = DSP_SOK;
14562 + u32 i = 0;
14564 + #ifndef RES_CLEANUP_DISABLE
14565 + DSP_STATUS res_status = DSP_SOK;
14566 + HANDLE hProcess;
14567 + HANDLE pCtxt = NULL;
14568 + HANDLE hDrvObject;
14569 + HANDLE hSTRMRes = NULL;
14570 + #endif
14571 + DBC_Require(cRefs > 0);
14572 + DBC_Require(apBuffer != NULL);
14574 + GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
14575 + "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
14577 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
14578 + status = DSP_EHANDLE;
14580 + if (DSP_SUCCEEDED(status)) {
14581 + for (i = 0; i < uNumBufs; i++) {
14582 + DBC_Assert(hStrm->hXlator != NULL);
14583 + status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
14584 + if (DSP_FAILED(status)) {
14585 + GT_0trace(STRM_debugMask, GT_7CLASS,
14586 + "STRM_FreeBuffer: DSP_FAILED"
14587 + " to free shared memory.\n");
14588 + break;
14590 + apBuffer[i] = NULL;
14593 +#ifndef RES_CLEANUP_DISABLE
14594 + /* Update the node and stream resource status */
14595 + PRCS_GetCurrentHandle(&hProcess);
14596 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
14597 + if (DSP_SUCCEEDED(res_status)) {
14598 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
14599 + if (pCtxt != NULL) {
14600 + if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
14601 + DSP_ENOTFOUND) {
14602 + DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
14603 + pCtxt);
14607 +#endif
14608 + return status;
14612 + * ======== STRM_GetInfo ========
14613 + * Purpose:
14614 + * Retrieves information about a stream.
14615 + */
14616 +DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
14617 + OUT struct STRM_INFO *pStreamInfo,
14618 + u32 uStreamInfoSize)
14620 + struct WMD_DRV_INTERFACE *pIntfFxns;
14621 + struct CHNL_INFO chnlInfo;
14622 + DSP_STATUS status = DSP_SOK;
14623 + void *pVirtBase = NULL; /* NULL if no SM used */
14625 + DBC_Require(cRefs > 0);
14626 + DBC_Require(pStreamInfo != NULL);
14627 + DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
14629 + GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
14630 + "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
14631 + pStreamInfo, uStreamInfoSize);
14632 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14633 + status = DSP_EHANDLE;
14634 + } else {
14635 + if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
14636 + /* size of users info */
14637 + status = DSP_ESIZE;
14640 + if (DSP_FAILED(status))
14641 + goto func_end;
14643 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
14644 + status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
14645 + if (DSP_FAILED(status))
14646 + goto func_end;
14648 + if (hStrm->hXlator) {
14649 + /* We have a translator */
14650 + DBC_Assert(hStrm->uSegment > 0);
14651 + CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
14652 + hStrm->uSegment, false);
14654 + pStreamInfo->uSegment = hStrm->uSegment;
14655 + pStreamInfo->lMode = hStrm->lMode;
14656 + pStreamInfo->pVirtBase = pVirtBase;
14657 + pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
14658 + pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
14659 + chnlInfo.cIOReqs;
14660 + /* # of bytes transferred since last call to DSPStream_Idle() */
14661 + pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
14662 + pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
14663 + /* Determine stream state based on channel state and info */
14664 + if (chnlInfo.dwState & CHNL_STATEEOS) {
14665 + pStreamInfo->pUser->ssStreamState = STREAM_DONE;
14666 + } else {
14667 + if (chnlInfo.cIOCs > 0)
14668 + pStreamInfo->pUser->ssStreamState = STREAM_READY;
14669 + else if (chnlInfo.cIOReqs > 0)
14670 + pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
14671 + else
14672 + pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
14675 +func_end:
14676 + return status;
14680 + * ======== STRM_Idle ========
14681 + * Purpose:
14682 + * Idles a particular stream.
14683 + */
14684 +DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
14686 + struct WMD_DRV_INTERFACE *pIntfFxns;
14687 + DSP_STATUS status = DSP_SOK;
14689 + DBC_Require(cRefs > 0);
14691 + GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
14692 + "fFlush: 0x%x\n", hStrm, fFlush);
14694 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14695 + status = DSP_EHANDLE;
14696 + } else {
14697 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
14699 + status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
14700 + hStrm->uTimeout, fFlush);
14702 + return status;
14706 + * ======== STRM_Init ========
14707 + * Purpose:
14708 + * Initialize the STRM module.
14709 + */
14710 +bool STRM_Init(void)
14712 + bool fRetVal = true;
14714 + DBC_Require(cRefs >= 0);
14716 + if (cRefs == 0) {
14717 +#if GT_TRACE
14718 + DBC_Assert(!STRM_debugMask.flags);
14719 + GT_create(&STRM_debugMask, "ST"); /* "ST" for STrm */
14720 +#endif
14723 + if (fRetVal)
14724 + cRefs++;
14726 + GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
14727 + cRefs);
14729 + DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
14731 + return fRetVal;
14735 + * ======== STRM_Issue ========
14736 + * Purpose:
14737 + * Issues a buffer on a stream
14738 + */
14739 +DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
14740 + u32 ulBufSize, u32 dwArg)
14742 + struct WMD_DRV_INTERFACE *pIntfFxns;
14743 + DSP_STATUS status = DSP_SOK;
14744 + void *pTmpBuf = NULL;
14746 + DBC_Require(cRefs > 0);
14747 + DBC_Require(pBuf != NULL);
14749 + GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
14750 + "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
14751 + dwArg);
14752 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14753 + status = DSP_EHANDLE;
14754 + } else {
14755 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
14757 + if (hStrm->uSegment != 0) {
14758 + pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
14759 + (void *)pBuf, CMM_VA2DSPPA);
14760 + if (pTmpBuf == NULL)
14761 + status = DSP_ETRANSLATE;
14764 + if (DSP_SUCCEEDED(status)) {
14765 + status = (*pIntfFxns->pfnChnlAddIOReq)
14766 + (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
14767 + (u32) pTmpBuf, dwArg);
14769 + if (DSP_FAILED(status)) {
14770 + if (status == CHNL_E_NOIORPS)
14771 + status = DSP_ESTREAMFULL;
14772 + else
14773 + status = DSP_EFAIL;
14777 + return status;
14781 + * ======== STRM_Open ========
14782 + * Purpose:
14783 + * Open a stream for sending/receiving data buffers to/from a task or
14784 + * XDAIS socket node on the DSP.
14785 + */
14786 +DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
14787 + IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
14789 + struct STRM_MGR *hStrmMgr;
14790 + struct WMD_DRV_INTERFACE *pIntfFxns;
14791 + u32 ulChnlId;
14792 + struct STRM_OBJECT *pStrm = NULL;
14793 + CHNL_MODE uMode;
14794 + struct CHNL_ATTRS chnlAttrs;
14795 + DSP_STATUS status = DSP_SOK;
14796 + struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
14798 + #ifndef RES_CLEANUP_DISABLE
14799 + DSP_STATUS res_status = DSP_SOK;
14800 + HANDLE hProcess;
14801 + HANDLE pCtxt = NULL;
14802 + HANDLE hDrvObject;
14803 + HANDLE hSTRMRes;
14804 + #endif
14805 + DBC_Require(cRefs > 0);
14806 + DBC_Require(phStrm != NULL);
14807 + DBC_Require(pAttr != NULL);
14808 + GT_5trace(STRM_debugMask, GT_ENTER,
14809 + "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
14810 + "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
14811 + hNode, uDir, uIndex, pAttr, phStrm);
14812 + *phStrm = NULL;
14813 + if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
14814 + status = DSP_EDIRECTION;
14815 + } else {
14816 + /* Get the channel id from the node (set in NODE_Connect()) */
14817 + status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
14819 + if (DSP_SUCCEEDED(status))
14820 + status = NODE_GetStrmMgr(hNode, &hStrmMgr);
14822 + if (DSP_SUCCEEDED(status)) {
14823 + MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
14824 + if (pStrm == NULL) {
14825 + status = DSP_EMEMORY;
14826 + GT_0trace(STRM_debugMask, GT_6CLASS,
14827 + "STRM_Open: MEM_AllocObject() failed!\n ");
14828 + } else {
14829 + pStrm->hStrmMgr = hStrmMgr;
14830 + pStrm->uDir = uDir;
14831 + pStrm->strmState = STREAM_IDLE;
14832 + pStrm->hUserEvent = pAttr->hUserEvent;
14833 + if (pAttr->pStreamAttrIn != NULL) {
14834 + pStrm->uTimeout = pAttr->pStreamAttrIn->
14835 + uTimeout;
14836 + pStrm->uNumBufs = pAttr->pStreamAttrIn->
14837 + uNumBufs;
14838 + pStrm->lMode = pAttr->pStreamAttrIn->lMode;
14839 + pStrm->uSegment = pAttr->pStreamAttrIn->
14840 + uSegment;
14841 + pStrm->uAlignment = pAttr->pStreamAttrIn->
14842 + uAlignment;
14843 + pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
14844 + uDMAChnlId;
14845 + pStrm->uDMAPriority = pAttr->pStreamAttrIn->
14846 + uDMAPriority;
14847 + chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
14848 + uNumBufs;
14849 + } else {
14850 + pStrm->uTimeout = DEFAULTTIMEOUT;
14851 + pStrm->uNumBufs = DEFAULTNUMBUFS;
14852 + pStrm->lMode = STRMMODE_PROCCOPY;
14853 + pStrm->uSegment = 0; /* local memory */
14854 + pStrm->uAlignment = 0;
14855 + pStrm->uDMAChnlId = 0;
14856 + pStrm->uDMAPriority = 0;
14857 + chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
14859 + chnlAttrs.hReserved1 = NULL;
14860 + /* DMA chnl flush timeout */
14861 + chnlAttrs.hReserved2 = pStrm->uTimeout;
14862 + chnlAttrs.hEvent = NULL;
14863 + if (pAttr->hUserEvent != NULL)
14864 + chnlAttrs.hEvent = pAttr->hUserEvent;
14868 + if (DSP_FAILED(status))
14869 + goto func_cont;
14871 + if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
14872 + goto func_cont;
14874 + DBC_Assert(pStrm->lMode != STRMMODE_LDMA); /* no System DMA */
14875 + /* Get the shared mem mgr for this streams dev object */
14876 + status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
14877 + if (DSP_FAILED(status)) {
14878 + GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
14879 + "CMM Mgr handle: 0x%x\n", status);
14880 + } else {
14881 + /*Allocate a SM addr translator for this strm.*/
14882 + status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
14883 + if (DSP_FAILED(status)) {
14884 + GT_1trace(STRM_debugMask, GT_6CLASS,
14885 + "STRM_Open: Failed to "
14886 + "create SM translator: 0x%x\n", status);
14887 + } else {
14888 + DBC_Assert(pStrm->uSegment > 0);
14889 + /* Set translators Virt Addr attributes */
14890 + status = CMM_XlatorInfo(pStrm->hXlator,
14891 + (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
14892 + pStrm->uSegment, true);
14893 + if (status != DSP_SOK) {
14894 + GT_0trace(STRM_debugMask, GT_6CLASS,
14895 + "STRM_Open: ERROR: "
14896 + "in setting CMM_XlatorInfo.\n");
14900 +func_cont:
14901 + if (DSP_SUCCEEDED(status)) {
14902 + /* Open channel */
14903 + uMode = (uDir == DSP_TONODE) ?
14904 + CHNL_MODETODSP : CHNL_MODEFROMDSP;
14905 + pIntfFxns = hStrmMgr->pIntfFxns;
14906 + status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
14907 + hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
14908 + if (DSP_FAILED(status)) {
14909 + /*
14910 + * over-ride non-returnable status codes so we return
14911 + * something documented
14912 + */
14913 + if (status != DSP_EMEMORY && status !=
14914 + DSP_EINVALIDARG && status != DSP_EFAIL) {
14915 + /*
14916 + * We got a status that's not return-able.
14917 + * Assert that we got something we were
14918 + * expecting (DSP_EHANDLE isn't acceptable,
14919 + * hStrmMgr->hChnlMgr better be valid or we
14920 + * assert here), and then return DSP_EFAIL.
14921 + */
14922 + DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
14923 + status == CHNL_E_BADCHANID ||
14924 + status == CHNL_E_CHANBUSY ||
14925 + status == CHNL_E_NOIORPS);
14926 + status = DSP_EFAIL;
14928 + GT_2trace(STRM_debugMask, GT_6CLASS,
14929 + "STRM_Open: Channel open failed, "
14930 + "chnl id = %d, status = 0x%x\n", ulChnlId,
14931 + status);
14934 + if (DSP_SUCCEEDED(status))
14935 + *phStrm = pStrm;
14936 + else
14937 + (void)DeleteStrm(pStrm);
14939 +#ifndef RES_CLEANUP_DISABLE
14940 + PRCS_GetCurrentHandle(&hProcess);
14941 + res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
14942 + if (DSP_SUCCEEDED(res_status)) {
14943 + DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, hNode, 0);
14944 + if (pCtxt != NULL)
14945 + DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
14948 +#endif
14950 + /* ensure we return a documented error code */
14951 + DBC_Ensure((DSP_SUCCEEDED(status) &&
14952 + MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
14953 + (*phStrm == NULL && (status == DSP_EHANDLE ||
14954 + status == DSP_EDIRECTION || status == DSP_EVALUE ||
14955 + status == DSP_EFAIL)));
14956 + return status;
14960 + * ======== STRM_Reclaim ========
14961 + * Purpose:
14962 + * Relcaims a buffer from a stream.
14963 + */
14964 +DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
14965 + u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
14967 + struct WMD_DRV_INTERFACE *pIntfFxns;
14968 + struct CHNL_IOC chnlIOC;
14969 + DSP_STATUS status = DSP_SOK;
14970 + void *pTmpBuf = NULL;
14972 + DBC_Require(cRefs > 0);
14973 + DBC_Require(pBufPtr != NULL);
14974 + DBC_Require(pulBytes != NULL);
14975 + DBC_Require(pdwArg != NULL);
14977 + GT_4trace(STRM_debugMask, GT_ENTER,
14978 + "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
14979 + "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
14980 + pdwArg);
14982 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
14983 + status = DSP_EHANDLE;
14984 + goto func_end;
14986 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
14988 + status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
14989 + &chnlIOC);
14990 + if (DSP_FAILED(status)) {
14991 + GT_1trace(STRM_debugMask, GT_6CLASS,
14992 + "STRM_Reclaim: GetIOC failed! "
14993 + "Status = 0x%x\n", status);
14994 + } else {
14995 + *pulBytes = chnlIOC.cBytes;
14996 + if (pulBufSize)
14997 + *pulBufSize = chnlIOC.cBufSize;
14999 + *pdwArg = chnlIOC.dwArg;
15000 + if (!CHNL_IsIOComplete(chnlIOC)) {
15001 + if (CHNL_IsTimedOut(chnlIOC)) {
15002 + status = DSP_ETIMEOUT;
15003 + } else {
15004 + /* Allow reclaims after idle to succeed */
15005 + if (!CHNL_IsIOCancelled(chnlIOC))
15006 + status = DSP_EFAIL;
15010 + /* Translate zerocopy buffer if channel not canceled. */
15011 + if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
15012 + (hStrm->lMode == STRMMODE_ZEROCOPY)) {
15013 + /*
15014 + * This is a zero-copy channel so chnlIOC.pBuf
15015 + * contains the DSP address of SM. We need to
15016 + * translate it to a virtual address for the user
15017 + * thread to access.
15018 + * Note: Could add CMM_DSPPA2VA to CMM in the future.
15019 + */
15020 + pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
15021 + chnlIOC.pBuf, CMM_DSPPA2PA);
15022 + if (pTmpBuf != NULL) {
15023 + /* now convert this GPP Pa to Va */
15024 + pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
15025 + pTmpBuf, CMM_PA2VA);
15027 + if (pTmpBuf == NULL) {
15028 + GT_0trace(STRM_debugMask, GT_7CLASS,
15029 + "STRM_Reclaim: Failed "
15030 + "SM translation!\n");
15031 + status = DSP_ETRANSLATE;
15033 + chnlIOC.pBuf = pTmpBuf;
15035 + *pBufPtr = chnlIOC.pBuf;
15037 +func_end:
15038 + /* ensure we return a documented return code */
15039 + DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
15040 + status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
15041 + status == DSP_EFAIL);
15042 + return status;
15046 + * ======== STRM_RegisterNotify ========
15047 + * Purpose:
15048 + * Register to be notified on specific events for this stream.
15049 + */
15050 +DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
15051 + u32 uNotifyType, struct DSP_NOTIFICATION
15052 + *hNotification)
15054 + struct WMD_DRV_INTERFACE *pIntfFxns;
15055 + DSP_STATUS status = DSP_SOK;
15057 + DBC_Require(cRefs > 0);
15058 + DBC_Require(hNotification != NULL);
15060 + GT_4trace(STRM_debugMask, GT_ENTER,
15061 + "STRM_RegisterNotify: hStrm: 0x%x\t"
15062 + "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
15063 + hStrm, uEventMask, uNotifyType, hNotification);
15064 + if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
15065 + status = DSP_EHANDLE;
15066 + } else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
15067 + DSP_STREAMDONE)) != 0) {
15068 + status = DSP_EVALUE;
15069 + } else {
15070 + if (uNotifyType != DSP_SIGNALEVENT)
15071 + status = DSP_ENOTIMPL;
15074 + if (DSP_SUCCEEDED(status)) {
15075 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
15077 + status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
15078 + uEventMask, uNotifyType, hNotification);
15080 + /* ensure we return a documented return code */
15081 + DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
15082 + status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
15083 + status == DSP_ENOTIMPL || status == DSP_EFAIL);
15084 + return status;
15088 + * ======== STRM_Select ========
15089 + * Purpose:
15090 + * Selects a ready stream.
15091 + */
15092 +DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
15093 + OUT u32 *pMask, u32 uTimeout)
15095 + u32 uIndex;
15096 + struct CHNL_INFO chnlInfo;
15097 + struct WMD_DRV_INTERFACE *pIntfFxns;
15098 + struct SYNC_OBJECT **hSyncEvents = NULL;
15099 + u32 i;
15100 + DSP_STATUS status = DSP_SOK;
15102 + DBC_Require(cRefs > 0);
15103 + DBC_Require(aStrmTab != NULL);
15104 + DBC_Require(pMask != NULL);
15105 + DBC_Require(nStrms > 0);
15107 + GT_4trace(STRM_debugMask, GT_ENTER,
15108 + "STRM_Select: aStrmTab: 0x%x \tnStrms: "
15109 + "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
15110 + nStrms, pMask, uTimeout);
15111 + *pMask = 0;
15112 + for (i = 0; i < nStrms; i++) {
15113 + if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
15114 + status = DSP_EHANDLE;
15115 + break;
15118 + if (DSP_FAILED(status))
15119 + goto func_end;
15121 + /* Determine which channels have IO ready */
15122 + for (i = 0; i < nStrms; i++) {
15123 + pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
15124 + status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
15125 + &chnlInfo);
15126 + if (DSP_FAILED(status)) {
15127 + break;
15128 + } else {
15129 + if (chnlInfo.cIOCs > 0)
15130 + *pMask |= (1 << i);
15134 + if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
15135 + /* Non-zero timeout */
15136 + hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
15137 + sizeof(struct SYNC_OBJECT *), MEM_PAGED);
15138 + if (hSyncEvents == NULL) {
15139 + status = DSP_EMEMORY;
15140 + } else {
15141 + for (i = 0; i < nStrms; i++) {
15142 + pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
15143 + status = (*pIntfFxns->pfnChnlGetInfo)
15144 + (aStrmTab[i]->hChnl, &chnlInfo);
15145 + if (DSP_FAILED(status))
15146 + break;
15147 + else
15148 + hSyncEvents[i] = chnlInfo.hSyncEvent;
15152 + if (DSP_SUCCEEDED(status)) {
15153 + status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
15154 + uTimeout, &uIndex);
15155 + if (DSP_SUCCEEDED(status)) {
15156 + /* Since we waited on the event, we have to
15157 + * reset it */
15158 + SYNC_SetEvent(hSyncEvents[uIndex]);
15159 + *pMask = 1 << uIndex;
15163 +func_end:
15164 + if (hSyncEvents)
15165 + MEM_Free(hSyncEvents);
15167 + DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
15168 + (DSP_FAILED(status) && *pMask == 0));
15170 + return status;
15174 + * ======== DeleteStrm ========
15175 + * Purpose:
15176 + * Frees the resources allocated for a stream.
15177 + */
15178 +static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
15180 + struct WMD_DRV_INTERFACE *pIntfFxns;
15181 + DSP_STATUS status = DSP_SOK;
15183 + if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
15184 + if (hStrm->hChnl) {
15185 + pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
15186 + /* Channel close can fail only if the channel handle
15187 + * is invalid. */
15188 + status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
15189 + /* Free all SM address translator resources */
15190 + if (DSP_SUCCEEDED(status)) {
15191 + if (hStrm->hXlator) {
15192 + /* force free */
15193 + (void)CMM_XlatorDelete(hStrm->hXlator,
15194 + true);
15198 + MEM_FreeObject(hStrm);
15199 + } else {
15200 + status = DSP_EHANDLE;
15202 + return status;
15206 + * ======== DeleteStrmMgr ========
15207 + * Purpose:
15208 + * Frees stream manager.
15209 + */
15210 +static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
15212 + if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
15214 + if (hStrmMgr->hSync)
15215 + SYNC_DeleteCS(hStrmMgr->hSync);
15217 + MEM_FreeObject(hStrmMgr);