From bfd2348cf1e329ed8c94d20ee01d5308ff1eb531 Mon Sep 17 00:00:00 2001
From: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
Date: Fri, 15 Aug 2008 01:55:54 +0300
Subject: [PATCH 07/15] TI DSP BRIDGE: Resource Manager

Initial port from omapzoom
	http://omapzoom.org/gf/project/omapbridge

For details,
http://omapzoom.org/gf/project/omapbridge/docman/?subdir=3

Signed-off-by: Hiroshi DOYU <Hiroshi.DOYU@nokia.com>
---
 drivers/dsp/bridge/rmgr/dbdcd.c         | 1599 +++++++++++++++
 drivers/dsp/bridge/rmgr/disp.c          |  915 +++++++++
 drivers/dsp/bridge/rmgr/drv.c           | 1883 +++++++++++++++++
 drivers/dsp/bridge/rmgr/drv_interface.c |  780 +++++++
 drivers/dsp/bridge/rmgr/drv_interface.h |   40 +
 drivers/dsp/bridge/rmgr/dspdrv.c        |  276 +++
 drivers/dsp/bridge/rmgr/mgr.c           |  491 +++++
 drivers/dsp/bridge/rmgr/nldr.c          | 1966 ++++++++++++++++++
 drivers/dsp/bridge/rmgr/node.c          | 3365 +++++++++++++++++++++++++++++++
 drivers/dsp/bridge/rmgr/proc.c          | 1958 ++++++++++++++++++
 drivers/dsp/bridge/rmgr/pwr.c           |  184 ++
 drivers/dsp/bridge/rmgr/rmm.c           |  604 ++++++
 drivers/dsp/bridge/rmgr/strm.c          | 1053 ++++++++++
 13 files changed, 15114 insertions(+), 0 deletions(-)
 create mode 100644 drivers/dsp/bridge/rmgr/dbdcd.c
 create mode 100644 drivers/dsp/bridge/rmgr/disp.c
 create mode 100644 drivers/dsp/bridge/rmgr/drv.c
 create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.c
 create mode 100644 drivers/dsp/bridge/rmgr/drv_interface.h
 create mode 100644 drivers/dsp/bridge/rmgr/dspdrv.c
 create mode 100644 drivers/dsp/bridge/rmgr/mgr.c
 create mode 100644 drivers/dsp/bridge/rmgr/nldr.c
 create mode 100644 drivers/dsp/bridge/rmgr/node.c
 create mode 100644 drivers/dsp/bridge/rmgr/proc.c
 create mode 100644 drivers/dsp/bridge/rmgr/pwr.c
 create mode 100644 drivers/dsp/bridge/rmgr/rmm.c
 create mode 100644 drivers/dsp/bridge/rmgr/strm.c

diff --git a/drivers/dsp/bridge/rmgr/dbdcd.c b/drivers/dsp/bridge/rmgr/dbdcd.c
new file mode 100644
index 0000000..928555f
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/dbdcd.c
@@ -0,0 +1,1599 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/dbdcd.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== dbdcd.c ========
+ *  Description:
+ *      This file contains the implementation of the DSP/BIOS Bridge
+ *      Configuration Database (DCD).
+ *
+ *  Notes:
+ *      The fxn DCD_GetObjects can apply a callback fxn to each DCD object
+ *      that is located in a specified COFF file.  At the moment,
+ *      DCD_AutoRegister, DCD_AutoUnregister, and NLDR module all use
+ *      DCD_GetObjects.
+ *
+ *! Revision History
+ *! ================
+ *! 03-Dec-2003 map Changed DCD_OBJTYPE to DSP_DCDOBJTYPE
+ *! 17-Dec-2002 map Modified DCD_GetDepLibs, DCD_GetNumDepLibs, GetDepLibInfo
+ *!                 to include phase information
+ *! 02-Dec-2002 map Modified DCD_GetLibraryName for phases in different
+ *!                 libraries
+ *! 26-Feb-2003 kc  Updated DCD_AutoUnregister and DCD_GetObjects to simplify
+ *!                 DCD implementation.
+ *! 17-Jul-2002 jeh Call COD_Open() instead of COD_OpenBase(), call COD_Close()
+ *! 11-Jul-2002 jeh Added DCD_GetDepLibs(), DCD_GetNumDepLibs().
+ *! 18-Feb-2003 vp  Code review updates
+ *! 18-Oct-2002 vp  Ported to Linux platform
+ *! 15-Mar-2002 jeh Read dynamic loading memory requirements into node object
+ *!                 data. Added DCD_GetLibraryName().
+ *! 13-Feb-2002 jeh Get system stack size in GetAttrsFromBuf().
+ *! 01-Aug-2001 ag: Added check for PROC "extended" attributes used for
+ *!                    DSP-MMU setup. These are private attributes.
+ *! 18-Apr-2001 jeh Use COD_OpenBase instead of COD_LoadBase.
+ *! 03-Apr-2001 sg: Changed error names to DSP_EDCD* format.
+ *! 11-Jan-2001 jeh Changes to DCD_GetObjectDef to match node.cdb, proc.cdb.
+ *! 12-Dec-2000 kc: Added DCD_AutoUnregister. MSGNODE, DAISNODE added in
+ *!                 GetAttrsFromBuf
+ *! 22-Nov-2000 kc: Replaced sprintf() calls with CSL_Strncat.
+ *! 09-Nov-2000 kc: Optimized DCD module.
+ *! 30-Oct-2000 kc: Added DCD_AutoRegister function; changed local var. names.
+ *! 29-Sep-2000 kc: Added code review changes (src/reviews/dcd_reviews.txt).
+ *! 06-Sep-2000 jeh Get message segid, message notification type. Added Atoi()
+ *!                 to replace atoi(), until cdb generation can output in
+ *!                 decimal format.
+ *! 26-Jul-2000 kc: Created.
+ *!
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <csl.h>
+#include <mem.h>
+#include <reg.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <cod.h>
+
+/*  ----------------------------------- Others */
+#include <uuidutil.h>
+
+/*  ----------------------------------- This */
+#include <dbdcd.h>
+
+/*  ----------------------------------- Global defines. */
+#define SIGNATURE       0x5f444344	/* "DCD_" (in reverse). */
+
+#define IsValidHandle(h)    (((h) != NULL) && (h->dwSignature == SIGNATURE))
+
+#define MAX_INT2CHAR_LENGTH     16   /* Maximum int2char len of 32 bit int. */
+
+/* Name of section containing dependent libraries */
+#define DEPLIBSECT              ".dspbridge_deplibs"
+
+/* DCD specific structures. */
+struct DCD_MANAGER {
+	u32 dwSignature;	/* Used for object validation.   */
+	struct COD_MANAGER *hCodMgr;	/* Handle to COD manager object. */
+};
+
+/* Global reference variables. */
+static u32 cRefs;
+static u32 cEnumRefs;
+
+extern struct GT_Mask curTrace;
+
+/* helper function prototypes. */
+static s32 Atoi(char *pszBuf);
+
+static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
+				  enum DSP_DCDOBJTYPE objType,
+				  struct DCD_GENERICOBJ *pGenObj);
+
+static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize);
+
+static char DspChar2GppChar(char *pWord, s32 cDspCharSize);
+
+static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
+				IN struct DSP_UUID *pUuid,
+				IN OUT u16 *pNumLibs,
+				OPTIONAL OUT u16 *pNumPersLibs,
+				OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
+				OPTIONAL OUT bool *pPersistentDepLibs,
+				IN enum NLDR_PHASE phase);
+
+/*
+ *  ======== DCD_AutoRegister ========
+ *  Purpose:
+ *      Parses the supplied image and resigsters with DCD.
+ */
+
+DSP_STATUS DCD_AutoRegister(IN struct DCD_MANAGER *hDcdMgr,
+			    IN char *pszCoffPath)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_AutoRegister: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	if (IsValidHandle(hDcdMgr)) {
+		status = DCD_GetObjects(hDcdMgr, pszCoffPath,
+					(DCD_REGISTERFXN)DCD_RegisterObject,
+					(void *)pszCoffPath);
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_AutoRegister: invalid DCD manager handle.\n");
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DCD_AutoUnregister ========
+ *  Purpose:
+ *      Parses the supplied DSP image and unresiters from DCD.
+ */
+DSP_STATUS DCD_AutoUnregister(IN struct DCD_MANAGER *hDcdMgr,
+			     IN char *pszCoffPath)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_AutoUnregister: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	if (IsValidHandle(hDcdMgr)) {
+		status = DCD_GetObjects(hDcdMgr, pszCoffPath,
+				       (DCD_REGISTERFXN)DCD_RegisterObject,
+				       NULL);
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_AutoUnregister: invalid DCD manager"
+			 " handle.\n");
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DCD_CreateManager ========
+ *  Purpose:
+ *      Creates DCD manager.
+ */
+DSP_STATUS DCD_CreateManager(IN char *pszZlDllName,
+			    OUT struct DCD_MANAGER **phDcdMgr)
+{
+	struct COD_MANAGER *hCodMgr;	/* COD manager handle */
+	struct DCD_MANAGER *pDcdMgr = NULL;	/* DCD Manager pointer */
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs >= 0);
+	DBC_Require(phDcdMgr);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_CreateManager: phDcdMgr 0x%x\n",
+		 phDcdMgr);
+
+	status = COD_Create(&hCodMgr, pszZlDllName, NULL);
+	if (DSP_SUCCEEDED(status)) {
+
+		/* Create a DCD object. */
+		MEM_AllocObject(pDcdMgr, struct DCD_MANAGER, SIGNATURE);
+		if (pDcdMgr != NULL) {
+
+			/* Fill out the object. */
+			pDcdMgr->hCodMgr = hCodMgr;
+
+			/* Return handle to this DCD interface. */
+			*phDcdMgr = pDcdMgr;
+
+			GT_2trace(curTrace, GT_5CLASS,
+				 "DCD_CreateManager: pDcdMgr 0x%x, "
+				 " hCodMgr 0x%x", pDcdMgr, hCodMgr);
+		} else {
+			status = DSP_EMEMORY;
+
+			/*
+			 * If allocation of DcdManager object failed, delete the
+			 * COD manager.
+			 */
+			COD_Delete(hCodMgr);
+
+			GT_0trace(curTrace, GT_6CLASS,
+				 "DCD_CreateManager: MEM_AllocObject failed\n");
+		}
+	} else {
+		status = DSP_EFAIL;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_CreateManager: COD_Create failed\n");
+	}
+
+	DBC_Ensure((DSP_SUCCEEDED(status)) || ((hCodMgr == NULL) &&
+		  (status == DSP_EFAIL)) || ((pDcdMgr == NULL) &&
+		  (status == DSP_EMEMORY)));
+
+	return status;
+}
+
+/*
+ *  ======== DCD_DestroyManager ========
+ *  Purpose:
+ *      Frees DCD Manager object.
+ */
+DSP_STATUS DCD_DestroyManager(IN struct DCD_MANAGER *hDcdMgr)
+{
+	struct DCD_MANAGER *pDcdMgr = hDcdMgr;
+	DSP_STATUS status = DSP_EHANDLE;
+
+	DBC_Require(cRefs >= 0);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_DestroyManager: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	if (IsValidHandle(hDcdMgr)) {
+
+		/* Delete the COD manager. */
+		COD_Delete(pDcdMgr->hCodMgr);
+
+		/* Deallocate a DCD manager object. */
+		MEM_FreeObject(pDcdMgr);
+
+		status = DSP_SOK;
+	} else {
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_DestroyManager: invalid DCD manager handle.\n");
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DCD_EnumerateObject ========
+ *  Purpose:
+ *      Enumerates objects in the DCD.
+ */
+DSP_STATUS DCD_EnumerateObject(IN s32 cIndex, IN enum DSP_DCDOBJTYPE objType,
+			       OUT struct DSP_UUID *pUuid)
+{
+	DSP_STATUS status = DSP_SOK;
+	char szRegKey[REG_MAXREGPATHLENGTH];
+	char szValue[REG_MAXREGPATHLENGTH];
+	char szData[REG_MAXREGPATHLENGTH];
+	u32 dwValueSize;
+	u32 dwDataSize;
+	struct DSP_UUID dspUuid;
+	char szObjType[MAX_INT2CHAR_LENGTH];	/* str. rep. of objType. */
+	u32 dwKeyLen = 0;
+
+	DBC_Require(cRefs >= 0);
+	DBC_Require(cIndex >= 0);
+	DBC_Require(pUuid != NULL);
+
+	GT_3trace(curTrace, GT_ENTER,
+		 "DCD_EnumerateObject: cIndex %d, objType %d, "
+		 " pUuid 0x%x\n", cIndex, objType, pUuid);
+
+	if ((cIndex != 0) && (cEnumRefs == 0)) {
+		/*
+		 * If an enumeration is being performed on an index greater
+		 * than zero, then the current cEnumRefs must have been
+		 * incremented to greater than zero.
+		 */
+		status = DSP_ECHANGEDURINGENUM;
+	} else {
+		/* Enumerate a specific key in the registry by index. */
+		dwValueSize = REG_MAXREGPATHLENGTH;
+		dwDataSize = REG_MAXREGPATHLENGTH;
+
+		/*
+		 * Pre-determine final key length. It's length of DCD_REGKEY +
+		 *  "_\0" + length of szObjType string + terminating NULL.
+		 */
+		dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+		DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+
+		/* Create proper REG key; concatenate DCD_REGKEY with
+		 * objType. */
+		CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, "_\0", 2);
+		} else {
+			status = DSP_EFAIL;
+		}
+
+		/* This snprintf is guaranteed not to exceed max size of an
+		 * integer. */
+		status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d",
+				 objType);
+
+		if (status == -1) {
+			status = DSP_EFAIL;
+		} else {
+			status = DSP_SOK;
+			if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
+			   REG_MAXREGPATHLENGTH) {
+				CSL_Strncat(szRegKey, szObjType,
+					   CSL_Strlen(szObjType) + 1);
+			} else {
+				status = DSP_EFAIL;
+			}
+		}
+
+		if (DSP_SUCCEEDED(status)) {
+			status = REG_EnumValue(NULL, cIndex, szRegKey, szValue,
+					      &dwValueSize, szData,
+					      &dwDataSize);
+		}
+
+		if (DSP_SUCCEEDED(status)) {
+			/* Create UUID value using string retrieved from
+			 * registry. */
+			UUID_UuidFromString(szValue, &dspUuid);
+
+			*pUuid = dspUuid;
+
+			/* Increment cEnumRefs to update reference count. */
+			cEnumRefs++;
+
+			status = DSP_SOK;
+		} else if (status == REG_E_NOMOREITEMS) {
+			/* At the end of enumeration. Reset cEnumRefs. */
+			cEnumRefs = 0;
+
+			status = DSP_SENUMCOMPLETE;
+		} else {
+			status = DSP_EFAIL;
+			GT_1trace(curTrace, GT_6CLASS,
+				 "DCD_EnumerateObject: REG_EnumValue"
+				 " failed, status = 0x%x\n", status);
+		}
+	}
+
+	DBC_Ensure(pUuid || (status == DSP_EFAIL));
+
+	return status;
+}
+
+/*
+ *  ======== DCD_Exit ========
+ *  Purpose:
+ *      Discontinue usage of the DCD module.
+ */
+void DCD_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	GT_1trace(curTrace, GT_5CLASS, "DCD_Exit: cRefs 0x%x\n", cRefs);
+
+	cRefs--;
+	if (cRefs == 0) {
+		REG_Exit();
+		COD_Exit();
+		MEM_Exit();
+	}
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== DCD_GetDepLibs ========
+ */
+DSP_STATUS DCD_GetDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+			 IN struct DSP_UUID *pUuid,
+			 u16 numLibs, OUT struct DSP_UUID *pDepLibUuids,
+			 OUT bool *pPersistentDepLibs, IN enum NLDR_PHASE phase)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(IsValidHandle(hDcdMgr));
+	DBC_Require(pUuid != NULL);
+	DBC_Require(pDepLibUuids != NULL);
+	DBC_Require(pPersistentDepLibs != NULL);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_GetDepLibs: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	status = GetDepLibInfo(hDcdMgr, pUuid, &numLibs, NULL, pDepLibUuids,
+			      pPersistentDepLibs, phase);
+
+	return status;
+}
+
+/*
+ *  ======== DCD_GetNumDepLibs ========
+ */
+DSP_STATUS DCD_GetNumDepLibs(IN struct DCD_MANAGER *hDcdMgr,
+			    IN struct DSP_UUID *pUuid, OUT u16 *pNumLibs,
+			    OUT u16 *pNumPersLibs, IN enum NLDR_PHASE phase)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(IsValidHandle(hDcdMgr));
+	DBC_Require(pNumLibs != NULL);
+	DBC_Require(pNumPersLibs != NULL);
+	DBC_Require(pUuid != NULL);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	status = GetDepLibInfo(hDcdMgr, pUuid, pNumLibs, pNumPersLibs,
+			      NULL, NULL, phase);
+
+	return status;
+}
+
+/*
+ *  ======== DCD_GetObjectDef ========
+ *  Purpose:
+ *      Retrieves the properties of a node or processor based on the UUID and
+ *      object type.
+ */
+DSP_STATUS DCD_GetObjectDef(IN struct DCD_MANAGER *hDcdMgr,
+			   IN struct DSP_UUID *pObjUuid,
+			   IN enum DSP_DCDOBJTYPE objType,
+			   OUT struct DCD_GENERICOBJ *pObjDef)
+{
+	struct DCD_MANAGER *pDcdMgr = hDcdMgr;	/* pointer to DCD manager */
+	struct COD_LIBRARYOBJ *lib = NULL;
+	DSP_STATUS status = DSP_SOK;
+	u32 ulAddr = 0;	/* Used by COD_GetSection */
+	u32 ulLen = 0;	/* Used by COD_GetSection */
+	u32 dwBufSize;	/* Used by REG functions */
+	char szRegKey[REG_MAXREGPATHLENGTH];
+	char *szUuid;		/*[MAXUUIDLEN];*/
+	char szRegData[MAXUUIDLEN];
+	char szSectName[MAXUUIDLEN + 2];	/* ".[UUID]\0" */
+	char *pszCoffBuf;
+	u32 dwKeyLen;		/* Len of REG key. */
+	char szObjType[MAX_INT2CHAR_LENGTH];	/* str. rep. of objType. */
+#ifdef _DB_TIOMAP
+	char *pTempCoffBuf;
+#endif
+	DBC_Require(cRefs > 0);
+	DBC_Require(pObjDef != NULL);
+	DBC_Require(pObjUuid != NULL);
+
+	GT_4trace(curTrace, GT_ENTER,
+		 "DCD_GetObjectDef: hDcdMgr 0x%x, " "objUuid"
+		 " 0x%x, objType 0x%x, pObjDef 0x%x\n", hDcdMgr, pObjUuid,
+		 objType, pObjDef);
+	szUuid = (char *)MEM_Calloc(MAXUUIDLEN, MEM_PAGED);
+	if (!szUuid)
+		return status = DSP_EMEMORY;
+
+	if (!IsValidHandle(hDcdMgr)) {
+		status = DSP_EHANDLE;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: invalid "
+			 "DCD manager handle.\n");
+		goto func_end;
+	}
+	 /* Pre-determine final key length. It's length of DCD_REGKEY +
+	 *  "_\0" + length of szObjType string + terminating NULL */
+	dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+	DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+	/* Create proper REG key; concatenate DCD_REGKEY with objType. */
+	CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
+
+	if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
+		CSL_Strncat(szRegKey, "_\0", 2);
+	else
+		status = DSP_EFAIL;
+
+	status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
+	if (status == -1) {
+		status = DSP_EFAIL;
+	} else {
+		status = DSP_SOK;
+
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szObjType,
+				   CSL_Strlen(szObjType) + 1);
+		} else {
+			status = DSP_EFAIL;
+		}
+		/* Create UUID value to set in registry. */
+		UUID_UuidToString(pObjUuid, szUuid, MAXUUIDLEN);
+
+		if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
+		} else {
+			status = DSP_EFAIL;
+		}
+		/* Retrieve paths from the registry based on struct DSP_UUID */
+		dwBufSize = REG_MAXREGPATHLENGTH;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = REG_GetValue(NULL, szRegKey, szRegKey, (u8 *)szRegData,
+				     &dwBufSize);
+	}
+	if (DSP_FAILED(status)) {
+		status = DSP_EUUID;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+			 "REG_GetValue() failed\n");
+		goto func_end;
+	}
+	/* Open COFF file. */
+	status = COD_Open(pDcdMgr->hCodMgr, szRegData, COD_NOLOAD, &lib);
+	if (DSP_FAILED(status)) {
+		status = DSP_EDCDLOADBASE;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+			 "COD_OpenBase() failed\n");
+		goto func_end;
+	}
+	/* Ensure szUuid + 1 is not greater than sizeof szSectName. */
+	DBC_Assert((CSL_Strlen(szUuid) + 1) < sizeof(szSectName));
+	/* Create section name based on node UUID. A period is
+	 * pre-pended to the UUID string to form the section name.
+	 * I.e. ".24BC8D90_BB45_11d4_B756_006008BDB66F" */
+	CSL_Strcpyn(szSectName, ".", 2);
+	CSL_Strncat(szSectName, szUuid, CSL_Strlen(szUuid));
+	/* Get section information. */
+	status = COD_GetSection(lib, szSectName, &ulAddr, &ulLen);
+	if (DSP_FAILED(status)) {
+		status = DSP_EDCDGETSECT;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef:"
+			 " COD_GetSection() failed\n");
+		goto func_end;
+	}
+	/* Allocate zeroed buffer. */
+	pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+#ifdef _DB_TIOMAP
+	pTempCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+
+	if (CSL_Strstr(szRegData, "iva") == NULL) {
+		/* Locate section by objectID and read its content. */
+		status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+	} else {
+		status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+		GT_0trace(curTrace, GT_4CLASS,
+			 "Skipped Byte swap for IVA !!\n");
+	}
+#else
+	status = COD_ReadSection(lib, szSectName, pszCoffBuf, ulLen);
+#endif
+	if (DSP_SUCCEEDED(status)) {
+		/* Compres DSP buffer to conform to PC format. */
+		if (CSL_Strstr(szRegData, "iva") == NULL) {
+			CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+		} else {
+			CompressBuf(pszCoffBuf, ulLen, 1);
+			GT_0trace(curTrace, GT_4CLASS, "Compressing IVA "
+				 "COFF buffer by 1 for IVA !!\n");
+		}
+		/* Parse the content of the COFF buffer. */
+		status = GetAttrsFromBuf(pszCoffBuf, ulLen, objType, pObjDef);
+		if (DSP_FAILED(status)) {
+			status = DSP_EDCDPARSESECT;
+			GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+				 "GetAttrsFromBuf() failed\n");
+		}
+	} else {
+		status = DSP_EDCDREADSECT;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjectDef: "
+			 "COD_ReadSection() failed\n");
+	}
+	/* Free the previously allocated dynamic buffer. */
+	MEM_Free(pszCoffBuf);
+#ifdef _DB_TIOMAP
+	MEM_Free(pTempCoffBuf);
+#endif
+func_end:
+	if (lib)
+		COD_Close(lib);
+
+	if (szUuid)
+		MEM_Free(szUuid);
+	return status;
+}
+
+/*
+ *  ======== DCD_GetObjects ========
+ */
+DSP_STATUS DCD_GetObjects(IN struct DCD_MANAGER *hDcdMgr, IN char *pszCoffPath,
+			 DCD_REGISTERFXN registerFxn, void *handle)
+{
+	struct DCD_MANAGER *pDcdMgr = hDcdMgr;	/* pointer to DCD manager */
+	DSP_STATUS status = DSP_SOK;
+	char *pszCoffBuf;
+	char *pszCur;
+#ifdef _DB_TIOMAP
+	char *pTempCoffBuf;
+#endif
+	struct COD_LIBRARYOBJ *lib = NULL;
+	u32 ulAddr = 0;	/* Used by COD_GetSection */
+	u32 ulLen = 0;	/* Used by COD_GetSection */
+	char seps[] = ":, ";
+	char *pToken = NULL;
+	struct DSP_UUID dspUuid;
+	s32 cObjectType;
+	DBC_Require(cRefs > 0);
+	GT_1trace(curTrace, GT_ENTER,
+		 "DCD_GetObjects: hDcdMgr 0x%x\n", hDcdMgr);
+	if (!IsValidHandle(hDcdMgr)) {
+		status = DSP_EHANDLE;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_GetObjects: invalid DCD manager handle.\n");
+		goto func_end;
+	}
+	/* Open DSP coff file, don't load symbols. */
+	status = COD_Open(pDcdMgr->hCodMgr, pszCoffPath, COD_NOLOAD, &lib);
+	if (DSP_FAILED(status)) {
+		status = DSP_EDCDLOADBASE;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_AutoRegister: COD_Open() failed\n");
+		goto func_cont;
+	}
+	/* Get DCD_RESIGER_SECTION section information. */
+	status = COD_GetSection(lib, DCD_REGISTER_SECTION, &ulAddr, &ulLen);
+	if (DSP_FAILED(status) ||  !(ulLen > 0)) {
+		status = DSP_EDCDNOAUTOREGISTER;
+		GT_0trace(curTrace, GT_6CLASS,
+			 "DCD_GetObjects: COD_GetSection() "
+			 "- no auto register section\n");
+		goto func_cont;
+	}
+	/* Allocate zeroed buffer. */
+	pszCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+#ifdef _DB_TIOMAP
+	pTempCoffBuf = MEM_Calloc(ulLen + 4, MEM_PAGED);
+	if (strstr(pszCoffPath, "iva") == NULL) {
+		/* Locate section by objectID and read its content. */
+		status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
+					pszCoffBuf, ulLen);
+	} else {
+		GT_0trace(curTrace, GT_4CLASS, "Skipped Byte swap for IVA!!\n");
+		status = COD_ReadSection(lib, DCD_REGISTER_SECTION,
+					pszCoffBuf, ulLen);
+	}
+#else
+	status = COD_ReadSection(lib, DCD_REGISTER_SECTION, pszCoffBuf, ulLen);
+#endif
+	if (DSP_SUCCEEDED(status)) {
+		/* Compress DSP buffer to conform to PC format. */
+		GT_0trace(curTrace, GT_4CLASS,
+			 "Successfully read section !!\n");
+		if (strstr(pszCoffPath, "iva") == NULL) {
+			CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+		} else {
+			CompressBuf(pszCoffBuf, ulLen, 1);
+			GT_0trace(curTrace, GT_4CLASS, "Compress COFF buffer "
+				 "with 1 word for IVA !!\n");
+		}
+		/* Read from buffer and register object in buffer. */
+		pToken = CSL_Strtokr(pszCoffBuf, seps, &pszCur);
+		while (pToken != NULL) {
+			/*  Retrieve UUID string. */
+			UUID_UuidFromString(pToken, &dspUuid);
+			/*  Retrieve object type */
+			pToken = CSL_Strtokr(NULL, seps, &pszCur);
+			/*  Retrieve object type */
+			cObjectType = Atoi(pToken);
+			/*
+			 *  Apply registerFxn to the found DCD object.
+			 *  Possible actions include:
+			 *
+			 *  1) Register found DCD object.
+			 *  2) Unregister found DCD object (when handle == NULL)
+			 *  3) Add overlay node.
+			 */
+			GT_1trace(curTrace, GT_4CLASS, "Registering objtype "
+				 "%d \n", cObjectType);
+			status = registerFxn(&dspUuid, cObjectType, handle);
+			if (DSP_SUCCEEDED(status)) {
+				GT_1trace(curTrace, GT_5CLASS,
+					 "DCD_GetObjects: status 0x%x\n",
+					 status);
+			} else {
+				GT_0trace(curTrace, GT_6CLASS,
+					 "DCD_GetObjects: "
+					 "registration() failed\n");
+				/* if error occurs, break from while loop. */
+				break;
+			}
+			/* Get next token */
+			pToken = CSL_Strtokr(NULL, seps, &pszCur);
+		}
+	} else {
+		status = DSP_EDCDREADSECT;
+		GT_0trace(curTrace, GT_6CLASS, "DCD_GetObjects: "
+			 "COD_ReadSection() failed\n");
+	}
+	/* Free the previously allocated dynamic buffer. */
+	MEM_Free(pszCoffBuf);
+#ifdef _DB_TIOMAP
+	MEM_Free(pTempCoffBuf);
+#endif
+func_cont:
+	if (lib)
+		COD_Close(lib);
+
+func_end:
+	return status;
+}
+
+/*
+ *  ======== DCD_GetLibraryName ========
+ *  Purpose:
+ *      Retrieves the library name for the given UUID.
+ *
+ */
+DSP_STATUS DCD_GetLibraryName(IN struct DCD_MANAGER *hDcdMgr,
+			     IN struct DSP_UUID *pUuid,
+			     IN OUT char *pstrLibName, IN OUT u32 *pdwSize,
+			     enum NLDR_PHASE phase, OUT bool *fPhaseSplit)
+{
+	char szRegKey[REG_MAXREGPATHLENGTH];
+	char szUuid[MAXUUIDLEN];
+	u32 dwKeyLen;		/* Len of REG key. */
+	char szObjType[MAX_INT2CHAR_LENGTH];	/* str. rep. of objType. */
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(pUuid != NULL);
+	DBC_Require(pstrLibName != NULL);
+	DBC_Require(pdwSize != NULL);
+	DBC_Require(IsValidHandle(hDcdMgr));
+
+	GT_4trace(curTrace, GT_ENTER,
+		 "DCD_GetLibraryName: hDcdMgr 0x%x, pUuid 0x%x, "
+		 " pstrLibName 0x%x, pdwSize 0x%x\n", hDcdMgr, pUuid,
+		 pstrLibName, pdwSize);
+	/*
+	 *  Pre-determine final key length. It's length of DCD_REGKEY +
+	 *  "_\0" + length of szObjType string + terminating NULL.
+	 */
+	dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+	DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+	/* Create proper REG key; concatenate DCD_REGKEY with objType. */
+	CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
+	if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
+		CSL_Strncat(szRegKey, "_\0", 2);
+	else
+		status = DSP_EFAIL;
+
+	switch (phase) {
+	case NLDR_CREATE:
+		/* create phase type */
+		sprintf(szObjType, "%d", DSP_DCDCREATELIBTYPE);
+		break;
+	case NLDR_EXECUTE:
+		/* execute phase type */
+		sprintf(szObjType, "%d", DSP_DCDEXECUTELIBTYPE);
+		break;
+	case NLDR_DELETE:
+		/* delete phase type */
+		sprintf(szObjType, "%d", DSP_DCDDELETELIBTYPE);
+		break;
+	case NLDR_NOPHASE:
+		/* known to be a dependent library */
+		sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
+		break;
+	default:
+		status = -1;
+		DBC_Assert(false);
+	}
+	if (status == -1) {
+		status = DSP_EFAIL;
+	} else {
+		status = DSP_SOK;
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType))
+		   < REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szObjType,
+				   CSL_Strlen(szObjType) + 1);
+		} else {
+			status = DSP_EFAIL;
+		}
+		/* Create UUID value to find match in registry. */
+		UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+		if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
+		} else {
+			status = DSP_EFAIL;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Retrieve path from the registry based on DSP_UUID */
+		status = REG_GetValue(NULL, szRegKey, szRegKey,
+					(u8 *)pstrLibName, pdwSize);
+	}
+	/* If can't find, phases might be registered as generic LIBRARYTYPE */
+	if (DSP_FAILED(status) && phase != NLDR_NOPHASE) {
+		if (fPhaseSplit)
+			*fPhaseSplit = false;
+
+		CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, "_\0", 2);
+		} else {
+			status = DSP_EFAIL;
+		}
+		sprintf(szObjType, "%d", DSP_DCDLIBRARYTYPE);
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType))
+		   < REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szObjType,
+				   CSL_Strlen(szObjType) + 1);
+		} else {
+			status = DSP_EFAIL;
+		}
+		UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+		if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
+		} else {
+			status = DSP_EFAIL;
+		}
+		status = REG_GetValue(NULL, szRegKey, szRegKey,
+					(u8 *)pstrLibName, pdwSize);
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DCD_Init ========
+ *  Purpose:
+ *      Initialize the DCD module.
+ */
+bool DCD_Init(void)
+{
+	bool fInitMEM;
+	bool fInitREG;
+	bool fInitCOD;
+	bool fInit = true;
+
+	DBC_Require(cRefs >= 0);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_Init: (on enter) cRefs = 0x%x\n",
+		 cRefs);
+
+	if (cRefs == 0) {
+
+		/* Initialize required modules. */
+		fInitMEM = MEM_Init();
+		fInitCOD = COD_Init();
+		fInitREG = REG_Init();
+		if (!fInitMEM || !fInitCOD || !fInitREG) {
+			fInit = false;
+			GT_0trace(curTrace, GT_6CLASS, "DCD_Init failed\n");
+			/* Exit initialized modules. */
+			if (fInitMEM)
+				MEM_Exit();
+
+			if (fInitCOD)
+				COD_Exit();
+
+			if (fInitREG)
+				REG_Exit();
+
+		}
+	}
+
+	if (fInit)
+		cRefs++;
+
+
+	GT_1trace(curTrace, GT_5CLASS, "DCD_Init: (on exit) cRefs = 0x%x\n",
+		 cRefs);
+
+	DBC_Ensure((fInit && (cRefs > 0)) || (!fInit && (cRefs == 0)));
+
+	return fInit;
+}
+
+/*
+ *  ======== DCD_RegisterObject ========
+ *  Purpose:
+ *      Registers a node or a processor with the DCD.
+ *      If pszPathName == NULL, unregister the specified DCD object.
+ */
+DSP_STATUS DCD_RegisterObject(IN struct DSP_UUID *pUuid,
+			     IN enum DSP_DCDOBJTYPE objType,
+			     IN char *pszPathName)
+{
+	DSP_STATUS status = DSP_SOK;
+	char szRegKey[REG_MAXREGPATHLENGTH];
+	char szUuid[MAXUUIDLEN + 1];
+	u32 dwPathSize = 0;
+	u32 dwKeyLen;		/* Len of REG key. */
+	char szObjType[MAX_INT2CHAR_LENGTH];	/* str. rep. of objType. */
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pUuid != NULL);
+	DBC_Require((objType == DSP_DCDNODETYPE) ||
+		   (objType == DSP_DCDPROCESSORTYPE) ||
+		   (objType == DSP_DCDLIBRARYTYPE) ||
+		   (objType == DSP_DCDCREATELIBTYPE) ||
+		   (objType == DSP_DCDEXECUTELIBTYPE) ||
+		   (objType == DSP_DCDDELETELIBTYPE));
+
+	GT_3trace(curTrace, GT_ENTER, "DCD_RegisterObject: object UUID 0x%x, "
+		 "objType %d, szPathName %s\n", pUuid, objType, pszPathName);
+	/*
+	 * Pre-determine final key length. It's length of DCD_REGKEY +
+	 *  "_\0" + length of szObjType string + terminating NULL.
+	 */
+	dwKeyLen = CSL_Strlen(DCD_REGKEY) + 1 + sizeof(szObjType) + 1;
+	DBC_Assert(dwKeyLen < REG_MAXREGPATHLENGTH);
+	/* Create proper REG key; concatenate DCD_REGKEY with objType. */
+	CSL_Strcpyn(szRegKey, DCD_REGKEY, CSL_Strlen(DCD_REGKEY) + 1);
+	if ((CSL_Strlen(szRegKey) + CSL_Strlen("_\0")) < REG_MAXREGPATHLENGTH)
+		CSL_Strncat(szRegKey, "_\0", 2);
+	else
+		status = DSP_EFAIL;
+
+	status = snprintf(szObjType, MAX_INT2CHAR_LENGTH, "%d", objType);
+	if (status == -1) {
+		status = DSP_EFAIL;
+	} else {
+		status = DSP_SOK;
+		if ((CSL_Strlen(szRegKey) + CSL_Strlen(szObjType)) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szObjType,
+				   CSL_Strlen(szObjType) + 1);
+		} else {
+			status = DSP_EFAIL;
+		}
+		/* Create UUID value to set in registry. */
+		UUID_UuidToString(pUuid, szUuid, MAXUUIDLEN);
+		if ((CSL_Strlen(szRegKey) + MAXUUIDLEN) <
+		   REG_MAXREGPATHLENGTH) {
+			CSL_Strncat(szRegKey, szUuid, MAXUUIDLEN);
+		} else {
+			status = DSP_EFAIL;
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/*
+		 * If pszPathName != NULL, perform registration, otherwise,
+		 * perform unregistration.
+		 */
+		if (pszPathName) {
+			/* Add new reg value (UUID+objType) with COFF path
+			 * info. */
+			dwPathSize = CSL_Strlen(pszPathName) + 1;
+			status = REG_SetValue(NULL, szRegKey, szRegKey, REG_SZ,
+					     (u8 *)pszPathName, dwPathSize);
+			GT_3trace(curTrace, GT_6CLASS,
+				 "REG_SetValue  REG_SZ=%d, "
+				 "(u8 *)pszPathName=%s, dwPathSize=%d\n",
+				 REG_SZ, pszPathName, dwPathSize);
+			if (DSP_FAILED(status)) {
+				status = DSP_EFAIL;
+				GT_0trace(curTrace, GT_6CLASS,
+				  "DCD_RegisterObject: REG_SetValue failed!\n");
+			}
+		} else {
+			/* Deregister an existing object. */
+			status = REG_DeleteValue(NULL, szRegKey, szRegKey);
+			if (DSP_FAILED(status)) {
+				status = DSP_EFAIL;
+				GT_0trace(curTrace, GT_6CLASS,
+					"DCD_UnregisterObject: "
+					"REG_DeleteValue failed!\n");
+			}
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/*
+		 *  Because the node database has been updated through a
+		 *  successful object registration/de-registration operation,
+		 *  we need to reset the object enumeration counter to allow
+		 *  current enumerations to reflect this update in the node
+		 *  database.
+		 */
+
+		cEnumRefs = 0;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DCD_UnregisterObject ========
+ *  Call DCD_Register object with pszPathName set to NULL to
+ *  perform actual object de-registration.
+ */
+DSP_STATUS DCD_UnregisterObject(IN struct DSP_UUID *pUuid,
+				IN enum DSP_DCDOBJTYPE objType)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pUuid != NULL);
+	DBC_Require((objType == DSP_DCDNODETYPE) ||
+		   (objType == DSP_DCDPROCESSORTYPE) ||
+		   (objType == DSP_DCDLIBRARYTYPE) ||
+		   (objType == DSP_DCDCREATELIBTYPE) ||
+		   (objType == DSP_DCDEXECUTELIBTYPE) ||
+		   (objType == DSP_DCDDELETELIBTYPE));
+
+	GT_2trace(curTrace, GT_ENTER,
+		 "DCD_UnregisterObject: object UUID 0x%x, "
+		 "objType %d\n", pUuid, objType);
+
+	/*
+	 *  When DCD_RegisterObject is called with NULL as pathname,
+	 *  it indicates an unregister object operation.
+	 */
+	status = DCD_RegisterObject(pUuid, objType, NULL);
+
+	return status;
+}
+
+/*
+ **********************************************************************
+ * DCD Helper Functions
+ **********************************************************************
+ */
+
+/*
+ *  ======== Atoi ========
+ *  Purpose:
+ *      This function converts strings in decimal or hex format to integers.
+ */
+static s32 Atoi(char *pszBuf)
+{
+	s32 result = 0;
+	char *pch = pszBuf;
+	char c;
+	char first;
+	s32 base = 10;
+	s32 len;
+
+	while (isspace(*pch))
+		pch++;
+
+	first = *pch;
+	if (first == '-' || first == '+') {
+		pch++;
+	} else {
+		/* Determine if base 10 or base 16 */
+		len = strlen(pch);
+		if (len  > 1) {
+			c = pch[1];
+			if ((*pch == '0' && (c == 'x' || c == 'X'))) {
+				base = 16;
+				pch += 2;
+			}
+			c = pch[len - 1];
+			if (c == 'h' || c == 'H')
+				base = 16;
+
+		}
+	}
+
+	while (isdigit(c = *pch) || ((base == 16) && isxdigit(c))) {
+		result *= base;
+		if ('A' <= c && c <= 'F') {
+			c = c - 'A' + 10;
+		} else {
+			if ('a' <= c && c <= 'f')
+				c = c - 'a' + 10;
+			else
+				c -= '0';
+
+		}
+		result += c;
+		++pch;
+	}
+
+	return result;
+}
+
+/*
+ *  ======== GetAttrsFromBuf ========
+ *  Purpose:
+ *      Parse the content of a buffer filled with DSP-side data and
+ *      retrieve an object's attributes from it. IMPORTANT: Assume the
+ *      buffer has been converted from DSP format to GPP format.
+ */
+static DSP_STATUS GetAttrsFromBuf(char *pszBuf, u32 ulBufSize,
+				 enum DSP_DCDOBJTYPE objType,
+				 struct DCD_GENERICOBJ *pGenObj)
+{
+	DSP_STATUS status = DSP_SOK;
+	char seps[] = ", ";
+	char *pszCur;
+	char *token;
+	s32 cLen = 0;
+	u32 i = 0;
+#ifdef _DB_TIOMAP
+	s32 iEntry;
+#endif
+
+	DBC_Require(pszBuf != NULL);
+	DBC_Require(ulBufSize != 0);
+	DBC_Require((objType == DSP_DCDNODETYPE)
+		    || (objType == DSP_DCDPROCESSORTYPE));
+	DBC_Require(pGenObj != NULL);
+
+	switch (objType) {
+	case DSP_DCDNODETYPE:
+		/*
+		 * Parse COFF sect buffer to retrieve individual tokens used
+		 * to fill in object attrs.
+		 */
+		token = CSL_Strtokr(pszBuf, seps, &pszCur);
+
+		/* u32 cbStruct */
+		pGenObj->objData.nodeObj.ndbProps.cbStruct =
+				(u32) Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* DSP_UUID uiNodeID */
+		UUID_UuidFromString(token,
+				  &pGenObj->objData.nodeObj.ndbProps.uiNodeID);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* acName */
+		cLen = strlen(token);
+		if (cLen > DSP_MAXNAMELEN - 1)
+			cLen = DSP_MAXNAMELEN - 1;
+
+		CSL_Strcpyn(pGenObj->objData.nodeObj.ndbProps.acName,
+			   token, cLen);
+		pGenObj->objData.nodeObj.ndbProps.acName[cLen] = '\0';
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		/* u32 uNodeType */
+		pGenObj->objData.nodeObj.ndbProps.uNodeType = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		/* u32 bCacheOnGPP */
+		pGenObj->objData.nodeObj.ndbProps.bCacheOnGPP = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		/* DSP_RESOURCEREQMTS dspResourceReqmts */
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.cbStruct =
+				(u32) Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uStaticDataSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uGlobalDataSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uProgramMemSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uWCExecutionTime = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uWCPeriod = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uWCDeadline = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uAvgExectionTime = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.nodeObj.ndbProps.dspResourceReqmts.
+			uMinimumPeriod = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* s32 iPriority */
+		pGenObj->objData.nodeObj.ndbProps.iPriority = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uStackSize */
+		pGenObj->objData.nodeObj.ndbProps.uStackSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uSysStackSize */
+		pGenObj->objData.nodeObj.ndbProps.uSysStackSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uStackSeg */
+		pGenObj->objData.nodeObj.ndbProps.uStackSeg = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uMessageDepth */
+		pGenObj->objData.nodeObj.ndbProps.uMessageDepth = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uNumInputStreams */
+		pGenObj->objData.nodeObj.ndbProps.uNumInputStreams =
+			Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uNumOutputStreams */
+		pGenObj->objData.nodeObj.ndbProps.uNumOutputStreams =
+			Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* u32 uTimeout */
+		pGenObj->objData.nodeObj.ndbProps.uTimeout =
+			Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* char * pstrCreatePhaseFxn */
+		cLen = strlen(token);
+		pGenObj->objData.nodeObj.pstrCreatePhaseFxn =
+			MEM_Calloc(cLen + 1, MEM_PAGED);
+		strncpy(pGenObj->objData.nodeObj.pstrCreatePhaseFxn,
+			token, cLen);
+		pGenObj->objData.nodeObj.pstrCreatePhaseFxn[cLen] = '\0';
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* char * pstrExecutePhaseFxn */
+		cLen = strlen(token);
+		pGenObj->objData.nodeObj.pstrExecutePhaseFxn =
+			 MEM_Calloc(cLen + 1, MEM_PAGED);
+		strncpy(pGenObj->objData.nodeObj.pstrExecutePhaseFxn,
+			token, cLen);
+		pGenObj->objData.nodeObj.pstrExecutePhaseFxn[cLen] = '\0';
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* char * pstrDeletePhaseFxn */
+		cLen = strlen(token);
+		pGenObj->objData.nodeObj.pstrDeletePhaseFxn =
+			MEM_Calloc(cLen + 1, MEM_PAGED);
+		strncpy(pGenObj->objData.nodeObj.pstrDeletePhaseFxn,
+			token, cLen);
+		pGenObj->objData.nodeObj.pstrDeletePhaseFxn[cLen] = '\0';
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* Segment id for message buffers */
+		pGenObj->objData.nodeObj.uMsgSegid = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* Message notification type */
+		pGenObj->objData.nodeObj.uMsgNotifyType = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		/* char * pstrIAlgName */
+		if (token) {
+			cLen = strlen(token);
+			pGenObj->objData.nodeObj.pstrIAlgName =
+				MEM_Calloc(cLen + 1, MEM_PAGED);
+			strncpy(pGenObj->objData.nodeObj.pstrIAlgName,
+				token, cLen);
+			pGenObj->objData.nodeObj.pstrIAlgName[cLen] = '\0';
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+		}
+
+		/* Load type (static, dynamic, or overlay) */
+		if (token) {
+			pGenObj->objData.nodeObj.usLoadType = Atoi(token);
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+		}
+
+		/* Dynamic load data requirements */
+		if (token) {
+			pGenObj->objData.nodeObj.ulDataMemSegMask = Atoi(token);
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+		}
+
+		/* Dynamic load code requirements */
+		if (token) {
+			pGenObj->objData.nodeObj.ulCodeMemSegMask = Atoi(token);
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+		}
+
+		/* Extract node profiles into node properties */
+		if (token) {
+
+			pGenObj->objData.nodeObj.ndbProps.uCountProfiles =
+				Atoi(token);
+			for (i = 0; i < pGenObj->objData.nodeObj.ndbProps.
+			    uCountProfiles; i++) {
+				token = CSL_Strtokr(NULL, seps, &pszCur);
+				if (token) {
+					/* Heap Size for the node */
+					pGenObj->objData.nodeObj.ndbProps.
+						aProfiles[i].ulHeapSize =
+						Atoi(token);
+				}
+			}
+		}
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+		if (token) {
+			pGenObj->objData.nodeObj.ndbProps.uStackSegName =
+				(u32)(token);
+		}
+
+		break;
+
+	case DSP_DCDPROCESSORTYPE:
+		/*
+		 * Parse COFF sect buffer to retrieve individual tokens used
+		 * to fill in object attrs.
+		 */
+		token = CSL_Strtokr(pszBuf, seps, &pszCur);
+
+		pGenObj->objData.procObj.cbStruct = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.uProcessorFamily = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.uProcessorType = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.uClockRate = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.ulInternalMemSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.ulExternalMemSize = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.uProcessorID = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.tyRunningRTOS = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.nNodeMinPriority = Atoi(token);
+		token = CSL_Strtokr(NULL, seps, &pszCur);
+
+		pGenObj->objData.procObj.nNodeMaxPriority = Atoi(token);
+
+#ifdef _DB_TIOMAP
+		/* Proc object may contain additional(extended) attributes. */
+		/* attr must match proc.hxx */
+		for (iEntry = 0; iEntry < 7; iEntry++) {
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+			pGenObj->objData.extProcObj.tyTlb[iEntry].ulGppPhys =
+				Atoi(token);
+
+			token = CSL_Strtokr(NULL, seps, &pszCur);
+			pGenObj->objData.extProcObj.tyTlb[iEntry].ulDspVirt =
+				Atoi(token);
+		}
+#endif
+
+		break;
+
+	default:
+		status = DSP_EFAIL;
+		break;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== CompressBuffer ========
+ *  Purpose:
+ *      Compress the DSP buffer, if necessary, to conform to PC format.
+ */
+static void CompressBuf(char *pszBuf, u32 ulBufSize, s32 cCharSize)
+{
+	char *p;
+	char ch;
+	char *q;
+
+	p = pszBuf;
+	if (p == NULL)
+		return;
+
+	for (q = pszBuf; q < (pszBuf + ulBufSize);) {
+
+		ch = DspChar2GppChar(q, cCharSize);
+		if (ch == '\\') {
+			q += cCharSize;
+			ch = DspChar2GppChar(q, cCharSize);
+			switch (ch) {
+			case 't':
+				*p = '\t';
+				break;
+
+			case 'n':
+				*p = '\n';
+				break;
+
+			case 'r':
+				*p = '\r';
+				break;
+
+			case '0':
+				*p = '\0';
+				break;
+
+			default:
+				*p = ch;
+				break;
+			}
+		} else {
+			*p = ch;
+		}
+		p++;
+		q += cCharSize;
+	}
+
+	/* NULL out remainder of buffer. */
+	while (p < q)
+		*p++ = '\0';
+
+}
+
+/*
+ *  ======== DspChar2GppChar ========
+ *  Purpose:
+ *      Convert DSP char to host GPP char in a portable manner
+ */
+static char DspChar2GppChar(char *pWord, s32 cDspCharSize)
+{
+	char ch = '\0';
+	char *chSrc;
+	s32 i;
+
+	for (chSrc = pWord, i = cDspCharSize; i > 0; i--)
+		ch |= *chSrc++;
+
+	return ch;
+}
+
+/*
+ *  ======== GetDepLibInfo ========
+ */
+static DSP_STATUS GetDepLibInfo(IN struct DCD_MANAGER *hDcdMgr,
+				IN struct DSP_UUID *pUuid,
+				IN OUT u16 *pNumLibs,
+				OPTIONAL OUT u16 *pNumPersLibs,
+				OPTIONAL OUT struct DSP_UUID *pDepLibUuids,
+				OPTIONAL OUT bool *pPersistentDepLibs,
+				enum NLDR_PHASE phase)
+{
+	struct DCD_MANAGER *pDcdMgr = hDcdMgr;	/* pointer to DCD manager */
+	char *pszCoffBuf = NULL;
+	char *pszCur;
+	char *pszFileName = NULL;
+	struct COD_LIBRARYOBJ *lib = NULL;
+#ifdef _DB_TIOMAP
+	char *pTempCoffBuf;
+#endif
+	u32 ulAddr = 0;	/* Used by COD_GetSection */
+	u32 ulLen = 0;	/* Used by COD_GetSection */
+	u32 dwDataSize = COD_MAXPATHLENGTH;
+	char seps[] = ", ";
+	char *pToken = NULL;
+	bool fGetUuids = (pDepLibUuids != NULL);
+	u16 nDepLibs = 0;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+
+	DBC_Require(IsValidHandle(hDcdMgr));
+	DBC_Require(pNumLibs != NULL);
+	DBC_Require(pUuid != NULL);
+
+	GT_1trace(curTrace, GT_ENTER, "DCD_GetNumDepLibs: hDcdMgr 0x%x\n",
+		 hDcdMgr);
+
+	/*  Initialize to 0 dependent libraries, if only counting number of
+	 *  dependent libraries */
+	if (!fGetUuids) {
+		*pNumLibs = 0;
+		*pNumPersLibs = 0;
+	}
+
+	/* Allocate a buffer for file name */
+	pszFileName = MEM_Calloc(dwDataSize, MEM_PAGED);
+	if (pszFileName == NULL) {
+		status = DSP_EMEMORY;
+	} else {
+		/* Get the name of the library */
+		status = DCD_GetLibraryName(hDcdMgr, pUuid, pszFileName,
+			 &dwDataSize, phase, NULL);
+	}
+	/* Open the library */
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_Open(pDcdMgr->hCodMgr, pszFileName,
+				 COD_NOLOAD, &lib);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Get dependent library section information. */
+		status = COD_GetSection(lib, DEPLIBSECT, &ulAddr, &ulLen);
+
+		if (DSP_FAILED(status)) {
+			/* Ok, no dependent libraries */
+			ulLen = 0;
+			status = DSP_SNODEPENDENTLIBS;
+		}
+	}
+
+	if (DSP_FAILED(status) || !(ulLen > 0))
+		goto func_cont;
+
+	/* Allocate zeroed buffer. */
+	pszCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
+	if (pszCoffBuf == NULL)
+		status = DSP_EMEMORY;
+
+#ifdef _DB_TIOMAP
+	pTempCoffBuf = MEM_Calloc(ulLen, MEM_PAGED);
+	if (pTempCoffBuf == NULL)
+		status = DSP_EMEMORY;
+
+#endif
+	/* Read section contents. */
+	status = COD_ReadSection(lib, DEPLIBSECT, pszCoffBuf, ulLen);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Compress and format DSP buffer to conform to PC format. */
+	CompressBuf(pszCoffBuf, ulLen, DSPWORDSIZE);
+	/* Read from buffer */
+	pToken = CSL_Strtokr(pszCoffBuf, seps, &pszCur);
+	while (pToken != NULL) {
+		if (fGetUuids) {
+			if (nDepLibs >= *pNumLibs) {
+				/* Gone beyond the limit */
+				break;
+			} else {
+				/* Retrieve UUID string. */
+				UUID_UuidFromString(pToken,
+						 &(pDepLibUuids[nDepLibs]));
+				/* Is this library persistent? */
+				pToken = CSL_Strtokr(NULL, seps, &pszCur);
+				pPersistentDepLibs[nDepLibs] = Atoi(pToken);
+				nDepLibs++;
+			}
+		} else {
+			/* Advanc to next token */
+			pToken = CSL_Strtokr(NULL, seps, &pszCur);
+			if (Atoi(pToken))
+				(*pNumPersLibs)++;
+
+			/* Just counting number of dependent libraries */
+			(*pNumLibs)++;
+		}
+		/* Get next token */
+		pToken = CSL_Strtokr(NULL, seps, &pszCur);
+	}
+func_cont:
+	if (lib)
+		COD_Close(lib);
+
+	/* Free previously allocated dynamic buffers. */
+	if (pszFileName)
+		MEM_Free(pszFileName);
+
+	if (pszCoffBuf)
+		MEM_Free(pszCoffBuf);
+
+	return status;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/disp.c b/drivers/dsp/bridge/rmgr/disp.c
new file mode 100644
index 0000000..759cc5c
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/disp.c
@@ -0,0 +1,915 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/disp.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software;  you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== disp.c ========
+ *
+ *  Description:
+ *      Node Dispatcher interface. Communicates with Resource Manager Server
+ *      (RMS) on DSP. Access to RMS is synchronized in NODE.
+ *
+ *  Public Functions:
+ *      DISP_Create
+ *      DISP_Delete
+ *      DISP_Exit
+ *      DISP_Init
+ *      DISP_NodeChangePriority
+ *      DISP_NodeCreate
+ *      DISP_NodeDelete
+ *      DISP_NodePause
+ *      DISP_NodeRun
+ *
+ *! Revision History:
+ *! =================
+ *! 18-Feb-2003 vp      Code review updates
+ *! 18-Oct-2002 vp      Ported to Linux platform
+ *! 16-May-2002 jeh     Added DISP_DoCinit().
+ *! 24-Apr-2002 jeh     Added DISP_MemWrite().
+ *! 13-Feb-2002 jeh     Pass system stack size to RMS.
+ *! 16-Jan-2002  ag     Added bufsize param to _ChnlAddIOReq() fxn
+ *! 10-May-2001 jeh     Code Review cleanup.
+ *! 26-Sep-2000 jeh     Fixed status values in SendMessage().
+ *! 19-Jun-2000 jeh     Created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <gt.h>
+#include <dbc.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <dev.h>
+#include <mem.h>
+#include <sync.h>
+#include <csl.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmd.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+#include <chnldefs.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <nodedefs.h>
+#include <nodepriv.h>
+#include <rms_sh.h>
+
+/*  ----------------------------------- This */
+#include <disp.h>
+
+#define DISP_SIGNATURE       0x50534944	/* "PSID" */
+
+/* Size of a reply from RMS */
+#define REPLYSIZE (3 * sizeof(RMS_WORD))
+
+/* Reserved channel offsets for communication with RMS */
+#define CHNLTORMSOFFSET       0
+#define CHNLFROMRMSOFFSET     1
+
+#define CHNLIOREQS      1
+
+#define SwapWord(x)     (((u32)(x) >> 16) | ((u32)(x) << 16))
+
+/*
+ *  ======== DISP_OBJECT ========
+ */
+struct DISP_OBJECT {
+	u32 dwSignature; 	/* Used for object validation */
+	struct DEV_OBJECT *hDevObject; 	/* Device for this processor */
+	struct WMD_DRV_INTERFACE *pIntfFxns; 	/* Function interface to WMD */
+	struct CHNL_MGR *hChnlMgr; 	/* Channel manager */
+	struct CHNL_OBJECT *hChnlToDsp;   /* Channel for commands to RMS */
+	struct CHNL_OBJECT *hChnlFromDsp;   /* Channel for replies from RMS */
+	u8 *pBuf; 		/* Buffer for commands, replies */
+	u32 ulBufsize; 	/* pBuf size in bytes */
+	u32 ulBufsizeRMS; 	/* pBuf size in RMS words */
+	u32 uCharSize; 		/* Size of DSP character */
+	u32 uWordSize; 		/* Size of DSP word */
+	u32 uDataMauSize; 	/* Size of DSP Data MAU */
+};
+
+static u32 cRefs;
+
+/* Debug msgs: */
+#if GT_TRACE
+static struct GT_Mask DISP_DebugMask = { NULL, NULL };
+#endif
+
+static void DeleteDisp(struct DISP_OBJECT *hDisp);
+static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
+				struct NODE_STRMDEF strmDef, u32 max,
+				u32 uCharsInRMSWord);
+static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
+			     u32 ulBytes, OUT u32 *pdwArg);
+
+/*
+ *  ======== DISP_Create ========
+ *  Create a NODE Dispatcher object.
+ */
+DSP_STATUS DISP_Create(OUT struct DISP_OBJECT **phDispObject,
+		      struct DEV_OBJECT *hDevObject,
+		      IN CONST struct DISP_ATTRS *pDispAttrs)
+{
+	struct DISP_OBJECT *pDisp;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	u32 ulChnlId;
+	struct CHNL_ATTRS chnlAttrs;
+	DSP_STATUS status = DSP_SOK;
+	u32 devType;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(phDispObject != NULL);
+	DBC_Require(pDispAttrs != NULL);
+	DBC_Require(hDevObject != NULL);
+
+	GT_3trace(DISP_DebugMask, GT_ENTER, "DISP_Create: phDispObject: 0x%x\t"
+		 "hDevObject: 0x%x\tpDispAttrs: 0x%x\n", phDispObject,
+		 hDevObject, pDispAttrs);
+
+	*phDispObject = NULL;
+
+	/* Allocate Node Dispatcher object */
+	MEM_AllocObject(pDisp, struct DISP_OBJECT, DISP_SIGNATURE);
+	if (pDisp == NULL) {
+		status = DSP_EMEMORY;
+		GT_0trace(DISP_DebugMask, GT_6CLASS,
+			 "DISP_Create: MEM_AllocObject() failed!\n");
+	} else {
+		pDisp->hDevObject = hDevObject;
+	}
+
+	/* Get Channel manager and WMD function interface */
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetChnlMgr(hDevObject, &(pDisp->hChnlMgr));
+		if (DSP_SUCCEEDED(status)) {
+			(void) DEV_GetIntfFxns(hDevObject, &pIntfFxns);
+			pDisp->pIntfFxns = pIntfFxns;
+		} else {
+			GT_1trace(DISP_DebugMask, GT_6CLASS,
+				 "DISP_Create: Failed to get "
+				 "channel manager! status = 0x%x\n", status);
+		}
+	}
+
+	/* check device type and decide if streams or messag'ing is used for
+	 * RMS/EDS */
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	status = DEV_GetDevType(hDevObject, &devType);
+	GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP for "
+		 "device = 0x%x\n", devType);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	if (devType != DSP_UNIT) {
+		GT_0trace(DISP_DebugMask, GT_6CLASS,
+			 "DISP_Create: Unkown device "
+			 "type in Device object !! \n");
+		status = DSP_EFAIL;
+		goto func_cont;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pDisp->uCharSize = DSPWORDSIZE;
+		pDisp->uWordSize = DSPWORDSIZE;
+		pDisp->uDataMauSize = DSPWORDSIZE;
+		/* Open channels for communicating with the RMS */
+		chnlAttrs.uIOReqs = CHNLIOREQS;
+		chnlAttrs.hEvent = NULL;
+		ulChnlId = pDispAttrs->ulChnlOffset + CHNLTORMSOFFSET;
+		status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlToDsp),
+			 pDisp->hChnlMgr, CHNL_MODETODSP, ulChnlId, &chnlAttrs);
+		if (DSP_FAILED(status)) {
+			GT_2trace(DISP_DebugMask, GT_6CLASS,
+				 "DISP_Create:  Channel to RMS "
+				 "open failed, chnl id = %d, status = 0x%x\n",
+				 ulChnlId, status);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		ulChnlId = pDispAttrs->ulChnlOffset + CHNLFROMRMSOFFSET;
+		status = (*pIntfFxns->pfnChnlOpen)(&(pDisp->hChnlFromDsp),
+			 pDisp->hChnlMgr, CHNL_MODEFROMDSP, ulChnlId,
+			 &chnlAttrs);
+		if (DSP_FAILED(status)) {
+			GT_2trace(DISP_DebugMask, GT_6CLASS,
+				 "DISP_Create: Channel from RMS "
+				 "open failed, chnl id = %d, status = 0x%x\n",
+				 ulChnlId, status);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Allocate buffer for commands, replies */
+		pDisp->ulBufsize = pDispAttrs->ulChnlBufSize;
+		pDisp->ulBufsizeRMS = RMS_COMMANDBUFSIZE;
+		pDisp->pBuf = MEM_Calloc(pDisp->ulBufsize, MEM_PAGED);
+		if (pDisp->pBuf == NULL) {
+			status = DSP_EMEMORY;
+			GT_0trace(DISP_DebugMask, GT_6CLASS,
+				 "DISP_Create: Failed "
+				 "to allocate channel buffer!\n");
+		}
+	}
+func_cont:
+	if (DSP_SUCCEEDED(status))
+		*phDispObject = pDisp;
+	else
+		DeleteDisp(pDisp);
+
+	DBC_Ensure(((DSP_FAILED(status)) && ((*phDispObject == NULL))) ||
+		  ((DSP_SUCCEEDED(status)) &&
+		  (MEM_IsValidHandle((*phDispObject), DISP_SIGNATURE))));
+	return status;
+}
+
+/*
+ *  ======== DISP_Delete ========
+ *  Delete the NODE Dispatcher.
+ */
+void DISP_Delete(struct DISP_OBJECT *hDisp)
+{
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+
+	GT_1trace(DISP_DebugMask, GT_ENTER,
+		 "DISP_Delete: hDisp: 0x%x\n", hDisp);
+
+	DeleteDisp(hDisp);
+
+	DBC_Ensure(!MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+}
+
+/*
+ *  ======== DISP_Exit ========
+ *  Discontinue usage of DISP module.
+ */
+void DISP_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(DISP_DebugMask, GT_5CLASS,
+		 "Entered DISP_Exit, ref count:  0x%x\n", cRefs);
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== DISP_Init ========
+ *  Initialize the DISP module.
+ */
+bool DISP_Init(void)
+{
+	bool fRetVal = true;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+		DBC_Assert(!DISP_DebugMask.flags);
+		GT_create(&DISP_DebugMask, "DI");  /* "DI" for DIspatcher */
+	}
+
+	if (fRetVal)
+		cRefs++;
+
+	GT_1trace(DISP_DebugMask, GT_5CLASS,
+		 "DISP_Init(), ref count:  0x%x\n", cRefs);
+
+	DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+	return fRetVal;
+}
+
+/*
+ *  ======== DISP_NodeChangePriority ========
+ *  Change the priority of a node currently running on the target.
+ */
+DSP_STATUS DISP_NodeChangePriority(struct DISP_OBJECT *hDisp,
+				  struct NODE_OBJECT *hNode,
+				  u32 ulRMSFxn, NODE_ENV nodeEnv,
+				  s32 nPriority)
+{
+	u32 dwArg;
+	struct RMS_Command *pCommand;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+	DBC_Require(hNode != NULL);
+
+	GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeChangePriority: hDisp: "
+		"0x%x\thNode: 0x%x\tulRMSFxn: 0x%x\tnodeEnv: 0x%x\tnPriority\n",
+		hDisp, hNode, ulRMSFxn, nodeEnv, nPriority);
+
+	/* Send message to RMS to change priority */
+	pCommand = (struct RMS_Command *)(hDisp->pBuf);
+	pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+	pCommand->arg1 = (RMS_WORD)nodeEnv;
+	pCommand->arg2 = nPriority;
+	status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+		 sizeof(struct RMS_Command), &dwArg);
+	if (DSP_FAILED(status)) {
+		GT_1trace(DISP_DebugMask, GT_6CLASS,
+			 "DISP_NodeChangePriority failed! "
+			 "status = 0x%x\n", status);
+	}
+	return status;
+}
+
+/*
+ *  ======== DISP_NodeCreate ========
+ *  Create a node on the DSP by remotely calling the node's create function.
+ */
+DSP_STATUS DISP_NodeCreate(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+			  u32 ulRMSFxn, u32 ulCreateFxn,
+			  IN CONST struct NODE_CREATEARGS *pArgs,
+			  OUT NODE_ENV *pNodeEnv)
+{
+	struct NODE_MSGARGS msgArgs;
+	struct NODE_TASKARGS taskArgs;
+	struct RMS_Command *pCommand;
+	struct RMS_MsgArgs *pMsgArgs;
+	struct RMS_MoreTaskArgs *pMoreTaskArgs;
+	enum NODE_TYPE nodeType;
+	u32 dwLength;
+	RMS_WORD *pdwBuf = NULL;
+	u32 ulBytes;
+	u32 i;
+	u32 total;
+	u32 uCharsInRMSWord;
+	s32 taskArgsOffset;
+	s32 sioInDefOffset;
+	s32 sioOutDefOffset;
+	s32 sioDefsOffset;
+	s32 argsOffset = -1;
+	s32 offset;
+	struct NODE_STRMDEF strmDef;
+	u32 max;
+	DSP_STATUS status = DSP_SOK;
+	struct DSP_NODEINFO nodeInfo;
+	u32 devType;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+	DBC_Require(hNode != NULL);
+	DBC_Require(NODE_GetType(hNode) != NODE_DEVICE);
+	DBC_Require(pNodeEnv != NULL);
+
+	GT_6trace(DISP_DebugMask, GT_ENTER,
+	     "DISP_NodeCreate: hDisp: 0x%x\thNode:"
+	     " 0x%x\tulRMSFxn: 0x%x\tulCreateFxn: 0x%x\tpArgs: 0x%x\tpNodeEnv:"
+	     " 0x%x\n", hDisp, hNode, ulRMSFxn, ulCreateFxn, pArgs, pNodeEnv);
+
+	status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+	GT_1trace(DISP_DebugMask, GT_6CLASS, "DISP_Create: Creating DISP "
+		 "for device = 0x%x\n", devType);
+
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	if (devType != DSP_UNIT) {
+		GT_1trace(DISP_DebugMask, GT_7CLASS,
+			 "DISP_NodeCreate unknown device "
+			 "type = 0x%x\n", devType);
+		goto func_end;
+	}
+	DBC_Require(pArgs != NULL);
+	nodeType = NODE_GetType(hNode);
+	msgArgs = pArgs->asa.msgArgs;
+	max = hDisp->ulBufsizeRMS;    /*Max # of RMS words that can be sent */
+	DBC_Assert(max == RMS_COMMANDBUFSIZE);
+	uCharsInRMSWord = sizeof(RMS_WORD) / hDisp->uCharSize;
+	/* Number of RMS words needed to hold arg data */
+	dwLength = (msgArgs.uArgLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
+	/* Make sure msg args and command fit in buffer */
+	total = sizeof(struct RMS_Command) / sizeof(RMS_WORD) +
+		sizeof(struct RMS_MsgArgs)
+		/ sizeof(RMS_WORD)  - 1 + dwLength;
+	if (total >= max) {
+		status = DSP_EFAIL;
+		GT_2trace(DISP_DebugMask, GT_6CLASS,
+			"DISP_NodeCreate: Message args too"
+			" large for buffer! Message args size = %d, max = %d\n",
+			total, max);
+	}
+	/*
+	 *  Fill in buffer to send to RMS.
+	 *  The buffer will have the following  format:
+	 *
+	 *  RMS command:
+	 *      Address of RMS_CreateNode()
+	 *      Address of node's create function
+	 *      dummy argument
+	 *      node type
+	 *
+	 *  Message Args:
+	 *      max number of messages
+	 *      segid for message buffer allocation
+	 *      notification type to use when message is received
+	 *      length of message arg data
+	 *      message args data
+	 *
+	 *  Task Args (if task or socket node):
+	 *      priority
+	 *      stack size
+	 *      system stack size
+	 *      stack segment
+	 *      misc
+	 *      number of input streams
+	 *      pSTRMInDef[] - offsets of STRM definitions for input streams
+	 *      number of output streams
+	 *      pSTRMOutDef[] - offsets of STRM definitions for output
+	 *      streams
+	 *      STRMInDef[] - array of STRM definitions for input streams
+	 *      STRMOutDef[] - array of STRM definitions for output streams
+	 *
+	 *  Socket Args (if DAIS socket node):
+	 *
+	 */
+	if (DSP_SUCCEEDED(status)) {
+		total = 0; 	/* Total number of words in buffer so far */
+		pdwBuf = (RMS_WORD *)hDisp->pBuf;
+		pCommand = (struct RMS_Command *)pdwBuf;
+		pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+		pCommand->arg1 = (RMS_WORD)(ulCreateFxn);
+		if (NODE_GetLoadType(hNode) == NLDR_DYNAMICLOAD) {
+			/* Flush ICACHE on Load */
+			pCommand->arg2 = 1; 	/* dummy argument */
+		} else {
+			/* Do not flush ICACHE */
+			pCommand->arg2 = 0; 	/* dummy argument */
+		}
+		pCommand->data = NODE_GetType(hNode);
+		/*
+		 *  argsOffset is the offset of the data field in struct
+		 *  RMS_Command structure. We need this to calculate stream
+		 *  definition offsets.
+		 */
+		argsOffset = 3;
+		total += sizeof(struct RMS_Command) / sizeof(RMS_WORD);
+		/* Message args */
+		pMsgArgs = (struct RMS_MsgArgs *) (pdwBuf + total);
+		pMsgArgs->maxMessages = msgArgs.uMaxMessages;
+		pMsgArgs->segid = msgArgs.uSegid;
+		pMsgArgs->notifyType = msgArgs.uNotifyType;
+		pMsgArgs->argLength = msgArgs.uArgLength;
+		total += sizeof(struct RMS_MsgArgs) / sizeof(RMS_WORD) - 1;
+		memcpy(pdwBuf + total, msgArgs.pData, msgArgs.uArgLength);
+		total += dwLength;
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* If node is a task node, copy task create arguments into  buffer */
+	if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
+		taskArgs = pArgs->asa.taskArgs;
+		taskArgsOffset = total;
+		total += sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD) +
+			1 + taskArgs.uNumInputs + taskArgs.uNumOutputs;
+		/* Copy task arguments */
+		if (total < max) {
+			total = taskArgsOffset;
+			pMoreTaskArgs = (struct RMS_MoreTaskArgs *)(pdwBuf +
+					total);
+			/*
+			 * Get some important info about the node. Note that we
+			 * don't just reach into the hNode struct because
+			 * that would break the node object's abstraction.
+			 */
+			GetNodeInfo(hNode, &nodeInfo);
+			GT_2trace(DISP_DebugMask, GT_ENTER,
+				 "uExecutionPriority %x, nPriority %x\n",
+				 nodeInfo.uExecutionPriority,
+				 taskArgs.nPriority);
+			pMoreTaskArgs->priority = nodeInfo.uExecutionPriority;
+			pMoreTaskArgs->stackSize = taskArgs.uStackSize;
+			pMoreTaskArgs->sysstackSize = taskArgs.uSysStackSize;
+			pMoreTaskArgs->stackSeg = taskArgs.uStackSeg;
+			pMoreTaskArgs->heapAddr = taskArgs.uDSPHeapAddr;
+			pMoreTaskArgs->heapSize = taskArgs.uHeapSize;
+			pMoreTaskArgs->misc = taskArgs.ulDaisArg;
+			pMoreTaskArgs->numInputStreams = taskArgs.uNumInputs;
+			total +=
+			    sizeof(struct RMS_MoreTaskArgs) / sizeof(RMS_WORD);
+			GT_2trace(DISP_DebugMask, GT_7CLASS,
+				 "DISP::::uDSPHeapAddr %x, "
+				 "uHeapSize %x\n", taskArgs.uDSPHeapAddr,
+				 taskArgs.uHeapSize);
+			/* Keep track of pSIOInDef[] and pSIOOutDef[]
+			 * positions in the buffer, since this needs to be
+			 * filled in later.  */
+			sioInDefOffset = total;
+			total += taskArgs.uNumInputs;
+			pdwBuf[total++] = taskArgs.uNumOutputs;
+			sioOutDefOffset = total;
+			total += taskArgs.uNumOutputs;
+			sioDefsOffset = total;
+			/* Fill SIO defs and offsets */
+			offset = sioDefsOffset;
+			for (i = 0; i < taskArgs.uNumInputs; i++) {
+				if (DSP_FAILED(status))
+					break;
+
+				pdwBuf[sioInDefOffset + i] =
+					(offset - argsOffset)
+					* (sizeof(RMS_WORD) / DSPWORDSIZE);
+				strmDef = taskArgs.strmInDef[i];
+				status = FillStreamDef(pdwBuf, &total, offset,
+					 strmDef, max, uCharsInRMSWord);
+				offset = total;
+			}
+			for (i = 0;  (i < taskArgs.uNumOutputs) &&
+			    (DSP_SUCCEEDED(status)); i++) {
+				pdwBuf[sioOutDefOffset + i] =
+					(offset - argsOffset)
+					* (sizeof(RMS_WORD) / DSPWORDSIZE);
+				strmDef = taskArgs.strmOutDef[i];
+				status = FillStreamDef(pdwBuf, &total, offset,
+					 strmDef, max, uCharsInRMSWord);
+				offset = total;
+			}
+			if (DSP_FAILED(status)) {
+				GT_2trace(DISP_DebugMask, GT_6CLASS,
+				      "DISP_NodeCreate: Message"
+				      " args to large for buffer! Message args"
+				      " size = %d, max = %d\n", total, max);
+			}
+		} else {
+			/* Args won't fit */
+			status = DSP_EFAIL;
+			GT_2trace(DISP_DebugMask, GT_6CLASS,
+				 "DISP_NodeCreate: Message args "
+				 " too large for buffer! Message args size = %d"
+				 ", max = %d\n", total, max);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		ulBytes = total * sizeof(RMS_WORD);
+		DBC_Assert(ulBytes < (RMS_COMMANDBUFSIZE * sizeof(RMS_WORD)));
+		status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+			 ulBytes, pNodeEnv);
+		if (DSP_FAILED(status)) {
+			GT_1trace(DISP_DebugMask, GT_6CLASS,
+				  "DISP_NodeCreate  failed! "
+				  "status = 0x%x\n", status);
+		} else {
+			/*
+			 * Message successfully received from RMS.
+			 * Return the status of the Node's create function
+			 * on the DSP-side
+			 */
+			status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+			if (DSP_FAILED(status)) {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_NodeCreate, "
+					 "DSP-side Node Create failed: 0x%x\n",
+					 status);
+			}
+
+		}
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== DISP_NodeDelete ========
+ *  purpose:
+ *      Delete a node on the DSP by remotely calling the node's delete function.
+ *
+ */
+DSP_STATUS DISP_NodeDelete(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+			  u32 ulRMSFxn, u32 ulDeleteFxn, NODE_ENV nodeEnv)
+{
+	u32 dwArg;
+	struct RMS_Command *pCommand;
+	DSP_STATUS status = DSP_SOK;
+	u32 devType;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+	DBC_Require(hNode != NULL);
+
+	GT_5trace(DISP_DebugMask, GT_ENTER,
+		 "DISP_NodeDelete: hDisp: 0x%xthNode: "
+		 "0x%x\tulRMSFxn: 0x%x\tulDeleteFxn: 0x%x\tnodeEnv: 0x%x\n",
+		 hDisp, hNode, ulRMSFxn, ulDeleteFxn, nodeEnv);
+
+	status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+	if (DSP_SUCCEEDED(status)) {
+
+		if (devType == DSP_UNIT) {
+
+			/*
+			 *  Fill in buffer to send to RMS
+			 */
+			pCommand = (struct RMS_Command *)hDisp->pBuf;
+			pCommand->fxn = (RMS_WORD)(ulRMSFxn);
+			pCommand->arg1 = (RMS_WORD)nodeEnv;
+			pCommand->arg2 = (RMS_WORD)(ulDeleteFxn);
+			pCommand->data = NODE_GetType(hNode);
+
+			status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+					    sizeof(struct RMS_Command), &dwArg);
+			if (DSP_FAILED(status)) {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_NodeDelete failed!"
+					 "status = 0x%x\n", status);
+			} else {
+				/*
+				 * Message successfully received from RMS.
+				 * Return the status of the Node's delete
+				 * function on the DSP-side
+				 */
+				status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+				if (DSP_FAILED(status)) {
+					GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_NodeDelete, "
+					 "DSP-side Node Delete failed: 0x%x\n",
+					 status);
+				}
+			}
+
+
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== DISP_NodeRun ========
+ *  purpose:
+ *      Start execution of a node's execute phase, or resume execution of a node
+ *      that has been suspended (via DISP_NodePause()) on the DSP.
+ */
+DSP_STATUS DISP_NodeRun(struct DISP_OBJECT *hDisp, struct NODE_OBJECT *hNode,
+			u32 ulRMSFxn, u32 ulExecuteFxn, NODE_ENV nodeEnv)
+{
+	u32 dwArg;
+	struct RMS_Command *pCommand;
+	DSP_STATUS status = DSP_SOK;
+	u32 devType;
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hDisp, DISP_SIGNATURE));
+	DBC_Require(hNode != NULL);
+
+	GT_5trace(DISP_DebugMask, GT_ENTER, "DISP_NodeRun: hDisp: 0x%xthNode: \
+		 0x%x\tulRMSFxn: 0x%x\tulExecuteFxn: 0x%x\tnodeEnv: 0x%x\n", \
+		 hDisp, hNode, ulRMSFxn, ulExecuteFxn, nodeEnv);
+
+	status = DEV_GetDevType(hDisp->hDevObject, &devType);
+
+	if (DSP_SUCCEEDED(status)) {
+
+		if (devType == DSP_UNIT) {
+
+			/*
+			 *  Fill in buffer to send to RMS.
+			 */
+			pCommand = (struct RMS_Command *) hDisp->pBuf;
+			pCommand->fxn = (RMS_WORD) (ulRMSFxn);
+			pCommand->arg1 = (RMS_WORD) nodeEnv;
+			pCommand->arg2 = (RMS_WORD) (ulExecuteFxn);
+			pCommand->data = NODE_GetType(hNode);
+
+			status = SendMessage(hDisp, NODE_GetTimeout(hNode),
+				 sizeof(struct RMS_Command), &dwArg);
+			if (DSP_FAILED(status)) {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_NodeRun failed!"
+					 "status = 0x%x\n", status);
+			} else {
+				/*
+				 * Message successfully received from RMS.
+				 * Return the status of the Node's execute
+				 * function on the DSP-side
+				 */
+				status = (((RMS_WORD *)(hDisp->pBuf))[0]);
+				if (DSP_FAILED(status)) {
+					GT_1trace(DISP_DebugMask, GT_6CLASS,
+						"DISP_NodeRun, DSP-side Node "
+						"Execute failed: 0x%x\n",
+						status);
+		}
+		}
+
+	}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== DeleteDisp ========
+ *  purpose:
+ *      Frees the resources allocated for the dispatcher.
+ */
+static void DeleteDisp(struct DISP_OBJECT *hDisp)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+
+	if (MEM_IsValidHandle(hDisp, DISP_SIGNATURE)) {
+		pIntfFxns = hDisp->pIntfFxns;
+
+		/* Free Node Dispatcher resources */
+		if (hDisp->hChnlFromDsp) {
+			/* Channel close can fail only if the channel handle
+			 * is invalid. */
+			status = (*pIntfFxns->pfnChnlClose)
+				 (hDisp->hChnlFromDsp);
+			if (DSP_FAILED(status)) {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_Delete: Failed to "
+					 "close channel from RMS: 0x%x\n",
+					 status);
+			}
+		}
+		if (hDisp->hChnlToDsp) {
+			status = (*pIntfFxns->pfnChnlClose)(hDisp->hChnlToDsp);
+			if (DSP_FAILED(status)) {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "DISP_Delete: Failed to "
+					 "close channel to RMS: 0x%x\n",
+					 status);
+			}
+		}
+		if (hDisp->pBuf)
+			MEM_Free(hDisp->pBuf);
+
+		MEM_FreeObject(hDisp);
+	}
+}
+
+/*
+ *  ======== FillStreamDef ========
+ *  purpose:
+ *      Fills stream definitions.
+ */
+static DSP_STATUS FillStreamDef(RMS_WORD *pdwBuf, u32 *ptotal, u32 offset,
+				struct NODE_STRMDEF strmDef, u32 max,
+				u32 uCharsInRMSWord)
+{
+	struct RMS_StrmDef *pStrmDef;
+	u32 total = *ptotal;
+	u32 uNameLen;
+	u32 dwLength;
+	DSP_STATUS status = DSP_SOK;
+
+	if (total + sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) >= max) {
+		status = DSP_EFAIL;
+	} else {
+		pStrmDef = (struct RMS_StrmDef *)(pdwBuf + total);
+		pStrmDef->bufsize = strmDef.uBufsize;
+		pStrmDef->nbufs = strmDef.uNumBufs;
+		pStrmDef->segid = strmDef.uSegid;
+		pStrmDef->align = strmDef.uAlignment;
+		pStrmDef->timeout = strmDef.uTimeout;
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/*
+		 *  Since we haven't added the device name yet, subtract
+		 *  1 from total.
+		 */
+		total += sizeof(struct RMS_StrmDef) / sizeof(RMS_WORD) - 1;
+		dwLength = CSL_Strlen(strmDef.szDevice) + 1;
+
+		/* Number of RMS_WORDS needed to hold device name */
+		uNameLen = (dwLength + uCharsInRMSWord - 1) / uCharsInRMSWord;
+
+		if (total + uNameLen >= max) {
+			status = DSP_EFAIL;
+		} else {
+			/*
+			 *  Zero out last word, since the device name may not
+			 *  extend to completely fill this word.
+			 */
+			pdwBuf[total + uNameLen - 1] = 0;
+			/** TODO USE SERVICES **/
+			memcpy(pdwBuf + total, strmDef.szDevice, dwLength);
+			total += uNameLen;
+			*ptotal = total;
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== SendMessage ======
+ *  Send command message to RMS, get reply from RMS.
+ */
+static DSP_STATUS SendMessage(struct DISP_OBJECT *hDisp, u32 dwTimeout,
+			     u32 ulBytes, u32 *pdwArg)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct CHNL_OBJECT *hChnl;
+	u32 dwArg = 0;
+	u8 *pBuf;
+	struct CHNL_IOC chnlIOC;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(pdwArg != NULL);
+
+	*pdwArg = (u32) NULL;
+	pIntfFxns = hDisp->pIntfFxns;
+	hChnl = hDisp->hChnlToDsp;
+	pBuf = hDisp->pBuf;
+
+	/* Send the command */
+	status = (*pIntfFxns->pfnChnlAddIOReq) (hChnl, pBuf, ulBytes, 0,
+		 0L, dwArg);
+
+	if (DSP_FAILED(status)) {
+		GT_1trace(DISP_DebugMask, GT_6CLASS,
+			 "SendMessage: Channel AddIOReq to"
+			 " RMS failed! Status = 0x%x\n", status);
+		goto func_cont;
+	}
+	status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
+	if (DSP_SUCCEEDED(status)) {
+		if (!CHNL_IsIOComplete(chnlIOC)) {
+			if (CHNL_IsTimedOut(chnlIOC)) {
+				status = DSP_ETIMEOUT;
+			} else {
+				GT_1trace(DISP_DebugMask, GT_6CLASS,
+					 "SendMessage failed! "
+					 "Channel IOC status = 0x%x\n",
+					 chnlIOC.status);
+				status = DSP_EFAIL;
+			}
+		}
+	} else {
+		GT_1trace(DISP_DebugMask, GT_6CLASS,
+			 "SendMessage: Channel GetIOC to"
+			 " RMS failed! Status = 0x%x\n", status);
+	}
+func_cont:
+	/* Get the reply */
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	hChnl = hDisp->hChnlFromDsp;
+	ulBytes = REPLYSIZE;
+	status = (*pIntfFxns->pfnChnlAddIOReq)(hChnl, pBuf, ulBytes,
+		 0, 0L, dwArg);
+	if (DSP_FAILED(status)) {
+		GT_1trace(DISP_DebugMask, GT_6CLASS,
+			 "SendMessage: Channel AddIOReq "
+			 "from RMS failed! Status = 0x%x\n", status);
+		goto func_end;
+	}
+	status = (*pIntfFxns->pfnChnlGetIOC) (hChnl, dwTimeout, &chnlIOC);
+	if (DSP_SUCCEEDED(status)) {
+		if (CHNL_IsTimedOut(chnlIOC)) {
+			status = DSP_ETIMEOUT;
+		} else if (chnlIOC.cBytes < ulBytes) {
+			/* Did not get all of the reply from the RMS */
+			GT_1trace(DISP_DebugMask, GT_6CLASS,
+				 "SendMessage: Did not get all"
+				 "of reply from RMS! Bytes received: %d\n",
+				 chnlIOC.cBytes);
+			status = DSP_EFAIL;
+		} else {
+			if (CHNL_IsIOComplete(chnlIOC)) {
+				DBC_Assert(chnlIOC.pBuf == pBuf);
+				status = (*((RMS_WORD *)chnlIOC.pBuf));
+				*pdwArg = (((RMS_WORD *)(chnlIOC.pBuf))[1]);
+			} else {
+				status = DSP_EFAIL;
+			}
+		}
+	} else {
+		/* GetIOC failed */
+		GT_1trace(DISP_DebugMask, GT_6CLASS,
+			 "SendMessage: Failed to get "
+			 "reply from RMS! Status = 0x%x\n", status);
+	}
+func_end:
+	return status;
+}
diff --git a/drivers/dsp/bridge/rmgr/drv.c b/drivers/dsp/bridge/rmgr/drv.c
new file mode 100644
index 0000000..dacc8b1
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv.c
@@ -0,0 +1,1883 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/drv.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== drv.c ========
+ *  Description:
+ *      DSP/BIOS Bridge resource allocation module.
+ *
+ *  Public Functions:
+ *      DRV_Create
+ *      DRV_Destroy
+ *      DRV_Exit
+ *      DRV_GetDevObject
+ *      DRV_GetDevExtension
+ *      DRV_GetFirstDevObject
+ *      DRV_GetNextDevObject
+ *      DRV_GetNextDevExtension
+ *      DRV_Init
+ *      DRV_InsertDevObject
+ *      DRV_RemoveDevObject
+ *      DRV_RequestResources
+ *      DRV_ReleaseResources
+ *
+ *! Revision History
+ *! ======== ========
+ *! 19-Apr-2004 sb: Replaced OS specific APIs with MEM_AllocPhysMem and
+		    MEM_FreePhysMem. Fixed warnings. Cosmetic updates.
+ *! 12-Apr-2004 hp: IVA clean up during bridge-uninstall
+ *! 05-Jan-2004 vp: Updated for 24xx platform
+ *! 21-Mar-2003 sb: Get SHM size from registry
+ *! 10-Feb-2003 vp: Code review updates
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 30-Oct-2000 kc: Modified usage of REG_SetValue.
+ *! 06-Sep-2000 jeh Read channel info into struct CFG_HOSTRES in
+ *! 					RequestISAResources()
+ *! 21-Sep-2000 rr: numwindows is calculated instead of default value in
+ *!		 RequestISAResources.
+ *! 07-Aug-2000 rr: static list of dev objects removed.
+ *! 27-Jul-2000 rr: RequestResources split into two(Request and Release)
+ *!		 Device extension created to hold the DevNodeString.
+ *! 17-Jul-2000 rr: Driver Object holds the list of Device Objects.
+ *!		 Added DRV_Create, DRV_Destroy, DRV_GetDevObject,
+ *!		 DRV_GetFirst/NextDevObject, DRV_Insert/RemoveDevObject.
+ *! 09-May-2000 rr: PCI Support is not L301 specific.Use of MEM_Calloc
+ *!		 instead of MEM_Alloc.
+ *! 28-Mar-2000 rr: PCI Support added. L301 Specific. TBD.
+ *! 03-Feb-2000 rr: GT and Module Init/exit Changes. Merged with kc.
+ *! 19-Jan-2000 rr: DBC_Ensure in RequestPCMCIA moved within PCCARD ifdef
+ *! 29-Dec-1999 rr: PCCard support for any slot.Bus type stored in the
+ *!		 struct CFG_HOSTRES Structure.
+ *! 17-Dec-1999 rr: if PCCARD_Init fails we return DSP_EFAIL.
+ *!		 DBC_Ensure checks for sucess and pDevice != NULL
+ *! 11-Dec-1999 ag: #define "Isa" renamed to "IsaBus".
+ *! 09-Dec-1999 rr: windows.h included to remove warnings.
+ *! 02-Dec-1999 rr: struct GT_Mask is with in if DEBUG. Request resources checks
+ *!		 status while making call to Reg functions.
+ *! 23-Nov-1999 rr: windows.h included
+ *! 19-Nov-1999 rr: DRV_RELEASE bug while setting the registry to zero.
+ *!		 fixed.
+ *! 12-Nov-1999 rr: RequestResources() reads values from the registry.
+ *!		 Hardcoded bIRQRegister define removed.
+ *! 05-Nov-1999 rr: Added hardcoded device interrupt.
+ *! 25-Oct-1999 rr: Resource structure removed. Now it uses the Host
+ *!		 Resource structure directly.
+ *! 15-Oct-1999 rr: Resource Structure modified. See drv.h
+ *!		 dwBusType taken from the registry.Hard coded
+ *!		 registry entries removed.
+ *! 05-Oct-1999 rr: Calling DEV_StartDevice moved to wcdce.c. DRV_Register
+ *!		 MiniDriver has been renamed to DRV_RequestResources.
+ *!		 DRV_UnRegisterMiniDriver fxn removed.
+ *! 24-Sep-1999 rr: Significant changes to the RegisterMiniDriver fxns.
+ *!		 Now it is simpler. IT stores the dev node in the
+ *!		 registry, assign resources and calls the DEV_Start.
+ *! 10-Sep-1999 rr: Register Minidriver modified.
+ *!		 - Resource structure follows the NT model
+ *! 08-Aug-1999 rr: Adopted for WinCE. Exports Fxns removed. Hull Created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <csl.h>
+#include <list.h>
+#include <mem.h>
+#include <reg.h>
+
+/*  ----------------------------------- Others */
+#include <dbreg.h>
+
+/*  ----------------------------------- This */
+#include <drv.h>
+#include <dev.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <prcs.h>
+#include <node.h>
+#include <proc.h>
+#include <strm.h>
+#include <nodepriv.h>
+#include <wmdchnl.h>
+#endif
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define SIGNATURE   0x5f52474d	/* "DRV_" (in reverse) */
+
+struct DRV_OBJECT {
+	u32 dwSignature;
+	struct LST_LIST *devList;
+	struct LST_LIST *devNodeString;
+#ifndef RES_CLEANUP_DISABLE
+	struct PROCESS_CONTEXT  *procCtxtList;
+#endif
+};
+
+/*
+ *  This is the Device Extension. Named with the Prefix
+ *  DRV_ since it is living in this module
+ */
+struct DRV_EXT {
+	struct LST_ELEM link;
+	char szString[MAXREGPATHLENGTH];
+};
+
+/*  ----------------------------------- Globals */
+static s32 cRefs;
+
+#if GT_TRACE
+extern struct GT_Mask curTrace;
+#endif
+
+/*  ----------------------------------- Function Prototypes */
+static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 fRequest);
+static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 fRequest);
+
+#ifndef RES_CLEANUP_DISABLE
+
+
+/* GPP PROCESS CLEANUP CODE */
+static DSP_STATUS PrintProcessInformation(void);
+
+extern enum NODE_STATE NODE_GetState(HANDLE hNode);
+
+/* Get the process context list from driver object */
+
+/* Set the Process ID */
+DSP_STATUS DRV_ProcSetPID(HANDLE hPCtxt, s32 hProcess)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Assert(hPCtxt != NULL);
+
+	pCtxt->pid = hProcess;
+	return status;
+}
+
+
+/* Getting the head of the process context list */
+DSP_STATUS DRV_GetProcCtxtList(struct PROCESS_CONTEXT **pPctxt,
+				struct DRV_OBJECT *hDrvObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+
+	DBC_Assert(hDrvObject != NULL);
+	GT_2trace(curTrace, GT_ENTER,
+		"DRV_GetProcCtxtList: 2 *pPctxt:%x, pDrvObject"
+		":%x", *pPctxt, pDrvObject);
+	*pPctxt = pDrvObject->procCtxtList;
+	GT_2trace(curTrace, GT_ENTER,
+		"DRV_GetProcCtxtList: 3 *pPctxt:%x, pDrvObject"
+		":%x", *pPctxt, pDrvObject);
+	return status;
+}
+
+
+
+/* Get a particular process context based on process handle (phProcess) */
+DSP_STATUS DRV_GetProcContext(u32 phProcess,
+				struct DRV_OBJECT *hDrvObject,
+				HANDLE hPCtxt, DSP_HNODE hNode,
+				u32 pMapAddr)
+{
+	struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct PROCESS_CONTEXT *pCtxtList = NULL;
+	struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+	struct NODE_RES_OBJECT *pTempNode2 = NULL;
+	struct NODE_RES_OBJECT *pTempNode = NULL;
+	struct DMM_RES_OBJECT *pTempDMM2 = NULL;
+	struct DMM_RES_OBJECT *pTempDMM = NULL;
+	s32 pCtxtFound = 0;
+
+	DBC_Assert(pDrvObject != NULL);
+	pCtxtList = pDrvObject->procCtxtList;
+	GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 2");
+	while ((pCtxtList != NULL) && (pCtxtList->pid != phProcess)) {
+		pCtxtList = pCtxtList->next;
+		GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 3");
+	}
+	if (pCtxtList == NULL) {
+		if (hNode != NULL) {
+			pCtxtList = pDrvObject->procCtxtList;
+			while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
+				pTempNode = pCtxtList->pNodeList;
+				while ((pTempNode != NULL) &&
+				      (pTempNode->hNode != hNode)) {
+					pTempNode2 = pTempNode;
+					pTempNode = pTempNode->next;
+				}
+				if (pTempNode != NULL) {
+					pCtxtFound = 1;
+					status = DSP_SOK;
+				} else {
+					pCtxtList = pCtxtList->next;
+				}
+			}
+		} else if ((pMapAddr != 0) && (pCtxtFound == 0)) {
+			pCtxtList = pDrvObject->procCtxtList;
+			while ((pCtxtList != NULL) && (pCtxtFound == 0)) {
+				pTempDMM = pCtxtList->pDMMList;
+				while ((pTempDMM != NULL) &&
+				     (pTempDMM->ulDSPAddr != pMapAddr)) {
+					pTempDMM2 = pTempDMM;
+					pTempDMM = pTempDMM->next;
+				}
+				if (pTempDMM != NULL) {
+					pCtxtFound = 1;
+					status = DSP_SOK;
+				} else {
+					pCtxtList = pCtxtList->next;
+				}
+			}
+			if (pCtxtList == NULL)
+				status = DSP_ENOTFOUND;
+
+		}
+	} else{
+		status = DSP_SOK;
+	}
+	GT_0trace(curTrace, GT_ENTER, "2DRV_GetProcContext: 4");
+	*pCtxt = pCtxtList;
+	return status;
+}
+
+
+/* Add a new process context to process context list */
+DSP_STATUS DRV_InsertProcContext(struct DRV_OBJECT *hDrVObject, HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT **pCtxt = (struct PROCESS_CONTEXT **)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct PROCESS_CONTEXT *pCtxtList = NULL;
+	struct DRV_OBJECT	     *hDRVObject;
+
+	GT_0trace(curTrace, GT_ENTER, "\n In DRV_InsertProcContext\n");
+	status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+	DBC_Assert(hDRVObject != NULL);
+	*pCtxt = MEM_Calloc(1 * sizeof(struct PROCESS_CONTEXT), MEM_PAGED);
+	GT_0trace(curTrace, GT_ENTER,
+		 "\n In DRV_InsertProcContext Calling "
+		 "DRV_GetProcCtxtList\n");
+	DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
+	GT_0trace(curTrace, GT_ENTER,
+		 "\n In DRV_InsertProcContext After Calling "
+		 "DRV_GetProcCtxtList\n");
+	if (pCtxtList != NULL) {
+		GT_0trace(curTrace, GT_ENTER,
+			 "\n In DRV_InsertProcContext and pCtxt is "
+			 "not Null\n");
+		while (pCtxtList->next != NULL)
+			pCtxtList = pCtxtList->next;
+
+		pCtxtList->next = *pCtxt;
+	} else {
+		GT_0trace(curTrace, GT_ENTER,
+			 "\n In DRV_InsertProcContext and "
+			 "pCtxt is Null\n");
+		hDRVObject->procCtxtList = *pCtxt;
+	}
+	return status;
+}
+
+/* Delete a process context from process resource context list */
+DSP_STATUS DRV_RemoveProcContext(struct DRV_OBJECT *hDRVObject,
+				     HANDLE hPCtxt, HANDLE hProcess)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROCESS_CONTEXT    *pCtxt2 = NULL;
+	struct PROCESS_CONTEXT    *pTmp = NULL;
+	struct PROCESS_CONTEXT    *pCtxtList = NULL;
+
+	DBC_Assert(hDRVObject != NULL);
+	DRV_GetProcContext((u32)hProcess, hDRVObject, &pCtxt2, NULL, 0);
+
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 12");
+	DRV_GetProcCtxtList(&pCtxtList, hDRVObject);
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 13");
+	pTmp = pCtxtList;
+	while ((pCtxtList != NULL) && (pCtxtList != pCtxt2)) {
+		pTmp = pCtxtList;
+		pCtxtList = pCtxtList->next;
+		GT_0trace(curTrace, GT_ENTER,
+			 "DRV_RemoveProcContext: 2");
+	}
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 3");
+	if (hDRVObject->procCtxtList == pCtxt2)
+		hDRVObject->procCtxtList = pCtxt2->next;
+
+	if (pCtxtList == NULL)
+		return DSP_ENOTFOUND;
+	else if (pTmp->next != NULL)
+		pTmp->next = pTmp->next->next;
+
+	MEM_Free(pCtxt2);
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveProcContext: 7");
+
+	return status;
+}
+
+/* Update the state of process context */
+DSP_STATUS DRV_ProcUpdatestate(HANDLE hPCtxt, enum GPP_PROC_RES_STATE status)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status1 = DSP_SOK;
+	if (pCtxt != NULL) {
+		pCtxt->resState = status;
+	} else {
+		GT_0trace(curTrace, GT_ENTER,
+			 "DRV_ProcUpdatestate: Failed to update "
+			 "process state");
+	}
+	return status1;
+}
+
+/* Allocate and add a node resource element
+* This function is called from .Node_Allocate.  */
+DSP_STATUS DRV_InsertNodeResElement(HANDLE hNode, HANDLE hNodeRes,
+					HANDLE hPCtxt)
+{
+	struct NODE_RES_OBJECT **pNodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct NODE_RES_OBJECT   *pTempNodeRes = NULL;
+	GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 1");
+	*pNodeRes = (struct NODE_RES_OBJECT *)MEM_Calloc
+		    (1 * sizeof(struct NODE_RES_OBJECT), MEM_PAGED);
+	DBC_Assert(hPCtxt != NULL);
+	if ((*pNodeRes == NULL) || (hPCtxt == NULL)) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 12");
+		status = DSP_EHANDLE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		(*pNodeRes)->hNode = hNode;
+		if (pCtxt->pNodeList != NULL) {
+			pTempNodeRes = pCtxt->pNodeList;
+			while (pTempNodeRes->next != NULL)
+				pTempNodeRes = pTempNodeRes->next;
+
+			pTempNodeRes->next = *pNodeRes;
+			GT_0trace(curTrace, GT_ENTER,
+				 "DRV_InsertNodeResElement: 2");
+		} else {
+			pCtxt->pNodeList = *pNodeRes;
+			GT_0trace(curTrace, GT_ENTER,
+				 "DRV_InsertNodeResElement: 3");
+		}
+	}
+	GT_0trace(curTrace, GT_ENTER, "DRV_InsertNodeResElement: 4");
+	return status;
+}
+
+/* Release all Node resources and its context
+* This is called from .Node_Delete.  */
+DSP_STATUS DRV_RemoveNodeResElement(HANDLE hNodeRes, HANDLE hPCtxt)
+{
+	struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS	status = DSP_SOK;
+	struct NODE_RES_OBJECT *pTempNode2 = pCtxt->pNodeList;
+	struct NODE_RES_OBJECT *pTempNode = pCtxt->pNodeList;
+
+	DBC_Assert(hPCtxt != NULL);
+	GT_0trace(curTrace, GT_ENTER, "\nDRV_RemoveNodeResElement: 1\n");
+	while ((pTempNode != NULL) && (pTempNode != pNodeRes)) {
+		pTempNode2 = pTempNode;
+		pTempNode = pTempNode->next;
+	}
+	if (pCtxt->pNodeList == pNodeRes)
+		pCtxt->pNodeList = pNodeRes->next;
+
+	if (pTempNode == NULL)
+		return DSP_ENOTFOUND;
+	else if (pTempNode2->next != NULL)
+		pTempNode2->next = pTempNode2->next->next;
+
+	MEM_Free(pTempNode);
+	return status;
+}
+
+/* Actual Node De-Allocation */
+DSP_STATUS DRV_ProcFreeNodeRes(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct NODE_RES_OBJECT *pNodeList = NULL;
+	struct NODE_RES_OBJECT *pNodeRes = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	pNodeList = pCtxt->pNodeList;
+	while (pNodeList != NULL) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_ProcFreeNodeRes: 1");
+	pNodeRes = pNodeList;
+	pNodeList = pNodeList->next;
+	if (pNodeRes->nodeAllocated) {
+			if (NODE_GetState(pNodeRes->hNode) &
+			  (NODE_ALLOCATED | NODE_CREATED |
+			  NODE_RUNNING | NODE_PAUSED/*| NODE_TERMINATING */)) {
+				GT_1trace(curTrace, GT_5CLASS,
+					 "Calling Node_Terminate for Node:"
+					 " 0x%x\n", pNodeRes->hNode);
+				status = NODE_Terminate
+					(pNodeRes->hNode, &status);
+				GT_1trace(curTrace, GT_5CLASS,
+					 "Calling Node_Delete for Node:"
+					 " 0x%x\n", pNodeRes->hNode);
+				status = NODE_Delete(pNodeRes->hNode);
+				GT_1trace(curTrace, GT_5CLASS,
+					"the status after the NodeDelete %x\n",
+					status);
+			} else /*if (NODE_GetState(pNodeRes->hNode)
+				== NODE_DONE)*/ {
+				status = NODE_Delete(pNodeRes->hNode);
+			}
+			pNodeRes->nodeAllocated = 0;
+		}
+	}
+	return status;
+}
+
+/* Allocate the DMM resource element
+* This is called from Proc_Map. after the actual resource is allocated */
+DSP_STATUS DRV_InsertDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
+	DSP_STATUS	status = DSP_SOK;
+	struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+	*pDMMRes = (struct DMM_RES_OBJECT *)
+		    MEM_Calloc(1 * sizeof(struct DMM_RES_OBJECT), MEM_PAGED);
+	DBC_Assert(hPCtxt != NULL);
+	GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 1");
+	if ((*pDMMRes == NULL) || (hPCtxt == NULL)) {
+		GT_0trace(curTrace, GT_5CLASS, "DRV_InsertDMMResElement: 2");
+		status = DSP_EHANDLE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		if (pCtxt->pDMMList != NULL) {
+			GT_0trace(curTrace, GT_5CLASS,
+				 "DRV_InsertDMMResElement: 3");
+			pTempDMMRes = pCtxt->pDMMList;
+			while (pTempDMMRes->next != NULL)
+				pTempDMMRes = pTempDMMRes->next;
+
+			pTempDMMRes->next = *pDMMRes;
+		} else {
+			pCtxt->pDMMList = *pDMMRes;
+			GT_0trace(curTrace, GT_5CLASS,
+				 "DRV_InsertDMMResElement: 4");
+		}
+	}
+	GT_0trace(curTrace, GT_ENTER, "DRV_InsertDMMResElement: 5");
+	return status;
+}
+
+
+
+/* Release DMM resource element context
+* This is called from Proc_UnMap. after the actual resource is freed */
+DSP_STATUS 	DRV_RemoveDMMResElement(HANDLE hDMMRes, HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
+	DSP_STATUS status = DSP_SOK;
+	struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
+	struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	pTempDMMRes2 = pCtxt->pDMMList;
+	pTempDMMRes = pCtxt->pDMMList;
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 1");
+	while ((pTempDMMRes != NULL) && (pTempDMMRes != pDMMRes)) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 2");
+		pTempDMMRes2 = pTempDMMRes;
+		pTempDMMRes = pTempDMMRes->next;
+	}
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 3");
+	if (pCtxt->pDMMList == pTempDMMRes)
+		pCtxt->pDMMList = pTempDMMRes->next;
+
+	if (pTempDMMRes == NULL)
+		return DSP_ENOTFOUND;
+	else if (pTempDMMRes2->next != NULL)
+		pTempDMMRes2->next = pTempDMMRes2->next->next;
+
+	MEM_Free(pDMMRes);
+	GT_0trace(curTrace, GT_ENTER, "DRV_RemoveDMMResElement: 4");
+	return status;
+}
+
+
+
+/* Update DMM resource status */
+DSP_STATUS DRV_UpdateDMMResElement(HANDLE hDMMRes, u32 pMpuAddr, u32 ulSize,
+				  u32 pReqAddr, u32 pMapAddr,
+				  HANDLE hProcessor)
+{
+	struct DMM_RES_OBJECT *pDMMRes = (struct DMM_RES_OBJECT *)hDMMRes;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Assert(hDMMRes != NULL);
+	pDMMRes->ulMpuAddr = pMpuAddr;
+	pDMMRes->ulDSPAddr = pMapAddr;
+	pDMMRes->ulDSPResAddr = pReqAddr;
+	pDMMRes->dmmSize = ulSize;
+	pDMMRes->hProcessor = hProcessor;
+	pDMMRes->dmmAllocated = 1;
+
+	return status;
+}
+
+/* Actual DMM De-Allocation */
+DSP_STATUS  DRV_ProcFreeDMMRes(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct DMM_RES_OBJECT *pDMMList = pCtxt->pDMMList;
+	struct DMM_RES_OBJECT *pDMMRes = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	GT_0trace(curTrace, GT_ENTER, "\nDRV_ProcFreeDMMRes: 1\n");
+	while (pDMMList != NULL) {
+		pDMMRes = pDMMList;
+		pDMMList = pDMMList->next;
+		if (pDMMRes->dmmAllocated) {
+			status = PROC_UnMap(pDMMRes->hProcessor,
+				 (void *)pDMMRes->ulDSPResAddr);
+			status = PROC_UnReserveMemory(pDMMRes->hProcessor,
+				 (void *)pDMMRes->ulDSPResAddr);
+			pDMMRes->dmmAllocated = 0;
+		}
+	}
+	return status;
+}
+
+
+/* Release all DMM resources and its context
+* This is called from .bridge_release. */
+DSP_STATUS DRV_RemoveAllDMMResElements(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct DMM_RES_OBJECT *pTempDMMRes2 = NULL;
+	struct DMM_RES_OBJECT *pTempDMMRes = NULL;
+
+	DBC_Assert(pCtxt != NULL);
+	DRV_ProcFreeDMMRes(pCtxt);
+	pTempDMMRes = pCtxt->pDMMList;
+	while (pTempDMMRes != NULL) {
+		pTempDMMRes2 = pTempDMMRes;
+		pTempDMMRes = pTempDMMRes->next;
+		MEM_Free(pTempDMMRes2);
+	}
+	pCtxt->pDMMList = NULL;
+	return status;
+}
+
+DSP_STATUS DRV_GetDMMResElement(u32 pMapAddr, HANDLE hDMMRes, HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	struct DMM_RES_OBJECT **pDMMRes = (struct DMM_RES_OBJECT **)hDMMRes;
+	DSP_STATUS status = DSP_SOK;
+	struct DMM_RES_OBJECT *pTempDMM2 = NULL;
+	struct DMM_RES_OBJECT *pTempDMM = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	pTempDMM = pCtxt->pDMMList;
+	while ((pTempDMM != NULL) && (pTempDMM->ulDSPAddr != pMapAddr)) {
+		GT_3trace(curTrace, GT_ENTER,
+			 "DRV_GetDMMResElement: 2 pTempDMM:%x "
+			 "pTempDMM->ulDSPAddr:%x pMapAddr:%x\n", pTempDMM,
+			 pTempDMM->ulDSPAddr, pMapAddr);
+		pTempDMM2 = pTempDMM;
+		pTempDMM = pTempDMM->next;
+	}
+	if (pTempDMM != NULL) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 3");
+		*pDMMRes = pTempDMM;
+	} else {
+		status = DSP_ENOTFOUND;
+	} GT_0trace(curTrace, GT_ENTER, "DRV_GetDMMResElement: 4");
+	return status;
+}
+
+/* Update Node allocation status */
+void DRV_ProcNodeUpdateStatus(HANDLE hNodeRes, s32 status)
+{
+	struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+	DBC_Assert(hNodeRes != NULL);
+	pNodeRes->nodeAllocated = status;
+}
+
+/* Update Node Heap status */
+void DRV_ProcNodeUpdateHeapStatus(HANDLE hNodeRes, s32 status)
+{
+	struct NODE_RES_OBJECT *pNodeRes = (struct NODE_RES_OBJECT *)hNodeRes;
+	DBC_Assert(hNodeRes != NULL);
+	pNodeRes->heapAllocated = status;
+}
+
+/* Release all Node resources and its context
+* This is called from .bridge_release.
+*/
+DSP_STATUS 	DRV_RemoveAllNodeResElements(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct NODE_RES_OBJECT *pTempNode2 = NULL;
+	struct NODE_RES_OBJECT *pTempNode = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	DRV_ProcFreeNodeRes(pCtxt);
+	pTempNode = pCtxt->pNodeList;
+	while (pTempNode != NULL) {
+		pTempNode2 = pTempNode;
+		pTempNode = pTempNode->next;
+		MEM_Free(pTempNode2);
+	}
+	pCtxt->pNodeList = NULL;
+	return status;
+}
+
+/* Getting the node resource element */
+
+DSP_STATUS DRV_GetNodeResElement(HANDLE hNode, HANDLE hNodeRes, HANDLE hPCtxt)
+{
+	struct NODE_RES_OBJECT **nodeRes = (struct NODE_RES_OBJECT **)hNodeRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct NODE_RES_OBJECT *pTempNode2 = NULL;
+	struct NODE_RES_OBJECT *pTempNode = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	pTempNode = pCtxt->pNodeList;
+	GT_0trace(curTrace, GT_ENTER, "DRV_GetNodeResElement: 1");
+	while ((pTempNode != NULL) && (pTempNode->hNode != hNode)) {
+		pTempNode2 = pTempNode;
+		pTempNode = pTempNode->next;
+	}
+	if (pTempNode != NULL)
+		*nodeRes = pTempNode;
+	else
+		status = DSP_ENOTFOUND;
+
+	return status;
+}
+
+
+
+/* Allocate the STRM resource element
+* This is called after the actual resource is allocated
+*/
+DSP_STATUS DRV_ProcInsertSTRMResElement(HANDLE hStreamHandle, HANDLE hSTRMRes,
+					HANDLE hPCtxt)
+{
+	struct STRM_RES_OBJECT **pSTRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
+	DBC_Assert(hPCtxt != NULL);
+
+	*pSTRMRes = (struct STRM_RES_OBJECT *)
+		    MEM_Calloc(1 * sizeof(struct STRM_RES_OBJECT), MEM_PAGED);
+	if ((*pSTRMRes == NULL) || (hPCtxt == NULL)) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_InsertSTRMResElement: 2");
+		status = DSP_EHANDLE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		(*pSTRMRes)->hStream = hStreamHandle;
+		if (pCtxt->pSTRMList != NULL) {
+			GT_0trace(curTrace, GT_ENTER,
+				 "DRV_InsertiSTRMResElement: 3");
+			pTempSTRMRes = pCtxt->pSTRMList;
+			while (pTempSTRMRes->next != NULL)
+				pTempSTRMRes = pTempSTRMRes->next;
+
+			pTempSTRMRes->next = *pSTRMRes;
+		} else {
+			pCtxt->pSTRMList = *pSTRMRes;
+			GT_0trace(curTrace, GT_ENTER,
+				 "DRV_InsertSTRMResElement: 4");
+		}
+	}
+	return status;
+}
+
+
+
+/* Release Stream resource element context
+* This function called after the actual resource is freed
+*/
+DSP_STATUS 	DRV_ProcRemoveSTRMResElement(HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+	struct STRM_RES_OBJECT *pSTRMRes = (struct STRM_RES_OBJECT *)hSTRMRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct STRM_RES_OBJECT *pTempSTRMRes2 = pCtxt->pSTRMList;
+	struct STRM_RES_OBJECT *pTempSTRMRes = pCtxt->pSTRMList;
+
+	DBC_Assert(hPCtxt != NULL);
+	while ((pTempSTRMRes != NULL) && (pTempSTRMRes != pSTRMRes)) {
+		pTempSTRMRes2 = pTempSTRMRes;
+		pTempSTRMRes = pTempSTRMRes->next;
+	}
+	if (pCtxt->pSTRMList == pTempSTRMRes)
+		pCtxt->pSTRMList = pTempSTRMRes->next;
+
+	if (pTempSTRMRes == NULL)
+		status = DSP_ENOTFOUND;
+	else if (pTempSTRMRes2->next != NULL)
+		pTempSTRMRes2->next = pTempSTRMRes2->next->next;
+
+	MEM_Free(pSTRMRes);
+	return status;
+}
+
+
+/* Actual Stream De-Allocation */
+DSP_STATUS  DRV_ProcFreeSTRMRes(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+	u8 **apBuffer = NULL;
+	struct STRM_RES_OBJECT *pSTRMList = NULL;
+	struct STRM_RES_OBJECT *pSTRMRes = NULL;
+	u8 *pBufPtr;
+	u32 ulBytes;
+	u32 dwArg;
+	s32 ulBufSize;
+
+
+	DBC_Assert(hPCtxt != NULL);
+	pSTRMList = pCtxt->pSTRMList;
+	while (pSTRMList != NULL) {
+		pSTRMRes = pSTRMList;
+		pSTRMList = pSTRMList->next;
+		if (pSTRMRes->uNumBufs != 0) {
+			apBuffer = MEM_Alloc((pSTRMRes->uNumBufs *
+					    sizeof(u8 *)), MEM_NONPAGED);
+			status = STRM_FreeBuffer(pSTRMRes->hStream, apBuffer,
+						pSTRMRes->uNumBufs);
+			MEM_Free(apBuffer);
+		}
+		status = STRM_Close(pSTRMRes->hStream);
+		if (DSP_FAILED(status)) {
+			if (status == DSP_EPENDING) {
+				status = STRM_Reclaim(pSTRMRes->hStream,
+						     &pBufPtr, &ulBytes,
+						     (u32 *)&ulBufSize, &dwArg);
+				if (DSP_SUCCEEDED(status))
+					status = STRM_Close(pSTRMRes->hStream);
+
+			}
+		}
+	}
+	return status1;
+}
+
+/* Release all Stream resources and its context
+* This is called from .bridge_release.
+*/
+DSP_STATUS	DRV_RemoveAllSTRMResElements(HANDLE hPCtxt)
+{
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct STRM_RES_OBJECT *pTempSTRMRes2 = NULL;
+	struct STRM_RES_OBJECT *pTempSTRMRes = NULL;
+
+	DBC_Assert(hPCtxt != NULL);
+	DRV_ProcFreeSTRMRes(pCtxt);
+	pTempSTRMRes = pCtxt->pSTRMList;
+	while (pTempSTRMRes != NULL) {
+		pTempSTRMRes2 = pTempSTRMRes;
+		pTempSTRMRes = pTempSTRMRes->next;
+		MEM_Free(pTempSTRMRes2);
+	}
+	pCtxt->pSTRMList = NULL;
+	return status;
+}
+
+
+/* Getting the stream resource element */
+DSP_STATUS DRV_GetSTRMResElement(HANDLE hStrm, HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+	struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	DSP_STATUS status = DSP_SOK;
+	struct STRM_RES_OBJECT *pTempSTRM2 = NULL;
+	struct STRM_RES_OBJECT *pTempSTRM = pCtxt->pSTRMList;
+
+	DBC_Assert(hPCtxt != NULL);
+	while ((pTempSTRM != NULL) && (pTempSTRM->hStream != hStrm)) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 2");
+		pTempSTRM2 = pTempSTRM;
+		pTempSTRM = pTempSTRM->next;
+	}
+	if (pTempSTRM != NULL) {
+		GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 3");
+		*STRMRes = pTempSTRM;
+	} else {
+		GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 4");
+		status = DSP_ENOTFOUND;
+	}
+	GT_0trace(curTrace, GT_ENTER, "DRV_GetSTRMResElement: 5");
+	return status;
+}
+
+/* Updating the stream resource element */
+DSP_STATUS DRV_ProcUpdateSTRMRes(u32 uNumBufs, HANDLE hSTRMRes, HANDLE hPCtxt)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct STRM_RES_OBJECT **STRMRes = (struct STRM_RES_OBJECT **)hSTRMRes;
+
+	DBC_Assert(hPCtxt != NULL);
+	(*STRMRes)->uNumBufs = uNumBufs;
+	return status;
+}
+/* Displaying the resources allocated by a process */
+DSP_STATUS DRV_ProcDisplayResInfo(u8 *pBuf1, u32 *pSize)
+{
+	struct PROCESS_CONTEXT *pCtxt = NULL;
+	struct NODE_RES_OBJECT *pNodeRes = NULL;
+	struct DMM_RES_OBJECT *pDMMRes = NULL;
+	struct STRM_RES_OBJECT *pSTRMRes = NULL;
+	struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
+	u32 tempCount = 1;
+	HANDLE hDrvObject = NULL;
+	void *pBuf = pBuf1;
+	u8 pTempBuf[250];
+	u32 tempStrLen = 0, tempStrLen2 = 0;
+	DSP_STATUS status = DSP_SOK;
+
+	CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	DRV_GetProcCtxtList(&pCtxt, hDrvObject);
+	GT_0trace(curTrace, GT_ENTER, "*********************"
+		 "DRV_ProcDisplayResourceInfo:*\n");
+	while (pCtxt != NULL) {
+		tempStrLen2 = sprintf((char *)pTempBuf,
+				     "-------------------------------------"
+				     "-----------------------------------\n");
+		tempStrLen2 += 2;
+		memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+		tempStrLen += tempStrLen2;
+		if (pCtxt->resState == PROC_RES_ALLOCATED) {
+			tempStrLen2 = sprintf((char *)pTempBuf,
+					"GPP Process Resource State: "
+					"pCtxt->resState = PROC_RES_ALLOCATED, "
+					" Process ID: %d\n", pCtxt->pid);
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+		} else {
+			tempStrLen2 = sprintf((char *)pTempBuf,
+				"GPP Resource State: pCtxt->resState"
+				" = PROC_RES_DEALLOCATED, Process ID:%d\n",
+				pCtxt->pid);
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+		}
+		pNodeRes = pCtxt->pNodeList;
+		tempCount = 1;
+		while (pNodeRes != NULL) {
+			GT_2trace(curTrace, GT_ENTER,
+				 "DRV_ProcDisplayResourceInfo: #:%d "
+				 "pCtxt->pNodeList->hNode:%x\n",
+				 tempCount, pNodeRes->hNode);
+			tempStrLen2 = sprintf((char *)pTempBuf,
+					"Node Resource Information: Node #"
+					" %d Node Handle hNode:0X%x\n",
+					tempCount, (u32)pNodeRes->hNode);
+			pNodeRes = pNodeRes->next;
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+			tempCount++;
+		}
+		tempCount = 1;
+		pDSPHEAPRes = pCtxt->pDSPHEAPList;
+		while (pDSPHEAPRes != NULL) {
+			GT_2trace(curTrace, GT_ENTER,
+				 "DRV_ProcDisplayResourceInfo: #:%d "
+				 "pCtxt->pDSPHEAPRList->ulMpuAddr:%x\n",
+				 tempCount, pDSPHEAPRes->ulMpuAddr);
+			tempStrLen2 = sprintf((char *)pTempBuf,
+				 "DSP Heap Resource Info: HEAP # %d"
+				 " Mapped GPP Address: 0x%x, size: 0x%x\n",
+				 tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
+				 (u32)pDSPHEAPRes->heapSize);
+			pDSPHEAPRes = pDSPHEAPRes->next;
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+			tempCount++;
+		}
+		tempCount = 1;
+		pDMMRes = pCtxt->pDMMList;
+		while (pDMMRes != NULL) {
+			GT_2trace(curTrace, GT_ENTER,
+					"DRV_ProcDisplayResourceInfo: #:%d "
+					" pCtxt->pDMMList->ulMpuAddr:%x\n",
+					tempCount,
+					pDMMRes->ulMpuAddr);
+			tempStrLen2 = sprintf((char *)pTempBuf,
+					 "DMM Resource Info: DMM # %d Mapped"
+					 " GPP Address: 0x%x, size: 0x%x\n",
+					 tempCount, (u32)pDMMRes->ulMpuAddr,
+					 (u32)pDMMRes->dmmSize);
+			pDMMRes = pDMMRes->next;
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+			tempCount++;
+		}
+		tempCount = 1;
+		pSTRMRes = pCtxt->pSTRMList;
+		while (pSTRMRes != NULL) {
+			GT_2trace(curTrace, GT_ENTER,
+				 "DRV_ProcDisplayResourceInfo: #:%d "
+				 "pCtxt->pSTRMList->hStream:%x\n", tempCount,
+				 pSTRMRes->hStream);
+			tempStrLen2 = sprintf((char *)pTempBuf,
+					     "Stream Resource info: STRM # %d "
+					     "Stream Handle: 0x%x \n",
+					     tempCount, (u32)pSTRMRes->hStream);
+			pSTRMRes = pSTRMRes->next;
+			tempStrLen2 += 2;
+			memmove(pBuf+tempStrLen, pTempBuf, tempStrLen2);
+			tempStrLen += tempStrLen2;
+			tempCount++;
+		}
+		pCtxt = pCtxt->next;
+	}
+	*pSize = tempStrLen;
+	status = PrintProcessInformation();
+	GT_0trace(curTrace, GT_ENTER, "*********************"
+		"DRV_ProcDisplayResourceInfo:**\n");
+	return status;
+}
+
+/*
+ *  ======== PrintProcessInformation ========
+ *  Purpose:
+ *      This function prints the Process's information stored in
+ *      the process context list. Some of the information that
+ *      it displays is Process's state, Node, Stream, DMM, and
+ *      Heap information.
+ */
+static DSP_STATUS PrintProcessInformation(void)
+{
+	struct DRV_OBJECT *hDrvObject = NULL;
+	struct PROCESS_CONTEXT *pCtxtList = NULL;
+	struct NODE_RES_OBJECT *pNodeRes = NULL;
+	struct DMM_RES_OBJECT *pDMMRes = NULL;
+	struct STRM_RES_OBJECT *pSTRMRes = NULL;
+	struct DSPHEAP_RES_OBJECT *pDSPHEAPRes = NULL;
+	DSP_STATUS status = DSP_SOK;
+	u32 tempCount;
+	u32  procID;
+
+	/* Get the Process context list */
+	CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	DRV_GetProcCtxtList(&pCtxtList, hDrvObject);
+	GT_0trace(curTrace, GT_4CLASS, "\n### Debug information"
+			" for DSP bridge ##\n");
+	GT_0trace(curTrace, GT_4CLASS, " \n ###The  processes"
+			" information is as follows ### \n") ;
+	GT_0trace(curTrace, GT_4CLASS, "  ====================="
+			"============ \n");
+	/* Go through the entries in the Process context list */
+	while (pCtxtList  != NULL) {
+		GT_1trace(curTrace, GT_4CLASS, "\nThe process"
+				" id is %d\n", pCtxtList->pid);
+		GT_0trace(curTrace, GT_4CLASS, " -------------------"
+				"---------\n");
+		if (pCtxtList->resState == PROC_RES_ALLOCATED) {
+			GT_0trace(curTrace, GT_4CLASS, " \nThe Process"
+					" is in Allocated state\n");
+		} else {
+			GT_0trace(curTrace, GT_4CLASS, "\nThe Process"
+					" is in DeAllocated state\n");
+		}
+		GT_1trace(curTrace, GT_4CLASS, "\nThe  hProcessor"
+				" handle is: 0X%x\n",
+				(u32)pCtxtList->hProcessor);
+		if (pCtxtList->hProcessor != NULL) {
+			PROC_GetProcessorId(pCtxtList->hProcessor, &procID);
+			if (procID == DSP_UNIT) {
+				GT_0trace(curTrace, GT_4CLASS,
+					"\nProcess connected to"
+					" DSP Processor\n");
+			} else if (procID == IVA_UNIT) {
+				GT_0trace(curTrace, GT_4CLASS,
+					"\nProcess connected to"
+					" IVA Processor\n");
+			} else {
+				GT_0trace(curTrace, GT_7CLASS,
+					"\n***ERROR:Invalid Processor Id***\n");
+			}
+		}
+		pNodeRes = pCtxtList->pNodeList;
+		tempCount = 1;
+		while (pNodeRes != NULL) {
+			if (tempCount == 1)
+				GT_0trace(curTrace, GT_4CLASS,
+					"\n***The Nodes allocated by"
+					" this Process are***\n");
+			GT_2trace(curTrace, GT_4CLASS,
+					"Node # %d Node Handle hNode:0x%x\n",
+					tempCount, (u32)pNodeRes->hNode);
+			pNodeRes = pNodeRes->next;
+			tempCount++;
+		}
+		if (tempCount == 1)
+			GT_0trace(curTrace, GT_4CLASS,
+					"\n ***There are no Nodes"
+					" allocated by this Process***\n");
+		tempCount = 1;
+		pDSPHEAPRes = pCtxtList->pDSPHEAPList;
+		while (pDSPHEAPRes != NULL) {
+			if (tempCount == 1)
+				GT_0trace(curTrace, GT_4CLASS,
+						"\n***The Heaps allocated by"
+						" this Process are***\n");
+			GT_3trace(curTrace, GT_4CLASS,
+				"DSP Heap Resource Info: HEAP # %d "
+				"Mapped GPP Address:0x%x, Size: 0x%lx\n",
+				tempCount, (u32)pDSPHEAPRes->ulMpuAddr,
+				pDSPHEAPRes->heapSize);
+			pDSPHEAPRes = pDSPHEAPRes->next;
+			tempCount++;
+		}
+		if (tempCount == 1)
+			GT_0trace(curTrace, GT_4CLASS,
+				"\n ***There are no Heaps allocated"
+				" by this Process***\n");
+		tempCount = 1;
+		pDMMRes = pCtxtList->pDMMList;
+		while (pDMMRes != NULL) {
+			if (tempCount == 1)
+				GT_0trace(curTrace, GT_4CLASS,
+					"\n ***The DMM resources allocated by"
+					" this Process are***\n");
+			GT_3trace(curTrace, GT_4CLASS,
+				"DMM Resource Info: DMM # %d "
+				"Mapped GPP Address:0X%lx, Size: 0X%lx\n",
+				tempCount, pDMMRes->ulMpuAddr,
+				pDMMRes->dmmSize);
+			pDMMRes = pDMMRes->next;
+			tempCount++;
+		}
+		if (tempCount == 1)
+			GT_0trace(curTrace, GT_4CLASS,
+				"\n ***There are no DMM resources"
+				" allocated by this Process***\n");
+		tempCount = 1;
+		pSTRMRes = pCtxtList->pSTRMList;
+		while (pSTRMRes != NULL) {
+			if (tempCount == 1)
+				GT_0trace(curTrace, GT_4CLASS,
+					"\n***The Stream resources allocated by"
+					" this Process are***\n");
+			GT_2trace(curTrace, GT_4CLASS,
+				"Stream Resource info: STRM # %d"
+				"Stream Handle:0X%x\n",	tempCount,
+				(u32)pSTRMRes->hStream);
+			pSTRMRes = pSTRMRes->next;
+			tempCount++;
+		}
+		if (tempCount == 1)
+			GT_0trace(curTrace, GT_4CLASS,
+				"\n ***There are no Stream resources"
+				"allocated by this Process***\n");
+		pCtxtList = pCtxtList->next;
+	}
+	return status;
+}
+
+/* GPP PROCESS CLEANUP CODE END */
+#endif
+
+/*
+ *  ======== = DRV_Create ======== =
+ *  Purpose:
+ *      DRV Object gets created only once during Driver Loading.
+ */
+DSP_STATUS DRV_Create(OUT struct DRV_OBJECT **phDRVObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDRVObject = NULL;
+
+	DBC_Require(phDRVObject != NULL);
+	DBC_Require(cRefs > 0);
+	GT_1trace(curTrace, GT_ENTER, "Entering DRV_Create"
+			" phDRVObject 0x%x\n", phDRVObject);
+	MEM_AllocObject(pDRVObject, struct DRV_OBJECT, SIGNATURE);
+	if (pDRVObject) {
+		/* Create and Initialize List of device objects */
+		pDRVObject->devList = LST_Create();
+		if (pDRVObject->devList) {
+			/* Create and Initialize List of device Extension */
+			pDRVObject->devNodeString = LST_Create();
+			if (!(pDRVObject->devNodeString)) {
+				status = DSP_EFAIL;
+				GT_0trace(curTrace, GT_7CLASS,
+					 "Failed to Create DRV_EXT list ");
+				MEM_FreeObject(pDRVObject);
+			}
+		} else {
+			status = DSP_EFAIL;
+			GT_0trace(curTrace, GT_7CLASS,
+				 "Failed to Create Dev List ");
+			MEM_FreeObject(pDRVObject);
+		}
+	} else {
+		status = DSP_EFAIL;
+		GT_0trace(curTrace, GT_7CLASS,
+			 "Failed to Allocate Memory for DRV Obj");
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Store the DRV Object in the Registry */
+		if (DSP_SUCCEEDED
+		    (CFG_SetObject((u32) pDRVObject, REG_DRV_OBJECT))) {
+			GT_1trace(curTrace, GT_1CLASS,
+				 "DRV Obj Created pDrvObject 0x%x\n ",
+				 pDRVObject);
+			*phDRVObject = pDRVObject;
+		} else {
+			/* Free the DRV Object */
+			status = DSP_EFAIL;
+			MEM_Free(pDRVObject);
+			GT_0trace(curTrace, GT_7CLASS,
+				 "Failed to update the Registry with "
+				 "DRV Object ");
+		}
+	}
+	GT_2trace(curTrace, GT_ENTER,
+		 "Exiting DRV_Create: phDRVObject: 0x%x\tstatus:"
+		 "0x%x\n", phDRVObject, status);
+	DBC_Ensure(DSP_FAILED(status) ||
+		  MEM_IsValidHandle(pDRVObject, SIGNATURE));
+	return status;
+}
+
+/*
+ *  ======== DRV_Exit ========
+ *  Purpose:
+ *      Discontinue usage of the DRV module.
+ */
+void DRV_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	GT_0trace(curTrace, GT_5CLASS, "Entering DRV_Exit \n");
+
+	cRefs--;
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== = DRV_Destroy ======== =
+ *  purpose:
+ *      Invoked during bridge de-initialization
+ */
+DSP_STATUS DRV_Destroy(struct DRV_OBJECT *hDRVObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+
+	GT_1trace(curTrace, GT_ENTER, "Entering DRV_Destroy"
+			" hDRVObject 0x%x\n", hDRVObject);
+	/*
+	 *  Delete the List if it exists.Should not come here
+	 *  as the DRV_RemoveDevObject and the Last DRV_RequestResources
+	 *  removes the list if the lists are empty.
+	 */
+	if (pDRVObject->devList) {
+		/* Could assert if the list is not empty  */
+		LST_Delete(pDRVObject->devList);
+	}
+	if (pDRVObject->devNodeString) {
+		/* Could assert if the list is not empty */
+		LST_Delete(pDRVObject->devNodeString);
+	}
+	MEM_FreeObject(pDRVObject);
+	/* Update the DRV Object in Registry to be 0 */
+	(void)CFG_SetObject(0, REG_DRV_OBJECT);
+	GT_2trace(curTrace, GT_ENTER,
+		 "Exiting DRV_Destroy: hDRVObject: 0x%x\tstatus:"
+		 "0x%x\n", hDRVObject, status);
+	DBC_Ensure(!MEM_IsValidHandle(pDRVObject, SIGNATURE));
+	return status;
+}
+
+/*
+ *  ======== DRV_GetDevObject ========
+ *  Purpose:
+ *      Given a index, returns a handle to DevObject from the list.
+ */
+DSP_STATUS DRV_GetDevObject(u32 uIndex, struct DRV_OBJECT *hDrvObject,
+			   struct DEV_OBJECT **phDevObject)
+{
+	DSP_STATUS status = DSP_SOK;
+#if GT_TRACE	/* pDrvObject is used only for Assertions and debug messages.*/
+	struct DRV_OBJECT *pDrvObject = (struct DRV_OBJECT *)hDrvObject;
+#endif
+	struct DEV_OBJECT *pDevObject;
+	u32 i;
+	DBC_Require(MEM_IsValidHandle(pDrvObject, SIGNATURE));
+	DBC_Require(phDevObject != NULL);
+	DBC_Require(uIndex >= 0);
+	DBC_Require(cRefs > 0);
+	DBC_Assert(!(LST_IsEmpty(pDrvObject->devList)));
+	GT_3trace(curTrace, GT_ENTER,
+		 "Entered DRV_GetDevObject, args:\n\tuIndex: "
+		 "0x%x\n\thDrvObject:  0x%x\n\tphDevObject:  0x%x\n",
+		 uIndex, hDrvObject, phDevObject);
+	pDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+	for (i = 0; i < uIndex; i++) {
+		pDevObject =
+		   (struct DEV_OBJECT *)DRV_GetNextDevObject((u32)pDevObject);
+	}
+	if (pDevObject) {
+		*phDevObject = (struct DEV_OBJECT *) pDevObject;
+		status = DSP_SOK;
+	} else {
+		*phDevObject = NULL;
+		status = DSP_EFAIL;
+		GT_0trace(curTrace, GT_7CLASS,
+			 "DRV: Could not get the DevObject\n");
+	}
+	GT_2trace(curTrace, GT_ENTER,
+		 "Exiting Drv_GetDevObject\n\tstatus: 0x%x\n\t"
+		 "hDevObject: 0x%x\n", status, *phDevObject);
+	return status;
+}
+
+/*
+ *  ======== DRV_GetFirstDevObject ========
+ *  Purpose:
+ *      Retrieve the first Device Object handle from an internal linked list of
+ *      of DEV_OBJECTs maintained by DRV.
+ */
+u32 DRV_GetFirstDevObject(void)
+{
+	u32 dwDevObject = 0;
+	struct DRV_OBJECT *pDrvObject;
+
+	if (DSP_SUCCEEDED
+	    (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+		if ((pDrvObject->devList != NULL) &&
+		   !LST_IsEmpty(pDrvObject->devList)) {
+			dwDevObject = (u32) LST_First(pDrvObject->devList);
+		}
+	}
+
+	return dwDevObject;
+}
+
+/*
+ *  ======== DRV_GetFirstDevNodeString ========
+ *  Purpose:
+ *      Retrieve the first Device Extension from an internal linked list of
+ *      of Pointer to DevNode Strings maintained by DRV.
+ */
+u32 DRV_GetFirstDevExtension(void)
+{
+	u32 dwDevExtension = 0;
+	struct DRV_OBJECT *pDrvObject;
+
+	if (DSP_SUCCEEDED
+	    (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+
+		if ((pDrvObject->devNodeString != NULL) &&
+		   !LST_IsEmpty(pDrvObject->devNodeString)) {
+			dwDevExtension = (u32)LST_First(pDrvObject->
+							devNodeString);
+		}
+	}
+
+	return dwDevExtension;
+}
+
+/*
+ *  ======== DRV_GetNextDevObject ========
+ *  Purpose:
+ *      Retrieve the next Device Object handle from an internal linked list of
+ *      of DEV_OBJECTs maintained by DRV, after having previously called
+ *      DRV_GetFirstDevObject() and zero or more DRV_GetNext.
+ */
+u32 DRV_GetNextDevObject(u32 hDevObject)
+{
+	u32 dwNextDevObject = 0;
+	struct DRV_OBJECT *pDrvObject;
+
+	DBC_Require(hDevObject != 0);
+
+	if (DSP_SUCCEEDED
+	    (CFG_GetObject((u32 *)&pDrvObject, REG_DRV_OBJECT))) {
+
+		if ((pDrvObject->devList != NULL) &&
+		   !LST_IsEmpty(pDrvObject->devList)) {
+			dwNextDevObject = (u32)LST_Next(pDrvObject->devList,
+					  (struct LST_ELEM *)hDevObject);
+		}
+	}
+	return dwNextDevObject;
+}
+
+/*
+ *  ======== DRV_GetNextDevExtension ========
+ *  Purpose:
+ *      Retrieve the next Device Extension from an internal linked list of
+ *      of pointer to DevNodeString maintained by DRV, after having previously
+ *      called DRV_GetFirstDevExtension() and zero or more
+ *      DRV_GetNextDevExtension().
+ */
+u32 DRV_GetNextDevExtension(u32 hDevExtension)
+{
+	u32 dwDevExtension = 0;
+	struct DRV_OBJECT *pDrvObject;
+
+	DBC_Require(hDevExtension != 0);
+
+	if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDrvObject,
+	   REG_DRV_OBJECT))) {
+		if ((pDrvObject->devNodeString != NULL) &&
+		   !LST_IsEmpty(pDrvObject->devNodeString)) {
+			dwDevExtension = (u32)LST_Next(pDrvObject->
+				devNodeString,
+				(struct LST_ELEM *)hDevExtension);
+		}
+	}
+
+	return dwDevExtension;
+}
+
+/*
+ *  ======== DRV_Init ========
+ *  Purpose:
+ *      Initialize DRV module private state.
+ */
+DSP_STATUS DRV_Init(void)
+{
+	s32 fRetval = 1;	/* function return value */
+
+	DBC_Require(cRefs >= 0);
+
+	if (fRetval)
+		cRefs++;
+
+	GT_1trace(curTrace, GT_5CLASS, "Entering DRV_Entry  crefs 0x%x \n",
+		 cRefs);
+
+	DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+	return fRetval;
+}
+
+/*
+ *  ======== DRV_InsertDevObject ========
+ *  Purpose:
+ *      Insert a DevObject into the list of Manager object.
+ */
+DSP_STATUS DRV_InsertDevObject(struct DRV_OBJECT *hDRVObject,
+			       struct DEV_OBJECT *hDevObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hDevObject != NULL);
+	DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+	DBC_Assert(pDRVObject->devList);
+
+	GT_2trace(curTrace, GT_ENTER,
+		 "Entering DRV_InsertProcObject hDRVObject "
+		 "0x%x\n, hDevObject 0x%x\n", hDRVObject, hDevObject);
+
+	LST_PutTail(pDRVObject->devList, (struct LST_ELEM *)hDevObject);
+
+	GT_1trace(curTrace, GT_ENTER,
+		 "Exiting InsertDevObject status 0x%x\n", status);
+
+	DBC_Ensure(DSP_SUCCEEDED(status) && !LST_IsEmpty(pDRVObject->devList));
+
+	return status;
+}
+
+/*
+ *  ======== DRV_RemoveDevObject ========
+ *  Purpose:
+ *      Search for and remove a DeviceObject from the given list of DRV
+ *      objects.
+ */
+DSP_STATUS DRV_RemoveDevObject(struct DRV_OBJECT *hDRVObject,
+			       struct DEV_OBJECT *hDevObject)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDRVObject;
+	struct LST_ELEM *pCurElem;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(pDRVObject, SIGNATURE));
+	DBC_Require(hDevObject != NULL);
+
+	DBC_Require(pDRVObject->devList != NULL);
+	DBC_Require(!LST_IsEmpty(pDRVObject->devList));
+
+	GT_2trace(curTrace, GT_ENTER,
+		 "Entering DRV_RemoveDevObject hDevObject "
+		 "0x%x\n, hDRVObject 0x%x\n", hDevObject, hDRVObject);
+	/* Search list for pProcObject: */
+	for (pCurElem = LST_First(pDRVObject->devList); pCurElem != NULL;
+	    pCurElem = LST_Next(pDRVObject->devList, pCurElem)) {
+		/* If found, remove it. */
+		if ((struct DEV_OBJECT *) pCurElem == hDevObject) {
+			LST_RemoveElem(pDRVObject->devList, pCurElem);
+			status = DSP_SOK;
+			break;
+		}
+	}
+	/* Remove list if empty. */
+	if (LST_IsEmpty(pDRVObject->devList)) {
+		LST_Delete(pDRVObject->devList);
+		pDRVObject->devList = NULL;
+	}
+	DBC_Ensure((pDRVObject->devList == NULL) ||
+		  !LST_IsEmpty(pDRVObject->devList));
+	GT_1trace(curTrace, GT_ENTER,
+		 "DRV_RemoveDevObject returning 0x%x\n", status);
+	return status;
+}
+
+/*
+ *  ======== DRV_RequestResources ========
+ *  Purpose:
+ *      Requests  resources from the OS.
+ */
+DSP_STATUS DRV_RequestResources(u32 dwContext, u32 *pDevNodeString)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDRVObject;
+	struct DRV_EXT *pszdevNode;
+
+	DBC_Require(dwContext != 0);
+	DBC_Require(pDevNodeString != NULL);
+	GT_0trace(curTrace, GT_ENTER, "Entering DRV_RequestResources\n");
+	/*
+	 *  Allocate memory to hold the string. This will live untill
+	 *  it is freed in the Release resources. Update the driver object
+	 *  list.
+	 */
+	if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&pDRVObject,
+	   REG_DRV_OBJECT))) {
+		pszdevNode = MEM_Calloc(sizeof(struct DRV_EXT), MEM_NONPAGED);
+		if (pszdevNode) {
+			LST_InitElem(&pszdevNode->link);
+			CSL_Strcpyn((char *) pszdevNode->szString,
+				 (char *)dwContext, MAXREGPATHLENGTH);
+			/* Update the Driver Object List */
+			*pDevNodeString = (u32)pszdevNode->szString;
+			LST_PutTail(pDRVObject->devNodeString,
+				(struct LST_ELEM *)pszdevNode);
+		} else {
+			GT_0trace(curTrace, GT_7CLASS,
+				"Failed to Allocate Memory devNodeString ");
+			status = DSP_EFAIL;
+			*pDevNodeString = 0;
+		}
+	} else {
+		status = DSP_EFAIL;
+		GT_0trace(curTrace, GT_7CLASS,
+			 "Failed to get Driver Object from Registry");
+		*pDevNodeString = 0;
+	}
+
+	if (!(CSL_Strcmp((char *) dwContext, "TIOMAP1510"))) {
+		GT_0trace(curTrace, GT_1CLASS,
+			  " Allocating resources for UMA \n");
+		status = RequestBridgeResourcesDSP(dwContext, DRV_ASSIGN);
+	} else {
+		status = DSP_EFAIL;
+		GT_0trace(curTrace, GT_7CLASS, "Unknown Device ");
+	}
+
+	if (DSP_FAILED(status)) {
+		GT_0trace(curTrace, GT_7CLASS,
+			 "Failed to reserve bridge resources ");
+	}
+	DBC_Ensure((DSP_SUCCEEDED(status) && pDevNodeString != 0 &&
+		  !LST_IsEmpty(pDRVObject->devNodeString)) ||
+		  (DSP_FAILED(status) && *pDevNodeString == 0));
+
+	return status;
+}
+
+/*
+ *  ======== DRV_ReleaseResources ========
+ *  Purpose:
+ *      Releases  resources from the OS.
+ */
+DSP_STATUS DRV_ReleaseResources(u32 dwContext, struct DRV_OBJECT *hDrvObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DRV_OBJECT *pDRVObject = (struct DRV_OBJECT *)hDrvObject;
+	struct DRV_EXT *pszdevNode;
+
+	GT_0trace(curTrace, GT_ENTER, "Entering DRV_Release Resources\n");
+
+	if (!(CSL_Strcmp((char *)((struct DRV_EXT *)dwContext)->szString,
+	   "TIOMAP1510"))) {
+		GT_0trace(curTrace, GT_1CLASS,
+			 " Releasing DSP-Bridge resources \n");
+		status = RequestBridgeResources(dwContext, DRV_RELEASE);
+	} else {
+		GT_0trace(curTrace, GT_1CLASS, " Unknown device\n");
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		GT_0trace(curTrace, GT_1CLASS,
+			 "Failed to relese bridge resources\n");
+	}
+
+	/*
+	 *  Irrespective of the status go ahead and clean it
+	 *  The following will over write the status.
+	 */
+	for (pszdevNode = (struct DRV_EXT *)DRV_GetFirstDevExtension();
+	    pszdevNode != NULL; pszdevNode = (struct DRV_EXT *)
+	    DRV_GetNextDevExtension((u32)pszdevNode)) {
+		if ((u32)pszdevNode == dwContext) {
+			/* Found it */
+			/* Delete from the Driver object list */
+			LST_RemoveElem(pDRVObject->devNodeString,
+				      (struct LST_ELEM *)pszdevNode);
+			MEM_Free((void *) pszdevNode);
+			break;
+		}
+		/* Delete the List if it is empty */
+		if (LST_IsEmpty(pDRVObject->devNodeString)) {
+			LST_Delete(pDRVObject->devNodeString);
+			pDRVObject->devNodeString = NULL;
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== RequestBridgeResources ========
+ *  Purpose:
+ *      Reserves shared memory for bridge.
+ */
+static DSP_STATUS RequestBridgeResources(u32 dwContext, s32 bRequest)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CFG_HOSTRES *pResources;
+	u32 dwBuffSize;
+
+	struct DRV_EXT *driverExt;
+	u32 shm_size;
+
+	DBC_Require(dwContext != 0);
+
+	GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResources \n");
+
+	if (!bRequest) {
+		driverExt = (struct DRV_EXT *)dwContext;
+		/* Releasing resources by deleting the registry key  */
+		dwBuffSize = sizeof(struct CFG_HOSTRES);
+		pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+		if (DSP_FAILED(REG_GetValue(NULL, (char *)driverExt->szString,
+		   CURRENTCONFIG, (u8 *)pResources, &dwBuffSize))) {
+			status = CFG_E_RESOURCENOTAVAIL;
+			GT_0trace(curTrace, GT_1CLASS,
+				 "REG_GetValue Failed \n");
+		} else {
+			GT_0trace(curTrace, GT_1CLASS,
+				 "REG_GetValue Succeeded \n");
+		}
+
+		if (pResources != NULL) {
+			dwBuffSize = sizeof(shm_size);
+			status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
+				(u8 *)&shm_size, &dwBuffSize);
+			if (DSP_SUCCEEDED(status)) {
+				if ((pResources->dwMemBase[1]) &&
+				   (pResources->dwMemPhys[1])) {
+					MEM_FreePhysMem((void *)pResources->
+					dwMemBase[1], pResources->dwMemPhys[1],
+					shm_size);
+				}
+			} else {
+				GT_1trace(curTrace, GT_7CLASS,
+					"Error getting SHM size from registry: "
+					"%x. Not calling MEM_FreePhysMem\n",
+					status);
+			}
+			pResources->dwMemBase[1] = 0;
+			pResources->dwMemPhys[1] = 0;
+
+			if (pResources->dwPrmBase)
+				iounmap((void *)pResources->dwPrmBase);
+			if (pResources->dwCmBase)
+				iounmap((void *)pResources->dwCmBase);
+			if (pResources->dwMboxBase)
+				iounmap((void *)pResources->dwMboxBase);
+			if (pResources->dwMemBase[0])
+				iounmap((void *)pResources->dwMemBase[0]);
+			if (pResources->dwMemBase[2])
+				iounmap((void *)pResources->dwMemBase[2]);
+			if (pResources->dwMemBase[3])
+				iounmap((void *)pResources->dwMemBase[3]);
+			if (pResources->dwMemBase[4])
+				iounmap((void *)pResources->dwMemBase[4]);
+			if (pResources->dwWdTimerDspBase)
+				iounmap((void *)pResources->dwWdTimerDspBase);
+			if (pResources->dwDmmuBase)
+				iounmap((void *)pResources->dwDmmuBase);
+			if (pResources->dwPerBase)
+				iounmap((void *)pResources->dwPerBase);
+
+			if (pResources->dwSysCtrlBase) {
+				iounmap((void *)pResources->dwSysCtrlBase);
+				/* don't set pResources->dwSysCtrlBase to null
+				 * as it is used in BOARD_Stop */
+			}
+			pResources->dwPrmBase = (u32) NULL;
+			pResources->dwCmBase = (u32) NULL;
+			pResources->dwMboxBase = (u32) NULL;
+			pResources->dwMemBase[0] = (u32) NULL;
+			pResources->dwMemBase[2] = (u32) NULL;
+			pResources->dwMemBase[3] = (u32) NULL;
+			pResources->dwMemBase[4] = (u32) NULL;
+			pResources->dwWdTimerDspBase = (u32) NULL;
+			pResources->dwDmmuBase = (u32) NULL;
+
+			dwBuffSize = sizeof(struct CFG_HOSTRES);
+			status = REG_SetValue(NULL, (char *)driverExt->szString,
+				 CURRENTCONFIG, REG_BINARY, (u8 *)pResources,
+				 (u32)dwBuffSize);
+			/*  Set all the other entries to NULL */
+			MEM_Free(pResources);
+		}
+		GT_0trace(curTrace, GT_ENTER, " <- RequestBridgeResources \n");
+		return status;
+	}
+	dwBuffSize = sizeof(struct CFG_HOSTRES);
+	pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+	if (pResources != NULL) {
+		/* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
+		pResources->wNumMemWindows = 2;
+		/* First window is for DSP internal memory */
+
+		pResources->dwPrmBase = (u32)ioremap(OMAP_IVA2_PRM_BASE,
+							OMAP_IVA2_PRM_SIZE);
+		pResources->dwCmBase = (u32)ioremap(OMAP_IVA2_CM_BASE,
+							OMAP_IVA2_CM_SIZE);
+		pResources->dwMboxBase = (u32)ioremap(OMAP_MBOX_BASE,
+							OMAP_MBOX_SIZE);
+		pResources->dwSysCtrlBase = (u32)ioremap(OMAP_SYSC_BASE,
+							OMAP_SYSC_SIZE);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
+			 pResources->dwMemBase[0]);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
+			 pResources->dwMemBase[3]);
+		GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
+							pResources->dwPrmBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
+							pResources->dwCmBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
+						pResources->dwWdTimerDspBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
+						pResources->dwMboxBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
+						pResources->dwDmmuBase);
+
+		/* for 24xx base port is not mapping the mamory for DSP
+		 * internal memory TODO Do a ioremap here */
+		/* Second window is for DSP external memory shared with MPU */
+		if (DSP_SUCCEEDED(status)) {
+			/* for Linux, these are hard-coded values */
+			pResources->dwBusType = 0;
+			pResources->bIRQRegisters = 0;
+			pResources->bIRQAttrib = 0;
+			pResources->dwOffsetForMonitor = 0;
+			pResources->dwChnlOffset = 0;
+			/* CHNL_MAXCHANNELS */
+			pResources->dwNumChnls = CHNL_MAXCHANNELS;
+			pResources->dwChnlBufSize = 0x400;
+			dwBuffSize = sizeof(struct CFG_HOSTRES);
+			status = REG_SetValue(NULL, (char *) dwContext,
+					     CURRENTCONFIG, REG_BINARY,
+					     (u8 *)pResources,
+					     sizeof(struct CFG_HOSTRES));
+			if (DSP_SUCCEEDED(status)) {
+				GT_0trace(curTrace, GT_1CLASS,
+					 " Successfully set the registry "
+					 "value for CURRENTCONFIG\n");
+			} else {
+				GT_0trace(curTrace, GT_7CLASS,
+					 " Failed to set the registry "
+					 "value for CURRENTCONFIG\n");
+			}
+		}
+		MEM_Free(pResources);
+	}
+	/* End Mem alloc */
+	return status;
+}
+
+/*
+ *  ======== RequestBridgeResourcesDSP ========
+ *  Purpose:
+ *      Reserves shared memory for bridge.
+ */
+static DSP_STATUS RequestBridgeResourcesDSP(u32 dwContext, s32 bRequest)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct CFG_HOSTRES *pResources;
+	u32 dwBuffSize;
+	u32 dmaAddr;
+	u32 shm_size;
+
+	DBC_Require(dwContext != 0);
+
+	GT_0trace(curTrace, GT_ENTER, "->RequestBridgeResourcesDSP \n");
+
+	dwBuffSize = sizeof(struct CFG_HOSTRES);
+
+	pResources = MEM_Calloc(dwBuffSize, MEM_NONPAGED);
+
+	if (pResources != NULL) {
+		if (DSP_FAILED(CFG_GetHostResources((struct CFG_DEVNODE *)
+		   dwContext, pResources))) {
+			/* Call CFG_GetHostResources to get reserve resouces */
+			status = RequestBridgeResources(dwContext, bRequest);
+			if (DSP_SUCCEEDED(status)) {
+				status = CFG_GetHostResources
+					((struct CFG_DEVNODE *) dwContext,
+					pResources);
+			}
+		}
+		/* wNumMemWindows must not be more than CFG_MAXMEMREGISTERS */
+		pResources->wNumMemWindows = 4;
+
+		pResources->dwMemBase[0] = 0;
+		pResources->dwMemBase[2] = (u32)ioremap(OMAP_DSP_MEM1_BASE,
+							OMAP_DSP_MEM1_SIZE);
+		pResources->dwMemBase[3] = (u32)ioremap(OMAP_DSP_MEM2_BASE,
+							OMAP_DSP_MEM2_SIZE);
+		pResources->dwMemBase[4] = (u32)ioremap(OMAP_DSP_MEM3_BASE,
+							OMAP_DSP_MEM3_SIZE);
+		pResources->dwPerBase = (u32)ioremap(OMAP_PER_CM_BASE,
+							OMAP_PER_CM_SIZE);
+		pResources->dwDmmuBase = (u32)ioremap(OMAP_DMMU_BASE,
+							OMAP_DMMU_SIZE);
+		pResources->dwWdTimerDspBase = 0;
+
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[0] 0x%x\n",
+						pResources->dwMemBase[0]);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[1] 0x%x\n",
+						pResources->dwMemBase[1]);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[2] 0x%x\n",
+						pResources->dwMemBase[2]);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[3] 0x%x\n",
+						pResources->dwMemBase[3]);
+		GT_1trace(curTrace, GT_2CLASS, "dwMemBase[4] 0x%x\n",
+						pResources->dwMemBase[4]);
+		GT_1trace(curTrace, GT_2CLASS, "dwPrmBase 0x%x\n",
+						pResources->dwPrmBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwCmBase 0x%x\n",
+						pResources->dwCmBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwWdTimerDspBase 0x%x\n",
+						pResources->dwWdTimerDspBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwMboxBase 0x%x\n",
+						pResources->dwMboxBase);
+		GT_1trace(curTrace, GT_2CLASS, "dwDmmuBase 0x%x\n",
+						pResources->dwDmmuBase);
+		dwBuffSize = sizeof(shm_size);
+		status = REG_GetValue(NULL, CURRENTCONFIG, SHMSIZE,
+				     (u8 *)&shm_size, &dwBuffSize);
+		if (DSP_SUCCEEDED(status)) {
+			/* Allocate Physically contiguous,
+			 * non-cacheable  memory */
+			pResources->dwMemBase[1] =
+				(u32)MEM_AllocPhysMem(shm_size, 0x100000,
+							&dmaAddr);
+			if (pResources->dwMemBase[1] == 0) {
+				status = DSP_EMEMORY;
+				GT_0trace(curTrace, GT_7CLASS,
+					 "SHM reservation Failed\n");
+			} else {
+				pResources->dwMemLength[1] = shm_size;
+				pResources->dwMemPhys[1] = dmaAddr;
+
+				GT_3trace(curTrace, GT_1CLASS,
+					 "Bridge SHM address 0x%x dmaAddr"
+					 " %x size %x\n",
+					 pResources->dwMemBase[1],
+					 dmaAddr, shm_size);
+			}
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* for Linux, these are hard-coded values */
+			pResources->dwBusType = 0;
+			pResources->bIRQRegisters = 0;
+			pResources->bIRQAttrib = 0;
+			pResources->dwOffsetForMonitor = 0;
+			pResources->dwChnlOffset = 0;
+			/* CHNL_MAXCHANNELS */
+			pResources->dwNumChnls = CHNL_MAXCHANNELS;
+			pResources->dwChnlBufSize = 0x400;
+			dwBuffSize = sizeof(struct CFG_HOSTRES);
+			status = REG_SetValue(NULL, (char *)dwContext,
+					     CURRENTCONFIG, REG_BINARY,
+					     (u8 *)pResources,
+					     sizeof(struct CFG_HOSTRES));
+			if (DSP_SUCCEEDED(status)) {
+				GT_0trace(curTrace, GT_1CLASS,
+					 " Successfully set the registry"
+					 " value for CURRENTCONFIG\n");
+			} else {
+				GT_0trace(curTrace, GT_7CLASS,
+					 " Failed to set the registry value"
+					 " for CURRENTCONFIG\n");
+			}
+		}
+		MEM_Free(pResources);
+	}
+	/* End Mem alloc */
+	return status;
+}
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.c b/drivers/dsp/bridge/rmgr/drv_interface.c
new file mode 100644
index 0000000..7bc8ab5
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv_interface.c
@@ -0,0 +1,780 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/drv_interface.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
+ *  ======== linux_driver.c ========
+ *  Description:
+ *      DSP/BIOS Bridge driver interface.
+ *
+ *  Public Functions:
+ *      driver_init
+ *      driver_exit
+ *      driver_open
+ *      driver_release
+ *      driver_ioctl
+ *      driver_mmap
+ *
+ *! Revision History
+ *! ================
+ *! 21-Apr-2004 map   Deprecated use of MODULE_PARM for kernel versions
+ *!		   greater than 2.5, use module_param.
+ *! 08-Mar-2004 sb    Added the dsp_debug argument, which keeps the DSP in self
+ *!		   loop after image load and waits in a loop for DSP to start
+ *! 16-Feb-2004 vp    Deprecated the usage of MOD_INC_USE_COUNT and
+ *! 						MOD_DEC_USE_COUNT
+ *!		   for kernel versions greater than 2.5
+ *! 20-May-2003 vp    Added unregister functions for the DPM.
+ *! 24-Mar-2003 sb    Pass pid instead of driverContext to DSP_Close
+ *! 24-Mar-2003 vp    Added Power Management support.
+ *! 21-Mar-2003 sb    Configure SHM size using insmod argument shm_size
+ *! 10-Feb-2003 vp    Updated based on code review comments
+ *! 18-Oct-2002 sb    Created initial version
+ */
+
+/*  ----------------------------------- Host OS */
+
+#include <host_os.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+
+#ifdef MODULE
+#include <linux/module.h>
+#endif
+
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/moduleparam.h>
+#include <linux/cdev.h>
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+#include <asm/arch/prcm_34xx.h>
+#endif
+#endif
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <gt.h>
+#include <dbc.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <services.h>
+#include <sync.h>
+#include <reg.h>
+#include <csl.h>
+#include <prcs.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <wcdioctl.h>
+#include <_dcd.h>
+#include <dspdrv.h>
+#include <dbreg.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <pwr.h>
+
+/*  ----------------------------------- This */
+#include <drv_interface.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <cfg.h>
+#include <resourcecleanup.h>
+#include <chnl.h>
+#include <proc.h>
+#include <cfg.h>
+#include <dev.h>
+#include <drvdefs.h>
+#include <drv.h>
+#include <dbreg.h>
+#endif
+
+#define BRIDGE_NAME "C6410"
+/*  ----------------------------------- Globals */
+#define DRIVER_NAME  "DspBridge"
+#define DRIVER_MAJOR 0		/* Linux assigns our Major device number */
+#define DRIVER_MINOR 0		/* Linux assigns our Major device number */
+s32 dsp_debug;
+
+/* This is a test variable used by Bridge to test different sleep states */
+static s32 dsp_test_sleepstate;
+struct bridge_dev {
+	struct cdev cdev;
+};
+
+static struct bridge_dev *bridge_device;
+
+static struct class *bridge_class;
+
+static u32 driverContext;
+static char *GT_str;
+static s32 driver_major = DRIVER_MAJOR;
+static s32 driver_minor = DRIVER_MINOR;
+static char *base_img;
+char *iva_img;
+static char *num_procs = "C55=1";
+static s32 shm_size = 0x400000;	/* 4 MB */
+static u32 phys_mempool_base = 0x87000000;
+static u32 phys_mempool_size = 0x600000;
+#if !defined(CONFIG_ARCH_OMAP2430) && !defined(CONFIG_ARCH_OMAP3430)
+static int tc_wordswapon = 1;	/* Default value is always TRUE */
+#else
+static int tc_wordswapon = 0;	/* Default value is always TRUE */
+#endif
+
+
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+struct omap34xx_bridge_suspend_data {
+	int suspended;
+	wait_queue_head_t suspend_wq;
+};
+
+static struct omap34xx_bridge_suspend_data bridge_suspend_data;
+
+int omap34xxbridge_suspend_lockout(struct omap34xx_bridge_suspend_data *s,
+				  struct file *f)
+{
+	if ((s)->suspended) {
+		if ((f)->f_flags & O_NONBLOCK)
+			return DSP_EDPMSUSPEND;
+		wait_event_interruptible((s)->suspend_wq, (s)->suspended == 0);
+	}
+	return 0;
+}
+
+#endif
+
+#ifdef DEBUG
+module_param(GT_str, charp, 0);
+MODULE_PARM_DESC(GT_str, "GT string, default = NULL");
+
+module_param(dsp_debug, int, 0);
+MODULE_PARM_DESC(dsp_debug, "Wait after loading DSP image. default = false");
+#endif
+
+module_param(driver_major, int, 0);	/* Driver's major number */
+MODULE_PARM_DESC(driver_major, "Major device number, default = 0 (auto)");
+
+module_param(driver_minor, int, 0);	/* Driver's major number */
+MODULE_PARM_DESC(driver_minor, "Minor device number, default = 0 (auto)");
+
+module_param(dsp_test_sleepstate, int, 0);
+MODULE_PARM_DESC(dsp_test_sleepstate, "DSP Sleep state = 0");
+
+module_param(base_img, charp, 0);
+MODULE_PARM_DESC(base_img, "DSP base image, default = NULL");
+
+module_param(shm_size, int, 0);
+MODULE_PARM_DESC(shm_size, "SHM size, default = 4 MB, minimum = 64 KB");
+
+module_param(phys_mempool_base, uint, 0);
+MODULE_PARM_DESC(phys_mempool_base,
+		"Physical memory pool base passed to driver");
+
+module_param(phys_mempool_size, uint, 0);
+MODULE_PARM_DESC(phys_mempool_size,
+		"Physical memory pool size passed to driver");
+module_param(tc_wordswapon, int, 0);
+MODULE_PARM_DESC(tc_wordswapon, "TC Word Swap Option. default = 0");
+
+MODULE_AUTHOR("Texas Instruments");
+MODULE_LICENSE("GPL");
+
+static char *driver_name = DRIVER_NAME;
+static struct GT_Mask driverTrace;
+
+static struct file_operations bridge_fops = {
+	.open		= bridge_open,
+	.release	= bridge_release,
+	.ioctl		= bridge_ioctl,
+	.mmap		= bridge_mmap,
+};
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+u32 timeOut = 1000;
+
+static int bridge_suspend(struct platform_device *pdev, pm_message_t state);
+static int bridge_resume(struct platform_device *pdev);
+#endif
+
+static void bridge_free(struct device *dev);
+
+static int omap34xx_bridge_probe(struct platform_device *dev);
+
+static int omap34xx_bridge_probe(struct platform_device *dev)
+{
+	return 0;
+}
+
+#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+static struct platform_device omap_dspbridge_dev = {
+		.name = BRIDGE_NAME,
+		.id = -1,
+		.num_resources = 0,
+		.dev = {
+		.release = bridge_free,
+		},
+		.resource = NULL,
+};
+
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+/* The number of OPPs supported in the system */
+s32 dsp_max_opps = CO_VDD1_OPP5-2;
+u32 vdd1_dsp_freq[6][4] = {
+
+	 {0, 0, 0, 0},
+
+	 {0, 90000, 0, 86000},
+
+	{0, 180000, 80000, 170000},
+
+	{0, 360000, 160000, 340000},
+
+	{0, 396000, 325000, 376000},
+
+	{0, 430000, 355000, 430000},
+};
+
+/* The handle for setting constraints */
+struct constraint_handle *dsp_constraint_handle;
+struct constraint_handle *mpu_constraint_handle;
+
+static int dspbridge_post_scale(struct notifier_block *op, unsigned long level,
+				void *ptr)
+{
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	PWR_PM_PostScale(PRCM_VDD1, level);
+#endif
+#endif
+	return 0;
+}
+
+
+static struct notifier_block omap34xxbridge_post_scale = {
+	.notifier_call = dspbridge_post_scale,
+	NULL,
+};
+static struct constraint_id cnstr_id_vdd1 = {
+	.type = RES_OPP_CO,
+	.data = (void *)"vdd1_opp",
+};
+#endif
+#endif
+
+static struct platform_driver bridge_driver_ldm = {
+      .driver = {
+	      .owner	= THIS_MODULE,
+	      .name     = BRIDGE_NAME,
+	 },
+      .probe = omap34xx_bridge_probe,
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+      .suspend = bridge_suspend,
+      .resume = bridge_resume,
+#endif
+      .shutdown = NULL,
+      .remove = NULL,
+
+};
+
+#endif
+
+/* Initialization routine. Executed when the driver is loaded (as a kernel
+ * module), or when the system is booted (when included as part of the kernel
+ * image). */
+static int __init bridge_init(void)
+{
+	int status;
+	u32 initStatus;
+	u32 temp;
+	dev_t   dev = 0 ;
+	int     result;
+
+	/* use 2.6 device model */
+	if (driver_major) {
+		dev = MKDEV(driver_major, driver_minor);
+		result = register_chrdev_region(dev, 1, driver_name);
+	} else {
+		result = alloc_chrdev_region(&dev, driver_minor, 1,
+					    driver_name);
+		driver_major = MAJOR(dev);
+	}
+
+	if (result < 0) {
+		GT_1trace(driverTrace, GT_7CLASS, "bridge_init: "
+				"Can't get Major %d \n", driver_major);
+		return result;
+	}
+
+	bridge_device = kmalloc(sizeof(struct bridge_dev), GFP_KERNEL);
+	if (!bridge_device) {
+		result = -ENOMEM;
+		unregister_chrdev_region(dev, 1);
+		return result;
+	}
+	memset(bridge_device, 0, sizeof(struct bridge_dev));
+	cdev_init(&bridge_device->cdev, &bridge_fops);
+	bridge_device->cdev.owner = THIS_MODULE;
+	bridge_device->cdev.ops = &bridge_fops;
+
+	status = cdev_add(&bridge_device->cdev, dev, 1);
+
+	if (status) {
+		GT_0trace(driverTrace, GT_7CLASS,
+				"Failed to add the bridge device \n");
+		return status;
+	}
+
+	/* udev support */
+	bridge_class = class_create(THIS_MODULE, "ti_bridge");
+
+	if (IS_ERR(bridge_class))
+		GT_0trace(driverTrace, GT_7CLASS,
+				"Error creating bridge class \n");
+
+	device_create(bridge_class, NULL, MKDEV(driver_major,
+			driver_minor), NULL, "DspBridge");
+
+	GT_init();
+	GT_create(&driverTrace, "LD");
+
+#ifdef DEBUG
+	if (GT_str)
+		GT_set(GT_str);
+
+#else
+#if (defined DDSP_DEBUG_PRODUCT) && GT_TRACE
+	GT_set("**=67");
+#endif
+#endif
+
+
+	GT_0trace(driverTrace, GT_ENTER, "-> driver_init\n");
+	status = platform_driver_register(&bridge_driver_ldm);
+	if (!status)
+		status = platform_device_register(&omap_dspbridge_dev);
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+	/* Initialize the wait queue */
+	if (!status) {
+		bridge_suspend_data.suspended = 0;
+		init_waitqueue_head(&bridge_suspend_data.suspend_wq);
+	}
+#endif
+
+	SERVICES_Init();
+
+	/*  Autostart flag.  This should be set to true if the DSP image should
+	 *  be loaded and run during bridge module initialization  */
+
+	if (base_img) {
+		temp = true;
+		REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+			    sizeof(temp));
+		REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *)base_img,
+			    CSL_Strlen(base_img) + 1);
+	} else {
+		temp = false;
+		REG_SetValue(NULL, NULL, AUTOSTART, REG_DWORD, (u8 *)&temp,
+			    sizeof(temp));
+		REG_SetValue(NULL, NULL, DEFEXEC, REG_SZ, (u8 *) "\0", (u32)2);
+	}
+	REG_SetValue(NULL, NULL, NUMPROCS, REG_SZ, (u8 *) num_procs,
+		    CSL_Strlen(num_procs) + 1);
+
+	if (shm_size >= 0x10000) {	/* 64 KB */
+		initStatus = REG_SetValue(NULL, NULL, SHMSIZE, REG_DWORD,
+					  (u8 *)&shm_size, sizeof(shm_size));
+	} else {
+		initStatus = DSP_EINVALIDARG;
+		status = -1;
+		GT_0trace(driverTrace, GT_7CLASS,
+			 "SHM size must be atleast 64 KB\n");
+	}
+	GT_1trace(driverTrace, GT_7CLASS,
+		 "requested shm_size = 0x%x\n", shm_size);
+
+	if (phys_mempool_base > 0x0) {
+		initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLBASE,
+					 REG_DWORD, (u8 *)&phys_mempool_base,
+					 sizeof(phys_mempool_base));
+	}
+	GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_base = 0x%x \n",
+		 phys_mempool_base);
+
+	if (phys_mempool_size > 0x0) {
+		initStatus = REG_SetValue(NULL, NULL, PHYSMEMPOOLSIZE,
+					 REG_DWORD, (u8 *)&phys_mempool_size,
+					 sizeof(phys_mempool_size));
+	}
+	GT_1trace(driverTrace, GT_7CLASS, "phys_mempool_size = 0x%x \n",
+		 phys_mempool_base);
+	if ((phys_mempool_base > 0x0) && (phys_mempool_size > 0x0))
+		MEM_ExtPhysPoolInit(phys_mempool_base, phys_mempool_size);
+	if (tc_wordswapon) {
+		GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is enabled\n");
+		REG_SetValue(NULL, NULL, TCWORDSWAP, REG_DWORD,
+			    (u8 *)&tc_wordswapon, sizeof(tc_wordswapon));
+	} else {
+		GT_0trace(driverTrace, GT_7CLASS, "TC Word Swap is disabled\n");
+		REG_SetValue(NULL, NULL, TCWORDSWAP,
+			    REG_DWORD, (u8 *)&tc_wordswapon,
+			    sizeof(tc_wordswapon));
+	}
+	if (DSP_SUCCEEDED(initStatus)) {
+		driverContext = DSP_Init(&initStatus);
+		if (DSP_FAILED(initStatus)) {
+			status = -1;
+			GT_0trace(driverTrace, GT_7CLASS,
+				 "DSP/BIOS Bridge initialization Failed\n");
+		} else {
+			GT_0trace(driverTrace, GT_5CLASS,
+					"DSP/BIOS Bridge driver loaded\n");
+		}
+ #ifndef CONFIG_DISABLE_BRIDGE_PM
+ #ifndef CONFIG_DISABLE_BRIDGE_DVFS
+		/* Register for the constraints */
+		dsp_constraint_handle = constraint_get("dspbridge",
+						      &cnstr_id_vdd1);
+		constraint_register_post_notification(dsp_constraint_handle,
+						 &omap34xxbridge_post_scale,
+						 CO_VDD1_OPP5 + 1);
+		mpu_constraint_handle = constraint_get("mpubridge",
+						      &cnstr_id_vdd1);
+		constraint_register_post_notification(mpu_constraint_handle,
+						 &omap34xxbridge_post_scale,
+						 CO_VDD1_OPP5 + 1);
+#endif
+#endif
+	}
+
+	DBC_Assert(status == 0);
+	DBC_Assert(DSP_SUCCEEDED(initStatus));
+	GT_0trace(driverTrace, GT_ENTER, " <- driver_init\n");
+	return status;
+}
+
+/*  This function is invoked during unlinking of the bridge module from the
+ *  kernel. Bridge resources are freed in this function. */
+static void __exit bridge_exit(void)
+{
+	dev_t devno;
+	bool ret;
+	GT_0trace(driverTrace, GT_ENTER, "-> driver_exit\n");
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	/* remove the constraints */
+	if (dsp_constraint_handle != NULL) {
+		GT_0trace(driverTrace, GT_7CLASS,
+			 "bridge_exit: remove constraints\n");
+		constraint_remove(dsp_constraint_handle);
+		constraint_unregister_post_notification(dsp_constraint_handle,
+						&omap34xxbridge_post_scale,
+						CO_VDD1_OPP5 + 1);
+		constraint_put(dsp_constraint_handle);
+		dsp_constraint_handle = NULL;
+	} else {
+		GT_0trace(driverTrace, GT_7CLASS,
+			 "dsp_constraint_handle is NULL\n");
+
+	}
+	if (mpu_constraint_handle != NULL) {
+		GT_0trace(driverTrace, GT_7CLASS,
+			 "bridge_exit: remove constraints\n");
+		constraint_remove(mpu_constraint_handle);
+		constraint_unregister_post_notification(mpu_constraint_handle,
+						&omap34xxbridge_post_scale,
+						CO_VDD1_OPP5 + 1);
+		constraint_put(mpu_constraint_handle);
+		mpu_constraint_handle = NULL;
+	} else {
+		GT_0trace(driverTrace, GT_7CLASS,
+			 "mpu_constraint_handle is NULL\n");
+
+	}
+#endif /*#ifndef CONFIG_DISABLE_BRIDGE_DVFS*/
+#endif /*#ifndef CONFIG_DISABLE_BRIDGE_PM*/
+	/* unregister bridge driver */
+	platform_device_unregister(&omap_dspbridge_dev);
+	platform_driver_unregister(&bridge_driver_ldm);
+
+	if (driverContext) {
+		ret = DSP_Deinit(driverContext);
+		driverContext = 0;
+
+		DBC_Assert(ret == true);
+	}
+	SERVICES_Exit();
+	GT_exit();
+
+	devno = MKDEV(driver_major, driver_minor);
+	if (bridge_device) {
+		cdev_del(&bridge_device->cdev);
+		kfree(bridge_device);
+	}
+	unregister_chrdev_region(devno, 1);
+	if (bridge_class) {
+		/* remove the device from sysfs */
+		device_destroy(bridge_class, MKDEV(driver_major, driver_minor));
+		class_destroy(bridge_class);
+
+	}
+}
+
+/* This function is called when an application opens handle to the
+ * bridge driver. */
+
+int bridge_open(struct inode *ip, struct file *filp)
+{
+	int status = 0;
+#ifndef RES_CLEANUP_DISABLE
+	HANDLE	     hProcess;
+	DSP_STATUS dsp_status = DSP_SOK;
+	HANDLE	     hDrvObject = NULL;
+	struct PROCESS_CONTEXT    *pPctxt = NULL;
+	struct PROCESS_CONTEXT	*pTmp = NULL;
+	struct PROCESS_CONTEXT    *pCtxtclosed = NULL;
+	struct PROCESS_CONTEXT    *pCtxttraverse = NULL;
+	struct task_struct *tsk = NULL;
+	GT_0trace(driverTrace, GT_ENTER, "-> driver_open\n");
+	dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+
+	/* Checking weather task structure for all process existing
+	 * in the process context list If not removing those processes*/
+	if (DSP_FAILED(dsp_status))
+		goto func_cont;
+
+	DRV_GetProcCtxtList(&pCtxtclosed, hDrvObject);
+	while (pCtxtclosed != NULL) {
+		tsk = find_task_by_vpid(pCtxtclosed->pid);
+
+		if ((tsk == NULL) || (tsk->exit_state == EXIT_ZOMBIE)) {
+
+			GT_1trace(driverTrace, GT_5CLASS,
+				 "***Task structure not existing for "
+				 "process***%d\n", pCtxtclosed->pid);
+			DRV_RemoveAllResources(pCtxtclosed);
+			if (pCtxtclosed->hProcessor != NULL) {
+				DRV_GetProcCtxtList(&pCtxttraverse,
+						    hDrvObject);
+				if (pCtxttraverse->next == NULL) {
+					PROC_Detach(pCtxtclosed->hProcessor);
+				} else {
+					if ((pCtxtclosed->pid ==
+					  pCtxttraverse->pid) &&
+					  (pCtxttraverse->next != NULL)) {
+						pCtxttraverse =
+							pCtxttraverse->next;
+					}
+					while ((pCtxttraverse != NULL) &&
+					     (pCtxtclosed->hProcessor
+					     != pCtxttraverse->hProcessor)) {
+						pCtxttraverse =
+							pCtxttraverse->next;
+						if ((pCtxttraverse != NULL) &&
+						  (pCtxtclosed->pid ==
+						  pCtxttraverse->pid)) {
+							pCtxttraverse =
+							   pCtxttraverse->next;
+						}
+					}
+					if (pCtxttraverse == NULL) {
+						PROC_Detach
+						     (pCtxtclosed->hProcessor);
+					}
+				}
+			}
+			pTmp = pCtxtclosed->next;
+			DRV_RemoveProcContext(hDrvObject, pCtxtclosed,
+					      (void *)pCtxtclosed->pid);
+		} else {
+			pTmp = pCtxtclosed->next;
+		}
+		pCtxtclosed = pTmp;
+	}
+func_cont:
+	dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(dsp_status))
+		dsp_status = DRV_InsertProcContext(hDrvObject, &pPctxt);
+
+	if (pPctxt != NULL) {
+		PRCS_GetCurrentHandle(&hProcess);
+		DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
+		DRV_ProcSetPID(pPctxt, (s32) hProcess);
+	}
+#endif
+
+	GT_0trace(driverTrace, GT_ENTER, " <- driver_open\n");
+	return status;
+}
+
+/* This function is called when an application closes handle to the bridge
+ * driver. */
+int bridge_release(struct inode *ip, struct file *filp)
+{
+	int status;
+	HANDLE pid;
+
+	GT_0trace(driverTrace, GT_ENTER, "-> driver_release\n");
+
+	status = PRCS_GetCurrentHandle(&pid);
+
+	if (DSP_SUCCEEDED(status))
+		status = DSP_Close((u32) pid);
+
+
+	(status == true) ? (status = 0) : (status = -1);
+
+	GT_0trace(driverTrace, GT_ENTER, " <- driver_release\n");
+
+	return status;
+}
+
+static void bridge_free(struct device *dev)
+{
+	/* nothing to Free */
+}
+
+
+/* This function provides IO interface to the bridge driver. */
+int bridge_ioctl(struct inode *ip, struct file *filp, unsigned int code,
+		unsigned long args)
+{
+	int status;
+	u32 retval = DSP_SOK;
+	union Trapped_Args pBufIn;
+
+	DBC_Require(filp != 0);
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+	status = omap34xxbridge_suspend_lockout(&bridge_suspend_data, filp);
+	if (status != 0)
+		return status;
+
+#endif
+
+	GT_0trace(driverTrace, GT_ENTER, " -> driver_ioctl\n");
+
+	/* Deduct one for the CMD_BASE. */
+	code = (code - 1);
+
+	status = copy_from_user(&pBufIn, (union Trapped_Args *)args,
+				sizeof(union Trapped_Args));
+
+	if (status >= 0) {
+		status = WCD_CallDevIOCtl(code, &pBufIn, &retval);
+
+		if (DSP_SUCCEEDED(status)) {
+			status = retval;
+		} else {
+			GT_1trace(driverTrace, GT_7CLASS,
+				 "IOCTL Failed, code : 0x%x\n", code);
+			status = -1;
+		}
+
+	}
+
+	GT_0trace(driverTrace, GT_ENTER, " <- driver_ioctl\n");
+
+	return status;
+}
+
+/* This function maps kernel space memory to user space memory. */
+int bridge_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+#if GT_TRACE
+	u32 offset = vma->vm_pgoff << PAGE_SHIFT;
+#endif
+	u32 status;
+
+	DBC_Assert(vma->vm_start < vma->vm_end);
+
+	vma->vm_flags |= VM_RESERVED | VM_IO;
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	GT_6trace(driverTrace, GT_3CLASS,
+		 "vm filp %p offset %lx start %lx end %lx"
+		 " page_prot %lx flags %lx\n", filp, offset, vma->vm_start,
+		 vma->vm_end, vma->vm_page_prot, vma->vm_flags);
+
+	status = remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+				vma->vm_end - vma->vm_start, vma->vm_page_prot);
+	if (status != 0)
+		status = -EAGAIN;
+
+	return status;
+}
+
+#ifndef RES_CLEANUP_DISABLE
+/* To remove all process resources before removing the process from the
+ * process context list*/
+DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt;
+	if (pCtxt != NULL) {
+		DRV_RemoveAllSTRMResElements(pCtxt);
+		DRV_RemoveAllNodeResElements(pCtxt);
+		DRV_RemoveAllDMMResElements(pCtxt);
+		DRV_ProcUpdatestate(pCtxt, PROC_RES_FREED);
+	}
+	return status;
+}
+#endif
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+
+static int bridge_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	u32 status = DSP_EFAIL;
+	u32 command = PWR_EMERGENCYDEEPSLEEP;
+
+	status = PWR_SleepDSP(command, timeOut);
+	if (DSP_SUCCEEDED(status)) {
+		bridge_suspend_data.suspended = 1;
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+static int bridge_resume(struct platform_device *pdev)
+{
+	u32 status = DSP_EFAIL;
+
+	status = PWR_WakeDSP(timeOut);
+
+	if (DSP_SUCCEEDED(status)) {
+		bridge_suspend_data.suspended = 0;
+		wake_up(&bridge_suspend_data.suspend_wq);
+
+		return 0;
+	} else {
+		return -1;
+	}
+}
+
+#endif
+/* Bridge driver initialization and de-initialization functions */
+module_init(bridge_init);
+module_exit(bridge_exit);
+
diff --git a/drivers/dsp/bridge/rmgr/drv_interface.h b/drivers/dsp/bridge/rmgr/drv_interface.h
new file mode 100644
index 0000000..27bf1f3
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/drv_interface.h
@@ -0,0 +1,40 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/drv_interface.h
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== drv_interface.h ========
+ *
+ *! Revision History
+ *! ================
+ *! 24-Mar-2003 vp  Added hooks for Power Management Test
+ *! 18-Feb-2003 vp  Code review updates
+ *! 18-Oct-2002 sb  Created initial version
+
+ */
+
+#ifndef	_DRV_INTERFACE_H_
+#define _DRV_INTERFACE_H_
+
+/* Prototypes for all functions in this bridge */
+static int __init bridge_init(void);	/* Initialize bridge */
+static void __exit bridge_exit(void);	/* Opposite of initialize */
+static int bridge_open(struct inode *, struct file *);	/* Open */
+static int bridge_release(struct inode *, struct file *);	/* Release */
+static int bridge_ioctl(struct inode *, struct file *, unsigned int,
+			unsigned long);
+static int bridge_mmap(struct file *filp, struct vm_area_struct *vma);
+#endif				/* ifndef _DRV_INTERFACE_H_ */
diff --git a/drivers/dsp/bridge/rmgr/dspdrv.c b/drivers/dsp/bridge/rmgr/dspdrv.c
new file mode 100644
index 0000000..6c325a4
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/dspdrv.c
@@ -0,0 +1,276 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/dspdrv.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== dspdrv.c ========
+ *  Description:
+ *      Interface to allocate and free bridge resources.
+ *
+ *! Revision History
+ *! ================
+ *! 12-Apr-2004 hp: Compile IVA only for 24xx.
+ *! 09-Feb-2004 vp: Updated to support IVA.
+ *! 10-Feb-2003 vp: Code review updates.
+ *! 18-oct-2002 vp: Ported to the Linux platform.
+ *! 03-Mar-2002 rr: DSP_Deinit bug fixed (gets the Mgrhandle from registry
+ *!		            before calling MGR_Destroy.
+ *! 11-Jul-2001 jeh Moved MGR_Create() from DSP_Init() to DEV_StartDevice().
+ *! 02-Apr-2001 rr: WCD_InitComplete2 return value is not checked thus
+ *!                 sllowing the class driver to load irrespective of
+ *!                 the image load.
+ *! 30-Oct-2000 kc: Made changes w.r.t. usage of REG_SetValue.
+ *! 05-Oct-2000 rr: WCD_InitComplete2 return value checked for RM.
+ *!                 Failure in WCD_InitComplete2 will cause the
+ *!                 DSP_Init to fail.
+ *! 12-Aug-2000 kc: Changed REG_EnumValue to REG_EnumKey.
+ *! 07-Aug-2000 rr: MGR_Create does the job of loading the DCD Dll.
+ *! 26-Jul-2000 rr: Driver Object holds the DevNodeStrings for each
+ *!                 DevObjects. Static variables removed. Returns
+ *!                 the Driver Object in DSP_Init.
+ *! 17-Jul-2000 rr: Driver Object is created in DSP_Init and that holds
+ *!                 the list of Device objects.
+ *! 07-Jul-2000 rr: RM implementaion started.
+ *! 24-May-2000 ag: Cleaned up debug msgs.
+ *! 02-May-2000 rr: DSP_Open returns GetCallerProcess as dwOpenContext.
+ *! 03-Feb-2000 rr: GT Changes.
+ *! 28-Jan-2000 rr: Code Cleaned up.Type void changed to void.
+ *!                 DSP_Deinit checks return values.dwCode in
+ *!                 DSP_IO_CONTROL is decoded(not hard coded)
+ *! 27-Jan-2000 rr: REG_EnumValue Used .EnumerateKey fxn removed.
+ *! 13-Jan-2000 rr: CFG_GetPrivateDword renamed to CFG_GetDevObject.
+ *! 29-Dec-1999 rr: Code Cleaned up
+ *! 09-Dec-1999 rr: EnumerateKey changed for retail build.
+ *! 06-Dec-1999 rr: ArrayofInstalledNode, index and  ArrayofInstalledDev
+ *!                 is Global.DevObject stores this pointer as hDevNode.
+ *! 02-Dec-1999 rr: DBG_SetGT and RetailMSG conditionally included.
+ *!                 Comments changed.Deinit handled.Code cleaned up.
+ *!                 DSP_IOControl, Close, Deinit returns bool values.
+ *!                 Calls WCD_InitComplete2 for Board AutoStart.
+ *! 29-Nov-1999 rr: DSP_IOControl returns the result through pBufOut.
+ *!                 Global Arrays keeps track of installed devices.
+ *! 19-Nov-1999 rr: DSP_Init handles multiple drivers.
+ *! 12-Nov-1999 rr: GetDriverKey and EnumerateKey functions added.
+ *!                 for multiple mini driver support.PCCARD flag
+ *!                 checking to include PCMCIA related stuff.
+ *! 25-Oct-1999 rr: GT_Init is called within the Process Attach.
+ *!                 return value initalized to S_OK upfront in the
+ *!                 Process Attach.
+ *! 15-Oct-1999 rr: DSP_DeInit handles the return values
+ *! 05-Oct-1999 rr: All the PCMCIA related functions are now in PCCARD.c
+ *!                 DRV_Request Resources is used instead of the
+ *!                 RegisterMiniDriver as it sounds close to what we are doing.
+ *! 24-Sep-1999 rr: DRV_RegisterMiniDriver is being called from here. Only
+ *!                 neccessaryPCMCIA fxns are here. Soon they will move out
+ *!                  either to a seperate file for bus specific inits.
+ *! 10-Sep-1999 rr: GT Enabled. Considerably changed the  driver structure as
+ *!                 - This is the Class driver. After successfully initialized
+ *!                   the Class driver will attempt to load the Mini driver.
+ *!                 - Need to seperate the PCMCIA stuff based on bus type.
+ *!                 - Changed the name of the file to wcdce.c
+ *!                 - Made the Media Handle as Global again
+ *!
+ *! 19-Aug-1999 rr: Removed the Global hbhMediaHandle. Included the MemTest.
+ *!                 Modified the DSP_Init, now three windows are opened.
+ *!                 Split the driver into PDD so that hardware dependent
+ *!                 functions will reside in PDD.
+ *! 16-Jul-1999 ag  Adapted from rkw's CAC Bullet card driver.
+ *!
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <csl.h>
+#include <mem.h>
+#include <reg.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <drv.h>
+#include <dev.h>
+#include <_dcd.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <mgr.h>
+
+/*  ----------------------------------- Others */
+#include <dbreg.h>
+
+/*  ----------------------------------- This */
+#include <dspdrv.h>
+
+/*  ----------------------------------- Globals */
+struct GT_Mask curTrace;
+
+/*
+ *  ======== DSP_Init ========
+ *  	Allocates bridge resources. Loads a base image onto DSP, if specified.
+ */
+u32 DSP_Init(OUT u32 *initStatus)
+{
+	char devNode[MAXREGPATHLENGTH] = "TIOMAP1510";
+	DSP_STATUS status = DSP_EFAIL;
+	struct DRV_OBJECT *drvObject = NULL;
+	u32 index = 0;
+	u32 deviceNode;
+	u32 deviceNodeString;
+
+	GT_create(&curTrace, "DD");
+
+	GT_0trace(curTrace, GT_ENTER, "Entering DSP_Init \r\n");
+
+	if (DSP_FAILED(WCD_Init())) {
+		GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed \n");
+		goto func_cont;
+	}			/* End WCD_Exit */
+	if (DSP_FAILED(DRV_Create(&drvObject))) {
+		GT_0trace(curTrace, GT_7CLASS, "DSP_Init:DRV_Create Failed \n");
+		WCD_Exit();
+		goto func_cont;
+	}		/* End DRV_Create */
+	GT_0trace(curTrace, GT_5CLASS, "DSP_Init:DRV Created \r\n");
+
+	/* Request Resources */
+	if (DSP_SUCCEEDED(DRV_RequestResources((u32)&devNode,
+	   &deviceNodeString))) {
+		/* Attempt to Start the Device */
+		if (DSP_SUCCEEDED(DEV_StartDevice(
+		   (struct CFG_DEVNODE *)deviceNodeString))) {
+			/* Retreive the DevObject from the Registry */
+			GT_2trace(curTrace, GT_1CLASS,
+				 "DSP_Init Succeeded for Device1:"
+				 "%d: value: %x\n", index, deviceNodeString);
+			status = DSP_SOK;
+		} else {
+			GT_0trace(curTrace, GT_7CLASS,
+				 "DSP_Init:DEV_StartDevice Failed\n");
+			(void)DRV_ReleaseResources
+				((u32) deviceNodeString, drvObject);
+			status = DSP_EFAIL;
+		}
+	} else {
+		GT_0trace(curTrace, GT_7CLASS,
+			 "DSP_Init:DRV_RequestResources Failed \r\n");
+		status = DSP_EFAIL;
+	}	/* DRV_RequestResources */
+	index++;
+
+	/* Unwind whatever was loaded */
+	if (DSP_FAILED(status)) {
+		/* irrespective of the status of DEV_RemoveDevice we conitinue
+		 * unloading. Get the Driver Object iterate through and remove.
+		 * Reset the status to E_FAIL to avoid going through
+		 * WCD_InitComplete2. */
+		status = DSP_EFAIL;
+		for (deviceNode = DRV_GetFirstDevExtension(); deviceNode != 0;
+		    deviceNode = DRV_GetNextDevExtension(deviceNode)) {
+			(void)DEV_RemoveDevice
+				((struct CFG_DEVNODE *)deviceNode);
+			(void)DRV_ReleaseResources((u32)deviceNode,
+				drvObject);
+		}
+		/* Remove the Driver Object */
+		(void)DRV_Destroy(drvObject);
+		drvObject = 0;
+		WCD_Exit();
+		GT_0trace(curTrace, GT_7CLASS,
+			 "DSP_Init:Logical device Failed to Load\n");
+	}	/* Unwinding the loaded drivers */
+func_cont:
+	/* Attempt to Start the Board */
+	if (DSP_SUCCEEDED(status)) {
+		/* BRD_AutoStart could fail if the dsp execuetable is not the
+		 * correct one. We should not propagate that error
+		 * into the device loader. */
+		(void)WCD_InitComplete2();
+		GT_0trace(curTrace, GT_1CLASS, "DSP_Init Succeeded\n");
+	} else {
+		GT_0trace(curTrace, GT_7CLASS, "DSP_Init Failed\n");
+	}			/* End WCD_InitComplete2 */
+	DBC_Ensure((DSP_SUCCEEDED(status) && drvObject > 0) ||
+		  (DSP_FAILED(status) && drvObject == 0));
+	*initStatus = status;
+	/* Return the Driver Object */
+	return (u32)drvObject;
+}
+
+/*
+ *  ======== DSP_Deinit ========
+ *  	Frees the resources allocated for bridge.
+ */
+bool DSP_Deinit(u32 deviceContext)
+{
+	bool retVal = true;
+	u32 deviceNode;
+	struct MGR_OBJECT *mgrObject = NULL;
+
+	GT_0trace(curTrace, GT_ENTER, "Entering DSP_Deinit \r\n");
+
+	while ((deviceNode = DRV_GetFirstDevExtension()) != 0) {
+		(void)DEV_RemoveDevice((struct CFG_DEVNODE *)deviceNode);
+
+		(void)DRV_ReleaseResources((u32)deviceNode,
+			 (struct DRV_OBJECT *)deviceContext);
+	}
+
+	(void) DRV_Destroy((struct DRV_OBJECT *) deviceContext);
+
+	/* Get the Manager Object from Registry
+	 * MGR Destroy will unload the DCD dll */
+	if (DSP_SUCCEEDED(CFG_GetObject((u32 *)&mgrObject, REG_MGR_OBJECT)))
+		(void)MGR_Destroy(mgrObject);
+
+	WCD_Exit();
+
+	return retVal;
+}
+
+/*
+ *  ======== DSP_Close ========
+ *  	The Calling Process handle is passed to DEV_CleanupProcesState
+ *      for cleaning up of any resources used by the application
+ */
+bool DSP_Close(u32 dwOpenContext)
+{
+	bool retVal = false;
+
+	DBC_Require(dwOpenContext != 0);
+
+	GT_0trace(curTrace, GT_ENTER, "Entering DSP_Close\n");
+
+#ifdef RES_CLEANUP_DISABLE
+
+	if (DSP_SUCCEEDED(DEV_CleanupProcessState((HANDLE) dwOpenContext))) {
+		GT_0trace(curTrace, GT_1CLASS, "DSP_Close Succeeded \r\n");
+		retVal = true;
+	} else {
+		GT_0trace(curTrace, GT_7CLASS, "DSP_Close failed \r\n");
+	}
+#endif
+
+	return retVal;
+}
diff --git a/drivers/dsp/bridge/rmgr/mgr.c b/drivers/dsp/bridge/rmgr/mgr.c
new file mode 100644
index 0000000..791a456
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/mgr.c
@@ -0,0 +1,491 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/mgr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== mgr.c ========
+ *  Description:
+ *      Implementation of Manager interface to the device object at the
+ *      driver level. This queries the NDB data base and retrieves the
+ *      data about Node and Processor.
+ *
+ *
+ *! Revision History:
+ *! ================
+ *! 12-Feb-2003 vp: Code review updates.
+ *! 18-Oct-2002 vp: Ported to Linux platform
+ *! 01-Aug-2001 ag: Added extended info for DSP-MMU setup support.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 22-Nov-2000 kc: Added MGR_GetPerfData.
+ *! 03-Nov-2000 rr: Updated after code review.
+ *! 25-Sep-2000 rr: Updated to Version 0.9
+ *! 10-Aug-2000 rr: dwSignature is not specifically inserted in MGR Obj
+ *!                 as it is taken care by MEM_AllocObject. stdwin.h added
+ *!                 for retail build to succeed.
+ *! 07-Aug-2000 rr: MGR_Create does the job of Loading DCD Dll.
+ *! 26-Jul-2000 rr: MGR_Destroy releases the hNDBDll.
+ *! 20-Jun-2000 rr: Created.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <mem.h>
+#include <sync.h>
+
+/*  ----------------------------------- Others */
+#include <dbdcd.h>
+#include <dbreg.h>
+#include <drv.h>
+#include <dev.h>
+
+/*  ----------------------------------- This */
+#include <mgr.h>
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define ZLDLLNAME               ""
+#define SIGNATURE               0x5f52474d	/* "MGR_" (in reverse) */
+
+struct MGR_OBJECT {
+	u32 dwSignature;
+	struct DCD_MANAGER *hDcdMgr;	/* Proc/Node data manager */
+};
+
+/*  ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask MGR_DebugMask = { NULL, NULL };
+#endif
+
+static u32 cRefs;
+
+/*
+ *  ========= MGR_Create =========
+ *  Purpose:
+ *      MGR Object gets created only once during driver Loading.
+ */
+DSP_STATUS MGR_Create(OUT struct MGR_OBJECT **phMgrObject,
+		     struct CFG_DEVNODE *hDevNode)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct MGR_OBJECT *pMgrObject = NULL;
+
+	DBC_Require(phMgrObject != NULL);
+	DBC_Require(cRefs > 0);
+	GT_1trace(MGR_DebugMask, GT_ENTER,
+		 "Entering MGR_Create phMgrObject 0x%x\n ",
+		 phMgrObject);
+	MEM_AllocObject(pMgrObject, struct MGR_OBJECT, SIGNATURE);
+	if (pMgrObject) {
+		if (DSP_SUCCEEDED(DCD_CreateManager(ZLDLLNAME,
+		   &pMgrObject->hDcdMgr))) {
+			/* If succeeded store the handle in the MGR Object */
+			if (DSP_SUCCEEDED(CFG_SetObject((u32)pMgrObject,
+			   REG_MGR_OBJECT))) {
+				*phMgrObject = pMgrObject;
+				GT_0trace(MGR_DebugMask, GT_1CLASS,
+					 "MGR_Create:MGR Created\r\n");
+			} else {
+				status = DSP_EFAIL;
+				GT_0trace(MGR_DebugMask, GT_7CLASS,
+					 "MGR_Create:CFG_SetObject "
+					 "Failed\r\n");
+				DCD_DestroyManager(pMgrObject->hDcdMgr);
+				MEM_FreeObject(pMgrObject);
+			}
+		} else {
+			/* failed to Create DCD Manager */
+			status = DSP_EFAIL;
+			GT_0trace(MGR_DebugMask, GT_7CLASS,
+				 "MGR_Create:DCD_ManagerCreate Failed\r\n");
+			MEM_FreeObject(pMgrObject);
+		}
+	} else {
+		status = DSP_EMEMORY;
+		GT_0trace(MGR_DebugMask, GT_7CLASS,
+			 "MGR_Create DSP_FAILED to allocate memory \n");
+	}
+	GT_2trace(MGR_DebugMask, GT_ENTER,
+		 "Exiting MGR_Create: phMgrObject: 0x%x\t"
+		 "status: 0x%x\n", phMgrObject, status);
+	DBC_Ensure(DSP_FAILED(status) ||
+		  MEM_IsValidHandle(pMgrObject, SIGNATURE));
+	return status;
+}
+
+/*
+ *  ========= MGR_Destroy =========
+ *     This function is invoked during bridge driver unloading.Frees MGR object.
+ */
+DSP_STATUS MGR_Destroy(struct MGR_OBJECT *hMgrObject)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMgrObject;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hMgrObject, SIGNATURE));
+
+	GT_1trace(MGR_DebugMask, GT_ENTER,
+		 "Entering MGR_Destroy hMgrObject 0x%x\n", hMgrObject);
+	/* Free resources */
+	if (hMgrObject->hDcdMgr)
+		DCD_DestroyManager(hMgrObject->hDcdMgr);
+
+	MEM_FreeObject(pMgrObject);
+	/* Update the Registry with NULL for MGR Object */
+	(void)CFG_SetObject(0, REG_MGR_OBJECT);
+
+	GT_2trace(MGR_DebugMask, GT_ENTER,
+		 "Exiting MGR_Destroy: hMgrObject: 0x%x\t"
+		 "status: 0x%x\n", hMgrObject, status);
+
+	DBC_Ensure(DSP_FAILED(status) ||
+		 !MEM_IsValidHandle(hMgrObject, SIGNATURE));
+
+	return status;
+}
+
+/*
+ *  ======== MGR_EnumNodeInfo ========
+ *      Enumerate and get configuration information about nodes configured
+ *      in the node database.
+ */
+DSP_STATUS MGR_EnumNodeInfo(u32 uNode, OUT struct DSP_NDBPROPS *pNDBProps,
+			   u32 uNDBPropsSize, OUT u32 *puNumNodes)
+{
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+	struct DSP_UUID Uuid, uTempUuid;
+	u32 uTempIndex = 0;
+	u32 uNodeIndex = 0;
+	struct DCD_GENERICOBJ GenObj;
+	struct MGR_OBJECT *pMgrObject = NULL;
+
+	DBC_Require(pNDBProps != NULL);
+	DBC_Require(puNumNodes != NULL);
+	DBC_Require(uNDBPropsSize >= sizeof(struct DSP_NDBPROPS));
+	DBC_Require(cRefs > 0);
+
+	GT_4trace(MGR_DebugMask, GT_ENTER, "Entered Manager_EnumNodeInfo, "
+		 "args:\n\t uNode: 0x%x\n\tpNDBProps:  0x%x\n\tuNDBPropsSize:"
+		 "0x%x\tpuNumNodes: 0x%x\n", uNode, pNDBProps,
+		 uNDBPropsSize, puNumNodes);
+	*puNumNodes = 0;
+	/* Get The Manager Object from the Registry */
+	if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
+	   REG_MGR_OBJECT))) {
+		GT_0trace(MGR_DebugMask, GT_7CLASS,
+			 "Manager_EnumNodeInfo:Failed To Get"
+			 " MGR Object from Registry\r\n");
+		goto func_cont;
+	}
+	DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
+	/* Forever loop till we hit failed or no more items in the
+	 * Enumeration. We will exit the loop other than DSP_SOK; */
+	while (status == DSP_SOK) {
+		status = DCD_EnumerateObject(uTempIndex++, DSP_DCDNODETYPE,
+					    &uTempUuid);
+		if (status == DSP_SOK) {
+			uNodeIndex++;
+			if (uNode == (uNodeIndex - 1))
+				Uuid = uTempUuid;
+
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		if (uNode > (uNodeIndex - 1)) {
+			status = DSP_EINVALIDARG;
+			GT_0trace(MGR_DebugMask, GT_7CLASS,
+				 "Manager_EnumNodeInfo: uNode"
+				 " is Invalid \r\n");
+		} else {
+			status1 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
+						(struct DSP_UUID *)&Uuid,
+						DSP_DCDNODETYPE, &GenObj);
+			if (DSP_SUCCEEDED(status1)) {
+				/* Get the Obj def */
+				*pNDBProps = GenObj.objData.nodeObj.ndbProps;
+				*puNumNodes = uNodeIndex;
+				status = DSP_SOK;
+			} else {
+				GT_0trace(MGR_DebugMask, GT_7CLASS,
+					 "Manager_EnumNodeInfo: "
+					 "Failed to Get Node Info \r\n");
+				status = DSP_EFAIL;
+			}
+		}
+	} else {
+		/* This could be changed during enum, EFAIL ... */
+		GT_0trace(MGR_DebugMask, GT_7CLASS, "Manager_EnumNodeInfo: "
+			 "Enumeration failure\r\n");
+		status = DSP_EFAIL;
+	}
+func_cont:
+	GT_4trace(MGR_DebugMask, GT_ENTER,
+		 "Exiting Manager_EnumNodeInfo, args:\n\t"
+		 "uNode: 0x%x\n\tpNDBProps:  0x%x\n\tuNDBPropsSize:"
+		 " 0x%x\tuNumNodes: 0x%x\n", uNode, pNDBProps,
+		uNDBPropsSize, *puNumNodes);
+	DBC_Ensure((DSP_SUCCEEDED(status) && *puNumNodes > 0) ||
+		  (DSP_FAILED(status) && *puNumNodes == 0));
+
+	return status;
+}
+
+/*
+ *  ======== MGR_EnumProcessorInfo ========
+ *      Enumerate and get configuration information about available
+ *      DSP processors.
+ */
+DSP_STATUS MGR_EnumProcessorInfo(u32 uProcessor,
+				OUT struct DSP_PROCESSORINFO *pProcessorInfo,
+				u32 uProcessorInfoSize, OUT u32 *puNumProcs)
+{
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+	DSP_STATUS status2 = DSP_SOK;
+	struct DSP_UUID uTempUuid;
+	u32 uTempIndex = 0;
+	u32 uProcIndex = 0;
+	struct DCD_GENERICOBJ GenObj;
+	struct MGR_OBJECT *pMgrObject = NULL;
+	struct MGR_PROCESSOREXTINFO *pExtInfo;
+	struct DEV_OBJECT *hDevObject;
+	struct DRV_OBJECT *hDrvObject;
+	s32 devType;
+	struct CFG_DEVNODE *devNode;
+	struct CFG_DSPRES chipResources;
+	bool procDetect = false;
+
+	DBC_Require(pProcessorInfo != NULL);
+	DBC_Require(puNumProcs != NULL);
+	DBC_Require(uProcessorInfoSize >= sizeof(struct DSP_PROCESSORINFO));
+	DBC_Require(cRefs > 0);
+
+	GT_4trace(MGR_DebugMask, GT_ENTER,
+		 "Entered Manager_EnumProcessorInfo, "
+		 "args:\n\tuProcessor:  0x%x\n\tpProcessorInfo: 0x%x\n\t"
+		 "uProcessorInfoSize: 0x%x\tpuNumProcs: 0x%x\n", uProcessor,
+		 pProcessorInfo, uProcessorInfoSize, puNumProcs);
+	*puNumProcs = 0;
+	status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(status)) {
+		status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
+		if (DSP_SUCCEEDED(status)) {
+			status = DEV_GetDevType(hDevObject, (u32 *) &devType);
+			status = DEV_GetDevNode(hDevObject, &devNode);
+			if (devType == DSP_UNIT) {
+				status = CFG_GetDSPResources(devNode,
+							 &chipResources);
+			} else {
+				status = DSP_EFAIL;
+				GT_1trace(MGR_DebugMask, GT_7CLASS,
+					 "Unsupported dev type gotten"
+					 "from device object %d\n", devType);
+			}
+			if (DSP_SUCCEEDED(status)) {
+				pProcessorInfo->uProcessorType =
+						chipResources.uChipType;
+			}
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Get The Manager Object from the Registry */
+	if (DSP_FAILED(CFG_GetObject((u32 *)&pMgrObject,
+	   REG_MGR_OBJECT))) {
+		GT_0trace(MGR_DebugMask, GT_7CLASS,
+			 "Manager_EnumProcessorInfo: "
+			 "Failed To Get MGR Object from Registry\r\n");
+		goto func_end;
+	}
+	DBC_Assert(MEM_IsValidHandle(pMgrObject, SIGNATURE));
+	/* Forever loop till we hit no more items in the
+	 * Enumeration. We will exit the loop other than DSP_SOK; */
+	while (status1 == DSP_SOK) {
+		status1 = DCD_EnumerateObject(uTempIndex++,
+					     DSP_DCDPROCESSORTYPE,
+					     &uTempUuid);
+		if (status1 != DSP_SOK)
+			break;
+
+		uProcIndex++;
+		/* Get the Object properties to find the Device/Processor
+		 * Type */
+		if (procDetect != false)
+			continue;
+
+		status2 = DCD_GetObjectDef(pMgrObject->hDcdMgr,
+					(struct DSP_UUID *)&uTempUuid,
+					DSP_DCDPROCESSORTYPE,
+					&GenObj);
+		if (DSP_SUCCEEDED(status2)) {
+			/* Get the Obj def */
+			if (uProcessorInfoSize <
+					sizeof(struct MGR_PROCESSOREXTINFO)) {
+				*pProcessorInfo = GenObj.objData.procObj;
+			} else {
+				/* extended info */
+				pExtInfo = (struct MGR_PROCESSOREXTINFO *)
+						pProcessorInfo;
+				*pExtInfo = GenObj.objData.extProcObj;
+			}
+			GT_1trace(MGR_DebugMask, GT_7CLASS,
+				 "Manager_EnumProcessorInfo: Got"
+				 " Proctype  from DCD %x \r\n",
+				 pProcessorInfo->uProcessorType);
+			/* See if we got the needed processor */
+			if (devType == DSP_UNIT) {
+				if (pProcessorInfo->uProcessorType ==
+				   DSPPROCTYPE_C64)
+					procDetect = true;
+			} else if (devType == IVA_UNIT) {
+				if (pProcessorInfo->uProcessorType ==
+				   IVAPROCTYPE_ARM7)
+					procDetect = true;
+			}
+			/* User applciatiuons aonly check for chip type, so
+			 * this clumsy overwrite */
+			pProcessorInfo->uProcessorType =
+					 chipResources.uChipType;
+		} else {
+			GT_1trace(MGR_DebugMask, GT_7CLASS,
+				 "Manager_EnumProcessorInfo: "
+				 "Failed to Get DCD Processor Info %x \r\n",
+				 status2);
+			status = DSP_EFAIL;
+		}
+	}
+	*puNumProcs = uProcIndex;
+	if (procDetect == false) {
+		GT_0trace(MGR_DebugMask, GT_7CLASS,
+			 "Manager_EnumProcessorInfo: Failed"
+			 " to get Proc info from DCD , so use CFG registry\n");
+		pProcessorInfo->uProcessorType = chipResources.uChipType;
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== MGR_Exit ========
+ *      Decrement reference count, and free resources when reference count is
+ *      0.
+ */
+void CDECL MGR_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+	cRefs--;
+	if (cRefs == 0)
+		DCD_Exit();
+
+	GT_1trace(MGR_DebugMask, GT_5CLASS,
+		 "Entered MGR_Exit, ref count: 0x%x\n", cRefs);
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== MGR_GetDCDHandle ========
+ *      Retrieves the MGR handle. Accessor Function.
+ */
+DSP_STATUS MGR_GetDCDHandle(struct MGR_OBJECT *hMGRHandle,
+			   OUT u32 *phDCDHandle)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct MGR_OBJECT *pMgrObject = (struct MGR_OBJECT *)hMGRHandle;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(phDCDHandle != NULL);
+
+	*phDCDHandle = (u32)NULL;
+	if (MEM_IsValidHandle(pMgrObject, SIGNATURE)) {
+		*phDCDHandle = (u32) pMgrObject->hDcdMgr;
+		status = DSP_SOK;
+	}
+	DBC_Ensure((DSP_SUCCEEDED(status) && *phDCDHandle != (u32)NULL) ||
+		  (DSP_FAILED(status) && *phDCDHandle == (u32)NULL));
+
+	return status;
+}
+
+/*
+ *  ======== MGR_Init ========
+ *      Initialize MGR's private state, keeping a reference count on each call.
+ */
+bool CDECL MGR_Init(void)
+{
+	bool fRetval = true;
+	bool fInitDCD = false;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+
+		/* Set the Trace mask */
+		DBC_Assert(!MGR_DebugMask.flags);
+
+		GT_create(&MGR_DebugMask, "MG");	/* "MG" for Manager */
+		fInitDCD = DCD_Init();	/*  DCD Module */
+
+		if (!fInitDCD) {
+			fRetval = false;
+			GT_0trace(MGR_DebugMask, GT_6CLASS,
+				 "MGR_Init failed\n");
+		}
+	}
+
+	if (fRetval)
+		cRefs++;
+
+
+	GT_1trace(MGR_DebugMask, GT_5CLASS,
+		 "Entered MGR_Init, ref count:  0x%x\n", cRefs);
+	DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+	return fRetval;
+}
+
+/*
+ *  ======== MGR_WaitForBridgeEvents ========
+ *      Block on any Bridge event(s)
+ */
+DSP_STATUS MGR_WaitForBridgeEvents(struct DSP_NOTIFICATION **aNotifications,
+				  u32 uCount, OUT u32 *puIndex, u32 uTimeout)
+{
+	DSP_STATUS status;
+	struct SYNC_OBJECT *hSyncEvents[MAX_EVENTS];
+	u32 i;
+
+	DBC_Require(uCount < MAX_EVENTS);
+
+	for (i = 0; i < uCount; i++)
+		hSyncEvents[i] = aNotifications[i]->handle;
+
+	status = SYNC_WaitOnMultipleEvents(hSyncEvents, uCount, uTimeout,
+					 puIndex);
+
+	return status;
+
+}
+
diff --git a/drivers/dsp/bridge/rmgr/nldr.c b/drivers/dsp/bridge/rmgr/nldr.c
new file mode 100644
index 0000000..b1af6de
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/nldr.c
@@ -0,0 +1,1966 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/linux/nldr/nldr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== nldr.c ========
+ *  Description:
+ *      DSP/BIOS Bridge dynamic + overlay Node loader.
+ *
+ *  Public Functions:
+ *      NLDR_Allocate
+ *      NLDR_Create
+ *      NLDR_Delete
+ *      NLDR_Exit
+ *      NLDR_Free
+ *      NLDR_GetFxnAddr
+ *      NLDR_Init
+ *      NLDR_Load
+ *      NLDR_Unload
+ *
+ *  Notes:
+ *
+ *! Revision History
+ *! ================
+ *! 07-Apr-2003 map Removed references to dead DLDR module
+ *! 23-Jan-2003 map Updated RemoteAlloc to support memory granularity
+ *! 20-Jan-2003 map Updated to maintain persistent dependent libraries
+ *! 15-Jan-2003 map Adapted for use with multiple dynamic phase libraries
+ *! 19-Dec-2002 map Fixed overlay bug in AddOvlySect for overlay
+ *!		 sections > 1024 bytes.
+ *! 13-Dec-2002 map Fixed NLDR_GetFxnAddr bug by searching dependent
+ *!		 libs for symbols
+ *! 27-Sep-2002 map Added RemoteFree to convert size to words for
+ *!		 correct deallocation
+ *! 16-Sep-2002 map Code Review Cleanup(from dldr.c)
+ *! 29-Aug-2002 map Adjusted for ARM-side overlay copy
+ *! 05-Aug-2002 jeh Created.
+ */
+
+#include <host_os.h>
+
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+#include <dbc.h>
+#include <gt.h>
+#ifdef DEBUG
+#include <dbg.h>
+#endif
+
+/* OS adaptation layer */
+#include <csl.h>
+#include <mem.h>
+
+/* Platform manager */
+#include <cod.h>
+#include <dev.h>
+
+/* Resource manager */
+#include <dbll.h>
+#include <dbdcd.h>
+#include <rmm.h>
+#include <uuidutil.h>
+
+#include <nldr.h>
+
+#define NLDR_SIGNATURE      0x52444c4e	/* "RDLN" */
+#define NLDR_NODESIGNATURE  0x4e444c4e	/* "NDLN" */
+
+/* Name of section containing dynamic load mem */
+#define DYNMEMSECT  ".dspbridge_mem"
+
+/* Name of section containing dependent library information */
+#define DEPLIBSECT  ".dspbridge_deplibs"
+
+/* Max depth of recursion for loading node's dependent libraries */
+#define MAXDEPTH	    5
+
+/* Max number of persistent libraries kept by a node */
+#define MAXLIBS	 5
+
+/*
+ *  Defines for extracting packed dynamic load memory requirements from two
+ *  masks.
+ *  These defines must match node.cdb and dynm.cdb
+ *  Format of data/code mask is:
+ *   uuuuuuuu|fueeeeee|fudddddd|fucccccc|
+ *  where
+ *      u = unused
+ *      cccccc = prefered/required dynamic mem segid for create phase data/code
+ *      dddddd = prefered/required dynamic mem segid for delete phase data/code
+ *      eeeeee = prefered/req. dynamic mem segid for execute phase data/code
+ *      f = flag indicating if memory is preferred or required:
+ *	  f = 1 if required, f = 0 if preferred.
+ *
+ *  The 6 bits of the segid are interpreted as follows:
+ *
+ *  If the 6th bit (bit 5) is not set, then this specifies a memory segment
+ *  between 0 and 31 (a maximum of 32 dynamic loading memory segments).
+ *  If the 6th bit (bit 5) is set, segid has the following interpretation:
+ *      segid = 32 - Any internal memory segment can be used.
+ *      segid = 33 - Any external memory segment can be used.
+ *      segid = 63 - Any memory segment can be used (in this case the
+ *		   required/preferred flag is irrelevant).
+ *
+ */
+/* Maximum allowed dynamic loading memory segments */
+#define MAXMEMSEGS      32
+
+#define MAXSEGID	3	/* Largest possible (real) segid */
+#define MEMINTERNALID   32	/* Segid meaning use internal mem */
+#define MEMEXTERNALID   33	/* Segid meaning use external mem */
+#define NULLID	  63	/* Segid meaning no memory req/pref */
+#define FLAGBIT	 7	/* 7th bit is pref./req. flag */
+#define SEGMASK	 0x3f	/* Bits 0 - 5 */
+
+#define CREATEBIT       0	/* Create segid starts at bit 0 */
+#define DELETEBIT       8	/* Delete segid starts at bit 8 */
+#define EXECUTEBIT      16	/* Execute segid starts at bit 16 */
+
+/*
+ *  Masks that define memory type.  Must match defines in dynm.cdb.
+ */
+#define DYNM_CODE       0x2
+#define DYNM_DATA       0x4
+#define DYNM_CODEDATA   (DYNM_CODE | DYNM_DATA)
+#define DYNM_INTERNAL   0x8
+#define DYNM_EXTERNAL   0x10
+
+/*
+ *  Defines for packing memory requirement/preference flags for code and
+ *  data of each of the node's phases into one mask.
+ *  The bit is set if the segid is required for loading code/data of the
+ *  given phase. The bit is not set, if the segid is preferred only.
+ *
+ *  These defines are also used as indeces into a segid array for the node.
+ *  eg node's segid[CREATEDATAFLAGBIT] is the memory segment id that the
+ *  create phase data is required or preferred to be loaded into.
+ */
+#define CREATEDATAFLAGBIT   0
+#define CREATECODEFLAGBIT   1
+#define EXECUTEDATAFLAGBIT  2
+#define EXECUTECODEFLAGBIT  3
+#define DELETEDATAFLAGBIT   4
+#define DELETECODEFLAGBIT   5
+#define MAXFLAGS	    6
+
+#define IsInternal(hNldr, segid) (((segid) <= MAXSEGID && \
+	    hNldr->segTable[(segid)] & DYNM_INTERNAL) || \
+	    (segid) == MEMINTERNALID)
+
+#define IsExternal(hNldr, segid) (((segid) <= MAXSEGID && \
+	    hNldr->segTable[(segid)] & DYNM_EXTERNAL) || \
+	    (segid) == MEMEXTERNALID)
+
+#define SWAPLONG(x) ((((x) << 24) & 0xFF000000) | (((x) << 8) & 0xFF0000L) | \
+	(((x) >> 8) & 0xFF00L) | (((x) >> 24) & 0xFF))
+
+#define SWAPWORD(x) ((((x) << 8) & 0xFF00) | (((x) >> 8) & 0xFF))
+
+    /*
+     *  These names may be embedded in overlay sections to identify which
+     *  node phase the section should be overlayed.
+     */
+#define PCREATE	 "create"
+#define PDELETE	 "delete"
+#define PEXECUTE	"execute"
+
+#define IsEqualUUID(uuid1, uuid2) (\
+	((uuid1).ulData1 == (uuid2).ulData1) && \
+	((uuid1).usData2 == (uuid2).usData2) && \
+	((uuid1).usData3 == (uuid2).usData3) && \
+	((uuid1).ucData4 == (uuid2).ucData4) && \
+	((uuid1).ucData5 == (uuid2).ucData5) && \
+	(CSL_Strncmp((void *)(uuid1).ucData6, (void *)(uuid2).ucData6, 6)) == 0)
+
+    /*
+     *  ======== MemInfo ========
+     *  Format of dynamic loading memory segment info in coff file.
+     *  Must match dynm.h55.
+     */
+struct MemInfo {
+	u32 segid;		/* Dynamic loading memory segment number */
+	u32 base;
+	u32 len;
+	u32 type;		/* Mask of DYNM_CODE, DYNM_INTERNAL, etc. */
+};
+
+/*
+ *  ======== LibNode ========
+ *  For maintaining a tree of library dependencies.
+ */
+struct LibNode {
+	struct DBLL_LibraryObj *lib;	/* The library */
+	u16 nDepLibs;	/* Number of dependent libraries */
+	struct LibNode *pDepLibs;	/* Dependent libraries of lib */
+};
+
+/*
+ *  ======== OvlySect ========
+ *  Information needed to overlay a section.
+ */
+struct OvlySect {
+	struct OvlySect *pNextSect;
+	u32 loadAddr;		/* Load address of section */
+	u32 runAddr;		/* Run address of section */
+	u32 size;		/* Size of section */
+	u16 page;		/* DBL_CODE, DBL_DATA */
+};
+
+/*
+ *  ======== OvlyNode ========
+ *  For maintaining a list of overlay nodes, with sections that need to be
+ *  overlayed for each of the nodes phases.
+ */
+struct OvlyNode {
+	struct DSP_UUID uuid;
+	char *pNodeName;
+	struct OvlySect *pCreateSects;
+	struct OvlySect *pDeleteSects;
+	struct OvlySect *pExecuteSects;
+	struct OvlySect *pOtherSects;
+	u16 nCreateSects;
+	u16 nDeleteSects;
+	u16 nExecuteSects;
+	u16 nOtherSects;
+	u16 createRef;
+	u16 deleteRef;
+	u16 executeRef;
+	u16 otherRef;
+};
+
+/*
+ *  ======== NLDR_OBJECT ========
+ *  Overlay loader object.
+ */
+struct NLDR_OBJECT {
+	u32 dwSignature;	/* For object validation */
+	struct DEV_OBJECT *hDevObject;	/* Device object */
+	struct DCD_MANAGER *hDcdMgr;	/* Proc/Node data manager */
+	struct DBLL_TarObj *dbll;	/* The DBL loader */
+	struct DBLL_LibraryObj *baseLib;	/* Base image library */
+	struct RMM_TargetObj *rmm;	/* Remote memory manager for DSP */
+	struct DBLL_Fxns dbllFxns;	/* Loader function table */
+	struct DBLL_Attrs dbllAttrs;	/* attrs to pass to loader functions */
+	NLDR_OVLYFXN ovlyFxn;	/* "write" for overlay nodes */
+	NLDR_WRITEFXN writeFxn;	/* "write" for dynamic nodes */
+	struct OvlyNode *ovlyTable;	/* Table of overlay nodes */
+	u16 nOvlyNodes;	/* Number of overlay nodes in base */
+	u16 nNode;		/* Index for tracking overlay nodes */
+	u16 nSegs;		/* Number of dynamic load mem segs */
+	u32 *segTable;	/* memtypes of dynamic memory segs
+				 * indexed by segid
+				 */
+	u16 usDSPMauSize;	/* Size of DSP MAU */
+	u16 usDSPWordSize;	/* Size of DSP word */
+};
+
+/*
+ *  ======== NLDR_NODEOBJECT ========
+ *  Dynamic node object. This object is created when a node is allocated.
+ */
+struct NLDR_NODEOBJECT {
+	u32 dwSignature;	/* For object validation */
+	struct NLDR_OBJECT *pNldr;	/* Dynamic loader handle */
+	void *pPrivRef;		/* Handle to pass to DBL_WriteFxn */
+	struct DSP_UUID uuid;		/* Node's UUID */
+	bool fDynamic;		/* Dynamically loaded node? */
+	bool fOverlay;		/* Overlay node? */
+	bool *pfPhaseSplit;	/* Multiple phase libraries? */
+	struct LibNode root;		/* Library containing node phase */
+	struct LibNode createLib;    /* Library containing create phase lib */
+	struct LibNode executeLib;   /* Library containing execute phase lib */
+	struct LibNode deleteLib;    /* Library containing delete phase lib */
+	struct LibNode persLib[MAXLIBS];  /* libs remain loaded until Delete */
+	s32 nPersLib;		/* Number of persistent libraries */
+	/* Path in lib dependency tree */
+	struct DBLL_LibraryObj *libPath[MAXDEPTH + 1];
+	enum NLDR_PHASE phase;	/* Node phase currently being loaded */
+
+	/*
+	 *  Dynamic loading memory segments for data and code of each phase.
+	 */
+	u16 segId[MAXFLAGS];
+
+	/*
+	 *  Mask indicating whether each mem segment specified in segId[]
+	 *  is preferred or required.
+	 *  For example if (codeDataFlagMask & (1 << EXECUTEDATAFLAGBIT)) != 0,
+	 *  then it is required to load execute phase data into the memory
+	 *  specified by segId[EXECUTEDATAFLAGBIT].
+	 */
+	u32 codeDataFlagMask;
+};
+
+/* Dynamic loader function table */
+static struct DBLL_Fxns dbllFxns = {
+	(DBLL_CloseFxn) DBLL_close,
+	(DBLL_CreateFxn) DBLL_create,
+	(DBLL_DeleteFxn) DBLL_delete,
+	(DBLL_ExitFxn) DBLL_exit,
+	(DBLL_GetAttrsFxn) DBLL_getAttrs,
+	(DBLL_GetAddrFxn) DBLL_getAddr,
+	(DBLL_GetCAddrFxn) DBLL_getCAddr,
+	(DBLL_GetSectFxn) DBLL_getSect,
+	(DBLL_InitFxn) DBLL_init,
+	(DBLL_LoadFxn) DBLL_load,
+	(DBLL_LoadSectFxn) DBLL_loadSect,
+	(DBLL_OpenFxn) DBLL_open,
+	(DBLL_ReadSectFxn) DBLL_readSect,
+	(DBLL_SetAttrsFxn) DBLL_setAttrs,
+	(DBLL_UnloadFxn) DBLL_unload,
+	(DBLL_UnloadSectFxn) DBLL_unloadSect,
+};
+
+static struct GT_Mask NLDR_debugMask = { NULL, NULL };	/* GT trace variable */
+static u32 cRefs;		/* module reference count */
+
+static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
+			     u32 addr, u32 nBytes);
+static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
+			     enum DSP_DCDOBJTYPE objType,
+			     IN void *handle);
+static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
+			      struct OvlySect **pList,
+			      struct DBLL_SectInfo *pSectInfo, bool *pExists,
+			      u32 addr, u32 nBytes);
+static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
+			s32 mtype);
+static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
+		     u16 nAlloc);
+static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
+			  char *symName, struct DBLL_Symbol **sym);
+static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
+			 struct LibNode *root, struct DSP_UUID uuid,
+			 bool rootPersistent, struct DBLL_LibraryObj **libPath,
+			 enum NLDR_PHASE phase, u16 depth);
+static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+			  enum NLDR_PHASE phase);
+static DSP_STATUS RemoteAlloc(void **pRef, u16 memType, u32 size,
+			     u32 align, u32 *dspAddr,
+			     OPTIONAL s32 segmentId, OPTIONAL s32 req,
+			     bool reserve);
+static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
+			    u32 size, bool reserve);
+
+static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root);
+static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+		      enum NLDR_PHASE phase);
+static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
+				    struct DBLL_LibraryObj *lib);
+static u32 findLcm(u32 a, u32 b);
+static u32 findGcf(u32 a, u32 b);
+
+/*
+ *  ======== NLDR_Allocate ========
+ */
+DSP_STATUS NLDR_Allocate(struct NLDR_OBJECT *hNldr, void *pPrivRef,
+			 IN CONST struct DCD_NODEPROPS *pNodeProps,
+			 OUT struct NLDR_NODEOBJECT **phNldrNode,
+			 IN bool *pfPhaseSplit)
+{
+	struct NLDR_NODEOBJECT *pNldrNode = NULL;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pNodeProps != NULL);
+	DBC_Require(phNldrNode != NULL);
+	DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+
+	GT_5trace(NLDR_debugMask, GT_ENTER, "NLDR_Allocate(0x%x, 0x%x, 0x%x, "
+		 "0x%x, 0x%x)\n", hNldr, pPrivRef, pNodeProps, phNldrNode,
+		 pfPhaseSplit);
+
+	/* Initialize handle in case of failure */
+	*phNldrNode = NULL;
+	/* Allocate node object */
+	MEM_AllocObject(pNldrNode, struct NLDR_NODEOBJECT, NLDR_NODESIGNATURE);
+
+	if (pNldrNode == NULL) {
+		GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Allocate: "
+			 "Memory allocation failed\n");
+		status = DSP_EMEMORY;
+	} else {
+		pNldrNode->pfPhaseSplit = pfPhaseSplit;
+		pNldrNode->nPersLib = 0;
+		pNldrNode->pNldr = hNldr;
+		pNldrNode->pPrivRef = pPrivRef;
+		/* Save node's UUID. */
+		pNldrNode->uuid = pNodeProps->ndbProps.uiNodeID;
+		/*
+		 *  Determine if node is a dynamically loaded node from
+		 *  ndbProps.
+		 */
+		if (pNodeProps->usLoadType == NLDR_DYNAMICLOAD) {
+			/* Dynamic node */
+			pNldrNode->fDynamic = true;
+			/*
+			 *  Extract memory requirements from ndbProps masks
+			 */
+			/* Create phase */
+			pNldrNode->segId[CREATEDATAFLAGBIT] = (u16)
+				(pNodeProps->ulDataMemSegMask >> CREATEBIT) &
+				SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulDataMemSegMask >>
+				(CREATEBIT + FLAGBIT)) & 1) <<
+				CREATEDATAFLAGBIT;
+			pNldrNode->segId[CREATECODEFLAGBIT] = (u16)
+				(pNodeProps->ulCodeMemSegMask >>
+				CREATEBIT) & SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulCodeMemSegMask >>
+				(CREATEBIT + FLAGBIT)) & 1) <<
+				CREATECODEFLAGBIT;
+			/* Execute phase */
+			pNldrNode->segId[EXECUTEDATAFLAGBIT] = (u16)
+				(pNodeProps->ulDataMemSegMask >>
+				EXECUTEBIT) & SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulDataMemSegMask >>
+				(EXECUTEBIT + FLAGBIT)) & 1) <<
+				EXECUTEDATAFLAGBIT;
+			pNldrNode->segId[EXECUTECODEFLAGBIT] = (u16)
+				(pNodeProps->ulCodeMemSegMask >>
+				EXECUTEBIT) & SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulCodeMemSegMask >>
+				(EXECUTEBIT + FLAGBIT)) & 1) <<
+				EXECUTECODEFLAGBIT;
+			/* Delete phase */
+			pNldrNode->segId[DELETEDATAFLAGBIT] = (u16)
+			    (pNodeProps->ulDataMemSegMask >> DELETEBIT) &
+			    SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulDataMemSegMask >>
+				(DELETEBIT + FLAGBIT)) & 1) <<
+				DELETEDATAFLAGBIT;
+			pNldrNode->segId[DELETECODEFLAGBIT] = (u16)
+				(pNodeProps->ulCodeMemSegMask >>
+				DELETEBIT) & SEGMASK;
+			pNldrNode->codeDataFlagMask |=
+				((pNodeProps->ulCodeMemSegMask >>
+				(DELETEBIT + FLAGBIT)) & 1) <<
+				DELETECODEFLAGBIT;
+		} else {
+			/* Non-dynamically loaded nodes are part of the
+			 * base image */
+			pNldrNode->root.lib = hNldr->baseLib;
+			/* Check for overlay node */
+			if (pNodeProps->usLoadType == NLDR_OVLYLOAD)
+				pNldrNode->fOverlay = true;
+
+		}
+		*phNldrNode = (struct NLDR_NODEOBJECT *) pNldrNode;
+	}
+	/* Cleanup on failure */
+	if (DSP_FAILED(status) && pNldrNode)
+		NLDR_Free((struct NLDR_NODEOBJECT *) pNldrNode);
+
+	DBC_Ensure((DSP_SUCCEEDED(status) &&
+		  MEM_IsValidHandle(((struct NLDR_NODEOBJECT *)(*phNldrNode)),
+		  NLDR_NODESIGNATURE)) || (DSP_FAILED(status) &&
+		  *phNldrNode == NULL));
+	return status;
+}
+
+/*
+ *  ======== NLDR_Create ========
+ */
+DSP_STATUS NLDR_Create(OUT struct NLDR_OBJECT **phNldr,
+		      struct DEV_OBJECT *hDevObject,
+		      IN CONST struct NLDR_ATTRS *pAttrs)
+{
+	struct COD_MANAGER *hCodMgr;	/* COD manager */
+	char *pszCoffBuf = NULL;
+	char szZLFile[COD_MAXPATHLENGTH];
+	struct NLDR_OBJECT *pNldr = NULL;
+	struct DBLL_Attrs saveAttrs;
+	struct DBLL_Attrs newAttrs;
+	DBLL_Flags flags;
+	u32 ulEntry;
+	u16 nSegs = 0;
+	struct MemInfo *pMemInfo;
+	u32 ulLen = 0;
+	u32 ulAddr;
+	struct RMM_Segment *rmmSegs = NULL;
+	u16 i;
+	DSP_STATUS status = DSP_SOK;
+	DBC_Require(cRefs > 0);
+	DBC_Require(phNldr != NULL);
+	DBC_Require(hDevObject != NULL);
+	DBC_Require(pAttrs != NULL);
+	DBC_Require(pAttrs->pfnOvly != NULL);
+	DBC_Require(pAttrs->pfnWrite != NULL);
+	GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_Create(0x%x, 0x%x, 0x%x)\n",
+		 phNldr, hDevObject, pAttrs);
+	/* Allocate dynamic loader object */
+	MEM_AllocObject(pNldr, struct NLDR_OBJECT, NLDR_SIGNATURE);
+	if (pNldr) {
+		pNldr->hDevObject = hDevObject;
+		/* warning, lazy status checking alert! */
+		status = DEV_GetCodMgr(hDevObject, &hCodMgr);
+		DBC_Assert(DSP_SUCCEEDED(status));
+		status = COD_GetLoader(hCodMgr, &pNldr->dbll);
+		DBC_Assert(DSP_SUCCEEDED(status));
+		status = COD_GetBaseLib(hCodMgr, &pNldr->baseLib);
+		DBC_Assert(DSP_SUCCEEDED(status));
+		status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
+		DBC_Assert(DSP_SUCCEEDED(status));
+		status = DSP_SOK;
+		/* end lazy status checking */
+		pNldr->usDSPMauSize = pAttrs->usDSPMauSize;
+		pNldr->usDSPWordSize = pAttrs->usDSPWordSize;
+		pNldr->dbllFxns = dbllFxns;
+		if (!(pNldr->dbllFxns.initFxn()))
+			status = DSP_EMEMORY;
+
+	} else {
+		GT_0trace(NLDR_debugMask, GT_6CLASS, "NLDR_Create: "
+			 "Memory allocation failed\n");
+		status = DSP_EMEMORY;
+	}
+	/* Create the DCD Manager */
+	if (DSP_SUCCEEDED(status))
+		status = DCD_CreateManager(NULL, &pNldr->hDcdMgr);
+
+	/* Get dynamic loading memory sections from base lib */
+	if (DSP_SUCCEEDED(status)) {
+		status = pNldr->dbllFxns.getSectFxn(pNldr->baseLib, DYNMEMSECT,
+			 &ulAddr, &ulLen);
+		if (DSP_SUCCEEDED(status)) {
+			pszCoffBuf = MEM_Calloc(ulLen * pNldr->usDSPMauSize,
+						MEM_PAGED);
+			if (!pszCoffBuf) {
+				GT_0trace(NLDR_debugMask, GT_6CLASS,
+					 "NLDR_Create: Memory "
+					 "allocation failed\n");
+				status = DSP_EMEMORY;
+			}
+		} else {
+			/* Ok to not have dynamic loading memory */
+			status = DSP_SOK;
+			ulLen = 0;
+			GT_1trace(NLDR_debugMask, GT_6CLASS,
+				 "NLDR_Create: DBLL_getSect "
+				 "failed (no dynamic loading mem segments): "
+				 "0x%lx\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status) && ulLen > 0) {
+		/* Read section containing dynamic load mem segments */
+		status = pNldr->dbllFxns.readSectFxn(pNldr->baseLib, DYNMEMSECT,
+						    pszCoffBuf, ulLen);
+		if (DSP_FAILED(status)) {
+			GT_1trace(NLDR_debugMask, GT_6CLASS,
+				 "NLDR_Create: DBLL_read Section"
+				 "failed: 0x%lx\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status) && ulLen > 0) {
+		/* Parse memory segment data */
+		nSegs = (u16)(*((u32 *)pszCoffBuf));
+		if (nSegs > MAXMEMSEGS) {
+			GT_1trace(NLDR_debugMask, GT_6CLASS,
+				 "NLDR_Create: Invalid number of "
+				 "dynamic load mem segments: 0x%lx\n", nSegs);
+			status = DSP_ECORRUPTFILE;
+		}
+	}
+	/* Parse dynamic load memory segments */
+	if (DSP_SUCCEEDED(status) && nSegs > 0) {
+		rmmSegs = MEM_Calloc(sizeof(struct RMM_Segment) * nSegs,
+				    MEM_PAGED);
+		pNldr->segTable = MEM_Calloc(sizeof(u32) * nSegs, MEM_PAGED);
+		if (rmmSegs == NULL || pNldr->segTable == NULL) {
+			status = DSP_EMEMORY;
+		} else {
+			pNldr->nSegs = nSegs;
+			pMemInfo = (struct MemInfo *)(pszCoffBuf +
+				   sizeof(u32));
+			for (i = 0; i < nSegs; i++) {
+				rmmSegs[i].base = (pMemInfo + i)->base;
+				rmmSegs[i].length = (pMemInfo + i)->len;
+				rmmSegs[i].space = 0;
+				pNldr->segTable[i] = (pMemInfo + i)->type;
+#ifdef DEBUG
+				DBG_Trace(DBG_LEVEL7,
+				    "** (proc) DLL MEMSEGMENT: %d, Base: 0x%x, "
+				    "Length: 0x%x\n", i, rmmSegs[i].base,
+				    rmmSegs[i].length);
+#endif
+			}
+		}
+	}
+	/* Create Remote memory manager */
+	if (DSP_SUCCEEDED(status))
+		status = RMM_create(&pNldr->rmm, rmmSegs, nSegs);
+
+	if (DSP_SUCCEEDED(status)) {
+		/* set the alloc, free, write functions for loader */
+		pNldr->dbllFxns.getAttrsFxn(pNldr->dbll, &saveAttrs);
+		newAttrs = saveAttrs;
+		newAttrs.alloc = (DBLL_AllocFxn) RemoteAlloc;
+		newAttrs.free = (DBLL_FreeFxn) RemoteFree;
+		newAttrs.symLookup = (DBLL_SymLookup) GetSymbolValue;
+		newAttrs.symHandle = pNldr;
+		newAttrs.write = (DBLL_WriteFxn) pAttrs->pfnWrite;
+		pNldr->ovlyFxn = pAttrs->pfnOvly;
+		pNldr->writeFxn = pAttrs->pfnWrite;
+		pNldr->dbllAttrs = newAttrs;
+	}
+	if (rmmSegs)
+		MEM_Free(rmmSegs);
+
+	if (pszCoffBuf)
+		MEM_Free(pszCoffBuf);
+
+	/* Get overlay nodes */
+	if (DSP_SUCCEEDED(status)) {
+		status = COD_GetBaseName(hCodMgr, szZLFile, COD_MAXPATHLENGTH);
+		/* lazy check */
+		DBC_Assert(DSP_SUCCEEDED(status));
+		/* First count number of overlay nodes */
+		status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile, AddOvlyNode,
+					(void *) pNldr);
+		/* Now build table of overlay nodes */
+		if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
+			/* Allocate table for overlay nodes */
+			pNldr->ovlyTable =
+			MEM_Calloc(sizeof(struct OvlyNode) * pNldr->nOvlyNodes,
+				  MEM_PAGED);
+			/* Put overlay nodes in the table */
+			pNldr->nNode = 0;
+			status = DCD_GetObjects(pNldr->hDcdMgr, szZLFile,
+						AddOvlyNode,
+						(void *) pNldr);
+		}
+	}
+	/* Do a fake reload of the base image to get overlay section info */
+	if (DSP_SUCCEEDED(status) && pNldr->nOvlyNodes > 0) {
+		saveAttrs.write = fakeOvlyWrite;
+		saveAttrs.logWrite = AddOvlyInfo;
+		saveAttrs.logWriteHandle = pNldr;
+		flags = DBLL_CODE | DBLL_DATA | DBLL_SYMB;
+		status = pNldr->dbllFxns.loadFxn(pNldr->baseLib, flags,
+						&saveAttrs, &ulEntry);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		*phNldr = (struct NLDR_OBJECT *) pNldr;
+	} else {
+		if (pNldr)
+			NLDR_Delete((struct NLDR_OBJECT *) pNldr);
+
+		*phNldr = NULL;
+	}
+	/* FIXME:Temp. Fix. Must be removed */
+	DBC_Ensure((DSP_SUCCEEDED(status) &&
+			 MEM_IsValidHandle(((struct NLDR_OBJECT *)*phNldr),
+					  NLDR_SIGNATURE))
+			|| (DSP_FAILED(status) && (*phNldr == NULL)));
+	return status;
+}
+
+/*
+ *  ======== NLDR_Delete ========
+ */
+void NLDR_Delete(struct NLDR_OBJECT *hNldr)
+{
+	struct OvlySect *pSect;
+	struct OvlySect *pNext;
+	u16 i;
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+	GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Delete(0x%x)\n", hNldr);
+	hNldr->dbllFxns.exitFxn();
+	if (hNldr->rmm)
+		RMM_delete(hNldr->rmm);
+
+	if (hNldr->segTable)
+		MEM_Free(hNldr->segTable);
+
+	if (hNldr->hDcdMgr)
+		DCD_DestroyManager(hNldr->hDcdMgr);
+
+	/* Free overlay node information */
+	if (hNldr->ovlyTable) {
+		for (i = 0; i < hNldr->nOvlyNodes; i++) {
+			pSect = hNldr->ovlyTable[i].pCreateSects;
+			while (pSect) {
+				pNext = pSect->pNextSect;
+				MEM_Free(pSect);
+				pSect = pNext;
+			}
+			pSect = hNldr->ovlyTable[i].pDeleteSects;
+			while (pSect) {
+				pNext = pSect->pNextSect;
+				MEM_Free(pSect);
+				pSect = pNext;
+			}
+			pSect = hNldr->ovlyTable[i].pExecuteSects;
+			while (pSect) {
+				pNext = pSect->pNextSect;
+				MEM_Free(pSect);
+				pSect = pNext;
+			}
+			pSect = hNldr->ovlyTable[i].pOtherSects;
+			while (pSect) {
+				pNext = pSect->pNextSect;
+				MEM_Free(pSect);
+				pSect = pNext;
+			}
+		}
+		MEM_Free(hNldr->ovlyTable);
+	}
+	MEM_FreeObject(hNldr);
+	DBC_Ensure(!MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+}
+
+/*
+ *  ======== NLDR_Exit ========
+ *  Discontinue usage of NLDR module.
+ */
+void NLDR_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(NLDR_debugMask, GT_5CLASS,
+		 "Entered NLDR_Exit, ref count:  0x%x\n", cRefs);
+
+	if (cRefs == 0) {
+		RMM_exit();
+		NLDR_debugMask.flags = 0;
+	}
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== NLDR_Free ========
+ */
+void NLDR_Free(struct NLDR_NODEOBJECT *hNldrNode)
+{
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+
+	GT_1trace(NLDR_debugMask, GT_ENTER, "NLDR_Free(0x%x)\n", hNldrNode);
+
+	MEM_FreeObject(hNldrNode);
+}
+
+/*
+ *  ======== NLDR_GetFxnAddr ========
+ */
+DSP_STATUS NLDR_GetFxnAddr(struct NLDR_NODEOBJECT *hNldrNode, char *pstrFxn,
+			  u32 *pulAddr)
+{
+	struct DBLL_Symbol *pSym;
+	struct NLDR_OBJECT *hNldr;
+	DSP_STATUS status = DSP_SOK;
+	bool status1 = false;
+	s32 i = 0;
+	struct LibNode root = { NULL, 0, NULL };
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+	DBC_Require(pulAddr != NULL);
+	DBC_Require(pstrFxn != NULL);
+	GT_3trace(NLDR_debugMask, GT_ENTER, "NLDR_GetFxnAddr(0x%x, %s, 0x%x)\n",
+		 hNldrNode, pstrFxn, pulAddr);
+
+	hNldr = hNldrNode->pNldr;
+	/* Called from NODE_Create(), NODE_Delete(), or NODE_Run(). */
+	if (hNldrNode->fDynamic && *hNldrNode->pfPhaseSplit) {
+		switch (hNldrNode->phase) {
+		case NLDR_CREATE:
+			root = hNldrNode->createLib;
+			break;
+		case NLDR_EXECUTE:
+			root = hNldrNode->executeLib;
+			break;
+		case NLDR_DELETE:
+			root = hNldrNode->deleteLib;
+			break;
+		default:
+			DBC_Assert(false);
+			break;
+		}
+	} else {
+		/* for Overlay nodes or non-split Dynamic nodes */
+		root = hNldrNode->root;
+	}
+	status1 = hNldr->dbllFxns.getCAddrFxn(root.lib, pstrFxn, &pSym);
+	if (!status1)
+		status1 = hNldr->dbllFxns.getAddrFxn(root.lib, pstrFxn, &pSym);
+
+	/* If symbol not found, check dependent libraries */
+	if (!status1) {
+		for (i = 0; i < root.nDepLibs; i++) {
+			status1 = hNldr->dbllFxns.getAddrFxn(root.pDepLibs[i].
+					lib, pstrFxn, &pSym);
+			if (!status1) {
+				status1 = hNldr->dbllFxns.getCAddrFxn(root.
+					pDepLibs[i].lib, pstrFxn, &pSym);
+			}
+			if (status1) {
+				/* Symbol found */
+				break;
+			}
+		}
+	}
+	/* Check persistent libraries */
+	if (!status1) {
+		for (i = 0; i < hNldrNode->nPersLib; i++) {
+			status1 = hNldr->dbllFxns.getAddrFxn(hNldrNode->
+					persLib[i].lib,	pstrFxn, &pSym);
+			if (!status1) {
+				status1 =
+				    hNldr->dbllFxns.getCAddrFxn(hNldrNode->
+					persLib[i].lib,	pstrFxn, &pSym);
+			}
+			if (status1) {
+				/* Symbol found */
+				break;
+			}
+		}
+	}
+
+	if (status1) {
+		*pulAddr = pSym->value;
+	} else {
+		GT_1trace(NLDR_debugMask, GT_6CLASS,
+			 "NLDR_GetFxnAddr: Symbol not found: "
+			 "%s\n", pstrFxn);
+		status = DSP_ESYMBOL;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== NLDR_GetRmmManager ========
+ *  Given a NLDR object, retrieve RMM Manager Handle
+ */
+DSP_STATUS NLDR_GetRmmManager(struct NLDR_OBJECT *hNldrObject,
+			     OUT struct RMM_TargetObj **phRmmMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct NLDR_OBJECT *pNldrObject = hNldrObject;
+	DBC_Require(phRmmMgr != NULL);
+	GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_GetRmmManager(0x%x, 0x%x)\n",
+		 hNldrObject, phRmmMgr);
+	if (MEM_IsValidHandle(hNldrObject, NLDR_SIGNATURE)) {
+		*phRmmMgr = pNldrObject->rmm;
+	} else {
+		*phRmmMgr = NULL;
+		status = DSP_EHANDLE;
+		GT_0trace(NLDR_debugMask, GT_7CLASS,
+			 "NLDR_GetRmmManager:Invalid handle");
+	}
+
+	GT_2trace(NLDR_debugMask, GT_ENTER, "Exit NLDR_GetRmmManager: status "
+		 "0x%x\n\tphRmmMgr:  0x%x\n", status, *phRmmMgr);
+
+	DBC_Ensure(DSP_SUCCEEDED(status) || ((phRmmMgr != NULL) &&
+		  (*phRmmMgr == NULL)));
+
+	return status;
+}
+
+/*
+ *  ======== NLDR_Init ========
+ *  Initialize the NLDR module.
+ */
+bool NLDR_Init(void)
+{
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+		DBC_Assert(!NLDR_debugMask.flags);
+		GT_create(&NLDR_debugMask, "DL");	/* "DL" for DLdr */
+
+		RMM_init();
+	}
+
+	cRefs++;
+
+	GT_1trace(NLDR_debugMask, GT_5CLASS, "NLDR_Init(), ref count: 0x%x\n",
+		 cRefs);
+
+	DBC_Ensure(cRefs > 0);
+	return true;
+}
+
+/*
+ *  ======== NLDR_Load ========
+ */
+DSP_STATUS NLDR_Load(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+	struct NLDR_OBJECT *hNldr;
+	struct DSP_UUID libUUID;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+
+	hNldr = hNldrNode->pNldr;
+
+	GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Load(0x%x, 0x%x)\n",
+		 hNldrNode, phase);
+
+	if (hNldrNode->fDynamic) {
+		hNldrNode->phase = phase;
+
+		libUUID = hNldrNode->uuid;
+
+		/* At this point, we may not know if node is split into
+		 * different libraries. So we'll go ahead and load the
+		 * library, and then save the pointer to the appropriate
+		 * location after we know. */
+
+		status = LoadLib(hNldrNode, &hNldrNode->root, libUUID, false,
+				hNldrNode->libPath, phase, 0);
+
+		if (DSP_SUCCEEDED(status)) {
+			if (*hNldrNode->pfPhaseSplit) {
+				switch (phase) {
+				case NLDR_CREATE:
+					hNldrNode->createLib = hNldrNode->root;
+					break;
+
+				case NLDR_EXECUTE:
+					hNldrNode->executeLib = hNldrNode->root;
+					break;
+
+				case NLDR_DELETE:
+					hNldrNode->deleteLib = hNldrNode->root;
+					break;
+
+				default:
+					DBC_Assert(false);
+					break;
+				}
+			}
+		}
+	} else {
+		if (hNldrNode->fOverlay)
+			status = LoadOvly(hNldrNode, phase);
+
+	}
+
+	return status;
+}
+
+/*
+ *  ======== NLDR_Unload ========
+ */
+DSP_STATUS NLDR_Unload(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct LibNode *pRootLib = NULL;
+	s32 i = 0;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNldrNode, NLDR_NODESIGNATURE));
+	GT_2trace(NLDR_debugMask, GT_ENTER, "NLDR_Unload(0x%x, 0x%x)\n",
+		 hNldrNode, phase);
+	if (hNldrNode != NULL) {
+		if (hNldrNode->fDynamic) {
+			if (*hNldrNode->pfPhaseSplit) {
+				switch (phase) {
+				case NLDR_CREATE:
+					pRootLib = &hNldrNode->createLib;
+					break;
+				case NLDR_EXECUTE:
+					pRootLib = &hNldrNode->executeLib;
+					break;
+				case NLDR_DELETE:
+					pRootLib = &hNldrNode->deleteLib;
+					/* Unload persistent libraries */
+					for (i = 0; i < hNldrNode->nPersLib;
+					    i++) {
+						UnloadLib(hNldrNode,
+							&hNldrNode->persLib[i]);
+					}
+					hNldrNode->nPersLib = 0;
+					break;
+				default:
+					DBC_Assert(false);
+					break;
+				}
+			} else {
+				/* Unload main library */
+				pRootLib = &hNldrNode->root;
+			}
+			UnloadLib(hNldrNode, pRootLib);
+		} else {
+			if (hNldrNode->fOverlay)
+				UnloadOvly(hNldrNode, phase);
+
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== AddOvlyInfo ========
+ */
+static DSP_STATUS AddOvlyInfo(void *handle, struct DBLL_SectInfo *sectInfo,
+			     u32 addr, u32 nBytes)
+{
+	char *pNodeName;
+	char *pSectName = (char *)sectInfo->name;
+	bool fExists = false;
+	char seps = ':';
+	char *pch;
+	u16 i;
+	struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+	DSP_STATUS status = DSP_SOK;
+
+	/* Is this an overlay section (load address != run address)? */
+	if (sectInfo->loadAddr == sectInfo->runAddr)
+		goto func_end;
+
+	/* Find the node it belongs to */
+	for (i = 0; i < hNldr->nOvlyNodes; i++) {
+		pNodeName = hNldr->ovlyTable[i].pNodeName;
+		if (CSL_Strncmp(pNodeName, pSectName + 1,
+				CSL_Strlen(pNodeName)) == 0) {
+				/* Found the node */
+				break;
+		}
+	}
+	if (!(i < hNldr->nOvlyNodes))
+		goto func_end;
+
+	/* Determine which phase this section belongs to */
+	for (pch = pSectName + 1; *pch && *pch != seps; pch++)
+		;;
+
+	if (*pch) {
+		pch++;	/* Skip over the ':' */
+		if (CSL_Strncmp(pch, PCREATE, CSL_Strlen(PCREATE)) == 0) {
+			status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+				pCreateSects, sectInfo, &fExists, addr, nBytes);
+			if (DSP_SUCCEEDED(status) && !fExists)
+				hNldr->ovlyTable[i].nCreateSects++;
+
+		} else
+		if (CSL_Strncmp(pch, PDELETE, CSL_Strlen(PDELETE)) == 0) {
+			status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+					    pDeleteSects, sectInfo, &fExists,
+					    addr, nBytes);
+			if (DSP_SUCCEEDED(status) && !fExists)
+				hNldr->ovlyTable[i].nDeleteSects++;
+
+		} else
+		if (CSL_Strncmp(pch, PEXECUTE, CSL_Strlen(PEXECUTE)) == 0) {
+			status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+					    pExecuteSects, sectInfo, &fExists,
+					    addr, nBytes);
+			if (DSP_SUCCEEDED(status) && !fExists)
+				hNldr->ovlyTable[i].nExecuteSects++;
+
+		} else {
+			/* Put in "other" sectins */
+			status = AddOvlySect(hNldr, &hNldr->ovlyTable[i].
+					    pOtherSects, sectInfo, &fExists,
+					    addr, nBytes);
+			if (DSP_SUCCEEDED(status) && !fExists)
+				hNldr->ovlyTable[i].nOtherSects++;
+
+		}
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== AddOvlyNode =========
+ *  Callback function passed to DCD_GetObjects.
+ */
+static DSP_STATUS AddOvlyNode(struct DSP_UUID *pUuid,
+			     enum DSP_DCDOBJTYPE objType,
+			     IN void *handle)
+{
+	struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+	char *pNodeName = NULL;
+	char *pBuf = NULL;
+	u32 uLen;
+	struct DCD_GENERICOBJ objDef;
+	DSP_STATUS status = DSP_SOK;
+
+	if (objType != DSP_DCDNODETYPE)
+		goto func_end;
+
+	status = DCD_GetObjectDef(hNldr->hDcdMgr, pUuid, objType, &objDef);
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* If overlay node, add to the list */
+	if (objDef.objData.nodeObj.usLoadType == NLDR_OVLYLOAD) {
+		if (hNldr->ovlyTable == NULL) {
+			hNldr->nOvlyNodes++;
+		} else {
+			/* Add node to table */
+			hNldr->ovlyTable[hNldr->nNode].uuid = *pUuid;
+			uLen = CSL_Strlen(objDef.objData.nodeObj.ndbProps.
+					 acName);
+			pNodeName = objDef.objData.nodeObj.ndbProps.acName;
+			pBuf = MEM_Calloc(uLen + 1, MEM_PAGED);
+			if (pBuf == NULL) {
+				status = DSP_EMEMORY;
+			} else {
+				CSL_Strcpyn(pBuf, pNodeName, uLen);
+				hNldr->ovlyTable[hNldr->nNode].pNodeName = pBuf;
+				hNldr->nNode++;
+			}
+		}
+	}
+	/* These were allocated in DCD_GetObjectDef */
+	if (objDef.objData.nodeObj.pstrCreatePhaseFxn)
+		MEM_Free(objDef.objData.nodeObj.pstrCreatePhaseFxn);
+
+	if (objDef.objData.nodeObj.pstrExecutePhaseFxn)
+		MEM_Free(objDef.objData.nodeObj.pstrExecutePhaseFxn);
+
+	if (objDef.objData.nodeObj.pstrDeletePhaseFxn)
+		MEM_Free(objDef.objData.nodeObj.pstrDeletePhaseFxn);
+
+	if (objDef.objData.nodeObj.pstrIAlgName)
+		MEM_Free(objDef.objData.nodeObj.pstrIAlgName);
+
+func_end:
+	return status;
+}
+
+/*
+ *  ======== AddOvlySect ========
+ */
+static DSP_STATUS AddOvlySect(struct NLDR_OBJECT *hNldr,
+			      struct OvlySect **pList,
+			      struct DBLL_SectInfo *pSectInfo, bool *pExists,
+			      u32 addr, u32 nBytes)
+{
+	struct OvlySect *pNewSect = NULL;
+	struct OvlySect *pLastSect;
+	struct OvlySect *pSect;
+	DSP_STATUS status = DSP_SOK;
+
+	pSect = pLastSect = *pList;
+	*pExists = false;
+	while (pSect) {
+		/*
+		 *  Make sure section has not already been added. Multiple
+		 *  'write' calls may be made to load the section.
+		 */
+		if (pSect->loadAddr == addr) {
+			/* Already added */
+			*pExists = true;
+			break;
+		}
+		pLastSect = pSect;
+		pSect = pSect->pNextSect;
+	}
+
+	if (!pSect) {
+		/* New section */
+		pNewSect = MEM_Calloc(sizeof(struct OvlySect), MEM_PAGED);
+		if (pNewSect == NULL) {
+			status = DSP_EMEMORY;
+		} else {
+			pNewSect->loadAddr = addr;
+			pNewSect->runAddr = pSectInfo->runAddr +
+					    (addr - pSectInfo->loadAddr);
+			pNewSect->size = nBytes;
+			pNewSect->page = pSectInfo->type;
+		}
+
+		/* Add to the list */
+		if (DSP_SUCCEEDED(status)) {
+			if (*pList == NULL) {
+				/* First in the list */
+				*pList = pNewSect;
+			} else {
+				pLastSect->pNextSect = pNewSect;
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== fakeOvlyWrite ========
+ */
+static s32 fakeOvlyWrite(void *handle, u32 dspAddr, void *buf, u32 nBytes,
+			s32 mtype)
+{
+	return (s32)nBytes;
+}
+
+/*
+ *  ======== FreeSects ========
+ */
+static void FreeSects(struct NLDR_OBJECT *hNldr, struct OvlySect *pPhaseSects,
+		     u16 nAlloc)
+{
+	struct OvlySect *pSect = pPhaseSects;
+	u16 i = 0;
+	bool fRet;
+
+	while (pSect && i < nAlloc) {
+		/* 'Deallocate' */
+		/* segid - page not supported yet */
+		/* Reserved memory */
+		fRet = RMM_free(hNldr->rmm, 0, pSect->runAddr, pSect->size,
+				true);
+		DBC_Assert(fRet);
+		pSect = pSect->pNextSect;
+		i++;
+	}
+}
+
+/*
+ *  ======== GetSymbolValue ========
+ *  Find symbol in library's base image.  If not there, check dependent
+ *  libraries.
+ */
+static bool GetSymbolValue(void *handle, void *pArg, void *rmmHandle,
+			  char *name, struct DBLL_Symbol **sym)
+{
+	struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)handle;
+	struct NLDR_NODEOBJECT *hNldrNode = (struct NLDR_NODEOBJECT *)rmmHandle;
+	struct LibNode *root = (struct LibNode *)pArg;
+	u16 i;
+	bool status = false;
+
+	/* check the base image */
+	status = hNldr->dbllFxns.getAddrFxn(hNldr->baseLib, name, sym);
+	if (!status)
+		status = hNldr->dbllFxns.getCAddrFxn(hNldr->baseLib, name, sym);
+
+	/*
+	 *  Check in root lib itself. If the library consists of
+	 *  multiple object files linked together, some symbols in the
+	 *  library may need to be resolved.
+	 */
+	if (!status) {
+		status = hNldr->dbllFxns.getAddrFxn(root->lib, name, sym);
+		if (!status) {
+			status =
+			    hNldr->dbllFxns.getCAddrFxn(root->lib, name, sym);
+		}
+	}
+
+	/*
+	 *  Check in root lib's dependent libraries, but not dependent
+	 *  libraries' dependents.
+	 */
+	if (!status) {
+		for (i = 0; i < root->nDepLibs; i++) {
+			status = hNldr->dbllFxns.getAddrFxn(root->pDepLibs[i].
+							   lib, name, sym);
+			if (!status) {
+				status = hNldr->dbllFxns.getCAddrFxn(root->
+					 pDepLibs[i].lib, name, sym);
+			}
+			if (status) {
+				/* Symbol found */
+				break;
+			}
+		}
+	}
+	/*
+	 * Check in persistent libraries
+	 */
+	if (!status) {
+		for (i = 0; i < hNldrNode->nPersLib; i++) {
+			status = hNldr->dbllFxns.getAddrFxn(hNldrNode->
+				 persLib[i].lib, name, sym);
+			if (!status) {
+				status = hNldr->dbllFxns.getCAddrFxn
+					(hNldrNode->persLib[i].lib, name, sym);
+			}
+			if (status) {
+				/* Symbol found */
+				break;
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== LoadLib ========
+ *  Recursively load library and all its dependent libraries. The library
+ *  we're loading is specified by a uuid.
+ */
+static DSP_STATUS LoadLib(struct NLDR_NODEOBJECT *hNldrNode,
+			 struct LibNode *root, struct DSP_UUID uuid,
+			 bool rootPersistent, struct DBLL_LibraryObj **libPath,
+			 enum NLDR_PHASE phase, u16 depth)
+{
+	struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+	u16 nLibs = 0;	/* Number of dependent libraries */
+	u16 nPLibs = 0;	/* Number of persistent libraries */
+	u16 nLoaded = 0;	/* Number of dep. libraries loaded */
+	u16 i;
+	u32 entry;
+	u32 dwBufSize = NLDR_MAXPATHLENGTH;
+	DBLL_Flags flags = DBLL_SYMB | DBLL_CODE | DBLL_DATA | DBLL_DYNAMIC;
+	struct DBLL_Attrs newAttrs;
+	char *pszFileName = NULL;
+	struct DSP_UUID *depLibUUIDs = NULL;
+	bool *persistentDepLibs = NULL;
+	DSP_STATUS status = DSP_SOK;
+	bool fStatus = false;
+	struct LibNode *pDepLib;
+
+	if (depth > MAXDEPTH) {
+		/* Error */
+		DBC_Assert(false);
+	}
+	root->lib = NULL;
+	/* Allocate a buffer for library file name of size DBL_MAXPATHLENGTH */
+	pszFileName = MEM_Calloc(DBLL_MAXPATHLENGTH, MEM_PAGED);
+	if (pszFileName == NULL)
+		status = DSP_EMEMORY;
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Get the name of the library */
+		if (depth == 0) {
+			status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
+				&uuid, pszFileName, &dwBufSize, phase,
+				hNldrNode->pfPhaseSplit);
+		} else {
+			/* Dependent libraries are registered with a phase */
+			status = DCD_GetLibraryName(hNldrNode->pNldr->hDcdMgr,
+				&uuid, pszFileName, &dwBufSize, NLDR_NOPHASE,
+				NULL);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Open the library, don't load symbols */
+		status = hNldr->dbllFxns.openFxn(hNldr->dbll, pszFileName,
+			 DBLL_NOLOAD, &root->lib);
+	}
+	/* Done with file name */
+	if (pszFileName)
+		MEM_Free(pszFileName);
+
+	/* Check to see if library not already loaded */
+	if (DSP_SUCCEEDED(status) && rootPersistent) {
+		fStatus = findInPersistentLibArray(hNldrNode, root->lib);
+		/* Close library */
+		if (fStatus) {
+			hNldr->dbllFxns.closeFxn(root->lib);
+			return DSP_SALREADYLOADED;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Check for circular dependencies. */
+		for (i = 0; i < depth; i++) {
+			if (root->lib == libPath[i]) {
+				/* This condition could be checked by a
+				 * tool at build time. */
+				status = DSP_EDYNLOAD;
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Add library to current path in dependency tree */
+		libPath[depth] = root->lib;
+		depth++;
+		/* Get number of dependent libraries */
+		status = DCD_GetNumDepLibs(hNldrNode->pNldr->hDcdMgr, &uuid,
+					  &nLibs, &nPLibs, phase);
+	}
+	DBC_Assert(nLibs >= nPLibs);
+	if (DSP_SUCCEEDED(status)) {
+		if (!(*hNldrNode->pfPhaseSplit))
+			nPLibs = 0;
+
+		/* nLibs = #of dependent libraries */
+		root->nDepLibs = nLibs - nPLibs;
+		if (nLibs > 0) {
+			depLibUUIDs = MEM_Calloc(sizeof(struct DSP_UUID) *
+				      nLibs, MEM_PAGED);
+			persistentDepLibs = MEM_Calloc(sizeof(bool) *
+					    nLibs, MEM_PAGED);
+			if (!depLibUUIDs || !persistentDepLibs)
+				status = DSP_EMEMORY;
+
+			if (root->nDepLibs > 0) {
+				/* Allocate arrays for dependent lib UUIDs,
+				 * lib nodes */
+				root->pDepLibs = MEM_Calloc
+					(sizeof(struct LibNode) *
+					(root->nDepLibs), MEM_PAGED);
+				if (!(root->pDepLibs))
+					status = DSP_EMEMORY;
+
+			}
+
+			if (DSP_SUCCEEDED(status)) {
+				/* Get the dependent library UUIDs */
+				status = DCD_GetDepLibs(hNldrNode->pNldr->
+					hDcdMgr, &uuid, nLibs, depLibUUIDs,
+					persistentDepLibs, phase);
+			}
+		}
+	}
+
+	/*
+	 *  Recursively load dependent libraries.
+	 */
+	if (DSP_SUCCEEDED(status) && persistentDepLibs) {
+		for (i = 0; i < nLibs; i++) {
+			/* If root library is NOT persistent, and dep library
+			 * is, then record it.  If root library IS persistent,
+			 * the deplib is already included */
+			if (!rootPersistent && persistentDepLibs[i] &&
+			   *hNldrNode->pfPhaseSplit) {
+				if ((hNldrNode->nPersLib) > MAXLIBS) {
+					status = DSP_EDYNLOAD;
+					break;
+				}
+
+				/* Allocate library outside of phase */
+				pDepLib = &hNldrNode->persLib[hNldrNode->
+					  nPersLib];
+			} else {
+				if (rootPersistent)
+					persistentDepLibs[i] = true;
+
+
+				/* Allocate library within phase */
+				pDepLib = &root->pDepLibs[nLoaded];
+			}
+
+			if (depLibUUIDs) {
+				status = LoadLib(hNldrNode, pDepLib,
+						depLibUUIDs[i],
+						persistentDepLibs[i], libPath,
+						phase,
+						depth);
+			} else {
+				status = DSP_EMEMORY;
+			}
+
+			if (DSP_SUCCEEDED(status)) {
+				if ((status != DSP_SALREADYLOADED) &&
+				   !rootPersistent && persistentDepLibs[i] &&
+				   *hNldrNode->pfPhaseSplit) {
+					(hNldrNode->nPersLib)++;
+				} else {
+					if (!persistentDepLibs[i] ||
+					   !(*hNldrNode->pfPhaseSplit)) {
+						nLoaded++;
+					}
+				}
+			} else {
+				break;
+			}
+		}
+	}
+
+	/* Now we can load the root library */
+	if (DSP_SUCCEEDED(status)) {
+		newAttrs = hNldr->dbllAttrs;
+		newAttrs.symArg = root;
+		newAttrs.rmmHandle = hNldrNode;
+		newAttrs.wHandle = hNldrNode->pPrivRef;
+		newAttrs.baseImage = false;
+
+		status = hNldr->dbllFxns.loadFxn(root->lib, flags, &newAttrs,
+			 &entry);
+	}
+
+	/*
+	 *  In case of failure, unload any dependent libraries that
+	 *  were loaded, and close the root library.
+	 *  (Persistent libraries are unloaded from the very top)
+	 */
+	if (DSP_FAILED(status)) {
+		if (phase != NLDR_EXECUTE) {
+			for (i = 0; i < hNldrNode->nPersLib; i++)
+				UnloadLib(hNldrNode, &hNldrNode->persLib[i]);
+
+			hNldrNode->nPersLib = 0;
+		}
+		for (i = 0; i < nLoaded; i++)
+			UnloadLib(hNldrNode, &root->pDepLibs[i]);
+
+		if (root->lib)
+			hNldr->dbllFxns.closeFxn(root->lib);
+
+	}
+
+	/* Going up one node in the dependency tree */
+	depth--;
+
+	if (depLibUUIDs) {
+		MEM_Free(depLibUUIDs);
+		depLibUUIDs = NULL;
+	}
+
+	if (persistentDepLibs) {
+		MEM_Free(persistentDepLibs);
+		persistentDepLibs = NULL;
+	}
+
+	return status;
+}
+
+/*
+ *  ======== LoadOvly ========
+ */
+static DSP_STATUS LoadOvly(struct NLDR_NODEOBJECT *hNldrNode,
+			  enum NLDR_PHASE phase)
+{
+	struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+	struct OvlyNode *pONode = NULL;
+	struct OvlySect *pPhaseSects = NULL;
+	struct OvlySect *pOtherSects = NULL;
+	u16 i;
+	u16 nAlloc = 0;
+	u16 nOtherAlloc = 0;
+	u16 *pRefCount = NULL;
+	u16 *pOtherRef = NULL;
+	u32 nBytes;
+	struct OvlySect *pSect;
+	DSP_STATUS status = DSP_SOK;
+
+	/* Find the node in the table */
+	for (i = 0; i < hNldr->nOvlyNodes; i++) {
+		if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
+			/* Found it */
+			pONode = &(hNldr->ovlyTable[i]);
+			break;
+		}
+	}
+
+	DBC_Assert(i < hNldr->nOvlyNodes);
+	switch (phase) {
+	case NLDR_CREATE:
+		pRefCount = &(pONode->createRef);
+		pOtherRef = &(pONode->otherRef);
+		pPhaseSects = pONode->pCreateSects;
+		pOtherSects = pONode->pOtherSects;
+		break;
+
+	case NLDR_EXECUTE:
+		pRefCount = &(pONode->executeRef);
+		pPhaseSects = pONode->pExecuteSects;
+		break;
+
+	case NLDR_DELETE:
+		pRefCount = &(pONode->deleteRef);
+		pPhaseSects = pONode->pDeleteSects;
+		break;
+
+	default:
+		DBC_Assert(false);
+		break;
+	}
+
+	DBC_Assert(pRefCount != NULL);
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	if (pRefCount == NULL)
+		goto func_end;
+
+	if (*pRefCount != 0)
+		goto func_end;
+
+	/* 'Allocate' memory for overlay sections of this phase */
+	pSect = pPhaseSects;
+	while (pSect) {
+		/* allocate */ /* page not supported yet */
+		  /* reserve */ /* align */
+		status = RMM_alloc(hNldr->rmm, 0, pSect->size, 0,
+			 &(pSect->runAddr), true);
+		if (DSP_SUCCEEDED(status)) {
+			pSect = pSect->pNextSect;
+			nAlloc++;
+		} else {
+			break;
+		}
+	}
+	if (pOtherRef && *pOtherRef == 0) {
+		/* 'Allocate' memory for other overlay sections
+		 * (create phase) */
+		if (DSP_SUCCEEDED(status)) {
+			pSect = pOtherSects;
+			while (pSect) {
+				/* page not supported */ /* align */
+				/* reserve */
+				status = RMM_alloc(hNldr->rmm, 0, pSect->size,
+					 0, &(pSect->runAddr), true);
+				if (DSP_SUCCEEDED(status)) {
+					pSect = pSect->pNextSect;
+					nOtherAlloc++;
+				} else {
+					break;
+				}
+			}
+		}
+	}
+	if (*pRefCount == 0) {
+		if (DSP_SUCCEEDED(status)) {
+			/* Load sections for this phase */
+			pSect = pPhaseSects;
+			while (pSect && DSP_SUCCEEDED(status)) {
+				nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
+					 pSect->runAddr, pSect->loadAddr,
+					 pSect->size, pSect->page);
+				if (nBytes != pSect->size)
+					status = DSP_EFAIL;
+
+				pSect = pSect->pNextSect;
+			}
+		}
+	}
+	if (pOtherRef && *pOtherRef == 0) {
+		if (DSP_SUCCEEDED(status)) {
+			/* Load other sections (create phase) */
+			pSect = pOtherSects;
+			while (pSect && DSP_SUCCEEDED(status)) {
+				nBytes = (*hNldr->ovlyFxn)(hNldrNode->pPrivRef,
+					 pSect->runAddr, pSect->loadAddr,
+					 pSect->size, pSect->page);
+				if (nBytes != pSect->size)
+					status = DSP_EFAIL;
+
+				pSect = pSect->pNextSect;
+			}
+		}
+	}
+	if (DSP_FAILED(status)) {
+		/* 'Deallocate' memory */
+		FreeSects(hNldr, pPhaseSects, nAlloc);
+		FreeSects(hNldr, pOtherSects, nOtherAlloc);
+	}
+func_end:
+	if (DSP_SUCCEEDED(status) && (pRefCount != NULL)) {
+		*pRefCount += 1;
+		if (pOtherRef)
+			*pOtherRef += 1;
+
+	}
+
+	return status;
+}
+
+/*
+ *  ======== RemoteAlloc ========
+ */
+static DSP_STATUS RemoteAlloc(void **pRef, u16 space, u32 size,
+			     u32 align, u32 *dspAddr,
+			     OPTIONAL s32 segmentId, OPTIONAL s32 req,
+			     bool reserve)
+{
+	struct NLDR_NODEOBJECT *hNode = (struct NLDR_NODEOBJECT *)pRef;
+	struct NLDR_OBJECT *hNldr;
+	struct RMM_TargetObj *rmm;
+	u16 memPhaseBit = MAXFLAGS;
+	u16 segid = 0;
+	u16 i;
+	u16 memType;
+	u32 nWords;
+	struct RMM_Addr *pRmmAddr = (struct RMM_Addr *)dspAddr;
+	bool fReq = false;
+	DSP_STATUS status = DSP_EMEMORY;	/* Set to fail */
+	DBC_Require(MEM_IsValidHandle(hNode, NLDR_NODESIGNATURE));
+	DBC_Require(space == DBLL_CODE || space == DBLL_DATA ||
+		   space == DBLL_BSS);
+	hNldr = hNode->pNldr;
+	rmm = hNldr->rmm;
+	/* Convert size to DSP words */
+	nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
+	/* Modify memory 'align' to account for DSP cache line size */
+	align = findLcm(GEM_CACHE_LINE_SIZE, align);
+	GT_1trace(NLDR_debugMask, GT_7CLASS,
+		 "RemoteAlloc: memory align to 0x%x \n", align);
+	if (segmentId != -1) {
+		pRmmAddr->segid = segmentId;
+		segid = segmentId;
+		fReq = req;
+	} else {
+		switch (hNode->phase) {
+		case NLDR_CREATE:
+			memPhaseBit = CREATEDATAFLAGBIT;
+			break;
+		case NLDR_DELETE:
+			memPhaseBit = DELETEDATAFLAGBIT;
+			break;
+		case NLDR_EXECUTE:
+			memPhaseBit = EXECUTEDATAFLAGBIT;
+			break;
+		default:
+			DBC_Assert(false);
+			break;
+		}
+		if (space == DBLL_CODE)
+			memPhaseBit++;
+
+		if (memPhaseBit < MAXFLAGS)
+			segid = hNode->segId[memPhaseBit];
+
+		/* Determine if there is a memory loading requirement */
+		if ((hNode->codeDataFlagMask >> memPhaseBit) & 0x1)
+			fReq = true;
+
+	}
+	memType = (space == DBLL_CODE) ? DYNM_CODE : DYNM_DATA;
+
+	/* Find an appropriate segment based on space */
+	if (segid == NULLID) {
+		/* No memory requirements of preferences */
+		DBC_Assert(!fReq);
+		goto func_cont;
+	}
+	if (segid <= MAXSEGID) {
+		DBC_Assert(segid < hNldr->nSegs);
+		/* Attempt to allocate from segid first. */
+		pRmmAddr->segid = segid;
+		status = RMM_alloc(rmm, segid, nWords, align, dspAddr, false);
+		if (DSP_FAILED(status)) {
+			GT_1trace(NLDR_debugMask, GT_6CLASS,
+				 "RemoteAlloc:Unable allocate "
+				 "from segment %d.\n", segid);
+		}
+	} else {
+		/* segid > MAXSEGID ==> Internal or external memory */
+		DBC_Assert(segid == MEMINTERNALID || segid == MEMEXTERNALID);
+		 /*  Check for any internal or external memory segment,
+		  *  depending on segid.*/
+		memType |= segid == MEMINTERNALID ?
+				 DYNM_INTERNAL : DYNM_EXTERNAL;
+		for (i = 0; i < hNldr->nSegs; i++) {
+			if ((hNldr->segTable[i] & memType) != memType)
+				continue;
+
+			status = RMM_alloc(rmm, i, nWords, align, dspAddr,
+					   false);
+			if (DSP_SUCCEEDED(status)) {
+				/* Save segid for freeing later */
+				pRmmAddr->segid = i;
+				break;
+			}
+		}
+	}
+func_cont:
+	/* Haven't found memory yet, attempt to find any segment that works */
+	if (status == DSP_EMEMORY && !fReq) {
+		GT_0trace(NLDR_debugMask, GT_6CLASS,
+			 "RemoteAlloc: Preferred segment "
+			 "unavailable, trying another segment.\n");
+		for (i = 0; i < hNldr->nSegs; i++) {
+			/* All bits of memType must be set */
+			if ((hNldr->segTable[i] & memType) != memType)
+				continue;
+
+			status = RMM_alloc(rmm, i, nWords, align, dspAddr,
+					  false);
+			if (DSP_SUCCEEDED(status)) {
+				/* Save segid */
+				pRmmAddr->segid = i;
+				break;
+			}
+		}
+	}
+
+	return status;
+}
+
+static DSP_STATUS RemoteFree(void **pRef, u16 space, u32 dspAddr,
+				u32 size, bool reserve)
+{
+	struct NLDR_OBJECT *hNldr = (struct NLDR_OBJECT *)pRef;
+	struct RMM_TargetObj *rmm;
+	u32 nWords;
+	DSP_STATUS status = DSP_EMEMORY;	/* Set to fail */
+
+	DBC_Require(MEM_IsValidHandle(hNldr, NLDR_SIGNATURE));
+
+	rmm = hNldr->rmm;
+
+	/* Convert size to DSP words */
+	nWords = (size + hNldr->usDSPWordSize - 1) / hNldr->usDSPWordSize;
+
+	if (RMM_free(rmm, space, dspAddr, nWords, reserve))
+		status = DSP_SOK;
+
+	return status;
+}
+
+/*
+ *  ======== UnloadLib ========
+ */
+static void UnloadLib(struct NLDR_NODEOBJECT *hNldrNode, struct LibNode *root)
+{
+	struct DBLL_Attrs newAttrs;
+	struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+	u16 i;
+
+	DBC_Assert(root != NULL);
+
+	/* Unload dependent libraries */
+	for (i = 0; i < root->nDepLibs; i++)
+		UnloadLib(hNldrNode, &root->pDepLibs[i]);
+
+	root->nDepLibs = 0;
+
+	newAttrs = hNldr->dbllAttrs;
+	newAttrs.rmmHandle = hNldr->rmm;
+	newAttrs.wHandle = hNldrNode->pPrivRef;
+	newAttrs.baseImage = false;
+	newAttrs.symArg = root;
+
+	if (root->lib) {
+		/* Unload the root library */
+		hNldr->dbllFxns.unloadFxn(root->lib, &newAttrs);
+		hNldr->dbllFxns.closeFxn(root->lib);
+	}
+
+	/* Free dependent library list */
+	if (root->pDepLibs) {
+		MEM_Free(root->pDepLibs);
+		root->pDepLibs = NULL;
+	}
+}
+
+/*
+ *  ======== UnloadOvly ========
+ */
+static void UnloadOvly(struct NLDR_NODEOBJECT *hNldrNode, enum NLDR_PHASE phase)
+{
+	struct NLDR_OBJECT *hNldr = hNldrNode->pNldr;
+	struct OvlyNode *pONode = NULL;
+	struct OvlySect *pPhaseSects = NULL;
+	struct OvlySect *pOtherSects = NULL;
+	u16 i;
+	u16 nAlloc = 0;
+	u16 nOtherAlloc = 0;
+	u16 *pRefCount = NULL;
+	u16 *pOtherRef = NULL;
+	DSP_STATUS status = DSP_SOK;
+
+	/* Find the node in the table */
+	for (i = 0; i < hNldr->nOvlyNodes; i++) {
+		if (IsEqualUUID(hNldrNode->uuid, hNldr->ovlyTable[i].uuid)) {
+			/* Found it */
+			pONode = &(hNldr->ovlyTable[i]);
+			break;
+		}
+	}
+
+	DBC_Assert(i < hNldr->nOvlyNodes);
+	switch (phase) {
+	case NLDR_CREATE:
+		pRefCount = &(pONode->createRef);
+		pPhaseSects = pONode->pCreateSects;
+		nAlloc = pONode->nCreateSects;
+		break;
+	case NLDR_EXECUTE:
+		pRefCount = &(pONode->executeRef);
+		pPhaseSects = pONode->pExecuteSects;
+		nAlloc = pONode->nExecuteSects;
+		break;
+	case NLDR_DELETE:
+		pRefCount = &(pONode->deleteRef);
+		pOtherRef = &(pONode->otherRef);
+		pPhaseSects = pONode->pDeleteSects;
+		/* 'Other' overlay sections are unloaded in the delete phase */
+		pOtherSects = pONode->pOtherSects;
+		nAlloc = pONode->nDeleteSects;
+		nOtherAlloc = pONode->nOtherSects;
+		break;
+	default:
+		DBC_Assert(false);
+		break;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		DBC_Assert(pRefCount && (*pRefCount > 0));
+		 if (pRefCount && (*pRefCount > 0)) {
+			*pRefCount -= 1;
+			if (pOtherRef) {
+				DBC_Assert(*pOtherRef > 0);
+				*pOtherRef -= 1;
+			}
+		}
+	}
+	if (pRefCount && (*pRefCount == 0)) {
+		/* 'Deallocate' memory */
+		FreeSects(hNldr, pPhaseSects, nAlloc);
+	}
+	if (pOtherRef && *pOtherRef == 0)
+		FreeSects(hNldr, pOtherSects, nOtherAlloc);
+
+}
+
+/*
+ *  ======== findInPersistentLibArray ========
+ */
+static bool findInPersistentLibArray(struct NLDR_NODEOBJECT *hNldrNode,
+				    struct DBLL_LibraryObj *lib)
+{
+	s32 i = 0;
+
+	for (i = 0; i < hNldrNode->nPersLib; i++) {
+		if (lib == hNldrNode->persLib[i].lib)
+			return true;
+
+	}
+
+	return false;
+}
+
+/*
+ * ================ Find LCM (Least Common Multiplier ===
+ */
+static u32 findLcm(u32 a, u32 b)
+{
+	u32 retVal;
+
+	retVal = a * b / findGcf(a, b);
+
+	return retVal;
+}
+
+/*
+ * ================ Find GCF (Greatest Common Factor ) ===
+ */
+static u32 findGcf(u32 a, u32 b)
+{
+	u32 c;
+
+	/* Get the GCF (Greatest common factor between the numbers,
+	 * using Euclidian Algo */
+	while ((c = (a % b))) {
+		a = b;
+		b = c;
+	}
+	return b;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/node.c b/drivers/dsp/bridge/rmgr/node.c
new file mode 100644
index 0000000..ab6bf8e
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/node.c
@@ -0,0 +1,3365 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/node.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== node.c ========
+ *
+ *  Description:
+ *      DSP/BIOS Bridge Node Manager.
+ *
+ *  Public Functions:
+ *      NODE_Allocate
+ *      NODE_AllocMsgBuf
+ *      NODE_ChangePriority
+ *      NODE_Connect
+ *      NODE_Create
+ *      NODE_CreateMgr
+ *      NODE_Delete
+ *      NODE_DeleteMgr
+ *      NODE_EnumNodes
+ *      NODE_Exit
+ *      NODE_FreeMsgBuf
+ *      NODE_GetAttr
+ *      NODE_GetChannelId
+ *      NODE_GetMessage
+ *      NODE_GetStrmMgr
+ *      NODE_Init
+ *      NODE_OnExit
+ *      NODE_Pause
+ *      NODE_PutMessage
+ *      NODE_RegisterNotify
+ *      NODE_Run
+ *      NODE_Terminate
+ *
+ *! Revision History:
+ *! =================
+ *! 12-Apr-2004 hp  Compile IVA only for 24xx
+ *! 09-Feb-2004 vp  Updated to support IVA.
+ *! 07-Apr-2003 map	    Eliminated references to old DLDR
+ *! 26-Mar-2003 vp  Commented the call to DSP deep sleep in Node_Delete
+ *!		    function.
+ *! 18-Feb-2003 vp  Code review updates.
+ *! 06-Feb-2003 kc      Fixed FreeStream to release streams correctly.
+ *! 23-Jan-2003 map     Removed call to DISP_DoCinit within Write()
+ *! 03-Jan-2003 map     Only unload code after phase has executed if
+ *!		     overlay or split dynload phases
+ *! 18-Oct-2002 vp  Ported to Linux platform.
+ *! 06-Nov-2002 map     Fixed NODE_Run on NODE_PAUSED bug
+ *! 12-Oct-2002 map     Fixed DeleteNode bug in NODE_Create
+ *! 11-Sep-2002 rr      DeleteNode frees the memory for strmConnect and dcd obj
+ *! 29-Aug-2002 map     Modified Ovly and Write to use ARM-side copy
+ *! 22-May-2002 sg      Changed use of cbData for PWR calls.
+ *! 17-May-2002 jeh     Removed LoadLoaderFxns(). Get address of RMS_cinit()
+ *!		     function. Call DISP_DoCinit() from Write(), if .cinit.
+ *! 13-May-2002 sg      Added timeout to wake/sleep calls.
+ *! 02-May-2002 sg      Added wake/sleep of DSP to support "nap" mode.
+ *! 18-Apr-2002 jeh     Use dynamic loader if compile flag is set.
+ *! 13-Feb-2002 jeh     Get uSysStackSize from DSP_NDBPROPS.
+ *! 07-Jan-2002 ag      STRMMODE_ZEROCOPY(shared memory buffer swap) enabled.
+ *! 17-Dec-2001 ag      STRMMODE_RDMA(DDMA) enabled.
+ *! 12-Dec-2001 ag      Check for valid stream mode in NODE_Connect().
+ *! 04-Dec-2001 jeh     Check for node sufficiently connected in NODE_Create().
+ *! 15-Nov-2001 jeh     Removed DBC_Require(pNode->hXlator != NULL) from
+ *!		     NODE_AllocMsgBuf(), and check node type != NODE_DEVICE.
+ *! 11-Sep-2001 ag      Zero-copy messaging support.
+ *! 28-Aug-2001 jeh     Overlay/dynamic loader infrastructure added. Removed
+ *!		     NODE_GetDispatcher, excess node states.
+ *! 07-Aug-2001 jeh     Removed critical section for dispatcher.
+ *! 26-Jul-2001 jeh     Get ZL dll name through CFG.
+ *! 05-Jun-2001 jeh     Assume DSP_STRMATTRS.uBufsize in GPP bytes.
+ *! 11-May-2001 jeh     Some code review cleanup.
+ *! 13-Feb-2001 kc:     DSP/BIOS Bridge name updates.
+ *! 15-Dec-2000 sg      Convert IALG_Fxn address from byte addr to word addr.
+ *! 04-Dec-2000 jeh     Call MSG Get and Put functions.
+ *! 04-Dec-2000 ag      Added SM support for node messaging.
+ *! 10-Nov-2000 rr:     NODE_MIN/MAX Priority is defined in dspdefs.h.
+ *! 27-Oct-2000 jeh     Added NODE_AllocMsgBuf(), NODE_FreeMsgBuf().
+ *! 11-Oct-2000 jeh     Changed NODE_EnumNodeInfo to NODE_EnumNodes. Added
+ *!		     NODE_CloseOrphans(). Remove NODE_RegisterNotifyAllNodes
+ *! 19-Jun-2000 jeh     Created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <csl.h>
+#include <list.h>
+#include <mem.h>
+#include <proc.h>
+#include <strm.h>
+#include <sync.h>
+#include <ntfy.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <cmm.h>
+#include <cod.h>
+#include <dev.h>
+#include <msg.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <dbdcd.h>
+#include <disp.h>
+#include <rms_sh.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmd.h>
+#include <wmdioctl.h>
+
+/*  ----------------------------------- Others */
+#include <gb.h>
+#ifdef DEBUG
+#include <uuidutil.h>
+#include <dbg.h>
+#endif
+
+/*  ----------------------------------- This */
+#include <nodepriv.h>
+#include <node.h>
+
+/* Static/Dynamic Loader includes */
+#include <dbll.h>
+#include <nldr.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <drv.h>
+#include <drvdefs.h>
+#include <prcs.h>
+#include <dbreg.h>
+#include <resourcecleanup.h>
+#endif
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+#endif
+#endif
+
+#define NODE_SIGNATURE      0x45444f4e	/* "EDON" */
+#define NODEMGR_SIGNATURE   0x52474d4e	/* "RGMN" */
+
+#define HOSTPREFIX	  "/host"
+#define PIPEPREFIX	  "/dbpipe"
+
+#define MaxInputs(h)  ((h)->dcdProps.objData.nodeObj.ndbProps.uNumInputStreams)
+#define MaxOutputs(h) ((h)->dcdProps.objData.nodeObj.ndbProps.uNumOutputStreams)
+
+#define NODE_GetPriority(h) ((h)->nPriority)
+#define NODE_SetPriority(hNode, nPriority) ((hNode)->nPriority = nPriority)
+#define NODE_SetState(hNode, state) ((hNode)->nState = state)
+
+#define MAXPIPES	100	/* Max # of /pipe connections (CSL limit) */
+#define MAXDEVSUFFIXLEN 2	/* Max(Log base 10 of MAXPIPES, MAXSTREAMS) */
+
+#define PIPENAMELEN     (sizeof(PIPEPREFIX) + MAXDEVSUFFIXLEN)
+#define HOSTNAMELEN     (sizeof(HOSTPREFIX) + MAXDEVSUFFIXLEN)
+
+#define MAXDEVNAMELEN	   32	/* DSP_NDBPROPS.acName size */
+#define CREATEPHASE	     1
+#define EXECUTEPHASE	    2
+#define DELETEPHASE	     3
+
+/* Define default STRM parameters */
+/*
+ *  TBD: Put in header file, make global DSP_STRMATTRS with defaults,
+ *  or make defaults configurable.
+ */
+#define DEFAULTBUFSIZE	  32
+#define DEFAULTNBUFS	    2
+#define DEFAULTSEGID	    0
+#define DEFAULTALIGNMENT	0
+#define DEFAULTTIMEOUT	  10000
+
+#define RMSQUERYSERVER	  0
+#define RMSCONFIGURESERVER      1
+#define RMSCREATENODE	   2
+#define RMSEXECUTENODE	  3
+#define RMSDELETENODE	   4
+#define RMSCHANGENODEPRIORITY   5
+#define RMSREADMEMORY	   6
+#define RMSWRITEMEMORY	  7
+#define RMSCOPY		 8
+#define MAXTIMEOUT              2000
+
+#define NUMRMSFXNS	      9
+
+#define PWR_TIMEOUT	     500	/* default PWR timeout in msec */
+
+#define STACKSEGLABEL "L1DSRAM_HEAP"  /* Label for DSP Stack Segment Address */
+
+/*
+ *  ======== NODE_MGR ========
+ */
+struct NODE_MGR {
+	u32 dwSignature;	/* For object validation */
+	struct DEV_OBJECT *hDevObject;	/* Device object */
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD */
+	struct DCD_MANAGER *hDcdMgr;	/* Proc/Node data manager */
+	struct DISP_OBJECT *hDisp;	/* Node dispatcher */
+	struct LST_LIST *nodeList;	/* List of all allocated nodes */
+	u32 uNumNodes;		/* Number of nodes in nodeList */
+	u32 uNumCreated;	/* Number of nodes *created* on DSP */
+	struct GB_TMap *pipeMap;		/* Pipe connection bit map */
+	struct GB_TMap *pipeDoneMap;	/* Pipes that are half free */
+	struct GB_TMap *chnlMap;		/* Channel allocation bit map */
+	struct GB_TMap *dmaChnlMap;	/* DMA Channel allocation bit map */
+	struct GB_TMap *zChnlMap;	/* Zero-Copy Channel alloc bit map */
+	struct NTFY_OBJECT *hNtfy;	/* Manages registered notifications */
+	struct SYNC_CSOBJECT *hSync;	/* For critical sections */
+	struct SYNC_CSOBJECT *hAllocSync; /* For NODE_Alloc critical sections */
+	u32 ulFxnAddrs[NUMRMSFXNS];	/* RMS function addresses */
+	struct MSG_MGR *hMsg;
+
+	/* Processor properties needed by Node Dispatcher */
+	u32 ulNumChnls;	/* Total number of channels */
+	u32 ulChnlOffset;	/* Offset of chnl ids rsvd for RMS */
+	u32 ulChnlBufSize;	/* Buffer size for data to RMS */
+	DSP_PROCFAMILY procFamily;	/* eg, 5000 */
+	DSP_PROCTYPE procType;	/* eg, 5510 */
+	u32 uDSPWordSize;	/* Size of DSP word on host bytes */
+	u32 uDSPDataMauSize;	/* Size of DSP data MAU */
+	u32 uDSPMauSize;	/* Size of MAU */
+	s32 nMinPri;		/* Minimum runtime priority for node */
+	s32 nMaxPri;		/* Maximum runtime priority for node */
+
+	struct STRM_MGR *hStrmMgr;	/* STRM manager */
+
+	/* Loader properties */
+	struct NLDR_OBJECT *hNldr;	/* Handle to loader */
+	struct NLDR_FXNS nldrFxns;	/* Handle to loader functions */
+	bool fLoaderInit;	/* Loader Init function succeeded? */
+};
+
+/*
+ *  ======== CONNECTTYPE ========
+ */
+enum CONNECTTYPE {
+	NOTCONNECTED = 0,
+	NODECONNECT,
+	HOSTCONNECT,
+	DEVICECONNECT,
+} ;
+
+/*
+ *  ======== STREAM ========
+ */
+struct STREAM {
+	enum CONNECTTYPE type;	/* Type of stream connection */
+	u32 devId;		/* pipe or channel id */
+};
+
+/*
+ *  ======== NODE_OBJECT ========
+ */
+struct NODE_OBJECT {
+	struct LST_ELEM listElem;
+	u32 dwSignature;	/* For object validation */
+	struct NODE_MGR *hNodeMgr;	/* The manager of this node */
+	struct PROC_OBJECT *hProcessor;	/* Back pointer to processor */
+	struct DSP_UUID nodeId;	/* Node's ID */
+	s32 nPriority;		/* Node's current priority */
+	u32 uTimeout;		/* Timeout for blocking NODE calls */
+	u32 uHeapSize;		/* Heap Size */
+	u32 uDSPHeapVirtAddr;	/* Heap Size */
+	u32 uGPPHeapVirtAddr;	/* Heap Size */
+	enum NODE_TYPE nType;	/* Type of node: message, task, etc */
+	enum NODE_STATE nState;	/* NODE_ALLOCATED, NODE_CREATED, ... */
+	u32 uNumInputs;	/* Current number of inputs */
+	u32 uNumOutputs;	/* Current number of outputs */
+	u32 uMaxInputIndex;	/* Current max input stream index */
+	u32 uMaxOutputIndex;	/* Current max output stream index */
+	struct STREAM *inputs;		/* Node's input streams */
+	struct STREAM *outputs;	/* Node's output streams */
+	struct NODE_CREATEARGS createArgs;  /* Args for node create function */
+	NODE_ENV nodeEnv;	/* Environment returned by RMS */
+	struct DCD_GENERICOBJ dcdProps;	/* Node properties from DCD */
+	struct DSP_CBDATA *pArgs;	/* Optional args to pass to node */
+	struct NTFY_OBJECT *hNtfy;	/* Manages registered notifications */
+	char *pstrDevName;	/* device name, if device node */
+	struct SYNC_OBJECT *hSyncDone;	/* Synchronize NODE_Terminate */
+	s32 nExitStatus;	/* execute function return status */
+
+	/* Information needed for NODE_GetAttr() */
+	DSP_HNODE hDeviceOwner;	/* If dev node, task that owns it */
+	u32 uNumGPPInputs;	/* Current # of from GPP streams */
+	u32 uNumGPPOutputs;	/* Current # of to GPP streams */
+	/* Current stream connections */
+	struct DSP_STREAMCONNECT *streamConnect;
+
+	/* Message queue */
+	struct MSG_QUEUE *hMsgQueue;
+
+	/* These fields used for SM messaging */
+	struct CMM_XLATOROBJECT *hXlator;   /* Node's SM address translator */
+
+	/* Handle to pass to dynamic loader */
+	struct NLDR_NODEOBJECT *hNldrNode;
+	bool fLoaded;		/* Code is (dynamically) loaded */
+	bool fPhaseSplit;	/* Phases split in many libs or ovly */
+
+} ;
+
+/* Default buffer attributes */
+struct DSP_BUFFERATTR NODE_DFLTBUFATTRS = {
+	0, 			/* cbStruct */
+	1, 			/* uSegment */
+	0, 			/* uAlignment */
+};
+
+static void DeleteNode(struct NODE_OBJECT *hNode);
+static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr);
+static void FillStreamConnect(struct NODE_OBJECT *hNode1,
+			     struct NODE_OBJECT *hNode2, u32 uStream1,
+			     u32 uStream2);
+static void FillStreamDef(struct NODE_OBJECT *hNode,
+			struct NODE_STRMDEF *pstrmDef,
+			struct DSP_STRMATTR *pAttrs);
+static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream);
+static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
+				u32 uPhase);
+static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
+			       struct NODE_OBJECT *hNode,
+			       CONST struct DSP_UUID *pNodeId,
+			       struct DCD_GENERICOBJ *pdcdProps);
+static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
+			      struct DEV_OBJECT *hDevObject);
+static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr);
+static CDECL u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
+			u32 ulNumBytes, u32 nMemSpace);
+static CDECL u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
+			u32 ulNumBytes, u32 nMemSpace);
+#if GT_TRACE
+static struct GT_Mask NODE_debugMask = { NULL, NULL };  /* GT trace variable */
+#endif
+
+static u32 cRefs;		/* module reference count */
+
+/* Dynamic loader functions. */
+static struct NLDR_FXNS nldrFxns = {
+	NLDR_Allocate,
+	NLDR_Create,
+	NLDR_Delete,
+	NLDR_Exit,
+	NLDR_Free,
+	NLDR_GetFxnAddr,
+	NLDR_Init,
+	NLDR_Load,
+	NLDR_Unload,
+};
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+extern struct constraint_handle *mpu_constraint_handle;
+/*The maximum number of OPPs that DSP bridge can request */
+extern s32 dsp_max_opps;
+#endif
+#endif
+
+enum NODE_STATE NODE_GetState(HANDLE hNode)
+{
+   struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+   return pNode->nState;
+}
+
+/*
+ *  ======== NODE_Allocate ========
+ *  Purpose:
+ *      Allocate GPP resources to manage a node on the DSP.
+ */
+DSP_STATUS NODE_Allocate(struct PROC_OBJECT *hProcessor,
+			IN CONST struct DSP_UUID *pNodeId,
+			OPTIONAL IN CONST struct DSP_CBDATA *pArgs,
+			OPTIONAL IN CONST struct DSP_NODEATTRIN *pAttrIn,
+			OUT struct NODE_OBJECT **phNode)
+{
+	struct NODE_MGR *hNodeMgr;
+	struct DEV_OBJECT *hDevObject;
+	struct NODE_OBJECT *pNode = NULL;
+	enum NODE_TYPE nodeType = NODE_TASK;
+	struct NODE_MSGARGS *pmsgArgs;
+	struct NODE_TASKARGS *ptaskArgs;
+	u32 uNumStreams;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+	struct CMM_OBJECT *hCmmMgr = NULL; /* Shared memory manager hndl */
+	u32 procId;
+	char *label;
+	u32 pulValue;
+	u32 dynextBase;
+	u32 offSet = 0;
+	u32 ulStackSegAddr, ulStackSegVal;
+	u32 ulGppMemBase;
+	struct CFG_HOSTRES hostRes;
+	u32 pMappedAddr = 0;
+	u32 mapAttrs = 0x0;
+
+#ifndef RES_CLEANUP_DISABLE
+
+	HANDLE	     hDrvObject;
+	HANDLE	     nodeRes;
+	HANDLE	     hProcess;
+	struct PROCESS_CONTEXT   *pPctxt = NULL;
+	DSP_STATUS res_status = DSP_SOK;
+
+#endif
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hProcessor != NULL);
+	DBC_Require(phNode != NULL);
+	DBC_Require(pNodeId != NULL);
+
+	GT_5trace(NODE_debugMask, GT_ENTER, "NODE_Allocate: \thProcessor: "
+		"0x%x\tpNodeId: 0x%x\tpArgs: 0x%x\tpAttrIn: "
+		"0x%x\tphNode: 0x%x\n", hProcessor, pNodeId, pArgs, pAttrIn,
+		phNode);
+
+	*phNode = NULL;
+
+	status = PROC_GetProcessorId(hProcessor, &procId);
+
+	status = PROC_GetDevObject(hProcessor, &hDevObject);
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
+		if (hNodeMgr == NULL)
+			status = DSP_EFAIL;
+
+	}
+	if (procId != DSP_UNIT)
+		goto func_cont;
+
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Assuming that 0 is not a valid function address */
+	if (hNodeMgr->ulFxnAddrs[0] == 0) {
+		/* No RMS on target - we currently can't handle this */
+		GT_0trace(NODE_debugMask, GT_5CLASS, "No RMS functions in base "
+			 "image. Node allocation fails.\n");
+		status = DSP_EFAIL;
+	} else {
+		/* Validate pAttrIn fields, if non-NULL */
+		if (pAttrIn) {
+			/* Check if pAttrIn->iPriority is within range */
+			if (pAttrIn->iPriority < hNodeMgr->nMinPri ||
+			   pAttrIn->iPriority > hNodeMgr->nMaxPri)
+				status = DSP_ERANGE;
+		}
+	}
+func_cont:
+	/* Allocate node object and fill in */
+	if (DSP_FAILED(status))
+		goto func_cont2;
+
+	MEM_AllocObject(pNode, struct NODE_OBJECT, NODE_SIGNATURE);
+	if (pNode == NULL) {
+		status = DSP_EMEMORY;
+		goto func_cont1;
+	}
+	pNode->hNodeMgr = hNodeMgr;
+	/* This critical section protects GetNodeProps */
+	status = SYNC_EnterCS(hNodeMgr->hAllocSync);
+	if (procId != DSP_UNIT)
+		goto func_cont3;
+
+	/* Get DSP_NDBPROPS from node database */
+	status = GetNodeProps(hNodeMgr->hDcdMgr, pNode, pNodeId,
+			     &(pNode->dcdProps));
+	if (DSP_FAILED(status))
+		goto func_cont3;
+
+	pNode->nodeId = *pNodeId;
+	pNode->hProcessor = hProcessor;
+	pNode->nType = pNode->dcdProps.objData.nodeObj.ndbProps.uNodeType;
+	pNode->uTimeout = pNode->dcdProps.objData.nodeObj.ndbProps.uTimeout;
+	pNode->nPriority = pNode->dcdProps.objData.nodeObj.ndbProps.iPriority;
+
+	/* Currently only C64 DSP builds support Node Dynamic * heaps */
+	/* Allocate memory for node heap */
+	pNode->createArgs.asa.taskArgs.uHeapSize = 0;
+	pNode->createArgs.asa.taskArgs.uDSPHeapAddr = 0;
+	pNode->createArgs.asa.taskArgs.uDSPHeapResAddr = 0;
+	pNode->createArgs.asa.taskArgs.uGPPHeapAddr = 0;
+	if (!pAttrIn)
+		goto func_cont3;
+
+	/* Check if we have a user allocated node heap */
+	if (!(pAttrIn->pGPPVirtAddr))
+		goto func_cont3;
+
+	/* check for page aligned Heap size */
+	if (((pAttrIn->uHeapSize) & (PG_SIZE_4K - 1))) {
+		GT_1trace(NODE_debugMask, GT_7CLASS,
+			 "NODE_Allocate: node heap page size"
+			 " not aligned to 4K page, size=0x%x \n",
+			 pAttrIn->uHeapSize);
+		status = DSP_EINVALIDARG;
+	} else {
+		pNode->createArgs.asa.taskArgs.uHeapSize = pAttrIn->uHeapSize;
+		pNode->createArgs.asa.taskArgs.uGPPHeapAddr =
+						 (u32)pAttrIn->pGPPVirtAddr;
+	}
+	if (DSP_FAILED(status))
+		goto func_cont3;
+
+	status = PROC_ReserveMemory(hProcessor,
+			pNode->createArgs.asa.taskArgs.uHeapSize + PAGE_SIZE,
+			(void **)&(pNode->createArgs.asa.taskArgs.
+				uDSPHeapResAddr));
+	if (DSP_FAILED(status)) {
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Allocate:Failed to reserve "
+			 "memory for Heap: 0x%x\n", status);
+	} else {
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Allocate: DSPProcessor_Reserve"
+			 " Memory successful: 0x%x\n", status);
+	}
+	if (DSP_FAILED(status))
+		goto func_cont3;
+
+	mapAttrs |= DSP_MAPLITTLEENDIAN;
+	mapAttrs |= DSP_MAPELEMSIZE32;
+	mapAttrs |= DSP_MAPVIRTUALADDR;
+	status = PROC_Map(hProcessor, (void *)pAttrIn->pGPPVirtAddr,
+			pNode->createArgs.asa.taskArgs.uHeapSize,
+			(void *)pNode->createArgs.asa.taskArgs.uDSPHeapResAddr,
+			(void **)&pMappedAddr, mapAttrs);
+	if (DSP_FAILED(status)) {
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Allocate: Failed to map memory"
+			 " for Heap: 0x%x\n", status);
+	} else {
+		pNode->createArgs.asa.taskArgs.uDSPHeapAddr =
+			(u32) pMappedAddr;
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Allocate:DSPProcessor_Map"
+			 " successful: 0x%x\n", status);
+	}
+
+func_cont3:
+	(void)SYNC_LeaveCS(hNodeMgr->hAllocSync);
+func_cont1:
+	if (pAttrIn != NULL) {
+		/* Overrides of NBD properties */
+		pNode->uTimeout = pAttrIn->uTimeout;
+		pNode->nPriority = pAttrIn->iPriority;
+	}
+func_cont2:
+	/* Create object to manage notifications */
+	if (DSP_SUCCEEDED(status))
+		status = NTFY_Create(&pNode->hNtfy);
+
+	if (DSP_SUCCEEDED(status)) {
+		nodeType = NODE_GetType(pNode);
+		 /*  Allocate DSP_STREAMCONNECT array for device, task, and
+		 *  dais socket nodes.  */
+		if (nodeType != NODE_MESSAGE) {
+			uNumStreams = MaxInputs(pNode) + MaxOutputs(pNode);
+			pNode->streamConnect = MEM_Calloc(uNumStreams *
+					       sizeof(struct DSP_STREAMCONNECT),
+					       MEM_PAGED);
+			if (uNumStreams > 0 && pNode->streamConnect == NULL)
+				status = DSP_EMEMORY;
+
+		}
+		if (DSP_SUCCEEDED(status) && (nodeType == NODE_TASK ||
+		   nodeType == NODE_DAISSOCKET)) {
+			/* Allocate arrays for maintainig stream connections */
+			pNode->inputs =
+				MEM_Calloc(MaxInputs(pNode) *
+					sizeof(struct STREAM), MEM_PAGED);
+			pNode->outputs =
+				MEM_Calloc(MaxOutputs(pNode) *
+					sizeof(struct STREAM), MEM_PAGED);
+			ptaskArgs = &(pNode->createArgs.asa.taskArgs);
+			ptaskArgs->strmInDef =
+				MEM_Calloc(MaxInputs(pNode) *
+					sizeof(struct NODE_STRMDEF),
+					MEM_PAGED);
+			ptaskArgs->strmOutDef =
+					MEM_Calloc(MaxOutputs(pNode) *
+						sizeof(struct NODE_STRMDEF),
+						MEM_PAGED);
+			if ((MaxInputs(pNode) > 0 && (pNode->inputs == NULL ||
+			   ptaskArgs->strmInDef == NULL)) ||
+			   (MaxOutputs(pNode) > 0 && (pNode->outputs == NULL ||
+			   ptaskArgs->strmOutDef == NULL)))
+				status = DSP_EMEMORY;
+		}
+	}
+	if (DSP_SUCCEEDED(status) && (nodeType != NODE_DEVICE)) {
+		/* Create an event that will be posted when RMS_EXIT is
+		 * received. */
+		status = SYNC_OpenEvent(&pNode->hSyncDone, NULL);
+		if (DSP_SUCCEEDED(status)) {
+			/*Get the shared mem mgr for this nodes dev object */
+			status = CMM_GetHandle(hProcessor, &hCmmMgr);
+			if (DSP_FAILED(status)) {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+					 "NODE_Allocate: Failed to"
+					 " get CMM Mgr handle: 0x%x\n", status);
+			} else {
+				/* Allocate a SM addr translator for this node
+				 * w/ deflt attr */
+				status = CMM_XlatorCreate(&pNode->hXlator,
+					 hCmmMgr, NULL);
+				if (DSP_FAILED(status)) {
+					GT_1trace(NODE_debugMask, GT_5CLASS,
+					    "NODE_Allocate: Failed"
+					    " to create SM translator: 0x%x\n",
+					    status);
+				}
+			}
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* Fill in message args */
+			if ((pArgs != NULL) && (pArgs->cbData > 0)) {
+				pmsgArgs = &(pNode->createArgs.asa.msgArgs);
+				pmsgArgs->pData = MEM_Calloc(pArgs->cbData,
+							    MEM_PAGED);
+				if (pmsgArgs->pData == NULL) {
+					status = DSP_EMEMORY;
+				} else {
+					pmsgArgs->uArgLength = pArgs->cbData;
+					memcpy(pmsgArgs->pData, pArgs->cData,
+					      pArgs->cbData);
+				}
+			}
+		}
+	}
+
+	if (DSP_SUCCEEDED(status) && nodeType != NODE_DEVICE) {
+		/* Create a message queue for this node */
+		pIntfFxns = hNodeMgr->pIntfFxns;
+		status = (*pIntfFxns->pfnMsgCreateQueue)(hNodeMgr->hMsg,
+				&pNode->hMsgQueue, 0,
+				    pNode->createArgs.asa.msgArgs.uMaxMessages,
+				    pNode);
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Create object for dynamic loading */
+
+		status = hNodeMgr->nldrFxns.pfnAllocate(hNodeMgr->hNldr,
+					     (void *) pNode,
+					     &pNode->dcdProps.objData.nodeObj,
+					     &pNode->hNldrNode,
+					     &pNode->fPhaseSplit);
+		if (DSP_FAILED(status)) {
+			GT_1trace(NODE_debugMask, GT_5CLASS,
+				 "NODE_Allocate: Failed to "
+				 "allocate NLDR node: 0x%x\n", status);
+		}
+	}
+
+	/* Comapare value read from Node Properties and check if it is same as
+	 * STACKSEGLABEL, if yes read the Address of STACKSEGLABEL, calculate
+	 * GPP Address, Read the value in that address and override the
+	 * uStackSeg value in task args */
+	if (DSP_SUCCEEDED(status) &&
+	   (char *)pNode->dcdProps.objData.nodeObj.ndbProps.uStackSegName !=
+	   NULL) {
+		label = MEM_Calloc(sizeof(STACKSEGLABEL)+1, MEM_PAGED);
+		CSL_Strcpyn(label, STACKSEGLABEL, sizeof(STACKSEGLABEL)+1);
+
+		if (CSL_Strcmp((char *)pNode->dcdProps.objData.nodeObj.
+				     ndbProps.uStackSegName, label) == 0) {
+			status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
+				 hNldrNode, "DYNEXT_BEG", &dynextBase);
+			if (DSP_FAILED(status)) {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+				"NODE_Allocate: Failed to get Address for "
+				"DYNEXT_BEG: 0x%x\n", status);
+			}
+
+			status = hNodeMgr->nldrFxns.pfnGetFxnAddr(pNode->
+				 hNldrNode, "L1DSRAM_HEAP", &pulValue);
+
+			if (DSP_FAILED(status)) {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+				"NODE_Allocate: Failed to get Address for "
+				"L1DSRAM_HEAP: 0x%x\n", status);
+			}
+
+			status = CFG_GetHostResources((struct CFG_DEVNODE *)
+				 DRV_GetFirstDevExtension(), &hostRes);
+
+			if (DSP_FAILED(status)) {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+				"NODE_Allocate: Failed to get host resource "
+				"0x%x\n", status);
+			}
+
+			ulGppMemBase = hostRes.dwMemBase[1];
+			offSet = pulValue - dynextBase;
+			ulStackSegAddr = ulGppMemBase + offSet;
+			ulStackSegVal = (u32)*((REG_UWORD32 *)
+					((u32)(ulStackSegAddr)));
+
+			GT_1trace(NODE_debugMask, GT_5CLASS,
+				 "StackSegVal =0x%x\n", ulStackSegVal);
+			GT_1trace(NODE_debugMask, GT_5CLASS,
+				 "ulStackSegAddr = 0x%x\n", ulStackSegAddr);
+
+			pNode->createArgs.asa.taskArgs.uStackSeg =
+				ulStackSegVal;
+
+		}
+
+		if (label)
+			MEM_Free(label);
+
+	}
+
+
+	if (DSP_SUCCEEDED(status)) {
+		/* Add the node to the node manager's list of allocated
+		 * nodes. */
+		LST_InitElem((struct LST_ELEM *)pNode);
+		NODE_SetState(pNode, NODE_ALLOCATED);
+
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+
+		if (DSP_SUCCEEDED(status)) {
+			LST_PutTail(hNodeMgr->nodeList,
+			(struct LST_ELEM *) pNode);
+			++(hNodeMgr->uNumNodes);
+		}
+
+		/* Exit critical section */
+		(void) SYNC_LeaveCS(hNodeMgr->hSync);
+
+		/* Preset this to assume phases are split
+		 * (for overlay and dll) */
+		pNode->fPhaseSplit = true;
+
+		if (DSP_SUCCEEDED(status))
+			*phNode = pNode;
+
+
+		/* Notify all clients registered for DSP_NODESTATECHANGE. */
+		PROC_NotifyAllClients(hProcessor, DSP_NODESTATECHANGE);
+	} else {
+		/* Cleanup */
+		if (pNode)
+			DeleteNode(pNode);
+
+	}
+
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_SUCCEEDED(status)) {
+		PRCS_GetCurrentHandle(&hProcess);
+		res_status = CFG_GetObject((u32 *)&hDrvObject,
+					  REG_DRV_OBJECT);
+		if (DSP_SUCCEEDED(res_status)) {
+			DRV_GetProcContext(hProcess, hDrvObject, &pPctxt,
+					 *phNode, 0);
+			if (pPctxt == NULL) {
+				DRV_InsertProcContext(hDrvObject, &pPctxt);
+				if (pPctxt != NULL) {
+					DRV_ProcUpdatestate(pPctxt,
+							PROC_RES_ALLOCATED);
+					DRV_ProcSetPID(pPctxt, (s32) hProcess);
+					pPctxt->hProcessor =
+						 (DSP_HPROCESSOR)hProcessor;
+				}
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		PRCS_GetCurrentHandle(&hProcess);
+		res_status = CFG_GetObject((u32 *)&hDrvObject,
+					REG_DRV_OBJECT);
+		if (DSP_SUCCEEDED(res_status)) {
+			DRV_GetProcContext(hProcess, hDrvObject, &pPctxt,
+					 *phNode, 0);
+			if (pPctxt != NULL) {
+				DRV_InsertNodeResElement(*phNode, &nodeRes,
+							 pPctxt);
+				DRV_ProcNodeUpdateHeapStatus(nodeRes, true);
+				DRV_ProcNodeUpdateStatus(nodeRes, true);
+			}
+		}
+	}
+#endif
+	DBC_Ensure((DSP_FAILED(status) && (*phNode == NULL)) ||
+		  (DSP_SUCCEEDED(status)
+		    && MEM_IsValidHandle((*phNode), NODE_SIGNATURE)));
+	return status;
+}
+
+/*
+ *  ======== NODE_AllocMsgBuf ========
+ *  Purpose:
+ *      Allocates buffer for zero copy messaging.
+ */
+DBAPI NODE_AllocMsgBuf(struct NODE_OBJECT *hNode, u32 uSize,
+		       OPTIONAL IN OUT struct DSP_BUFFERATTR *pAttr,
+		       OUT u8 **pBuffer)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	DSP_STATUS status = DSP_SOK;
+	bool bVirtAddr = false;
+	bool bSetInfo;
+	u32 procId;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pBuffer != NULL);
+
+	DBC_Require(uSize > 0);
+
+	GT_4trace(NODE_debugMask, GT_ENTER,
+		 "NODE_AllocMsgBuf: hNode: 0x%x\tuSize:"
+		 " 0x%x\tpAttr: 0x%x\tpBuffer: %d\n", pNode, uSize, pAttr,
+		 pBuffer);
+
+	if (!MEM_IsValidHandle(pNode, NODE_SIGNATURE))
+		status = DSP_EHANDLE;
+
+	if (NODE_GetType(pNode) == NODE_DEVICE)
+		status = DSP_ENODETYPE;
+
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	if (pAttr == NULL)
+		pAttr = &NODE_DFLTBUFATTRS;	/* set defaults */
+
+	status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+	if (procId != DSP_UNIT) {
+		DBC_Assert(NULL);
+		goto func_end;
+	}
+	 /*  If segment ID includes MEM_SETVIRTUALSEGID then pBuffer is a
+	 *  virt  address, so set this info in this node's translator
+	 *  object for  future ref. If MEM_GETVIRTUALSEGID then retrieve
+	 *  virtual address  from node's translator.  */
+	if ((pAttr->uSegment & MEM_SETVIRTUALSEGID) ||
+			    (pAttr->uSegment & MEM_GETVIRTUALSEGID)) {
+		bVirtAddr = true;
+		bSetInfo = (pAttr->uSegment & MEM_SETVIRTUALSEGID) ?
+			   true : false;
+		pAttr->uSegment &= ~MEM_MASKVIRTUALSEGID; /* clear mask bits */
+		/* Set/get this node's translators virtual address base/size */
+		status = CMM_XlatorInfo(pNode->hXlator, pBuffer, uSize,
+					pAttr->uSegment, bSetInfo);
+		if (DSP_FAILED(status)) {
+			GT_1trace(NODE_debugMask, GT_7CLASS,
+				 "NODE_AllocMsgBuf "
+				 "failed: 0x%lx\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status) && (!bVirtAddr)) {
+		if (pAttr->uSegment != 1) {
+			/* Node supports single SM segment only. */
+			status = DSP_EBADSEGID;
+		}
+		 /*  Arbitrary SM buffer alignment not supported for host side
+		  *  allocs, but guaranteed for the following alignment
+		  *  values.  */
+		switch (pAttr->uAlignment) {
+		case 0:
+		case 1:
+		case 2:
+		case 4:
+			break;
+		default:
+			/* alignment value not suportted */
+			status = DSP_EALIGNMENT;
+			break;
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* allocate physical buffer from segId in node's
+			 * translator */
+			(void)CMM_XlatorAllocBuf(pNode->hXlator, pBuffer,
+						 uSize);
+			if (*pBuffer == NULL) {
+				GT_0trace(NODE_debugMask, GT_7CLASS,
+					 "NODE_AllocMsgBuf: "
+					 "ERROR: Out of shared memory.\n");
+				status = DSP_EMEMORY;
+			}
+		}
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_ChangePriority ========
+ *  Purpose:
+ *      Change the priority of a node in the allocated state, or that is
+ *      currently running or paused on the target.
+ */
+DSP_STATUS NODE_ChangePriority(struct NODE_OBJECT *hNode, s32 nPriority)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	struct NODE_MGR *hNodeMgr = NULL;
+	enum NODE_TYPE nodeType;
+	enum NODE_STATE state;
+	DSP_STATUS status = DSP_SOK;
+	u32 procId;
+
+	DBC_Require(cRefs > 0);
+
+	GT_2trace(NODE_debugMask, GT_ENTER, "NODE_ChangePriority: "
+		 "hNode: 0x%x\tnPriority: %d\n", hNode, nPriority);
+
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		GT_1trace(NODE_debugMask, GT_7CLASS,
+			 "Invalid NODE Handle: 0x%x\n", hNode);
+		status = DSP_EHANDLE;
+	} else {
+		hNodeMgr = hNode->hNodeMgr;
+		nodeType = NODE_GetType(hNode);
+		if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
+			status = DSP_ENODETYPE;
+		else if (nPriority < hNodeMgr->nMinPri ||
+				nPriority > hNodeMgr->nMaxPri)
+				status = DSP_ERANGE;
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Enter critical section */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	state = NODE_GetState(hNode);
+	if (state == NODE_ALLOCATED || state == NODE_PAUSED) {
+		NODE_SetPriority(hNode, nPriority);
+	} else {
+		if (state != NODE_RUNNING) {
+			status = DSP_EWRONGSTATE;
+			goto func_cont;
+		}
+		if (DSP_SUCCEEDED(status)) {
+			status = PROC_GetProcessorId(pNode->hProcessor,
+						    &procId);
+			if (procId == DSP_UNIT) {
+				status = DISP_NodeChangePriority(hNodeMgr->
+				    hDisp, hNode,
+				    hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
+				    hNode->nodeEnv, nPriority);
+			}
+			if (DSP_SUCCEEDED(status))
+				NODE_SetPriority(hNode, nPriority);
+
+		}
+	}
+func_cont:
+		/* Leave critical section */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_Connect ========
+ *  Purpose:
+ *      Connect two nodes on the DSP, or a node on the DSP to the GPP.
+ */
+DSP_STATUS NODE_Connect(struct NODE_OBJECT *hNode1, u32 uStream1,
+			struct NODE_OBJECT *hNode2,
+			u32 uStream2, OPTIONAL IN struct DSP_STRMATTR *pAttrs,
+			OPTIONAL IN struct DSP_CBDATA *pConnParam)
+{
+	struct NODE_MGR *hNodeMgr;
+	char *pstrDevName = NULL;
+	char *pstrDevName1;
+	char *pstrDevName2;
+	enum NODE_TYPE node1Type = NODE_TASK;
+	enum NODE_TYPE node2Type = NODE_TASK;
+	struct NODE_STRMDEF *pstrmDef;
+	struct NODE_STRMDEF *pInput = NULL;
+	struct NODE_STRMDEF *pOutput = NULL;
+	struct NODE_OBJECT *hDevNode;
+	struct NODE_OBJECT *hNode;
+	struct STREAM *pStream;
+	GB_BitNum pipeId = GB_NOBITS;
+	GB_BitNum chnlId = GB_NOBITS;
+	CHNL_MODE uMode;
+	u32 dwLength;
+	DSP_STATUS status = DSP_SOK;
+	DBC_Require(cRefs > 0);
+	GT_5trace(NODE_debugMask, GT_ENTER,
+		 "NODE_Connect: hNode1: 0x%x\tuStream1:"
+		 " %d\thNode2: 0x%x\tuStream2: %d\tpAttrs: 0x%x\n", hNode1,
+		 uStream1, hNode2, uStream2, pAttrs);
+	if (DSP_SUCCEEDED(status)) {
+		if ((hNode1 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
+		   !MEM_IsValidHandle(hNode1, NODE_SIGNATURE)) ||
+		   (hNode2 != (struct NODE_OBJECT *) DSP_HGPPNODE &&
+		   !MEM_IsValidHandle(hNode2, NODE_SIGNATURE)))
+			status = DSP_EHANDLE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* The two nodes must be on the same processor */
+		if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
+		   hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE &&
+		   hNode1->hNodeMgr != hNode2->hNodeMgr)
+			status = DSP_EFAIL;
+		/* Cannot connect a node to itself */
+		if (hNode1 == hNode2)
+			status = DSP_EFAIL;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* NODE_GetType() will return NODE_GPP if hNode =
+		 * DSP_HGPPNODE. */
+		node1Type = NODE_GetType(hNode1);
+		node2Type = NODE_GetType(hNode2);
+	/* Check stream indices ranges */
+		if ((node1Type != NODE_GPP && node1Type != NODE_DEVICE &&
+		   uStream1 >= MaxOutputs(hNode1)) || (node2Type != NODE_GPP &&
+		   node2Type != NODE_DEVICE && uStream2 >= MaxInputs(hNode2)))
+			status = DSP_EVALUE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/*
+		 *  Only the following types of connections are allowed:
+		 *      task/dais socket < == > task/dais socket
+		 *      task/dais socket < == > device
+		 *      task/dais socket < == > GPP
+		 *
+		 *  ie, no message nodes, and at least one task or dais
+		 *  socket node.
+		 */
+		if (node1Type == NODE_MESSAGE || node2Type == NODE_MESSAGE ||
+		    (node1Type != NODE_TASK && node1Type != NODE_DAISSOCKET &&
+		     node2Type != NODE_TASK && node2Type != NODE_DAISSOCKET))
+			status = DSP_EFAIL;
+	}
+	/*
+	 * Check stream mode. Default is STRMMODE_PROCCOPY.
+	 */
+	if (DSP_SUCCEEDED(status) && pAttrs) {
+		if (pAttrs->lMode != STRMMODE_PROCCOPY)
+			status = DSP_ESTRMMODE;	/* illegal stream mode */
+
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	if (node1Type != NODE_GPP) {
+		hNodeMgr = hNode1->hNodeMgr;
+	} else {
+		DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
+		hNodeMgr = hNode2->hNodeMgr;
+	}
+	/* Enter critical section */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Nodes must be in the allocated state */
+	if (node1Type != NODE_GPP && NODE_GetState(hNode1) != NODE_ALLOCATED)
+		status = DSP_EWRONGSTATE;
+
+	if (node2Type != NODE_GPP && NODE_GetState(hNode2) != NODE_ALLOCATED)
+		status = DSP_EWRONGSTATE;
+
+	if (DSP_SUCCEEDED(status)) {
+		/*  Check that stream indices for task and dais socket nodes
+		 *  are not already be used. (Device nodes checked later) */
+		if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
+			pOutput = &(hNode1->createArgs.asa.taskArgs.
+				  strmOutDef[uStream1]);
+			if (pOutput->szDevice != NULL)
+				status = DSP_EALREADYCONNECTED;
+
+		}
+		if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
+			pInput = &(hNode2->createArgs.asa.taskArgs.
+				 strmInDef[uStream2]);
+			if (pInput->szDevice != NULL)
+				status = DSP_EALREADYCONNECTED;
+
+		}
+	}
+	/* Connecting two task nodes? */
+	if (DSP_SUCCEEDED(status) && ((node1Type == NODE_TASK ||
+	   node1Type == NODE_DAISSOCKET) && (node2Type == NODE_TASK ||
+	   node2Type == NODE_DAISSOCKET))) {
+		/* Find available pipe */
+		pipeId = GB_findandset(hNodeMgr->pipeMap);
+		if (pipeId == GB_NOBITS) {
+			status = DSP_ENOMORECONNECTIONS;
+		} else {
+			hNode1->outputs[uStream1].type = NODECONNECT;
+			hNode2->inputs[uStream2].type = NODECONNECT;
+			hNode1->outputs[uStream1].devId = pipeId;
+			hNode2->inputs[uStream2].devId = pipeId;
+			pOutput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
+						      MEM_PAGED);
+			pInput->szDevice = MEM_Calloc(PIPENAMELEN + 1,
+						     MEM_PAGED);
+			if (pOutput->szDevice == NULL ||
+			   pInput->szDevice == NULL) {
+				/* Undo the connection */
+				if (pOutput->szDevice)
+					MEM_Free(pOutput->szDevice);
+
+				if (pInput->szDevice)
+					MEM_Free(pInput->szDevice);
+
+				pOutput->szDevice = NULL;
+				pInput->szDevice = NULL;
+				GB_clear(hNodeMgr->pipeMap, pipeId);
+				status = DSP_EMEMORY;
+			} else {
+				/* Copy "/dbpipe<pipId>" name to device names */
+				pstrDevName1 = pOutput->szDevice;
+				CSL_Strcpyn(pstrDevName1, PIPEPREFIX,
+					   sizeof(PIPEPREFIX));
+				pstrDevName1 += CSL_Strlen(pstrDevName1);
+				CSL_NumToAscii(pstrDevName1, pipeId);
+				pstrDevName1 = pOutput->szDevice;
+				pstrDevName2 = pInput->szDevice;
+				CSL_Strcpyn(pstrDevName2, pstrDevName1,
+					   PIPENAMELEN);
+			}
+		}
+	}
+	/* Connecting task node to host? */
+	if (DSP_SUCCEEDED(status) && (node1Type == NODE_GPP ||
+	   node2Type == NODE_GPP)) {
+		if (node1Type == NODE_GPP) {
+			uMode = CHNL_MODETODSP;
+		} else {
+			DBC_Assert(node2Type == NODE_GPP);
+			uMode = CHNL_MODEFROMDSP;
+		}
+		 /*  Reserve a channel id. We need to put the name "/host<id>"
+		 *  in the node's createArgs, but the host
+		 *  side channel will not be opened until DSPStream_Open is
+		 *  called for this node.  */
+		if (pAttrs) {
+			if (pAttrs->lMode == STRMMODE_RDMA) {
+				chnlId = GB_findandset(hNodeMgr->dmaChnlMap);
+				/* dma chans are 2nd transport chnl set
+				 * ids(e.g. 16-31)*/
+				(chnlId != GB_NOBITS) ?
+				   (chnlId = chnlId + hNodeMgr->ulNumChnls) :
+				   chnlId;
+			} else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
+				chnlId = GB_findandset(hNodeMgr->zChnlMap);
+				/* zero-copy chans are 3nd transport set
+				 * (e.g. 32-47) */
+				(chnlId != GB_NOBITS) ?  (chnlId = chnlId +
+					(2 * hNodeMgr->ulNumChnls)) : chnlId;
+			} else {	/* must be PROCCOPY */
+				DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
+				chnlId = GB_findandset(hNodeMgr->chnlMap);
+				/* e.g. 0-15 */
+			}
+		} else {
+			/* default to PROCCOPY */
+			chnlId = GB_findandset(hNodeMgr->chnlMap);
+		}
+		if (chnlId == GB_NOBITS) {
+			status = DSP_ENOMORECONNECTIONS;
+			goto func_cont2;
+		}
+		pstrDevName = MEM_Calloc(HOSTNAMELEN + 1, MEM_PAGED);
+		if (pstrDevName != NULL)
+			goto func_cont2;
+
+		if (pAttrs) {
+			if (pAttrs->lMode == STRMMODE_RDMA) {
+				GB_clear(hNodeMgr->dmaChnlMap, chnlId -
+					 hNodeMgr->ulNumChnls);
+			} else if (pAttrs->lMode == STRMMODE_ZEROCOPY) {
+				GB_clear(hNodeMgr->zChnlMap, chnlId -
+					(2*hNodeMgr->ulNumChnls));
+			} else {
+				DBC_Assert(pAttrs->lMode == STRMMODE_PROCCOPY);
+				GB_clear(hNodeMgr->chnlMap, chnlId);
+			}
+		} else {
+			GB_clear(hNodeMgr->chnlMap, chnlId);
+		}
+		status = DSP_EMEMORY;
+func_cont2:
+		if (DSP_SUCCEEDED(status)) {
+			if (hNode1 == (struct NODE_OBJECT *) DSP_HGPPNODE) {
+				hNode2->inputs[uStream2].type = HOSTCONNECT;
+				hNode2->inputs[uStream2].devId = chnlId;
+				pInput->szDevice = pstrDevName;
+			} else {
+				hNode1->outputs[uStream1].type = HOSTCONNECT;
+				hNode1->outputs[uStream1].devId = chnlId;
+				pOutput->szDevice = pstrDevName;
+			}
+			CSL_Strcpyn(pstrDevName, HOSTPREFIX,
+				   sizeof(HOSTPREFIX));
+			pstrDevName += CSL_Strlen(pstrDevName);
+			CSL_NumToAscii(pstrDevName, chnlId);
+		}
+	}
+	/* Connecting task node to device node? */
+	if (DSP_SUCCEEDED(status) && ((node1Type == NODE_DEVICE) ||
+	   (node2Type == NODE_DEVICE))) {
+		if (node2Type == NODE_DEVICE) {
+			/* node1 == > device */
+			hDevNode = hNode2;
+			hNode = hNode1;
+			pStream = &(hNode1->outputs[uStream1]);
+			pstrmDef = pOutput;
+		} else {
+			/* device == > node2 */
+			hDevNode = hNode1;
+			hNode = hNode2;
+			pStream = &(hNode2->inputs[uStream2]);
+			pstrmDef = pInput;
+		}
+		/* Set up create args */
+		pStream->type = DEVICECONNECT;
+		dwLength = CSL_Strlen(hDevNode->pstrDevName);
+		if (pConnParam != NULL) {
+			pstrmDef->szDevice = MEM_Calloc(dwLength + 1 +
+						(u32) pConnParam->cbData,
+						MEM_PAGED);
+		} else {
+			pstrmDef->szDevice = MEM_Calloc(dwLength + 1,
+							MEM_PAGED);
+		}
+		if (pstrmDef->szDevice == NULL) {
+			status = DSP_EMEMORY;
+		} else {
+			/* Copy device name */
+			CSL_Strcpyn(pstrmDef->szDevice, hDevNode->pstrDevName,
+				   dwLength);
+			if (pConnParam != NULL) {
+				CSL_Strncat(pstrmDef->szDevice,
+					   (char *)pConnParam->cData,
+					   (u32)pConnParam->cbData);
+			}
+			hDevNode->hDeviceOwner = hNode;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Fill in create args */
+		if (node1Type == NODE_TASK || node1Type == NODE_DAISSOCKET) {
+			hNode1->createArgs.asa.taskArgs.uNumOutputs++;
+			FillStreamDef(hNode1, pOutput, pAttrs);
+		}
+		if (node2Type == NODE_TASK || node2Type == NODE_DAISSOCKET) {
+			hNode2->createArgs.asa.taskArgs.uNumInputs++;
+			FillStreamDef(hNode2, pInput, pAttrs);
+		}
+		/* Update hNode1 and hNode2 streamConnect */
+		if (node1Type != NODE_GPP && node1Type != NODE_DEVICE) {
+			hNode1->uNumOutputs++;
+			if (uStream1 > hNode1->uMaxOutputIndex)
+				hNode1->uMaxOutputIndex = uStream1;
+
+		}
+		if (node2Type != NODE_GPP && node2Type != NODE_DEVICE) {
+			hNode2->uNumInputs++;
+			if (uStream2 > hNode2->uMaxInputIndex)
+				hNode2->uMaxInputIndex = uStream2;
+
+		}
+		FillStreamConnect(hNode1, hNode2, uStream1, uStream2);
+	}
+func_cont:
+	/* end of SYNC_EnterCS */
+	/* Exit critical section */
+	(void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_Create ========
+ *  Purpose:
+ *      Create a node on the DSP by remotely calling the node's create function.
+ */
+DSP_STATUS NODE_Create(struct NODE_OBJECT *hNode)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	struct NODE_MGR *hNodeMgr;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	u32 ulCreateFxn;
+	enum NODE_TYPE nodeType;
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+	bool bJustWokeDSP = false;
+	struct DSP_CBDATA cbData;
+	u32 procId = 255;
+
+	DBC_Require(cRefs > 0);
+	GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Create: hNode: 0x%x\n",
+		 hNode);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		goto func_end;
+	}
+	/* create struct DSP_CBDATA struct for PWR calls */
+	cbData.cbData = PWR_TIMEOUT;
+	nodeType = NODE_GetType(hNode);
+	hNodeMgr = hNode->hNodeMgr;
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	/* Get access to node dispatcher */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Check node state */
+	if (NODE_GetState(hNode) != NODE_ALLOCATED)
+		status = DSP_EWRONGSTATE;
+
+	if (DSP_SUCCEEDED(status))
+		status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+	if (DSP_FAILED(status))
+		goto func_cont2;
+
+	if (procId != DSP_UNIT)
+		goto func_cont2;
+
+	/* Make sure streams are properly connected */
+	if ((hNode->uNumInputs && hNode->uMaxInputIndex >
+	   hNode->uNumInputs - 1) ||
+	   (hNode->uNumOutputs && hNode->uMaxOutputIndex >
+	   hNode->uNumOutputs - 1))
+		status = DSP_ENOTCONNECTED;
+
+	if (DSP_SUCCEEDED(status)) {
+		/* If node's create function is not loaded, load it */
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+		/* Boost the OPP level to max level that DSP can be requested */
+		if (constraint_set(mpu_constraint_handle,
+		   dsp_max_opps) != 0)
+			GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
+			"Constraint set of %d failed\n", dsp_max_opps);
+		else
+			GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
+				 "Constraint set of %d passed\n",
+				 dsp_max_opps);
+#endif
+#endif
+		status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
+						   NLDR_CREATE);
+		/* Get address of node's create function */
+		if (DSP_SUCCEEDED(status)) {
+			hNode->fLoaded = true;
+			if (nodeType != NODE_DEVICE) {
+				status = GetFxnAddress(hNode, &ulCreateFxn,
+							CREATEPHASE);
+			}
+		} else {
+			GT_1trace(NODE_debugMask, GT_ENTER,
+				 "NODE_Create: failed to load"
+				 " create code: 0x%x\n", status);
+		}
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+		/* Request the lowest OPP level*/
+		if (constraint_set(mpu_constraint_handle,
+		   (CO_VDD1_OPP1)) != 0) {
+			GT_1trace(NODE_debugMask, GT_4CLASS,
+				 "NODE_Create: Constraint set of %d "
+				 "failed\n", CO_VDD1_OPP1);
+		} else {
+			GT_1trace(NODE_debugMask, GT_4CLASS, "NODE_Create:"
+			"Constraint set of %d passed\n", CO_VDD1_OPP1);
+		}
+#endif
+#endif
+		/* Get address of iAlg functions, if socket node */
+		if (DSP_SUCCEEDED(status)) {
+			if (nodeType == NODE_DAISSOCKET) {
+				status = hNodeMgr->nldrFxns.pfnGetFxnAddr
+					(hNode->hNldrNode, hNode->dcdProps.
+					objData.nodeObj.pstrIAlgName,
+					&hNode->createArgs.asa.taskArgs.
+					ulDaisArg);
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		if (nodeType != NODE_DEVICE) {
+			status = DISP_NodeCreate(hNodeMgr->hDisp, hNode,
+				 hNodeMgr->ulFxnAddrs[RMSCREATENODE],
+				 ulCreateFxn, &(hNode->createArgs),
+				 &(hNode->nodeEnv));
+			if (DSP_SUCCEEDED(status)) {
+				/* Set the message queue id to the node env
+				 * pointer */
+				pIntfFxns = hNodeMgr->pIntfFxns;
+				(*pIntfFxns->pfnMsgSetQueueId)(hNode->hMsgQueue,
+				hNode->nodeEnv);
+			}
+		}
+	}
+	/*  Phase II/Overlays: Create, execute, delete phases  possibly in
+	 *  different files/sections. */
+	if (hNode->fLoaded && hNode->fPhaseSplit) {
+		/* If create code was dynamically loaded, we can now unload
+		 * it. */
+		status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
+						      NLDR_CREATE);
+		hNode->fLoaded = false;
+	}
+	if (DSP_FAILED(status1)) {
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Create: Failed to unload "
+			 "create code: 0x%x\n", status1);
+	}
+func_cont2:
+	/* Update node state and node manager state */
+	if (DSP_SUCCEEDED(status)) {
+		NODE_SetState(hNode, NODE_CREATED);
+		hNodeMgr->uNumCreated++;
+		goto func_cont;
+	}
+	if (status != DSP_EWRONGSTATE) {
+		/* Put back in NODE_ALLOCATED state if error occurred */
+		NODE_SetState(hNode, NODE_ALLOCATED);
+	}
+	if (procId == DSP_UNIT) {
+		/* If node create failed, see if should sleep DSP now */
+		if (bJustWokeDSP == true) {
+			/* Check to see if partial create happened on DSP */
+			if (hNode->nodeEnv == (u32)NULL) {
+				/* No environment allocated on DSP, re-sleep
+				 * DSP now */
+				PROC_Ctrl(hNode->hProcessor, WMDIOCTL_DEEPSLEEP,
+					 &cbData);
+			} else {
+				/* Increment count, sleep later when node fully
+				 * deleted */
+				hNodeMgr->uNumCreated++;
+			}
+		}
+	}
+func_cont:
+		/* Free access to node dispatcher */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+func_end:
+	if (DSP_SUCCEEDED(status)) {
+		PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
+		NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+	}
+
+	return status;
+}
+
+/*
+ *  ======== NODE_CreateMgr ========
+ *  Purpose:
+ *      Create a NODE Manager object.
+ */
+DSP_STATUS NODE_CreateMgr(OUT struct NODE_MGR **phNodeMgr,
+			 struct DEV_OBJECT *hDevObject)
+{
+	u32 i;
+	struct NODE_MGR *pNodeMgr = NULL;
+	struct DISP_ATTRS dispAttrs;
+	char *szZLFile = "";
+	struct NLDR_ATTRS nldrAttrs;
+	DSP_STATUS status = DSP_SOK;
+	u32 devType;
+	DBC_Require(cRefs > 0);
+	DBC_Require(phNodeMgr != NULL);
+	DBC_Require(hDevObject != NULL);
+	GT_2trace(NODE_debugMask, GT_ENTER, "NODE_CreateMgr: phNodeMgr: 0x%x\t"
+		 "hDevObject: 0x%x\n", phNodeMgr, hDevObject);
+	*phNodeMgr = NULL;
+	/* Allocate Node manager object */
+	MEM_AllocObject(pNodeMgr, struct NODE_MGR, NODEMGR_SIGNATURE);
+	if (pNodeMgr) {
+		pNodeMgr->hDevObject = hDevObject;
+		pNodeMgr->nodeList = LST_Create();
+		pNodeMgr->pipeMap = GB_create(MAXPIPES);
+		pNodeMgr->pipeDoneMap = GB_create(MAXPIPES);
+		if (pNodeMgr->nodeList == NULL || pNodeMgr->pipeMap == NULL ||
+		   pNodeMgr->pipeDoneMap == NULL) {
+			status = DSP_EMEMORY;
+			GT_0trace(NODE_debugMask, GT_6CLASS,
+				 "NODE_CreateMgr: Memory "
+				 "allocation failed\n");
+		} else {
+			status = NTFY_Create(&pNodeMgr->hNtfy);
+		}
+		pNodeMgr->uNumCreated = 0;
+	} else {
+		GT_0trace(NODE_debugMask, GT_6CLASS,
+			 "NODE_CreateMgr: Memory allocation failed\n");
+		status = DSP_EMEMORY;
+	}
+	/* get devNodeType */
+	if (DSP_SUCCEEDED(status))
+		status = DEV_GetDevType(hDevObject, &devType);
+
+	/* Create the DCD Manager */
+	if (DSP_SUCCEEDED(status)) {
+		status = DCD_CreateManager(szZLFile, &pNodeMgr->hDcdMgr);
+		if (DSP_SUCCEEDED(status))
+			status = GetProcProps(pNodeMgr, hDevObject);
+
+	}
+	/* Create NODE Dispatcher */
+	if (DSP_SUCCEEDED(status)) {
+		dispAttrs.ulChnlOffset = pNodeMgr->ulChnlOffset;
+		dispAttrs.ulChnlBufSize = pNodeMgr->ulChnlBufSize;
+		dispAttrs.procFamily = pNodeMgr->procFamily;
+		dispAttrs.procType = pNodeMgr->procType;
+		status = DISP_Create(&pNodeMgr->hDisp, hDevObject, &dispAttrs);
+	}
+	/* Create a STRM Manager */
+	if (DSP_SUCCEEDED(status))
+		status = STRM_Create(&pNodeMgr->hStrmMgr, hDevObject);
+
+	if (DSP_SUCCEEDED(status)) {
+		DEV_GetIntfFxns(hDevObject, &pNodeMgr->pIntfFxns);
+		/* Get MSG queue manager */
+		DEV_GetMsgMgr(hDevObject, &pNodeMgr->hMsg);
+		status = SYNC_InitializeCS(&pNodeMgr->hSync);
+		if (DSP_FAILED(status))
+			status = DSP_EMEMORY;
+
+		if (DSP_SUCCEEDED(status)) {
+			status = SYNC_InitializeCS(&pNodeMgr->hAllocSync);
+			if (DSP_FAILED(status))
+				status = DSP_EMEMORY;
+
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pNodeMgr->chnlMap = GB_create(pNodeMgr->ulNumChnls);
+		/* dma chnl map. ulNumChnls is # per transport */
+		pNodeMgr->dmaChnlMap = GB_create(pNodeMgr->ulNumChnls);
+		pNodeMgr->zChnlMap = GB_create(pNodeMgr->ulNumChnls);
+		if ((pNodeMgr->chnlMap == NULL) ||
+		   (pNodeMgr->dmaChnlMap == NULL) ||
+		   (pNodeMgr->zChnlMap == NULL)) {
+			status = DSP_EMEMORY;
+		} else {
+			/* Block out reserved channels */
+			for (i = 0; i < pNodeMgr->ulChnlOffset; i++)
+				GB_set(pNodeMgr->chnlMap, i);
+
+			/* Block out channels reserved for RMS */
+			GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset);
+			GB_set(pNodeMgr->chnlMap, pNodeMgr->ulChnlOffset + 1);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* NO RM Server on the IVA */
+		if (devType != IVA_UNIT) {
+			/* Get addresses of any RMS functions loaded */
+			status = GetRMSFxns(pNodeMgr);
+			if (DSP_FAILED(status)) {
+				GT_1trace(NODE_debugMask, GT_6CLASS,
+				"NODE_CreateMgr: Failed to"
+				" get RMS functions: status = 0x%x", status);
+			}
+		}
+	}
+
+	/* Get loader functions and create loader */
+	if (DSP_SUCCEEDED(status)) {
+		GT_0trace(NODE_debugMask, GT_1CLASS,
+			 "NODE_CreateMgr: using dynamic loader\n");
+		pNodeMgr->nldrFxns = nldrFxns;	/* Dynamic loader functions */
+	}
+	if (DSP_SUCCEEDED(status)) {
+		nldrAttrs.pfnOvly = Ovly;
+		nldrAttrs.pfnWrite = Write;
+		nldrAttrs.usDSPWordSize = pNodeMgr->uDSPWordSize;
+		nldrAttrs.usDSPMauSize = pNodeMgr->uDSPMauSize;
+		pNodeMgr->fLoaderInit = pNodeMgr->nldrFxns.pfnInit();
+		status = pNodeMgr->nldrFxns.pfnCreate(&pNodeMgr->hNldr,
+						     hDevObject, &nldrAttrs);
+		if (DSP_FAILED(status)) {
+			GT_1trace(NODE_debugMask, GT_6CLASS,
+				 "NODE_CreateMgr: Failed to "
+				 "create loader: status = 0x%x\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status))
+		*phNodeMgr = pNodeMgr;
+	else
+		DeleteNodeMgr(pNodeMgr);
+
+	DBC_Ensure((DSP_FAILED(status) && (*phNodeMgr == NULL)) ||
+		  (DSP_SUCCEEDED(status) &&
+		  MEM_IsValidHandle((*phNodeMgr), NODEMGR_SIGNATURE)));
+
+	return status;
+}
+
+/*
+ *  ======== NODE_Delete ========
+ *  Purpose:
+ *      Delete a node on the DSP by remotely calling the node's delete function.
+ *      Loads the node's delete function if necessary. Free GPP side resources
+ *      after node's delete function returns.
+ */
+DSP_STATUS NODE_Delete(struct NODE_OBJECT *hNode)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	struct NODE_MGR *hNodeMgr;
+	struct PROC_OBJECT *hProcessor;
+	struct DISP_OBJECT *hDisp;
+	u32 ulDeleteFxn;
+	enum NODE_TYPE nodeType;
+	enum NODE_STATE state;
+	DSP_STATUS status = DSP_SOK;
+	DSP_STATUS status1 = DSP_SOK;
+	struct DSP_CBDATA cbData;
+	u32 procId;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+
+#ifndef RES_CLEANUP_DISABLE
+	HANDLE		hProcess;
+	HANDLE		nodeRes;
+	HANDLE		hDrvObject;
+	struct PROCESS_CONTEXT *pCtxt = NULL;
+	DSP_STATUS res_status = DSP_SOK;
+#endif
+
+	DBC_Require(cRefs > 0);
+	GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Delete: hNode: 0x%x\n",
+		  hNode);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		goto func_end;
+	}
+	/* create struct DSP_CBDATA struct for PWR call */
+	cbData.cbData = PWR_TIMEOUT;
+	hNodeMgr = hNode->hNodeMgr;
+	hProcessor = hNode->hProcessor;
+	hDisp = hNodeMgr->hDisp;
+	nodeType = NODE_GetType(hNode);
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	/* Enter critical section */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	state = NODE_GetState(hNode);
+	 /*  Execute delete phase code for non-device node in all cases
+	  *  except when the node was only allocated. Delete phase must be
+	  *  executed even if create phase was executed, but failed.
+	  *  If the node environment pointer is non-NULL, the delete phase
+	  *  code must be  executed.  */
+	if (!(state == NODE_ALLOCATED && hNode->nodeEnv == (u32)NULL) &&
+	   nodeType != NODE_DEVICE) {
+		status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+		if (DSP_FAILED(status))
+			goto func_cont1;
+
+		if (procId == DSP_UNIT || procId == IVA_UNIT) {
+			/*  If node has terminated, execute phase code will
+			 *  have already been unloaded in NODE_OnExit(). If the
+			 *  node is PAUSED, the execute phase is loaded, and it
+			 *  is now ok to unload it. If the node is running, we
+			 *  will unload the execute phase only after deleting
+			 *  the node.  */
+			if (state == NODE_PAUSED && hNode->fLoaded &&
+			   hNode->fPhaseSplit) {
+				/* Ok to unload execute code as long as node
+				 * is not * running */
+				status1 = hNodeMgr->nldrFxns.pfnUnload(hNode->
+					  hNldrNode, NLDR_EXECUTE);
+				hNode->fLoaded = false;
+				NODE_SetState(hNode, NODE_DONE);
+			}
+			/* Load delete phase code if not loaded or if haven't
+			 * * unloaded EXECUTE phase */
+			if ((!(hNode->fLoaded) || (state == NODE_RUNNING)) &&
+			   hNode->fPhaseSplit) {
+				status = hNodeMgr->nldrFxns.pfnLoad(hNode->
+					 hNldrNode, NLDR_DELETE);
+				if (DSP_SUCCEEDED(status)) {
+					hNode->fLoaded = true;
+				} else {
+					GT_1trace(NODE_debugMask, GT_ENTER,
+						 "NODE_Delete: failed to "
+						 "load delete code: 0x%x\n",
+						 status);
+				}
+			}
+		}
+func_cont1:
+		if (DSP_SUCCEEDED(status)) {
+			/* Unblock a thread trying to terminate the node */
+			(void)SYNC_SetEvent(hNode->hSyncDone);
+			if (procId == DSP_UNIT) {
+				/* ulDeleteFxn = address of node's delete
+				 * function */
+				status = GetFxnAddress(hNode, &ulDeleteFxn,
+						      DELETEPHASE);
+			} else if (procId == IVA_UNIT)
+				ulDeleteFxn = (u32)hNode->nodeEnv;
+			if (DSP_SUCCEEDED(status)) {
+				status = DISP_NodeDelete(hDisp, hNode,
+					 hNodeMgr->ulFxnAddrs[RMSDELETENODE],
+					 ulDeleteFxn, hNode->nodeEnv);
+				/* Unload execute, if not unloaded, and delete
+				 * function */
+				if (state == NODE_RUNNING &&
+				   hNode->fPhaseSplit) {
+					status1 = hNodeMgr->nldrFxns.pfnUnload(
+						hNode->hNldrNode, NLDR_EXECUTE);
+				}
+				if (DSP_FAILED(status1)) {
+					GT_1trace(NODE_debugMask, GT_ENTER,
+						  "NODE_Delete: failed to"
+						  "unload execute code: 0x%x\n",
+						  status1);
+				}
+				status1 = hNodeMgr->nldrFxns.pfnUnload(
+					  hNode->hNldrNode, NLDR_DELETE);
+				hNode->fLoaded = false;
+				if (DSP_FAILED(status1)) {
+					GT_1trace(NODE_debugMask, GT_ENTER,
+						  "NODE_Delete: failed to"
+						  "unload delete code: 0x%x\n",
+						  status1);
+				}
+			}
+		}
+	}
+	/* Free host side resources even if a failure occurred */
+	/* Remove node from hNodeMgr->nodeList */
+	LST_RemoveElem(hNodeMgr->nodeList, (struct LST_ELEM *) hNode);
+	hNodeMgr->uNumNodes--;
+	/* Decrement count of nodes created on DSP */
+	if ((state != NODE_ALLOCATED) || ((state == NODE_ALLOCATED) &&
+	   (hNode->nodeEnv != (u32) NULL))) {
+		hNodeMgr->uNumCreated--;
+		/* This is not acceptable since in deep sleep, all the
+		 * peripherals are switched off We just need to put DSP
+		 * CPU in idle mode */
+	}
+	 /*  Free host-side resources allocated by NODE_Create()
+	 *  DeleteNode() fails if SM buffers not freed by client!  */
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	/* Update the node and stream resource status */
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_FAILED(res_status))
+		goto func_cont;
+
+	DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, hNode, 0);
+	if (pCtxt == NULL)
+		goto func_cont;
+
+	if (DRV_GetNodeResElement(hNode, &nodeRes, pCtxt) != DSP_ENOTFOUND) {
+		GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete12:\n");
+		DRV_ProcNodeUpdateStatus(nodeRes, false);
+	}
+#endif
+func_cont:
+	GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete13:\n ");
+	DeleteNode(hNode);
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_SUCCEEDED(status)) {
+		GT_0trace(NODE_debugMask, GT_5CLASS, "\nNODE_Delete2:\n ");
+		if (pCtxt != NULL)
+			DRV_RemoveNodeResElement(nodeRes, (HANDLE)pCtxt);
+
+	}
+#endif
+	GT_0trace(NODE_debugMask, GT_ENTER, "\nNODE_Delete3:\n ");
+			/* Exit critical section */
+			(void)SYNC_LeaveCS(hNodeMgr->hSync);
+			PROC_NotifyClients(hProcessor, DSP_NODESTATECHANGE);
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_DeleteMgr ========
+ *  Purpose:
+ *      Delete the NODE Manager.
+ */
+DSP_STATUS NODE_DeleteMgr(struct NODE_MGR *hNodeMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
+
+	GT_1trace(NODE_debugMask, GT_ENTER, "NODE_DeleteMgr: hNodeMgr: 0x%x\n",
+		 hNodeMgr);
+	DeleteNodeMgr(hNodeMgr);
+
+	return status;
+}
+
+/*
+ *  ======== NODE_EnumNodes ========
+ *  Purpose:
+ *      Enumerate currently allocated nodes.
+ */
+DSP_STATUS NODE_EnumNodes(struct NODE_MGR *hNodeMgr, IN DSP_HNODE *aNodeTab,
+			 u32 uNodeTabSize, OUT u32 *puNumNodes,
+			 OUT u32 *puAllocated)
+{
+	struct NODE_OBJECT *hNode;
+	u32 i;
+	DSP_STATUS status = DSP_SOK;
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE));
+	DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
+	DBC_Require(puNumNodes != NULL);
+	DBC_Require(puAllocated != NULL);
+	GT_5trace(NODE_debugMask, GT_ENTER, "NODE_EnumNodes: hNodeMgr: 0x%x\t"
+		 "aNodeTab: %d\tuNodeTabSize: 0x%x\tpuNumNodes: 0x%x\t"
+		 "puAllocated\n", hNodeMgr, aNodeTab, uNodeTabSize, puNumNodes,
+		 puAllocated);
+	/* Enter critical section */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_SUCCEEDED(status)) {
+		if (hNodeMgr->uNumNodes > uNodeTabSize) {
+			*puAllocated = hNodeMgr->uNumNodes;
+			*puNumNodes = 0;
+			status = DSP_ESIZE;
+		} else {
+			hNode = (struct NODE_OBJECT *)LST_First(hNodeMgr->
+				nodeList);
+			for (i = 0; i < hNodeMgr->uNumNodes; i++) {
+				DBC_Assert(MEM_IsValidHandle(hNode,
+					  NODE_SIGNATURE));
+				aNodeTab[i] = hNode;
+				hNode = (struct NODE_OBJECT *)LST_Next
+					(hNodeMgr->nodeList,
+					(struct LST_ELEM *)hNode);
+			}
+			*puAllocated = *puNumNodes = hNodeMgr->uNumNodes;
+		}
+	}
+	/* end of SYNC_EnterCS */
+	/* Exit critical section */
+	(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	return status;
+}
+
+/*
+ *  ======== NODE_Exit ========
+ *  Purpose:
+ *      Discontinue usage of NODE module.
+ */
+void NODE_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(NODE_debugMask, GT_5CLASS,
+		 "Entered NODE_Exit, ref count:  0x%x\n", cRefs);
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== NODE_FreeMsgBuf ========
+ *  Purpose:
+ *      Frees the message buffer.
+ */
+DSP_STATUS NODE_FreeMsgBuf(struct NODE_OBJECT *hNode, IN u8 *pBuffer,
+				 OPTIONAL struct DSP_BUFFERATTR *pAttr)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	DSP_STATUS status = DSP_SOK;
+	u32 procId;
+	DBC_Require(cRefs > 0);
+	DBC_Require(pBuffer != NULL);
+	DBC_Require(pNode != NULL);
+	DBC_Require(pNode->hXlator != NULL);
+	GT_3trace(NODE_debugMask, GT_ENTER, "NODE_FreeMsgBuf: hNode: 0x%x\t"
+		 "pBuffer: 0x%x\tpAttr: 0x%x\n", hNode, pBuffer, pAttr);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+		status = DSP_EHANDLE;
+
+	status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+	if (procId == DSP_UNIT) {
+		if (DSP_SUCCEEDED(status)) {
+			if (pAttr == NULL) {
+				/* set defaults */
+				pAttr = &NODE_DFLTBUFATTRS;
+			}
+			 /* Node supports single SM segment only */
+			if (pAttr->uSegment != 1)
+				status = DSP_EBADSEGID;
+
+			/* pBuffer is clients Va. */
+			status = CMM_XlatorFreeBuf(pNode->hXlator, pBuffer);
+			if (DSP_FAILED(status))
+				status = DSP_EFAIL;
+			else
+				status = DSP_SOK;
+
+		}
+	} else {
+		DBC_Assert(NULL);	/* BUG */
+	}
+	return status;
+}
+
+/*
+ *  ======== NODE_GetAttr ========
+ *  Purpose:
+ *      Copy the current attributes of the specified node into a DSP_NODEATTR
+ *      structure.
+ */
+DSP_STATUS NODE_GetAttr(struct NODE_OBJECT *hNode,
+			OUT struct DSP_NODEATTR *pAttr, u32 uAttrSize)
+{
+	struct NODE_MGR *hNodeMgr;
+	DSP_STATUS status = DSP_SOK;
+	DBC_Require(cRefs > 0);
+	DBC_Require(pAttr != NULL);
+	DBC_Require(uAttrSize >= sizeof(struct DSP_NODEATTR));
+	GT_3trace(NODE_debugMask, GT_ENTER, "NODE_GetAttr: hNode: "
+		 "0x%x\tpAttr: 0x%x \tuAttrSize: 0x%x\n", hNode, pAttr,
+		 uAttrSize);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		hNodeMgr = hNode->hNodeMgr;
+		 /* Enter hNodeMgr critical section (since we're accessing
+		  * data that could be changed by NODE_ChangePriority() and
+		  * NODE_Connect().  */
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+		if (DSP_SUCCEEDED(status)) {
+			pAttr->cbStruct = sizeof(struct DSP_NODEATTR);
+			/* DSP_NODEATTRIN */
+			pAttr->inNodeAttrIn.cbStruct =
+					 sizeof(struct DSP_NODEATTRIN);
+			pAttr->inNodeAttrIn.iPriority = hNode->nPriority;
+			pAttr->inNodeAttrIn.uTimeout = hNode->uTimeout;
+			pAttr->inNodeAttrIn.uHeapSize =
+				hNode->createArgs.asa.taskArgs.uHeapSize;
+			pAttr->inNodeAttrIn.pGPPVirtAddr = (void *)
+				hNode->createArgs.asa.taskArgs.uGPPHeapAddr;
+			pAttr->uInputs = hNode->uNumGPPInputs;
+			pAttr->uOutputs = hNode->uNumGPPOutputs;
+			/* DSP_NODEINFO */
+			GetNodeInfo(hNode, &(pAttr->iNodeInfo));
+		}
+		/* end of SYNC_EnterCS */
+		/* Exit critical section */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	}
+	return status;
+}
+
+/*
+ *  ======== NODE_GetChannelId ========
+ *  Purpose:
+ *      Get the channel index reserved for a stream connection between the
+ *      host and a node.
+ */
+DSP_STATUS NODE_GetChannelId(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
+			    OUT u32 *pulId)
+{
+	enum NODE_TYPE nodeType;
+	DSP_STATUS status = DSP_EVALUE;
+	DBC_Require(cRefs > 0);
+	DBC_Require(uDir == DSP_TONODE || uDir == DSP_FROMNODE);
+	DBC_Require(pulId != NULL);
+	GT_4trace(NODE_debugMask, GT_ENTER, "NODE_GetChannelId: hNode: "
+		 "0x%x\tuDir: %d\tuIndex: %d\tpulId: 0x%x\n", hNode, uDir,
+		 uIndex, pulId);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		return status;
+	}
+	nodeType = NODE_GetType(hNode);
+	if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET) {
+		status = DSP_ENODETYPE;
+		return status;
+	}
+	if (uDir == DSP_TONODE) {
+		if (uIndex < MaxInputs(hNode)) {
+			if (hNode->inputs[uIndex].type == HOSTCONNECT) {
+				*pulId = hNode->inputs[uIndex].devId;
+				status = DSP_SOK;
+			}
+		}
+	} else {
+		DBC_Assert(uDir == DSP_FROMNODE);
+		if (uIndex < MaxOutputs(hNode)) {
+			if (hNode->outputs[uIndex].type == HOSTCONNECT) {
+				*pulId = hNode->outputs[uIndex].devId;
+				status = DSP_SOK;
+			}
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== NODE_GetMessage ========
+ *  Purpose:
+ *      Retrieve a message from a node on the DSP.
+ */
+DSP_STATUS NODE_GetMessage(struct NODE_OBJECT *hNode, OUT struct DSP_MSG *pMsg,
+			  u32 uTimeout)
+{
+	struct NODE_MGR *hNodeMgr;
+	enum NODE_TYPE nodeType;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+	void *pTmpBuf;
+	DBC_Require(cRefs > 0);
+	DBC_Require(pMsg != NULL);
+	GT_3trace(NODE_debugMask, GT_ENTER,
+		 "NODE_GetMessage: hNode: 0x%x\tpMsg: "
+		 "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		goto func_end;
+	}
+	hNodeMgr = hNode->hNodeMgr;
+	nodeType = NODE_GetType(hNode);
+	if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
+	   nodeType != NODE_DAISSOCKET) {
+		status = DSP_ENODETYPE;
+		goto func_end;
+	}
+	 /*  This function will block unless a message is available. Since
+	 *  DSPNode_RegisterNotify() allows notification when a message
+	 *  is available, the system can be designed so that
+	 *  DSPNode_GetMessage() is only called when a message is
+	 *  available.  */
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	status = (*pIntfFxns->pfnMsgGet)(hNode->hMsgQueue, pMsg, uTimeout);
+	/* Check if message contains SM descriptor */
+	if (DSP_FAILED(status) ||  !(pMsg->dwCmd & DSP_RMSBUFDESC))
+		goto func_end;
+
+	 /* Translate DSP byte addr to GPP Va.  */
+	pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
+		(void *)(pMsg->dwArg1 * hNode->hNodeMgr->uDSPWordSize),
+		CMM_DSPPA2PA);
+	if (pTmpBuf  != NULL) {
+		/* now convert this GPP Pa to Va */
+		pTmpBuf = CMM_XlatorTranslate(hNode->hXlator, pTmpBuf,
+							CMM_PA2VA);
+		if (pTmpBuf != NULL) {
+			/* Adjust SM size in msg */
+			pMsg->dwArg1 = (u32) pTmpBuf;
+			pMsg->dwArg2 *= hNode->hNodeMgr->uDSPWordSize;
+		} else {
+			GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: "
+				 "Failed SM translation!\n");
+			status = DSP_ETRANSLATE;
+		}
+	} else {
+		GT_0trace(NODE_debugMask, GT_7CLASS, "NODE_GetMessage: Failed "
+			 "SM Pa/Pa translation!\n");
+		status = DSP_ETRANSLATE;
+	}
+func_end:
+	return status;
+}
+
+/*
+ *   ======== NODE_GetNldrObj ========
+ */
+DSP_STATUS NODE_GetNldrObj(struct NODE_MGR *hNodeMgr,
+			  struct NLDR_OBJECT **phNldrObj)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct NODE_MGR *pNodeMgr = hNodeMgr;
+	DBC_Require(phNldrObj != NULL);
+	GT_2trace(NODE_debugMask, GT_ENTER,
+		 "Entered NODE_GetNldrObj, hNodeMgr: "
+		 "0x%x\n\tphNldrObj:  0x%x\n", hNodeMgr, phNldrObj);
+	if (!MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE))
+		status = DSP_EHANDLE;
+	else
+		*phNldrObj = pNodeMgr->hNldr;
+
+	GT_2trace(NODE_debugMask, GT_ENTER,
+		 "Exit NODE_GetNldrObj: status 0x%x\n\t"
+		 "phNldrObj:  0x%x\n", status, *phNldrObj);
+	DBC_Ensure(DSP_SUCCEEDED(status) || ((phNldrObj != NULL) &&
+		  (*phNldrObj == NULL)));
+	return status;
+}
+
+/*
+ *  ======== NODE_GetStrmMgr ========
+ *  Purpose:
+ *      Returns the Stream manager.
+ */
+DSP_STATUS NODE_GetStrmMgr(struct NODE_OBJECT *hNode,
+			  struct STRM_MGR **phStrmMgr)
+{
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+		status = DSP_EHANDLE;
+	else
+		*phStrmMgr = hNode->hNodeMgr->hStrmMgr;
+
+	return status;
+}
+
+/*
+ *  ======== NODE_GetLoadType ========
+ */
+enum NLDR_LOADTYPE NODE_GetLoadType(struct NODE_OBJECT *hNode)
+{
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+
+	return hNode->dcdProps.objData.nodeObj.usLoadType;
+}
+
+/*
+ *  ======== NODE_GetTimeout ========
+ *  Purpose:
+ *      Returns the timeout value for this node.
+ */
+u32 NODE_GetTimeout(struct NODE_OBJECT *hNode)
+{
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+
+	return hNode->uTimeout;
+}
+
+/*
+ *  ======== NODE_GetType ========
+ *  Purpose:
+ *      Returns the node type.
+ */
+enum NODE_TYPE NODE_GetType(struct NODE_OBJECT *hNode)
+{
+	enum NODE_TYPE nodeType;
+
+	if (hNode == (struct NODE_OBJECT *) DSP_HGPPNODE)
+		nodeType = NODE_GPP;
+	else
+		nodeType = hNode->nType;
+
+	return nodeType;
+}
+
+/*
+ *  ======== NODE_Init ========
+ *  Purpose:
+ *      Initialize the NODE module.
+ */
+bool NODE_Init(void)
+{
+	bool fRetVal = true;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+		DBC_Assert(!NODE_debugMask.flags);
+		GT_create(&NODE_debugMask, "NO");	/* "NO" for NOde */
+	}
+
+	if (fRetVal)
+		cRefs++;
+
+	GT_1trace(NODE_debugMask, GT_5CLASS, "NODE_Init(), ref count: 0x%x\n",
+		 cRefs);
+
+	DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+	return fRetVal;
+}
+
+/*
+ *  ======== NODE_OnExit ========
+ *  Purpose:
+ *      Gets called when RMS_EXIT is received for a node.
+ */
+CDECL void NODE_OnExit(struct NODE_OBJECT *hNode, s32 nStatus)
+{
+	DBC_Assert(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+	/* Set node state to done */
+	NODE_SetState(hNode, NODE_DONE);
+	hNode->nExitStatus = nStatus;
+	if (hNode->fLoaded && hNode->fPhaseSplit) {
+		(void)hNode->hNodeMgr->nldrFxns.pfnUnload(hNode->hNldrNode,
+							 NLDR_EXECUTE);
+		hNode->fLoaded = false;
+	}
+	/* Unblock call to NODE_Terminate */
+	(void) SYNC_SetEvent(hNode->hSyncDone);
+	/* Notify clients */
+	PROC_NotifyClients(hNode->hProcessor, DSP_NODESTATECHANGE);
+	NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+}
+
+/*
+ *  ======== NODE_Pause ========
+ *  Purpose:
+ *      Suspend execution of a node currently running on the DSP.
+ */
+DSP_STATUS NODE_Pause(struct NODE_OBJECT *hNode)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	enum NODE_TYPE nodeType;
+	enum NODE_STATE state;
+	struct NODE_MGR *hNodeMgr;
+	DSP_STATUS status = DSP_SOK;
+	u32 procId;
+
+	DBC_Require(cRefs > 0);
+
+	GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Pause: hNode: 0x%x\n", hNode);
+
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		nodeType = NODE_GetType(hNode);
+		if (nodeType != NODE_TASK && nodeType != NODE_DAISSOCKET)
+			status = DSP_ENODETYPE;
+
+	}
+
+	status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+	if (procId == IVA_UNIT)
+		status = DSP_ENOTIMPL;
+
+	if (DSP_SUCCEEDED(status)) {
+		hNodeMgr = hNode->hNodeMgr;
+
+		/* Enter critical section */
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+
+		if (DSP_SUCCEEDED(status)) {
+			state = NODE_GetState(hNode);
+			/* Check node state */
+			if (state != NODE_RUNNING)
+				status = DSP_EWRONGSTATE;
+
+			if (DSP_SUCCEEDED(status)) {
+				status = DISP_NodeChangePriority(hNodeMgr->
+				   hDisp, hNode,
+				   hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY],
+				   hNode->nodeEnv, NODE_SUSPENDEDPRI);
+			}
+
+			/* Update state */
+			if (DSP_SUCCEEDED(status)) {
+				NODE_SetState(hNode, NODE_PAUSED);
+			} else {
+				GT_1trace(NODE_debugMask, GT_6CLASS,
+					 "NODE_Pause: Failed. hNode:"
+					 " 0x%x\n", hNode);
+			}
+		}
+		/* End of SYNC_EnterCS */
+		/* Leave critical section */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+		if (DSP_SUCCEEDED(status)) {
+			PROC_NotifyClients(hNode->hProcessor,
+					  DSP_NODESTATECHANGE);
+			NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== NODE_PutMessage ========
+ *  Purpose:
+ *      Send a message to a message node, task node, or XDAIS socket node. This
+ *      function will block until the message stream can accommodate the
+ *      message, or a timeout occurs.
+ */
+DSP_STATUS NODE_PutMessage(struct NODE_OBJECT *hNode,
+			  IN CONST struct DSP_MSG *pMsg, u32 uTimeout)
+{
+	struct NODE_MGR *hNodeMgr = NULL;
+	enum NODE_TYPE nodeType;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	enum NODE_STATE state;
+	DSP_STATUS status = DSP_SOK;
+	void *pTmpBuf;
+	struct DSP_MSG newMsg;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pMsg != NULL);
+	GT_3trace(NODE_debugMask, GT_ENTER,
+		 "NODE_PutMessage: hNode: 0x%x\tpMsg: "
+		 "0x%x\tuTimeout: 0x%x\n", hNode, pMsg, uTimeout);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+		status = DSP_EHANDLE;
+	else {
+		hNodeMgr = hNode->hNodeMgr;
+		nodeType = NODE_GetType(hNode);
+		if (nodeType != NODE_MESSAGE && nodeType != NODE_TASK &&
+		    nodeType != NODE_DAISSOCKET)
+			status = DSP_ENODETYPE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/*  Check node state. Can't send messages to a node after
+		 *  we've sent the RMS_EXIT command. There is still the
+		 *  possibility that NODE_Terminate can be called after we've
+		 *  checked the state. Could add another SYNC object to
+		 *  prevent this (can't use hNodeMgr->hSync, since we don't
+		 *  want to block other NODE functions). However, the node may
+		 *  still exit on its own, before this message is sent.  */
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+		if (DSP_SUCCEEDED(status)) {
+			state = NODE_GetState(hNode);
+			if (state == NODE_TERMINATING || state == NODE_DONE)
+				status = DSP_EWRONGSTATE;
+
+		}
+		/* end of SYNC_EnterCS */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* assign pMsg values to new msg  */
+	newMsg = *pMsg;
+	/* Now, check if message contains a SM buffer descriptor */
+	if (pMsg->dwCmd & DSP_RMSBUFDESC) {
+		/* Translate GPP Va to DSP physical buf Ptr. */
+		pTmpBuf = CMM_XlatorTranslate(hNode->hXlator,
+			(void *)newMsg.dwArg1, CMM_VA2DSPPA);
+		if (pTmpBuf != NULL) {
+			/* got translation, convert to MAUs in msg */
+			if (hNode->hNodeMgr->uDSPWordSize != 0) {
+				newMsg.dwArg1 =
+					(u32)pTmpBuf /
+					hNode->hNodeMgr->uDSPWordSize;
+				/* MAUs */
+				newMsg.dwArg2 /= hNode->hNodeMgr->uDSPWordSize;
+			} else {
+				GT_0trace(NODE_debugMask, GT_7CLASS,
+					 "NODE_PutMessage: "
+					 "uDSPWordSize is zero!\n");
+				status = DSP_EFAIL;	/* bad DSPWordSize */
+			}
+		} else {	/* failed to translate buffer address */
+			GT_0trace(NODE_debugMask, GT_7CLASS,
+				 "NODE_PutMessage: Failed to"
+				 " translate SM address\n");
+			status = DSP_ETRANSLATE;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pIntfFxns = hNodeMgr->pIntfFxns;
+		status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue,
+			 &newMsg, uTimeout);
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_RegisterNotify ========
+ *  Purpose:
+ *      Register to be notified on specific events for this node.
+ */
+DSP_STATUS NODE_RegisterNotify(struct NODE_OBJECT *hNode, u32 uEventMask,
+			       u32 uNotifyType,
+			       struct DSP_NOTIFICATION *hNotification)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hNotification != NULL);
+
+	GT_4trace(NODE_debugMask, GT_ENTER,
+		 "NODE_RegisterNotify: hNode: 0x%x\t"
+		 "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
+		 hNode, uEventMask, uNotifyType, hNotification);
+
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		/* Check if event mask is a valid node related event */
+		if (uEventMask & ~(DSP_NODESTATECHANGE |
+		   DSP_NODEMESSAGEREADY))
+			status = DSP_EVALUE;
+
+		/* Check if notify type is valid */
+		if (uNotifyType != DSP_SIGNALEVENT)
+			status = DSP_EVALUE;
+
+		/* Only one Notification can be registered at a
+		 * time - Limitation */
+		if (uEventMask == (DSP_NODESTATECHANGE |
+		   DSP_NODEMESSAGEREADY))
+			status = DSP_EVALUE;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		if (uEventMask == DSP_NODESTATECHANGE) {
+			status = NTFY_Register(hNode->hNtfy, hNotification,
+				 uEventMask & DSP_NODESTATECHANGE, uNotifyType);
+		} else {
+			/* Send Message part of event mask to MSG */
+			pIntfFxns = hNode->hNodeMgr->pIntfFxns;
+			status = (*pIntfFxns->pfnMsgRegisterNotify)
+				 (hNode->hMsgQueue,
+				 uEventMask & DSP_NODEMESSAGEREADY, uNotifyType,
+				 hNotification);
+		}
+
+	}
+	return status;
+}
+
+/*
+ *  ======== NODE_Run ========
+ *  Purpose:
+ *      Start execution of a node's execute phase, or resume execution of a node
+ *      that has been suspended (via NODE_NodePause()) on the DSP. Load the
+ *      node's execute function if necessary.
+ */
+DSP_STATUS NODE_Run(struct NODE_OBJECT *hNode)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	struct NODE_MGR *hNodeMgr;
+	enum NODE_TYPE nodeType;
+	enum NODE_STATE state;
+	u32 ulExecuteFxn;
+	u32 ulFxnAddr;
+	DSP_STATUS status = DSP_SOK;
+	u32 procId;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+
+	DBC_Require(cRefs > 0);
+	GT_1trace(NODE_debugMask, GT_ENTER, "NODE_Run: hNode: 0x%x\n", hNode);
+	if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		nodeType = NODE_GetType(hNode);
+		if (nodeType == NODE_DEVICE)
+			status = DSP_ENODETYPE;
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	hNodeMgr = hNode->hNodeMgr;
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	/* Enter critical section */
+	status = SYNC_EnterCS(hNodeMgr->hSync);
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	state = NODE_GetState(hNode);
+	if (state != NODE_CREATED && state != NODE_PAUSED)
+		status = DSP_EWRONGSTATE;
+
+	if (DSP_SUCCEEDED(status))
+		status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+	if (DSP_FAILED(status))
+		goto func_cont1;
+
+	if ((procId != DSP_UNIT) && (procId != IVA_UNIT))
+		goto func_cont1;
+
+	if (state == NODE_CREATED) {
+		/* If node's execute function is not loaded, load it */
+		if (!(hNode->fLoaded) && hNode->fPhaseSplit) {
+			status = hNodeMgr->nldrFxns.pfnLoad(hNode->hNldrNode,
+				NLDR_EXECUTE);
+			if (DSP_SUCCEEDED(status)) {
+				hNode->fLoaded = true;
+			} else {
+				GT_1trace(NODE_debugMask, GT_ENTER,
+					 "NODE_Run: failed to load "
+					 "execute code:0x%x\n", status);
+			}
+		}
+		if (DSP_SUCCEEDED(status)) {
+			/* Get address of node's execute function */
+			if (procId == IVA_UNIT)
+				ulExecuteFxn = (u32) hNode->nodeEnv;
+			else {
+				status = GetFxnAddress(hNode, &ulExecuteFxn,
+					 EXECUTEPHASE);
+			}
+		}
+		if (DSP_SUCCEEDED(status)) {
+			ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSEXECUTENODE];
+			status = DISP_NodeRun(hNodeMgr->hDisp, hNode, ulFxnAddr,
+					     ulExecuteFxn, hNode->nodeEnv);
+		}
+	} else if (state == NODE_PAUSED) {
+		ulFxnAddr = hNodeMgr->ulFxnAddrs[RMSCHANGENODEPRIORITY];
+		status = DISP_NodeChangePriority(hNodeMgr->hDisp, hNode,
+						ulFxnAddr, hNode->nodeEnv,
+						NODE_GetPriority(hNode));
+	} else {
+		/* We should never get here */
+		DBC_Assert(false);
+	}
+func_cont1:
+	/* Update node state. */
+	if (DSP_SUCCEEDED(status))
+		NODE_SetState(hNode, NODE_RUNNING);
+	 else /* Set state back to previous value */
+		NODE_SetState(hNode, state);
+	/*End of SYNC_EnterCS */
+	/* Exit critical section */
+func_cont:
+	(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	if (DSP_SUCCEEDED(status)) {
+		PROC_NotifyClients(hNode->hProcessor,
+			  DSP_NODESTATECHANGE);
+		NTFY_Notify(hNode->hNtfy, DSP_NODESTATECHANGE);
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== NODE_Terminate ========
+ *  Purpose:
+ *      Signal a node running on the DSP that it should exit its execute phase
+ *      function.
+ */
+DSP_STATUS NODE_Terminate(struct NODE_OBJECT *hNode, OUT DSP_STATUS *pStatus)
+{
+	struct NODE_OBJECT *pNode = (struct NODE_OBJECT *)hNode;
+	struct NODE_MGR *hNodeMgr = NULL;
+	enum NODE_TYPE nodeType;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	enum NODE_STATE state;
+	struct DSP_MSG msg, killmsg;
+	DSP_STATUS status = DSP_SOK;
+	u32 procId, killTimeOut;
+	struct DEH_MGR *hDehMgr;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pStatus != NULL);
+
+	GT_1trace(NODE_debugMask, GT_ENTER,
+		 "NODE_Terminate: hNode: 0x%x\n", hNode);
+
+	status = PROC_GetProcessorId(pNode->hProcessor, &procId);
+
+	if (DSP_SUCCEEDED(status)) {
+		hNodeMgr = hNode->hNodeMgr;
+
+		if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE))
+			status = DSP_EHANDLE;
+		else {
+			nodeType = NODE_GetType(hNode);
+			if (nodeType != NODE_TASK && nodeType !=
+			   NODE_DAISSOCKET)
+				status = DSP_ENODETYPE;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Check node state */
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+		if (DSP_SUCCEEDED(status)) {
+			state = NODE_GetState(hNode);
+			if (state != NODE_RUNNING) {
+				status = DSP_EWRONGSTATE;
+				/* Set the exit status if node terminated on
+				 * its own. */
+				if (state == NODE_DONE)
+					*pStatus = hNode->nExitStatus;
+
+			} else {
+				NODE_SetState(hNode, NODE_TERMINATING);
+			}
+		}
+		/* end of SYNC_EnterCS */
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/*
+		 *  Send exit message. Do not change state to NODE_DONE
+		 *  here. That will be done in callback.
+		 */
+		GT_1trace(NODE_debugMask, GT_5CLASS,
+			 "NODE_Terminate: env = 0x%x\n", hNode->nodeEnv);
+		msg.dwCmd = RMS_EXIT;
+		msg.dwArg1 = hNode->nodeEnv;
+		killmsg.dwCmd = RMS_KILLTASK;
+		killmsg.dwArg1 = hNode->nodeEnv;
+		pIntfFxns = hNodeMgr->pIntfFxns;
+
+		if (hNode->uTimeout > MAXTIMEOUT)
+			killTimeOut = MAXTIMEOUT;
+		else
+			killTimeOut = (hNode->uTimeout)*2;
+
+		status = (*pIntfFxns->pfnMsgPut)(hNode->hMsgQueue, &msg,
+							hNode->uTimeout);
+		if (DSP_SUCCEEDED(status)) {
+			/*  Wait on synchronization object that will be
+			 *  posted in the callback on receiving RMS_EXIT
+			 *  message, or by NODE_Delete. Check for valid hNode,
+			 *  in case posted by NODE_Delete().  */
+			status = SYNC_WaitOnEvent(hNode->hSyncDone,
+							killTimeOut/2);
+			if (DSP_FAILED(status)) {
+				if (status == DSP_ETIMEOUT) {
+					status = (*pIntfFxns->pfnMsgPut)
+						 (hNode->hMsgQueue, &killmsg,
+						 hNode->uTimeout);
+					if (DSP_SUCCEEDED(status)) {
+						status = SYNC_WaitOnEvent
+							(hNode->hSyncDone,
+							killTimeOut/2);
+						if (DSP_FAILED(status)) {
+							/* Here it goes the part
+							* of the simulation of
+							* the DSP exception */
+						    DEV_GetDehMgr(hNodeMgr->
+							hDevObject, &hDehMgr);
+						    if (hDehMgr) {
+							(*pIntfFxns->
+							pfnDehNotify)(hDehMgr,
+							DSP_SYSERROR,
+							DSP_EXCEPTIONABORT);
+							    status = DSP_EFAIL;
+						    }
+						} else
+						    status = DSP_SOK;
+					}
+				} else
+					status = DSP_EFAIL;
+			} else 	/* Convert SYNC status to DSP status */
+				status = DSP_SOK;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Enter CS before getting exit status, in case node was
+		 * deleted. */
+		status = SYNC_EnterCS(hNodeMgr->hSync);
+		/* Make sure node wasn't deleted while we blocked */
+		if (!MEM_IsValidHandle(hNode, NODE_SIGNATURE)) {
+			status = DSP_EFAIL;
+		} else {
+			*pStatus = hNode->nExitStatus;
+			GT_1trace(NODE_debugMask, GT_ENTER,
+				 "NODE_Terminate: env = 0x%x "
+				 "succeeded.\n", hNode->nodeEnv);
+		}
+		(void)SYNC_LeaveCS(hNodeMgr->hSync);
+	}		/*End of SYNC_EnterCS */
+
+	return status;
+}
+
+/*
+ *  ======== DeleteNode ========
+ *  Purpose:
+ *      Free GPP resources allocated in NODE_Allocate() or NODE_Connect().
+ */
+static void DeleteNode(struct NODE_OBJECT *hNode)
+{
+	struct NODE_MGR *hNodeMgr;
+	struct CMM_XLATOROBJECT *hXlator;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	u32 i;
+	enum NODE_TYPE nodeType;
+	struct STREAM stream;
+	struct NODE_MSGARGS msgArgs;
+	struct NODE_TASKARGS taskArgs;
+	DSP_STATUS status;
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+	hNodeMgr = hNode->hNodeMgr;
+	hXlator = hNode->hXlator;
+	nodeType = NODE_GetType(hNode);
+	if (nodeType != NODE_DEVICE) {
+		msgArgs = hNode->createArgs.asa.msgArgs;
+		if (msgArgs.pData)
+			MEM_Free(msgArgs.pData);
+
+		/* Free MSG queue */
+		if (hNode->hMsgQueue) {
+			pIntfFxns = hNodeMgr->pIntfFxns;
+			(*pIntfFxns->pfnMsgDeleteQueue) (hNode->hMsgQueue);
+		}
+		if (hNode->hSyncDone)
+			(void) SYNC_CloseEvent(hNode->hSyncDone);
+
+		/* Free all stream info */
+		if (hNode->inputs) {
+			for (i = 0; i < MaxInputs(hNode); i++) {
+				stream = hNode->inputs[i];
+				FreeStream(hNodeMgr, stream);
+			}
+			MEM_Free(hNode->inputs);
+		}
+		if (hNode->outputs) {
+			for (i = 0; i < MaxOutputs(hNode); i++) {
+				stream = hNode->outputs[i];
+				FreeStream(hNodeMgr, stream);
+			}
+			MEM_Free(hNode->outputs);
+		}
+		taskArgs = hNode->createArgs.asa.taskArgs;
+		if (taskArgs.strmInDef) {
+			for (i = 0; i < MaxInputs(hNode); i++) {
+				if (taskArgs.strmInDef[i].szDevice) {
+					MEM_Free(taskArgs.strmInDef[i].
+						szDevice);
+				}
+			}
+			MEM_Free(taskArgs.strmInDef);
+			taskArgs.strmInDef = NULL;
+		}
+		if (taskArgs.strmOutDef) {
+			for (i = 0; i < MaxOutputs(hNode); i++) {
+				if (taskArgs.strmOutDef[i].szDevice) {
+					MEM_Free(taskArgs.strmOutDef[i].
+						szDevice);
+				}
+			}
+			MEM_Free(taskArgs.strmOutDef);
+			taskArgs.strmOutDef = NULL;
+		}
+		if (taskArgs.uDSPHeapResAddr) {
+			status = PROC_UnMap(hNode->hProcessor,
+					   (void *)taskArgs.uDSPHeapAddr);
+			if (DSP_SUCCEEDED(status)) {
+				GT_0trace(NODE_debugMask, GT_5CLASS,
+					 "DSPProcessor_UnMap succeeded.\n");
+			} else {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+					 "DSPProcessor_UnMap failed."
+					 " Status = 0x%x\n", (u32)status);
+			}
+			status = PROC_UnReserveMemory(hNode->hProcessor,
+					(void *)taskArgs.uDSPHeapResAddr);
+			if (DSP_SUCCEEDED(status)) {
+				GT_0trace(NODE_debugMask, GT_5CLASS,
+					 "DSPProcessor_UnReserveMemory "
+					 "succeeded.\n");
+			} else {
+				GT_1trace(NODE_debugMask, GT_5CLASS,
+					 "DSPProcessor_UnReserveMemory "
+					 "failed. Status = 0x%x\n",
+					 (u32)status);
+			}
+		}
+	}
+	if (nodeType != NODE_MESSAGE) {
+		if (hNode->streamConnect)
+			MEM_Free(hNode->streamConnect);
+
+	}
+	if (hNode->pstrDevName)
+		MEM_Free(hNode->pstrDevName);
+
+	if (hNode->hNtfy)
+		NTFY_Delete(hNode->hNtfy);
+
+	/* These were allocated in DCD_GetObjectDef (via NODE_Allocate) */
+	if (hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn)
+		MEM_Free(hNode->dcdProps.objData.nodeObj.pstrCreatePhaseFxn);
+
+	if (hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn)
+		MEM_Free(hNode->dcdProps.objData.nodeObj.pstrExecutePhaseFxn);
+
+	if (hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn)
+		MEM_Free(hNode->dcdProps.objData.nodeObj.pstrDeletePhaseFxn);
+
+	if (hNode->dcdProps.objData.nodeObj.pstrIAlgName)
+		MEM_Free(hNode->dcdProps.objData.nodeObj.pstrIAlgName);
+
+	/* Free all SM address translator resources */
+	if (hXlator)
+		(void) CMM_XlatorDelete(hXlator, TRUE);	/* force free */
+
+	if (hNode->hNldrNode)
+		hNodeMgr->nldrFxns.pfnFree(hNode->hNldrNode);
+
+	MEM_FreeObject(hNode);
+}
+
+/*
+ *  ======== DeleteNodeMgr ========
+ *  Purpose:
+ *      Frees the node manager.
+ */
+static void DeleteNodeMgr(struct NODE_MGR *hNodeMgr)
+{
+	struct NODE_OBJECT *hNode;
+
+	if (MEM_IsValidHandle(hNodeMgr, NODEMGR_SIGNATURE)) {
+		/* Free resources */
+		if (hNodeMgr->hDcdMgr)
+			DCD_DestroyManager(hNodeMgr->hDcdMgr);
+
+		/* Remove any elements remaining in lists */
+		if (hNodeMgr->nodeList) {
+			while ((hNode =
+				(struct NODE_OBJECT *)LST_GetHead(hNodeMgr->
+				nodeList)))
+					DeleteNode(hNode);
+
+			DBC_Assert(LST_IsEmpty(hNodeMgr->nodeList));
+			LST_Delete(hNodeMgr->nodeList);
+		}
+		if (hNodeMgr->hNtfy)
+			NTFY_Delete(hNodeMgr->hNtfy);
+
+		if (hNodeMgr->pipeMap)
+			GB_delete(hNodeMgr->pipeMap);
+
+		if (hNodeMgr->pipeDoneMap)
+			GB_delete(hNodeMgr->pipeDoneMap);
+
+		if (hNodeMgr->chnlMap)
+			GB_delete(hNodeMgr->chnlMap);
+
+		if (hNodeMgr->dmaChnlMap)
+			GB_delete(hNodeMgr->dmaChnlMap);
+
+		if (hNodeMgr->zChnlMap)
+			GB_delete(hNodeMgr->zChnlMap);
+
+		if (hNodeMgr->hDisp)
+			DISP_Delete(hNodeMgr->hDisp);
+
+		if (hNodeMgr->hSync)
+			SYNC_DeleteCS(hNodeMgr->hSync);
+
+		if (hNodeMgr->hSync)
+			SYNC_DeleteCS(hNodeMgr->hAllocSync);
+
+		if (hNodeMgr->hStrmMgr)
+			STRM_Delete(hNodeMgr->hStrmMgr);
+
+		/* Delete the loader */
+		if (hNodeMgr->hNldr)
+			hNodeMgr->nldrFxns.pfnDelete(hNodeMgr->hNldr);
+
+		if (hNodeMgr->fLoaderInit)
+			hNodeMgr->nldrFxns.pfnExit();
+
+		MEM_FreeObject(hNodeMgr);
+	}
+}
+
+/*
+ *  ======== FillStreamConnect ========
+ *  Purpose:
+ *      Fills stream information.
+ */
+static void FillStreamConnect(struct NODE_OBJECT *hNode1,
+			     struct NODE_OBJECT *hNode2,
+			     u32 uStream1, u32 uStream2)
+{
+	u32 uStrmIndex;
+	struct DSP_STREAMCONNECT *pStrm1 = NULL;
+	struct DSP_STREAMCONNECT *pStrm2 = NULL;
+	enum NODE_TYPE node1Type = NODE_TASK;
+	enum NODE_TYPE node2Type = NODE_TASK;
+
+	node1Type = NODE_GetType(hNode1);
+	node2Type = NODE_GetType(hNode2);
+	if (hNode1 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
+
+		if (node1Type != NODE_DEVICE) {
+			uStrmIndex = hNode1->uNumInputs +
+				     hNode1->uNumOutputs - 1;
+			pStrm1 = &(hNode1->streamConnect[uStrmIndex]);
+			pStrm1->cbStruct = sizeof(struct DSP_STREAMCONNECT);
+			pStrm1->uThisNodeStreamIndex = uStream1;
+		}
+
+		if (hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE) {
+				/* NODE == > NODE */
+			if (node1Type != NODE_DEVICE) {
+				pStrm1->hConnectedNode = hNode2;
+				pStrm1->uiConnectedNodeID = hNode2->nodeId;
+				pStrm1->uConnectedNodeStreamIndex = uStream2;
+				pStrm1->lType = CONNECTTYPE_NODEOUTPUT;
+			}
+			if (node2Type != NODE_DEVICE) {
+				uStrmIndex = hNode2->uNumInputs +
+						hNode2->uNumOutputs - 1;
+				pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
+				pStrm2->cbStruct =
+					sizeof(struct DSP_STREAMCONNECT);
+				pStrm2->uThisNodeStreamIndex = uStream2;
+				pStrm2->hConnectedNode = hNode1;
+				pStrm2->uiConnectedNodeID = hNode1->nodeId;
+				pStrm2->uConnectedNodeStreamIndex = uStream1;
+				pStrm2->lType = CONNECTTYPE_NODEINPUT;
+			}
+		} else if (node1Type != NODE_DEVICE)
+				pStrm1->lType = CONNECTTYPE_GPPOUTPUT;
+	} else {
+		/* GPP == > NODE */
+		DBC_Assert(hNode2 != (struct NODE_OBJECT *)DSP_HGPPNODE);
+		uStrmIndex = hNode2->uNumInputs + hNode2->uNumOutputs - 1;
+		pStrm2 = &(hNode2->streamConnect[uStrmIndex]);
+		pStrm2->cbStruct = sizeof(struct DSP_STREAMCONNECT);
+		pStrm2->uThisNodeStreamIndex = uStream2;
+		pStrm2->lType = CONNECTTYPE_GPPINPUT;
+	}
+}
+
+/*
+ *  ======== FillStreamDef ========
+ *  Purpose:
+ *      Fills Stream attributes.
+ */
+static void FillStreamDef(struct NODE_OBJECT *hNode,
+			  struct NODE_STRMDEF *pstrmDef,
+			  struct DSP_STRMATTR *pAttrs)
+{
+	struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
+
+	if (pAttrs != NULL) {
+		pstrmDef->uNumBufs = pAttrs->uNumBufs;
+		pstrmDef->uBufsize = pAttrs->uBufsize / hNodeMgr->
+							uDSPDataMauSize;
+		pstrmDef->uSegid = pAttrs->uSegid;
+		pstrmDef->uAlignment = pAttrs->uAlignment;
+		pstrmDef->uTimeout = pAttrs->uTimeout;
+	} else {
+		pstrmDef->uNumBufs = DEFAULTNBUFS;
+		pstrmDef->uBufsize = DEFAULTBUFSIZE / hNodeMgr->
+						      uDSPDataMauSize;
+		pstrmDef->uSegid = DEFAULTSEGID;
+		pstrmDef->uAlignment = DEFAULTALIGNMENT;
+		pstrmDef->uTimeout = DEFAULTTIMEOUT;
+	}
+}
+
+/*
+ *  ======== FreeStream ========
+ *  Purpose:
+ *      Updates the channel mask and frees the pipe id.
+ */
+static void FreeStream(struct NODE_MGR *hNodeMgr, struct STREAM stream)
+{
+	/* Free up the pipe id unless other node has not yet been deleted. */
+	if (stream.type == NODECONNECT) {
+		if (GB_test(hNodeMgr->pipeDoneMap, stream.devId)) {
+			/* The other node has already been deleted */
+			GB_clear(hNodeMgr->pipeDoneMap, stream.devId);
+			GB_clear(hNodeMgr->pipeMap, stream.devId);
+		} else {
+			/* The other node has not been deleted yet */
+			GB_set(hNodeMgr->pipeDoneMap, stream.devId);
+		}
+	} else if (stream.type == HOSTCONNECT) {
+		if (stream.devId < hNodeMgr->ulNumChnls) {
+			GB_clear(hNodeMgr->chnlMap, stream.devId);
+		} else if (stream.devId < (2 * hNodeMgr->ulNumChnls)) {
+			/* dsp-dma */
+			GB_clear(hNodeMgr->dmaChnlMap, stream.devId -
+				(1 * hNodeMgr->ulNumChnls));
+		} else if (stream.devId < (3 * hNodeMgr->ulNumChnls)) {
+			/* zero-copy */
+			GB_clear(hNodeMgr->zChnlMap, stream.devId -
+				(2 * hNodeMgr->ulNumChnls));
+		}
+	}
+}
+
+/*
+ *  ======== GetFxnAddress ========
+ *  Purpose:
+ *      Retrieves the address for create, execute or delete phase for a node.
+ */
+static DSP_STATUS GetFxnAddress(struct NODE_OBJECT *hNode, u32 *pulFxnAddr,
+				u32 uPhase)
+{
+	char *pstrFxnName = NULL;
+	struct NODE_MGR *hNodeMgr = hNode->hNodeMgr;
+	DSP_STATUS status = DSP_SOK;
+	DBC_Require(NODE_GetType(hNode) == NODE_TASK ||
+			NODE_GetType(hNode) == NODE_DAISSOCKET ||
+			NODE_GetType(hNode) == NODE_MESSAGE);
+
+	switch (uPhase) {
+	case CREATEPHASE:
+		pstrFxnName = hNode->dcdProps.objData.nodeObj.
+			      pstrCreatePhaseFxn;
+		break;
+	case EXECUTEPHASE:
+		pstrFxnName = hNode->dcdProps.objData.nodeObj.
+			      pstrExecutePhaseFxn;
+		break;
+	case DELETEPHASE:
+		pstrFxnName = hNode->dcdProps.objData.nodeObj.
+			      pstrDeletePhaseFxn;
+		break;
+	default:
+		/* Should never get here */
+		DBC_Assert(false);
+		break;
+	}
+
+	status = hNodeMgr->nldrFxns.pfnGetFxnAddr(hNode->hNldrNode, pstrFxnName,
+						pulFxnAddr);
+
+	return status;
+}
+
+/*
+ *  ======== GetNodeInfo ========
+ *  Purpose:
+ *      Retrieves the node information.
+ */
+void GetNodeInfo(struct NODE_OBJECT *hNode, struct DSP_NODEINFO *pNodeInfo)
+{
+	u32 i;
+
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+	DBC_Require(pNodeInfo != NULL);
+
+	pNodeInfo->cbStruct = sizeof(struct DSP_NODEINFO);
+	pNodeInfo->nbNodeDatabaseProps = hNode->dcdProps.objData.nodeObj.
+					 ndbProps;
+	pNodeInfo->uExecutionPriority = hNode->nPriority;
+	pNodeInfo->hDeviceOwner = hNode->hDeviceOwner;
+	pNodeInfo->uNumberStreams = hNode->uNumInputs + hNode->uNumOutputs;
+	pNodeInfo->uNodeEnv = hNode->nodeEnv;
+
+	pNodeInfo->nsExecutionState = NODE_GetState(hNode);
+
+	/* Copy stream connect data */
+	for (i = 0; i < hNode->uNumInputs + hNode->uNumOutputs; i++)
+		pNodeInfo->scStreamConnection[i] = hNode->streamConnect[i];
+
+}
+
+/*
+ *  ======== GetNodeProps ========
+ *  Purpose:
+ *      Retrieve node properties.
+ */
+static DSP_STATUS GetNodeProps(struct DCD_MANAGER *hDcdMgr,
+			      struct NODE_OBJECT *hNode,
+			      CONST struct DSP_UUID *pNodeId,
+			      struct DCD_GENERICOBJ *pdcdProps)
+{
+	u32 uLen;
+	struct NODE_MSGARGS *pMsgArgs;
+	struct NODE_TASKARGS *pTaskArgs;
+	enum NODE_TYPE nodeType = NODE_TASK;
+	struct DSP_NDBPROPS *pndbProps = &(pdcdProps->objData.nodeObj.ndbProps);
+	DSP_STATUS status = DSP_SOK;
+#ifdef DEBUG
+	char szUuid[MAXUUIDLEN];
+#endif
+
+	status = DCD_GetObjectDef(hDcdMgr, (struct DSP_UUID *)pNodeId,
+				 DSP_DCDNODETYPE, pdcdProps);
+
+	if (DSP_SUCCEEDED(status)) {
+		hNode->nType = nodeType = pndbProps->uNodeType;
+
+#ifdef DEBUG
+		/* Create UUID value to set in registry. */
+		UUID_UuidToString((struct DSP_UUID *)pNodeId, szUuid,
+				 MAXUUIDLEN);
+		DBG_Trace(DBG_LEVEL7, "\n** (node) UUID: %s\n", szUuid);
+#endif
+
+		/* Fill in message args that come from NDB */
+		if (nodeType != NODE_DEVICE) {
+			pMsgArgs = &(hNode->createArgs.asa.msgArgs);
+			pMsgArgs->uSegid = pdcdProps->objData.nodeObj.uMsgSegid;
+			pMsgArgs->uNotifyType = pdcdProps->objData.nodeObj.
+						uMsgNotifyType;
+			pMsgArgs->uMaxMessages = pndbProps->uMessageDepth;
+#ifdef DEBUG
+			DBG_Trace(DBG_LEVEL7,
+				 "** (node) Max Number of Messages: 0x%x\n",
+				 pMsgArgs->uMaxMessages);
+#endif
+		} else {
+			/* Copy device name */
+			uLen = CSL_Strlen(pndbProps->acName);
+			DBC_Assert(uLen < MAXDEVNAMELEN);
+			hNode->pstrDevName = MEM_Calloc(uLen + 1, MEM_PAGED);
+			if (hNode->pstrDevName == NULL) {
+				status = DSP_EMEMORY;
+			} else {
+				CSL_Strcpyn(hNode->pstrDevName,
+					   pndbProps->acName, uLen);
+			}
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Fill in create args that come from NDB */
+		if (nodeType == NODE_TASK || nodeType == NODE_DAISSOCKET) {
+			pTaskArgs = &(hNode->createArgs.asa.taskArgs);
+			pTaskArgs->nPriority = pndbProps->iPriority;
+			pTaskArgs->uStackSize = pndbProps->uStackSize;
+			pTaskArgs->uSysStackSize = pndbProps->uSysStackSize;
+			pTaskArgs->uStackSeg = pndbProps->uStackSeg;
+#ifdef DEBUG
+			DBG_Trace(DBG_LEVEL7,
+				 "** (node) Priority: 0x%x\n" "** (node) Stack"
+				 " Size: 0x%x words\n" "** (node) System Stack"
+				 " Size: 0x%x words\n" "** (node) Stack"
+				 " Segment: 0x%x\n\n",
+				  "** (node) profile count : 0x%x \n \n",
+				  pTaskArgs->nPriority, pTaskArgs->uStackSize,
+				  pTaskArgs->uSysStackSize,
+				  pTaskArgs->uStackSeg,
+				  pndbProps->uCountProfiles);
+#endif
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== GetProcProps ========
+ *  Purpose:
+ *      Retrieve the processor properties.
+ */
+static DSP_STATUS GetProcProps(struct NODE_MGR *hNodeMgr,
+				struct DEV_OBJECT *hDevObject)
+{
+	struct CFG_DEVNODE *hDevNode;
+	struct CFG_HOSTRES hostRes;
+	DSP_STATUS status = DSP_SOK;
+
+	status = DEV_GetDevNode(hDevObject, &hDevNode);
+	if (DSP_SUCCEEDED(status))
+		status = CFG_GetHostResources(hDevNode, &hostRes);
+
+	if (DSP_SUCCEEDED(status)) {
+		hNodeMgr->ulChnlOffset = hostRes.dwChnlOffset;
+		hNodeMgr->ulChnlBufSize = hostRes.dwChnlBufSize;
+		hNodeMgr->ulNumChnls = hostRes.dwNumChnls;
+
+		/*
+		 *  PROC will add an API to get DSP_PROCESSORINFO.
+		 *  Fill in default values for now.
+		 */
+		/* TODO -- Instead of hard coding, take from registry */
+		hNodeMgr->procFamily = 6000;
+		hNodeMgr->procType = 6410;
+		hNodeMgr->nMinPri = DSP_NODE_MIN_PRIORITY;
+		hNodeMgr->nMaxPri = DSP_NODE_MAX_PRIORITY;
+		hNodeMgr->uDSPWordSize = DSPWORDSIZE;
+		hNodeMgr->uDSPDataMauSize = DSPWORDSIZE;
+		hNodeMgr->uDSPMauSize = 1;
+
+	}
+	return status;
+}
+
+
+
+/*
+ *  ======== NODE_GetUUIDProps ========
+ *  Purpose:
+ *      Fetch Node UUID properties from DCD/DOF file.
+ */
+DSP_STATUS NODE_GetUUIDProps(DSP_HPROCESSOR hProcessor,
+			    IN CONST struct DSP_UUID *pNodeId,
+			    OUT struct DSP_NDBPROPS *pNodeProps)
+{
+	struct NODE_MGR *hNodeMgr = NULL;
+	struct DEV_OBJECT *hDevObject;
+	DSP_STATUS status = DSP_SOK;
+	struct DCD_NODEPROPS   dcdNodeProps;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hProcessor != NULL);
+	DBC_Require(pNodeId != NULL);
+
+	GT_3trace(NODE_debugMask, GT_ENTER,
+		 "NODE_GetUUIDProps: " "\thProcessor: "
+		 "0x%x\tpNodeId: 0x%x" "\tpNodeProps: 0x%x\n", hProcessor,
+		 pNodeId, pNodeProps);
+
+	status = PROC_GetDevObject(hProcessor, &hDevObject);
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetNodeManager(hDevObject, &hNodeMgr);
+		if (hNodeMgr == NULL)
+			status = DSP_EFAIL;
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		dcdNodeProps.pstrCreatePhaseFxn = NULL;
+		dcdNodeProps.pstrExecutePhaseFxn = NULL;
+		dcdNodeProps.pstrDeletePhaseFxn = NULL;
+		dcdNodeProps.pstrIAlgName = NULL;
+
+		status = DCD_GetObjectDef(hNodeMgr->hDcdMgr,
+				(struct DSP_UUID *) pNodeId,
+				DSP_DCDNODETYPE,
+				(struct DCD_GENERICOBJ *) &dcdNodeProps);
+		if (DSP_SUCCEEDED(status)) {
+			*pNodeProps = dcdNodeProps.ndbProps;
+			if (dcdNodeProps.pstrCreatePhaseFxn)
+				MEM_Free(dcdNodeProps.pstrCreatePhaseFxn);
+
+			if (dcdNodeProps.pstrExecutePhaseFxn)
+				MEM_Free(dcdNodeProps.pstrExecutePhaseFxn);
+
+			if (dcdNodeProps.pstrDeletePhaseFxn)
+				MEM_Free(dcdNodeProps.pstrDeletePhaseFxn);
+
+			if (dcdNodeProps.pstrIAlgName)
+				MEM_Free(dcdNodeProps.pstrIAlgName);
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== GetRMSFxns ========
+ *  Purpose:
+ *      Retrieve the RMS functions.
+ */
+static DSP_STATUS GetRMSFxns(struct NODE_MGR *hNodeMgr)
+{
+	s32 i;
+	struct DEV_OBJECT *hDev = hNodeMgr->hDevObject;
+	DSP_STATUS status = DSP_SOK;
+
+	static char *pszFxns[NUMRMSFXNS] = {
+		"RMS_queryServer", 	/* RMSQUERYSERVER */
+		"RMS_configureServer", 	/* RMSCONFIGURESERVER */
+		"RMS_createNode", 	/* RMSCREATENODE */
+		"RMS_executeNode", 	/* RMSEXECUTENODE */
+		"RMS_deleteNode", 	/* RMSDELETENODE */
+		"RMS_changeNodePriority", 	/* RMSCHANGENODEPRIORITY */
+		"RMS_readMemory", 	/* RMSREADMEMORY */
+		"RMS_writeMemory", 	/* RMSWRITEMEMORY */
+		"RMS_copy", 	/* RMSCOPY */
+	};
+
+	for (i = 0; i < NUMRMSFXNS; i++) {
+		status = DEV_GetSymbol(hDev, pszFxns[i],
+			 &(hNodeMgr->ulFxnAddrs[i]));
+		if (DSP_FAILED(status)) {
+			if (status == COD_E_SYMBOLNOTFOUND) {
+				/*
+				 *  May be loaded dynamically (in the future),
+				 *  but return an error for now.
+				 */
+				GT_1trace(NODE_debugMask, GT_6CLASS,
+					 "RMS function: %s "
+					 "currently not loaded\n", pszFxns[i]);
+			} else {
+				GT_2trace(NODE_debugMask, GT_6CLASS,
+					 "GetRMSFxns: Symbol not "
+					 "found: %s\tstatus = 0x%x\n",
+					 pszFxns[i], status);
+				break;
+			}
+		}
+	}
+
+	return status;
+}
+
+/*
+ *  ======== Ovly ========
+ *  Purpose:
+ *      Called during overlay.Sends command to RMS to copy a block of data.
+ */
+static CDECL u32 Ovly(void *pPrivRef, u32 ulDspRunAddr, u32 ulDspLoadAddr,
+			u32 ulNumBytes, u32 nMemSpace)
+{
+	struct NODE_OBJECT *hNode = (struct NODE_OBJECT *)pPrivRef;
+	struct NODE_MGR *hNodeMgr;
+	u32 ulBytes = 0;
+	u32 ulSize;
+	u32 ulTimeout;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *hWmdContext;
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD */
+
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+
+	hNodeMgr = hNode->hNodeMgr;
+
+	ulSize = ulNumBytes / hNodeMgr->uDSPWordSize;
+	ulTimeout = hNode->uTimeout;
+
+	/* Call new MemCopy function */
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
+	status = (*pIntfFxns->pfnBrdMemCopy)(hWmdContext, ulDspRunAddr,
+		 ulDspLoadAddr,	ulNumBytes, (u32) nMemSpace);
+
+	if (DSP_SUCCEEDED(status))
+		ulBytes = ulNumBytes;
+
+	return ulBytes;
+}
+
+/*
+ *  ======== Write ========
+ */
+static CDECL u32 Write(void *pPrivRef, u32 ulDspAddr, void *pBuf,
+			u32 ulNumBytes, u32 nMemSpace)
+{
+	struct NODE_OBJECT *hNode = (struct NODE_OBJECT *) pPrivRef;
+	struct NODE_MGR *hNodeMgr;
+	u16 memType;
+	u32 ulTimeout;
+	DSP_STATUS status = DSP_SOK;
+	struct WMD_DEV_CONTEXT *hWmdContext;
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD */
+
+	DBC_Require(MEM_IsValidHandle(hNode, NODE_SIGNATURE));
+	DBC_Require(nMemSpace & DBLL_CODE || nMemSpace & DBLL_DATA);
+
+	hNodeMgr = hNode->hNodeMgr;
+
+	ulTimeout = hNode->uTimeout;
+	memType = (nMemSpace & DBLL_CODE) ? RMS_CODE : RMS_DATA;
+
+	/* Call new MemWrite function */
+	pIntfFxns = hNodeMgr->pIntfFxns;
+	status = DEV_GetWMDContext(hNodeMgr->hDevObject, &hWmdContext);
+	status = (*pIntfFxns->pfnBrdMemWrite) (hWmdContext, pBuf, ulDspAddr,
+		 ulNumBytes, memType);
+
+	return ulNumBytes;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/proc.c b/drivers/dsp/bridge/rmgr/proc.c
new file mode 100644
index 0000000..4895a49
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/proc.c
@@ -0,0 +1,1958 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/proc.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== proc.c ========
+ *  Description:
+ *      Processor interface at the driver level.
+ *
+ *  Public Functions:
+ *      PROC_Attach
+ *      PROC_Ctrl
+ *      PROC_Detach
+ *      PROC_EnumNodes
+ *      PROC_GetResourceInfo
+ *      PROC_Exit
+ *      PROC_FlushMemory
+ *      PROC_GetState
+ *      PROC_GetProcessorId
+ *      PROC_GetTrace
+ *      PROC_Init
+ *      PROC_Load
+ *      PROC_Map
+ *      PROC_NotifyClients
+ *      PROC_RegisterNotify
+ *      PROC_ReserveMemory
+ *      PROC_Start
+ *      PROC_UnMap
+ *      PROC_UnReserveMemory
+ *      PROC_InvalidateMemory
+
+ *! Revision History
+ *! ======== ========
+ *! 04-Apr-2007 sh  Added PROC_InvalidateMemory API
+ *! 19-Apr-2004 sb  Aligned DMM definitions with Symbian
+ *!		 Used MEM_FlushCache instead of OS specific API
+ *!		 Integrated Alan's code review updates
+ *! 08-Mar-2004 sb  Added the Dynamic Memory Mapping feature
+ *! 08-Mar-2004 vp  Added g_pszLastCoff member to PROC_OBJECT.
+ *!		 This is required for multiprocessor environment.
+ *! 09-Feb-2004 vp  Added PROC_GetProcessorID function
+ *! 22-Apr-2003 vp  Fixed issue with the string that stores coff file name
+ *! 03-Apr-2003 sb  Fix DEH deregistering bug
+ *! 26-Mar-2003 vp  Commented the call to DSP deep sleep in PROC_Start function.
+ *! 18-Feb-2003 vp  Code review updates.
+ *! 18-Oct-2002 vp  Ported to Linux platform.
+ *! 22-May-2002 sg  Do IOCTL-to-PWR translation before calling PWR_SleepDSP.
+ *! 14-May-2002 sg  Use CSL_Atoi() instead of atoi().
+ *! 13-May-2002 sg  Propagate PWR return codes upwards.
+ *! 07-May-2002 sg  Added check for, and call to PWR functions in PROC_Ctrl.
+ *! 02-May-2002 sg  Added "nap" mode: put DSP to sleep once booted.
+ *! 01-Apr-2002 jeh Assume word addresses in PROC_GetTrace().
+ *! 29-Nov-2001 jeh Don't call DEH function if hDehMgr == NULL.
+ *! 05-Nov-2001 kc: Updated PROC_RegisterNotify and PROC_GetState to support
+ *!		 DEH module.
+ *! 09-Oct-2001 jeh Fix number of bytes calculated in PROC_GetTrace().
+ *! 11-Sep-2001 jeh Delete MSG manager in PROC_Monitor() to fix memory leak.
+ *! 29-Aug-2001 rr: DCD_AutoRegister and IOOnLoaded moved before COD_LoadBase
+ *!		 to facilitate the external loading.
+ *! 14-Aug-2001 ag  DCD_AutoRegister() now called before IOOnLoaded() fxn.
+ *! 21-Jun-2001 rr: MSG_Create is done only the first time.
+ *! 02-May-2001 jeh Return failure in PROC_Load if IOOnLoaded function returns
+ *!		 error other than E_NOTIMPL.
+ *! 03-Apr-2001 sg: Changed DSP_DCD_ENOAUTOREGISTER to DSP_EDCDNOAUTOREGISTER.
+ *! 13-Feb-2001 kc: DSP/BIOS Bridge name updates.
+ *! 05-Jan-2001 rr: PROC_LOAD MSG_Create error is checked.
+ *! 15-Dec-2000 rr: IoOnLoaded is checked for WSX_STATUS. We fail to load
+ *!		 if DEV_Create2 fails; ie, no non-RMS targets can be
+ *!		 loaded.
+ *! 12-Dec-2000 rr: PROC_Start's DEV_Create2 is checked for WSX_STATUS.
+ *! 28-Nov-2000 jeh Added call to IO OnLoaded function to PROC_Load().
+ *! 29-Nov-2000 rr: Incorporated code review changes.
+ *! 03-Nov-2000 rr: Auto_Register happens after PROC_Load.
+ *! 06-Oct-2000 rr: Updated to ver 0.9. PROC_Start calls DEV_Create2 and
+ *!		 WMD_BRD_STOP is always followed by DEV_Destroy2.
+ *! 05-Sep-2000 rr: PROC_GetTrace calculates the Trace symbol for 55 in a
+ *!		 different way.
+ *! 10-Aug-2000 rr: PROC_NotifyClients, PROC_GetProcessorHandle Added
+ *! 07-Aug-2000 rr: PROC_IDLE/SYNCINIT/UNKNOWN state removed.
+ *!		 WMD fxns are checked for WSX_STATUS.
+ *!		 PROC_Attach does not alter the state of the BRD.
+ *!		 PROC_Run removed.
+ *! 04-Aug-2000 rr: All the functions return DSP_EHANDLE if proc handle is
+ *!		 invalid
+ *! 27-Jul-2000 rr: PROC_GetTrace and PROC_Load implemented. Updated to
+ *!		 ver 0.8 API.
+ *! 06-Jul-2000 rr: Created.
+ */
+
+/* ------------------------------------ Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <cfg.h>
+#include <csl.h>
+#include <list.h>
+#include <mem.h>
+#include <ntfy.h>
+#include <prcs.h>
+
+/*  ----------------------------------- Mini Driver */
+#include <wmd.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <cod.h>
+#include <dev.h>
+#include <drv.h>
+#include <procpriv.h>
+#include <dmm.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <mgr.h>
+#include <node.h>
+#include <nldr.h>
+#include <rmm.h>
+
+/*  ----------------------------------- Others */
+#include <dbdcd.h>
+#include <dbreg.h>
+#include <msg.h>
+#include <pwr.h>
+#include <wmdioctl.h>
+
+/*  ----------------------------------- This */
+#include <proc.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <resourcecleanup.h>
+#endif
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+#include <asm/arch/resource.h>
+#endif
+#endif
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define PROC_SIGNATURE	   0x434F5250	/* "PROC" (in reverse). */
+#define MAXCMDLINELEN       255
+#define PROC_ENVPROCID      "PROC_ID=%d"
+#define MAXPROCIDLEN	(8 + 5)
+#define PROC_DFLT_TIMEOUT   10000	/* Time out in milliseconds  */
+#define PWR_TIMEOUT	 500	/* Sleep/wake timout in msec */
+#define EXTEND	      "_EXT_END"	/* Extmem end addr in DSP binary */
+
+extern char *iva_img;
+/* The PROC_OBJECT structure.   */
+struct PROC_OBJECT {
+	struct LST_ELEM link;		/* Link to next PROC_OBJECT */
+	u32 dwSignature;	/* Used for object validation */
+	struct DEV_OBJECT *hDevObject;	/* Device this PROC represents */
+	HANDLE hProcess;	/* Process owning this Processor */
+	struct MGR_OBJECT *hMgrObject;	/* Manager Object Handle */
+	u32 uAttachCount;	/* Processor attach count */
+	u32 uProcessor;	/* Processor number */
+	u32 uTimeout;		/* Time out count */
+	enum DSP_PROCSTATE sState;	/* Processor state */
+	u32 ulUnit;		/* DDSP unit number */
+	bool bIsAlreadyAttached;	/*
+					 * True if the Device below has
+					 * GPP Client attached
+					 */
+	struct NTFY_OBJECT *hNtfy;	/* Manages  notifications */
+	struct WMD_DEV_CONTEXT *hWmdContext;	/* WMD Context Handle */
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD */
+	char *g_pszLastCoff;
+} ;
+
+/*  ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask PROC_DebugMask = { NULL, NULL };	/* WCD MGR Mask */
+#endif
+
+static u32 cRefs;
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+extern struct constraint_handle *mpu_constraint_handle;
+#endif
+#endif
+
+/*  ----------------------------------- Function Prototypes */
+static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcessor);
+static s32 GetEnvpCount(char **envp);
+static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
+			 char *szVar);
+
+
+/*
+ *  ======== PROC_Attach ========
+ *  Purpose:
+ *      Prepare for communication with a particular DSP processor, and return
+ *      a handle to the processor object.
+ */
+DSP_STATUS
+PROC_Attach(u32 uProcessor, OPTIONAL CONST struct DSP_PROCESSORATTRIN *pAttrIn,
+	   OUT DSP_HPROCESSOR *phProcessor)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct DEV_OBJECT *hDevObject;
+	struct PROC_OBJECT *pProcObject = NULL;
+	struct MGR_OBJECT *hMgrObject = NULL;
+	struct DRV_OBJECT *hDrvObject = NULL;
+	u32 devType;
+
+#ifndef RES_CLEANUP_DISABLE
+	HANDLE	     hDRVObject;
+	HANDLE	     hProcess;
+	DSP_STATUS res_status = DSP_SOK;
+	struct PROCESS_CONTEXT   *pPctxt = NULL;
+#endif
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(phProcessor != NULL);
+
+	GT_3trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Attach, args:\n\t"
+		 "uProcessor:  0x%x\n\tpAttrIn:  0x%x\n\tphProcessor:"
+		 "0x%x\n", uProcessor, pAttrIn, phProcessor);
+	/* Get the Driver and Manager Object Handles */
+	status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(status)) {
+		status = CFG_GetObject((u32 *)&hMgrObject, REG_MGR_OBJECT);
+		if (DSP_FAILED(status)) {
+			/* don't propogate CFG errors from this PROC function */
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Attach: DSP_FAILED to get"
+				 "the Manager Object.\n", status);
+		}
+	} else {
+		/* don't propogate CFG errors from this PROC function */
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Attach: failed to get the"
+			 " DriverObject, 0x%x!\n", status);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Get the Device Object */
+		status = DRV_GetDevObject(uProcessor, hDrvObject, &hDevObject);
+		if (DSP_FAILED(status)) {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Attach: failed to get"
+				 " DevObject, 0x%x!\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetDevType(hDevObject, &devType);
+		if (DSP_FAILED(status)) {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Attach: failed to get"
+				 " DevType, 0x%x!\n", status);
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* If we made it this far, create the Proceesor object: */
+	MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
+	/* Fill out the Processor Object: */
+	if (pProcObject == NULL) {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Attach:Out of memeory \n");
+		status = DSP_EFAIL;
+		goto func_end;
+	}
+	pProcObject->hDevObject = hDevObject;
+	pProcObject->hMgrObject = hMgrObject;
+	pProcObject->uProcessor = devType;
+	/* Get Caller Process and store it */
+	(void)PRCS_GetCurrentHandle(&pProcObject->hProcess);
+	if (pAttrIn)
+		pProcObject->uTimeout = pAttrIn->uTimeout;
+	else
+		pProcObject->uTimeout = PROC_DFLT_TIMEOUT;
+
+	status = DEV_GetIntfFxns(hDevObject, &pProcObject->pIntfFxns);
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetWMDContext(hDevObject,
+					 &pProcObject->hWmdContext);
+		if (DSP_FAILED(status)) {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Attach Could not"
+				 " get the WMD Context.\n", status);
+			MEM_FreeObject(pProcObject);
+		}
+	} else {
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Attach Could not get"
+			 " the DEV_ Interface fxns.\n", status);
+		MEM_FreeObject(pProcObject);
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Create the Notification Object */
+	/* This is created with no event mask, no notify mask
+	 * and no valid handle to the notification. They all get
+	 * filled up when PROC_RegisterNotify is called */
+	status = NTFY_Create(&pProcObject->hNtfy);
+	if (DSP_SUCCEEDED(status)) {
+		/* Insert the Processor Object into the DEV List.
+		 * Return handle to this Processor Object:
+		 * Find out if the Device is already attached to a
+		 * Processor. If so, return AlreadyAttached status */
+		LST_InitElem(&pProcObject->link);
+		status = DEV_InsertProcObject(pProcObject->hDevObject,
+					     (u32)pProcObject,
+					     &pProcObject->bIsAlreadyAttached);
+		if (DSP_SUCCEEDED(status)) {
+			if (pProcObject->bIsAlreadyAttached) {
+				status = DSP_SALREADYATTACHED;
+				GT_0trace(PROC_DebugMask, GT_1CLASS,
+					 "PROC_Attach: Processor "
+					 "Already Attached!\n");
+			}
+		} else {
+			if (pProcObject->hNtfy)
+				NTFY_Delete(pProcObject->hNtfy);
+
+			MEM_FreeObject(pProcObject);
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Attach: failed to insert "
+				 "Proc Object into DEV, 0x%x!\n", status);
+		}
+		if (DSP_SUCCEEDED(status)) {
+			*phProcessor = (DSP_HPROCESSOR)pProcObject;
+			(void)PROC_NotifyClients(pProcObject,
+						 DSP_PROCESSORATTACH);
+			GT_0trace(PROC_DebugMask, GT_1CLASS,
+				 "PROC_Attach: Processor "
+				 "Attach Success!\n");
+		}
+	} else {
+		/* Don't leak memory if DSP_FAILED */
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Attach: Could not allocate "
+			 "storage for notification \n");
+		MEM_FreeObject(pProcObject);
+	}
+func_end:
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+	if (DSP_FAILED(res_status))
+		goto func_cont;
+
+	DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
+	if (pPctxt == NULL) {
+		DRV_InsertProcContext(hDRVObject, &pPctxt);
+		if (pPctxt != NULL) {
+			DRV_ProcUpdatestate(pPctxt, PROC_RES_ALLOCATED);
+			DRV_ProcSetPID(pPctxt, (s32)hProcess);
+		}
+	}
+func_cont:
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(res_status)) {
+		DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
+		if (pPctxt != NULL)
+			pPctxt->hProcessor = (DSP_HPROCESSOR)*phProcessor;
+
+	}
+#endif
+	DBC_Ensure((status == DSP_EFAIL && *phProcessor == NULL) ||
+		  (DSP_SUCCEEDED(status) &&
+		  MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) ||
+		  (status == DSP_SALREADYATTACHED &&
+		  MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)));
+	GT_2trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Attach, results:\n\t"
+		 "status: 0x%x\n\thProcessor: 0x%x\n", status, *phProcessor);
+
+	return status;
+}
+
+static DSP_STATUS GetExecFile(struct CFG_DEVNODE *hDevNode,
+			     struct DEV_OBJECT *hDevObject,
+			     u32 size, char *execFile)
+{
+	s32 devType;
+	s32 len;
+
+	DEV_GetDevType(hDevObject, (u32 *) &devType);
+	if (devType == DSP_UNIT) {
+		return CFG_GetExecFile(hDevNode, size, execFile);
+	} else if (devType == IVA_UNIT) {
+		if (iva_img) {
+			len = CSL_Strlen(iva_img);
+			CSL_Strcpyn(execFile, iva_img, len + 1);
+			return DSP_SOK;
+		}
+	}
+	return DSP_EFILE;
+}
+
+/*
+ *  ======== PROC_AutoStart ======== =
+ *  Purpose:
+ *      A Particular device gets loaded with the default image
+ *      if the AutoStart flag is set.
+ *  Parameters:
+ *      hDevObject:     Handle to the Device
+ *  Returns:
+ *      DSP_SOK:   On Successful Loading
+ *      DSP_EFAIL  General Failure
+ *  Requires:
+ *      hDevObject != NULL
+ *  Ensures:
+ */
+DSP_STATUS PROC_AutoStart(struct CFG_DEVNODE *hDevNode,
+			 struct DEV_OBJECT *hDevObject)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	u32 dwAutoStart = 0;	/* autostart flag */
+	struct PROC_OBJECT *pProcObject;
+	struct PROC_OBJECT *hProcObject;
+	char szExecFile[MAXCMDLINELEN];
+	char *argv[2];
+	struct MGR_OBJECT *hMgrObject = NULL;
+	s32 devType;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hDevNode != NULL);
+	DBC_Require(hDevObject != NULL);
+
+	GT_2trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_AutoStart, args:\n\t"
+		 "hDevNode: 0x%x\thDevObject: 0x%x\n", hDevNode, hDevObject);
+	/* Create a Dummy PROC Object */
+	if (DSP_FAILED(CFG_GetObject((u32 *)&hMgrObject,
+	   REG_MGR_OBJECT))) {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_AutoStart: DSP_FAILED to "
+			 "Get MGR Object\n");
+		goto func_end;
+	}
+	MEM_AllocObject(pProcObject, struct PROC_OBJECT, PROC_SIGNATURE);
+	if (pProcObject == NULL) {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_AutoStart: DSP_FAILED "
+			 "to Create a dummy Processor\n");
+		goto func_end;
+	}
+	GT_0trace(PROC_DebugMask, GT_1CLASS, "NTFY Created \n");
+	pProcObject->hDevObject = hDevObject;
+	pProcObject->hMgrObject = hMgrObject;
+	hProcObject = pProcObject;
+	if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+	   &pProcObject->pIntfFxns))) {
+		if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+				 &pProcObject->hWmdContext))) {
+			status = DSP_SOK;
+		} else {
+			MEM_FreeObject(hProcObject);
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_AutoStart: Failed "
+				 "to get WMD Context \n");
+		}
+	} else {
+		MEM_FreeObject(hProcObject);
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_AutoStart: Failed to "
+			 "get IntFxns \n");
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Stop the Device, put it into standby mode */
+	status = PROC_Stop(hProcObject);
+	if (DSP_FAILED(CFG_GetAutoStart(hDevNode, &dwAutoStart)) ||
+			   !dwAutoStart) {
+		status = DSP_EFAIL;
+		/* DSP_FAILED to Get s32 Fxn or Wmd Context */
+		GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_AutoStart: "
+			 "CFG_GetAutoStart DSP_FAILED \n");
+		goto func_cont;
+	}
+	/* Get the default executable for this board... */
+	DEV_GetDevType(hDevObject, (u32 *)&devType);
+	pProcObject->uProcessor = devType;
+	if (DSP_SUCCEEDED(GetExecFile(hDevNode, hDevObject,
+			 sizeof(szExecFile), szExecFile))) {
+		argv[0] = szExecFile;
+		argv[1] = NULL;
+		/* ...and try to load it: */
+		status = PROC_Load(hProcObject, 1, (CONST char **)argv, NULL);
+		if (DSP_SUCCEEDED(status)) {
+			status = PROC_Start(hProcObject);
+			if (DSP_SUCCEEDED(status)) {
+				GT_0trace(PROC_DebugMask, GT_1CLASS,
+					  "PROC_AutoStart: Processor started "
+					  "running\n");
+			} else {
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					  "PROC_AutoStart: DSP_FAILED To "
+					  "Start \n");
+			}
+		} else {
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				  "PROC_AutoStart: DSP_FAILED to Load\n");
+		}
+	} else {
+		status = DSP_EFILE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_AutoStart: "
+			 "No Exec file found \n");
+	}
+func_cont:
+	MEM_FreeObject(hProcObject);
+func_end:
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Exiting PROC_AutoStart, status:0x%x\n", status);
+	return status;
+}
+
+/*
+ *  ======== PROC_Ctrl ========
+ *  Purpose:
+ *      Pass control information to the GPP device driver managing the
+ *      DSP processor.
+ *
+ *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
+ *      application developer's API.
+ *      Call the WMD_ICOTL Fxn with the Argument This is a Synchronous
+ *      Operation. arg can be null.
+ */
+DSP_STATUS PROC_Ctrl(DSP_HPROCESSOR hProcessor, u32 dwCmd,
+		    IN struct DSP_CBDATA *arg)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = hProcessor;
+	u32 timeout = 0;
+
+	DBC_Require(cRefs > 0);
+	GT_3trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_Ctrl, args:\n\thProcessor:"
+		 " 0x%x\n\tdwCmd: 0x%x\n\targ: 0x%x\n", hProcessor, dwCmd, arg);
+
+	if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		/* intercept PWR deep sleep command */
+		if (dwCmd == WMDIOCTL_DEEPSLEEP) {
+			timeout = arg->cbData;
+			status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
+		}
+		/* intercept PWR emergency sleep command */
+		else if (dwCmd == WMDIOCTL_EMERGENCYSLEEP) {
+			timeout = arg->cbData;
+			status = PWR_SleepDSP(PWR_EMERGENCYDEEPSLEEP, timeout);
+		} else if (dwCmd == PWR_DEEPSLEEP) {
+			/* timeout = arg->cbData; */
+			status = PWR_SleepDSP(PWR_DEEPSLEEP, timeout);
+		}
+		/* intercept PWR wake commands */
+		else if (dwCmd == WMDIOCTL_WAKEUP) {
+			timeout = arg->cbData;
+			status = PWR_WakeDSP(timeout);
+		} else if (dwCmd == PWR_WAKEUP) {
+			/* timeout = arg->cbData; */
+			status = PWR_WakeDSP(timeout);
+		} else
+		    if (DSP_SUCCEEDED
+			((*pProcObject->pIntfFxns->pfnDevCntrl)
+				(pProcObject->hWmdContext, dwCmd, arg))) {
+			status = DSP_SOK;
+		} else {
+			status = DSP_EFAIL;
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Ctrl: Failed \n");
+		}
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Ctrl: InValid Processor Handle \n");
+	}
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Ctrl, 0x%x\n",
+		 status);
+	return status;
+}
+
+/*
+ *  ======== PROC_Detach ========
+ *  Purpose:
+ *      Destroys the  Processor Object. Removes the notification from the Dev
+ *      List.
+ */
+DSP_STATUS PROC_Detach(DSP_HPROCESSOR hProcessor)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+#ifndef RES_CLEANUP_DISABLE
+	HANDLE hDRVObject;
+	HANDLE hProcess;
+	DSP_STATUS res_status = DSP_SOK;
+	struct PROCESS_CONTEXT   *pPctxt = NULL;
+#endif
+	DBC_Require(cRefs > 0);
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Detach, args:\n\t"
+		 "hProcessor:  0x%x\n", hProcessor);
+
+	if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		/* Notify the Client */
+		NTFY_Notify(pProcObject->hNtfy, DSP_PROCESSORDETACH);
+		/* Remove the notification memory */
+		if (pProcObject->hNtfy)
+			NTFY_Delete(pProcObject->hNtfy);
+
+		/* Remove the Proc from the DEV List */
+		(void)DEV_RemoveProcObject(pProcObject->hDevObject,
+			(u32)pProcObject);
+		/* Free the Processor Object */
+		MEM_FreeObject(pProcObject);
+#ifndef RES_CLEANUP_DISABLE
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDRVObject, REG_DRV_OBJECT);
+	/* res_status = CFG_GetObject(REG_DRV_OBJECT, (u32*)&hDRVObject); */
+	if (DSP_SUCCEEDED(res_status)) {
+		DRV_GetProcContext(hProcess, hDRVObject, &pPctxt, NULL, 0);
+		if (pPctxt != NULL)
+			pPctxt->hProcessor = NULL;
+	}
+#endif
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Detach: InValid Processor Handle \n");
+	}
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Detach, 0x%x\n",
+		 status);
+	return status;
+}
+
+/*
+ *  ======== PROC_EnumNodes ========
+ *  Purpose:
+ *      Enumerate and get configuration information about nodes allocated
+ *      on a DSP processor.
+ */
+DSP_STATUS PROC_EnumNodes(DSP_HPROCESSOR hProcessor, OUT DSP_HNODE *aNodeTab,
+			 IN u32 uNodeTabSize, OUT u32 *puNumNodes,
+			 OUT u32 *puAllocated)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct NODE_MGR *hNodeMgr = NULL;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(aNodeTab != NULL || uNodeTabSize == 0);
+	DBC_Require(puNumNodes != NULL);
+	DBC_Require(puAllocated != NULL);
+
+	GT_5trace(PROC_DebugMask, GT_ENTER, "Entered PROC_EnumNodes, args:\n\t"
+			"hProcessor:  0x%x\n\taNodeTab:  0x%x\n\tuNodeTabSize: "
+			" 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n",
+			hProcessor, aNodeTab, uNodeTabSize, puNumNodes,
+			puAllocated);
+	if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		if (DSP_SUCCEEDED(DEV_GetNodeManager(pProcObject->hDevObject,
+				 &hNodeMgr))) {
+			if (hNodeMgr) {
+				status = NODE_EnumNodes(hNodeMgr, aNodeTab,
+							uNodeTabSize,
+							puNumNodes,
+							puAllocated);
+			}
+		}
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_EnumNodes: "
+			 "InValid Processor Handle \n");
+	}
+	GT_6trace(PROC_DebugMask, GT_ENTER, "Exit PROC_EnumNodes, args:\n\t"
+			"hProcessor:  0x%x\n\taNodeTab:  0x%x\n\tuNodeTabSize: "
+			" 0x%x\n\t puNumNodes 0x%x\n\t puAllocated: 0x%x\n\t "
+			"status: 0x%x \n", hProcessor, aNodeTab, uNodeTabSize,
+			puNumNodes, puAllocated, status);
+
+	return status;
+}
+
+/*
+ *  ======== PROC_FlushMemory ========
+ *  Purpose:
+ *     Flush cache
+ */
+DSP_STATUS PROC_FlushMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
+			   u32 ulSize, u32 ulFlags)
+{
+	/* Keep STATUS here for future additions to this function */
+	DSP_STATUS status = DSP_SOK;
+	enum DSP_FLUSHTYPE FlushMemType = PROC_WRITEBACK_INVALIDATE_MEM;
+	DBC_Require(cRefs > 0);
+
+	GT_4trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_FlushMemory, args:\n\t"
+		 "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x, ulFlags 0x%x\n",
+		 hProcessor, pMpuAddr, ulSize, ulFlags);
+
+	MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
+
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_FlushMemory [0x%x]",
+		 status);
+
+	return status;
+}
+
+
+/*
+ *  ======== PROC_InvalidateMemory ========
+ *  Purpose:
+ *     Invalidates the memory specified
+ */
+DSP_STATUS PROC_InvalidateMemory(DSP_HPROCESSOR hProcessor, void *pMpuAddr,
+				u32 ulSize)
+{
+	/* Keep STATUS here for future additions to this function */
+	DSP_STATUS status = DSP_SOK;
+	enum DSP_FLUSHTYPE FlushMemType = PROC_INVALIDATE_MEM;
+	DBC_Require(cRefs > 0);
+	GT_3trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_InvalidateMemory, args:\n\t"
+		 "hProcessor: 0x%x pMpuAddr: 0x%x ulSize 0x%x\n", hProcessor,
+		 pMpuAddr, ulSize);
+	MEM_FlushCache(pMpuAddr, ulSize, FlushMemType);
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Leaving PROC_InvalidateMemory [0x%x]", status);
+	return status;
+}
+
+/*
+ *  ======== PROC_GetResourceInfo ========
+ *  Purpose:
+ *      Enumerate the resources currently available on a processor.
+ */
+DSP_STATUS PROC_GetResourceInfo(DSP_HPROCESSOR hProcessor, u32 uResourceType,
+				OUT struct DSP_RESOURCEINFO *pResourceInfo,
+				u32 uResourceInfoSize)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct NODE_MGR *hNodeMgr = NULL;
+	struct NLDR_OBJECT *hNldr = NULL;
+	struct RMM_TargetObj *rmm = NULL;
+	struct IO_MGR *hIOMgr = NULL;		/* IO manager handle */
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pResourceInfo != NULL);
+	DBC_Require(uResourceInfoSize >= sizeof(struct DSP_RESOURCEINFO));
+
+	GT_4trace(PROC_DebugMask, GT_ENTER, "Entered PROC_GetResourceInfo,\n\t"
+		 "hProcessor:  0x%x\n\tuResourceType:  0x%x\n\tpResourceInfo:"
+		 " 0x%x\n\t uResourceInfoSize 0x%x\n", hProcessor,
+		 uResourceType, pResourceInfo, uResourceInfoSize);
+	if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_GetResourceInfo: InValid "
+			 "Processor Handle \n");
+		goto func_end;
+	}
+	switch (uResourceType) {
+	case DSP_RESOURCE_DYNDARAM:
+	case DSP_RESOURCE_DYNSARAM:
+	case DSP_RESOURCE_DYNEXTERNAL:
+	case DSP_RESOURCE_DYNSRAM:
+		if (DSP_FAILED(DEV_GetNodeManager(pProcObject->hDevObject,
+		   &hNodeMgr)))
+			goto func_end;
+
+		if (DSP_SUCCEEDED(NODE_GetNldrObj(hNodeMgr, &hNldr))) {
+			if (DSP_SUCCEEDED(NLDR_GetRmmManager(hNldr, &rmm))) {
+				DBC_Assert(rmm != NULL);
+				status = DSP_EVALUE;
+				if (RMM_stat(rmm,
+				   (enum DSP_MEMTYPE)uResourceType,
+				   (struct DSP_MEMSTAT *)&(pResourceInfo->
+				   result.memStat)))
+					status = DSP_SOK;
+			}
+		}
+		break;
+	case DSP_RESOURCE_PROCLOAD:
+		status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
+		status = pProcObject->pIntfFxns->pfnIOGetProcLoad(hIOMgr,
+			 (struct DSP_PROCLOADSTAT *)&(pResourceInfo->
+			 result.procLoadStat));
+		if (DSP_FAILED(status)) {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+			"Error in procLoadStat function 0x%x\n", status);
+		}
+		break;
+	default:
+		status = DSP_EFAIL;
+		break;
+	}
+func_end:
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_GetResourceInfo, "
+		 "status 0x%x\n", status);
+	return status;
+}
+
+/*
+ *  ======== PROC_Exit ========
+ *  Purpose:
+ *      Decrement reference count, and free resources when reference count is
+ *      0.
+ */
+void CDECL PROC_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(PROC_DebugMask, GT_5CLASS,
+		 "Entered PROC_Exit, ref count:0x%x\n",	cRefs);
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== PROC_GetDevObject ========
+ *  Purpose:
+ *      Return the Dev Object handle for a given Processor.
+ *
+ */
+DSP_STATUS PROC_GetDevObject(DSP_HPROCESSOR hProcessor,
+			     struct DEV_OBJECT **phDevObject)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(phDevObject != NULL);
+
+	if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		*phDevObject = pProcObject->hDevObject;
+		status = DSP_SOK;
+	} else {
+		*phDevObject = 0;
+	}
+
+	DBC_Ensure((DSP_SUCCEEDED(status) && *phDevObject > 0) ||
+		   (DSP_FAILED(status) && *phDevObject == 0));
+
+	return status;
+}
+
+/*
+ *  ======== PROC_GetState ========
+ *  Purpose:
+ *      Report the state of the specified DSP processor.
+ */
+DSP_STATUS PROC_GetState(DSP_HPROCESSOR hProcessor,
+			OUT struct DSP_PROCESSORSTATE *pProcStatus,
+			u32 uStateInfoSize)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	BRD_STATUS brdStatus;
+	struct DEH_MGR *hDehMgr;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pProcStatus != NULL);
+	DBC_Require(uStateInfoSize >= sizeof(struct DSP_PROCESSORSTATE));
+
+	GT_3trace(PROC_DebugMask, GT_ENTER, "Entering PROC_GetState, args:\n\t"
+		 "pProcStatus: 0x%x\n\thProcessor: 0x%x\n\t uStateInfoSize"
+		 " 0x%x\n", pProcStatus, hProcessor, uStateInfoSize);
+	if (MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		/* First, retrieve BRD state information */
+		if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+		   (pProcObject->hWmdContext, &brdStatus))) {
+			switch (brdStatus) {
+			case BRD_STOPPED:
+				pProcStatus->iState = PROC_STOPPED;
+				break;
+			case BRD_RUNNING:
+				pProcStatus->iState = PROC_RUNNING;
+				break;
+			case BRD_LOADED:
+				pProcStatus->iState = PROC_LOADED;
+				break;
+			default:
+				status = DSP_EFAIL;
+				break;
+			}
+		} else {
+			status = DSP_EFAIL;
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_GetState: General Failure"
+				 " to read the PROC Status \n");
+		}
+		/* Next, retrieve error information, if any */
+		status = DEV_GetDehMgr(pProcObject->hDevObject, &hDehMgr);
+		if (DSP_SUCCEEDED(status) && hDehMgr) {
+			status = (*pProcObject->pIntfFxns->pfnDehGetInfo)
+				 (hDehMgr, &(pProcStatus->errInfo));
+			if (DSP_FAILED(status)) {
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					 "PROC_GetState: Failed "
+					 "retrieve exception info.\n");
+			}
+		} else {
+			status = DSP_EFAIL;
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_GetState: Failed to "
+				 "retrieve DEH handle.\n");
+		}
+	} else {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_GetState:InValid Processor Handle \n");
+	}
+	GT_2trace(PROC_DebugMask, GT_ENTER,
+		 "Exiting PROC_GetState, results:\n\t"
+		 "status:  0x%x\n\tpProcStatus: 0x%x\n", status, *pProcStatus);
+	return status;
+}
+
+/*
+ *  ======== PROC_GetTrace ========
+ *  Purpose:
+ *      Retrieve the current contents of the trace buffer, located on the
+ *      Processor.  Predefined symbols for the trace buffer must have been
+ *      configured into the DSP executable.
+ *  Details:
+ *      We support using the symbols SYS_PUTCBEG and SYS_PUTCEND to define a
+ *      trace buffer, only.  Treat it as an undocumented feature.
+ *      This call is destructive, meaning the processor is placed in the monitor
+ *      state as a result of this function.
+ */
+DSP_STATUS PROC_GetTrace(DSP_HPROCESSOR hProcessor, u8 *pBuf, u32 uMaxSize)
+{
+	DSP_STATUS status;
+	status = DSP_ENOTIMPL;
+	return status;
+}
+
+/*
+ *  ======== PROC_Init ========
+ *  Purpose:
+ *      Initialize PROC's private state, keeping a reference count on each call
+ */
+bool CDECL PROC_Init(void)
+{
+	bool fRetval = true;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+		/* Set the Trace mask */
+		DBC_Assert(!PROC_DebugMask.flags);
+		GT_create(&PROC_DebugMask, "PR");  /* "PR" for Processor */
+
+	}
+
+	if (fRetval)
+		cRefs++;
+
+	GT_1trace(PROC_DebugMask, GT_5CLASS,
+		 "Entered PROC_Init, ref count:0x%x\n",	cRefs);
+	DBC_Ensure((fRetval && (cRefs > 0)) || (!fRetval && (cRefs >= 0)));
+
+	return fRetval;
+}
+
+/*
+ *  ======== PROC_Load ========
+ *  Purpose:
+ *      Reset a processor and load a new base program image.
+ *      This will be an OEM-only function, and not part of the DSP/BIOS Bridge
+ *      application developer's API.
+ */
+DSP_STATUS PROC_Load(DSP_HPROCESSOR hProcessor, IN CONST s32 iArgc,
+		    IN CONST char **aArgv, IN CONST char **aEnvp)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct IO_MGR *hIOMgr;		/* IO manager handle */
+	struct MSG_MGR *hMsgMgr;
+	struct COD_MANAGER *hCodMgr;	/* Code manager handle */
+	char *pargv0;		/* temp argv[0] ptr */
+	char **newEnvp;		/* Updated envp[] array. */
+	char szProcID[MAXPROCIDLEN];	/* Size of "PROC_ID=<n>" */
+	s32 cEnvp;		/* Num elements in envp[]. */
+	s32 cNewEnvp;		/* "  " in newEnvp[]     */
+	s32 nProcID = 0;	/* Anticipate MP version. */
+	struct DCD_MANAGER *hDCDHandle;
+	struct DMM_OBJECT *hDmmMgr;
+	u32 dwExtEnd;
+	u32 uProcId;
+#ifdef DEBUG
+	BRD_STATUS uBrdState;
+#endif
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+	struct timeval tv1;
+	struct timeval tv2;
+#endif
+	DBC_Require(cRefs > 0);
+	DBC_Require(iArgc > 0);
+	DBC_Require(aArgv != NULL);
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+	do_gettimeofday(&tv1);
+#endif
+	GT_2trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Load, args:\n\t"
+		 "hProcessor:  0x%x\taArgv: 0x%x\n", hProcessor, aArgv[0]);
+	/* Call the WMD_BRD_Load Fxn */
+	if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_1CLASS,
+			 "PROC_Load: Invalid Processor Handle..\n");
+		goto func_end;
+	}
+	if (pProcObject->bIsAlreadyAttached) {
+		status = DSP_EATTACHED;
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Load  Abort becuase a GPP "
+			 "Client is already attached status 0x%x \n", status);
+		goto func_end;
+	}
+	if (DSP_FAILED(DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr))) {
+		status = DSP_EFAIL;
+		GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: DSP_FAILED in "
+			 "DEV_GetCodMgr status 0x%x \n", status);
+		goto func_end;
+	}
+	status = PROC_Stop(hProcessor);
+	if (DSP_FAILED(status)) {
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Load: DSP_FAILED to Place the"
+			 " Processor in Stop Mode(PROC_STOP) status 0x%x \n",
+			 status);
+		goto func_end;
+	}
+	/* Place the board in the monitor state. */
+	status = PROC_Monitor(hProcessor);
+	if (DSP_FAILED(status)) {
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Load: DSP_FAILED to Place the"
+			 " Processor in Monitor Mode(PROC_IDLE) status 0x%x\n",
+			 status);
+		goto func_end;
+	}
+	/* Save ptr to  original argv[0]. */
+	pargv0 = (char *)aArgv[0];
+	/*Prepend "PROC_ID=<nProcID>"to envp array for target.*/
+	cEnvp = GetEnvpCount((char **)aEnvp);
+	cNewEnvp = (cEnvp ? (cEnvp + 1) : (cEnvp + 2));
+	newEnvp = MEM_Calloc(cNewEnvp * sizeof(char **), MEM_PAGED);
+	if (newEnvp) {
+		status = snprintf(szProcID, MAXPROCIDLEN, PROC_ENVPROCID,
+				    nProcID);
+		if (status == -1) {
+			GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Load: "
+				 "Proc ID string overflow \n");
+			status = DSP_EFAIL;
+		} else {
+			newEnvp = PrependEnvp(newEnvp, (char **)aEnvp, cEnvp,
+					     cNewEnvp, szProcID);
+			/* Get the DCD Handle */
+			status = MGR_GetDCDHandle(pProcObject->hMgrObject,
+						 (u32 *)&hDCDHandle);
+			if (DSP_SUCCEEDED(status)) {
+				/*  Before proceeding with new load,
+				 *  check if a previously registered COFF
+				 *  exists.
+				 *  If yes, unregister nodes in previously
+				 *  registered COFF.  If any error occurred,
+				 *  set previously registered COFF to NULL.  */
+				if (pProcObject->g_pszLastCoff != NULL) {
+					status = DCD_AutoUnregister(hDCDHandle,
+						 pProcObject->g_pszLastCoff);
+					/* Regardless of auto unregister status,
+					 *  free previously allocated
+					 *  memory.  */
+					MEM_Free(pProcObject->g_pszLastCoff);
+					pProcObject->g_pszLastCoff = NULL;
+				}
+			}
+			/* On success, do COD_OpenBase() */
+			status = COD_OpenBase(hCodMgr, (char *)aArgv[0],
+					     COD_SYMB);
+			if (DSP_FAILED(status)) {
+				GT_1trace(PROC_DebugMask, GT_7CLASS,
+					 "PROC_Load: COD_OpenBase "
+					 "failed (0x%x)\n", status);
+			}
+		}
+	} else {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 " PROC_Load:Out of Memory \n");
+		status = DSP_EMEMORY;
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Auto-register data base */
+		/* Get the DCD Handle */
+		status = MGR_GetDCDHandle(pProcObject->hMgrObject,
+					 (u32 *)&hDCDHandle);
+		if (DSP_SUCCEEDED(status)) {
+			/*  Auto register nodes in specified COFF
+			 *  file.  If registration did not fail,
+			 *  (status = DSP_SOK or DSP_EDCDNOAUTOREGISTER)
+			 *  save the name of the COFF file for
+			 *  de-registration in the future.  */
+			status = DCD_AutoRegister(hDCDHandle, (char *)aArgv[0]);
+			if (status == DSP_EDCDNOAUTOREGISTER) {
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					  "PROC_Load: No Auto "
+					  "Register section.  Proceeding..\n");
+				status = DSP_SOK;
+			}
+			if (DSP_FAILED(status)) {
+				status = DSP_EFAIL;
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					  "PROC_Load: Failed to "
+					  "Auto Register..\n");
+			} else {
+				DBC_Assert(pProcObject->g_pszLastCoff == NULL);
+				/* Allocate memory for pszLastCoff */
+				pProcObject->g_pszLastCoff = MEM_Calloc(
+					(CSL_Strlen((char *)aArgv[0]) + 1),
+					MEM_PAGED);
+				/* If memory allocated, save COFF file name*/
+				if (pProcObject->g_pszLastCoff) {
+					CSL_Strcpyn(pProcObject->g_pszLastCoff,
+						(char *)aArgv[0],
+						(CSL_Strlen((char *)aArgv[0])
+						+ 1));
+				}
+			}
+		}
+	}
+	/* Update shared memory address and size */
+	if (DSP_SUCCEEDED(status)) {
+		/*  Create the message manager. This must be done
+		 *  before calling the IOOnLoaded function.  */
+		DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+		if (!hMsgMgr) {
+			status = MSG_Create(&hMsgMgr, pProcObject->hDevObject,
+					   (MSG_ONEXIT)NODE_OnExit);
+			DBC_Assert(DSP_SUCCEEDED(status));
+			DEV_SetMsgMgr(pProcObject->hDevObject, hMsgMgr);
+		}
+		if (status == DSP_ENOTIMPL) {
+			/* It's OK not to have a message manager */
+			status = DSP_SOK;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Set the Device object's message manager */
+		status = DEV_GetIOMgr(pProcObject->hDevObject, &hIOMgr);
+		DBC_Assert(DSP_SUCCEEDED(status));
+		status = (*pProcObject->pIntfFxns->pfnIOOnLoaded)(hIOMgr);
+		if (status == DSP_ENOTIMPL) {
+			/* Ok not to implement this function */
+			status = DSP_SOK;
+		} else {
+			if (DSP_FAILED(status)) {
+				GT_1trace(PROC_DebugMask, GT_7CLASS,
+					  "PROC_Load: Failed to get shared "
+					  "memory or message buffer address "
+					  "from COFF status 0x%x\n", status);
+				status = DSP_EFAIL;
+			}
+		}
+	} else {
+		status = DSP_EFAIL;
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			  "PROC_Load: DSP_FAILED in "
+			  "MSG_Create status 0x%x\n", status);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Now, attempt to load an exec: */
+
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	/* Boost the OPP level to Maximum level supported by baseport*/
+	if (constraint_set(mpu_constraint_handle, CO_VDD1_OPP5) != 0)
+		GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
+			  "Constraint set of %d failed\n", CO_VDD1_OPP5);
+	else
+		GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
+			 "Constraint set of %d passed\n", CO_VDD1_OPP5);
+#endif
+#endif
+		status = COD_LoadBase(hCodMgr, iArgc, (char **)aArgv,
+				     DEV_BrdWriteFxn,
+				     pProcObject->hDevObject, NULL);
+		if (DSP_FAILED(status)) {
+			if (status == COD_E_OPENFAILED) {
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					"PROC_Load:Failure to Load the EXE\n");
+			}
+			if (status == COD_E_SYMBOLNOTFOUND) {
+				GT_0trace(PROC_DebugMask, GT_7CLASS,
+					"PROC_Load:Could not parse the file\n");
+			} else {
+				GT_1trace(PROC_DebugMask, GT_7CLASS,
+					 "PROC_Load: DSP_FAILED in "
+					 "COD_Load  status 0x%x \n", status);
+			}
+		}
+#ifndef CONFIG_DISABLE_BRIDGE_PM
+#ifndef CONFIG_DISABLE_BRIDGE_DVFS
+	/* Requesting the lowest opp supported by baseport*/
+		if (constraint_set(mpu_constraint_handle, CO_VDD1_OPP1) != 0)
+			GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
+				 "Constraint setting of %d failed\n",
+				 CO_VDD1_OPP1);
+		else
+			GT_1trace(PROC_DebugMask, GT_4CLASS, "PROC_Load:"
+				 "Constraint setting  of %d passed\n",
+				 CO_VDD1_OPP1);
+#endif
+#endif
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Update the Processor status to loaded */
+		status = (*pProcObject->pIntfFxns->pfnBrdSetState)
+			 (pProcObject->hWmdContext, BRD_LOADED);
+		if (DSP_SUCCEEDED(status)) {
+			pProcObject->sState = PROC_LOADED;
+			if (pProcObject->hNtfy) {
+				PROC_NotifyClients(pProcObject,
+						 DSP_PROCESSORSTATECHANGE);
+			}
+		} else {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Load, pfnBrdSetState "
+				 "failed: 0x%x\n", status);
+			status = DSP_EFAIL;
+		}
+	}
+	if (DSP_SUCCEEDED(status)) {
+		status = PROC_GetProcessorId(hProcessor, &uProcId);
+		if (uProcId == DSP_UNIT) {
+			/* Use all available DSP address space after EXTMEM
+			 * for DMM */
+			if (DSP_SUCCEEDED(status)) {
+				status = COD_GetSymValue(hCodMgr, EXTEND,
+								&dwExtEnd);
+				if (DSP_FAILED(status)) {
+					GT_1trace(PROC_DebugMask, GT_7CLASS,
+						 "PROC_Load: Failed on "
+						 "COD_GetSymValue %s.\n",
+						 EXTEND);
+				}
+			}
+			/* Reset DMM structs and add an initial free chunk*/
+			if (DSP_SUCCEEDED(status)) {
+				status = DEV_GetDmmMgr(pProcObject->hDevObject,
+						      &hDmmMgr);
+				if (DSP_SUCCEEDED(status)) {
+					/* Set dwExtEnd to DMM START u8
+					  * address */
+					dwExtEnd = (dwExtEnd + 1) * DSPWORDSIZE;
+					 /* DMM memory is from EXT_END */
+					status = DMM_CreateTables(hDmmMgr,
+						dwExtEnd, DMMPOOLSIZE);
+				}
+			}
+		}
+	}
+	/* Restore the original argv[0] */
+	MEM_Free(newEnvp);
+	aArgv[0] = pargv0;
+#ifdef DEBUG
+	if (DSP_SUCCEEDED(status)) {
+		if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+		   (pProcObject->hWmdContext, &uBrdState))) {
+			GT_0trace(PROC_DebugMask, GT_1CLASS,
+				 "PROC_Load: Processor Loaded\n");
+			DBC_Assert(uBrdState == BRD_LOADED);
+		}
+	}
+#endif
+func_end:
+#ifdef DEBUG
+	if (DSP_FAILED(status)) {
+		GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Load: "
+			 "Processor Load Failed.\n");
+
+	}
+#endif
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Exiting PROC_Load, status:  0x%x\n", status);
+	DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState == PROC_LOADED)
+		   || DSP_FAILED(status));
+#ifdef OPT_LOAD_TIME_INSTRUMENTATION
+	do_gettimeofday(&tv2);
+	if (tv2.tv_usec < tv1.tv_usec) {
+		tv2.tv_usec += 1000000;
+		tv2.tv_sec--;
+	}
+	GT_2trace(PROC_DebugMask, GT_1CLASS,
+			"Proc_Load: time to load %d sec and %d usec \n",
+		    tv2.tv_sec - tv1.tv_sec, tv2.tv_usec - tv1.tv_usec);
+#endif
+	return status;
+}
+
+/*
+ *  ======== PROC_Map ========
+ *  Purpose:
+ *      Maps a MPU buffer to DSP address space.
+ */
+DSP_STATUS PROC_Map(DSP_HPROCESSOR hProcessor, void *pMpuAddr, u32 ulSize,
+		   void *pReqAddr, void **ppMapAddr, u32 ulMapAttr)
+{
+	u32 vaAlign;
+	u32 paAlign;
+	struct DMM_OBJECT *hDmmMgr;
+	u32 sizeAlign;
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+#ifndef RES_CLEANUP_DISABLE
+	    HANDLE	      hProcess;
+	    HANDLE	      pCtxt = NULL;
+	    HANDLE	      hDrvObject;
+	    HANDLE	      dmmRes;
+		DSP_STATUS res_status = DSP_SOK;
+#endif
+
+	GT_6trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Map, args:\n\t"
+		 "hProcessor %x, pMpuAddr %x, ulSize %x, pReqAddr %x, "
+		 "ulMapAttr %x, ppMapAddr %x\n", hProcessor, pMpuAddr, ulSize,
+		 pReqAddr, ulMapAttr, ppMapAddr);
+	/* Calculate the page-aligned PA, VA and size */
+	vaAlign = PG_ALIGN_LOW((u32) pReqAddr, PG_SIZE_4K);
+	paAlign = PG_ALIGN_LOW((u32) pMpuAddr, PG_SIZE_4K);
+	sizeAlign = PG_ALIGN_HIGH(ulSize + (u32)pMpuAddr - paAlign,
+				 PG_SIZE_4K);
+
+	GT_3trace(PROC_DebugMask, GT_ENTER, "PROC_Map: vaAlign %x, paAlign %x, "
+		 "sizeAlign %x\n", vaAlign, paAlign, sizeAlign);
+
+	status = DMM_GetHandle(pProcObject, &hDmmMgr);
+	if (DSP_FAILED(status)) {
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Map: Failed to get DMM Mgr "
+			 "handle: 0x%x\n", status);
+	} else {
+		status = DMM_MapMemory(hDmmMgr, vaAlign, sizeAlign);
+	}
+	/* Add mapping to the page tables. */
+	if (DSP_SUCCEEDED(status)) {
+
+		status = (*pProcObject->pIntfFxns->pfnBrdMemMap)
+			(pProcObject->hWmdContext, paAlign, vaAlign, sizeAlign,
+			ulMapAttr);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* Mapped address = MSB of VA | LSB of PA */
+		*ppMapAddr = (void *) (vaAlign | ((u32) pMpuAddr &
+			     (PG_SIZE_4K - 1)));
+	} else {
+		DMM_UnMapMemory(hDmmMgr, vaAlign, &sizeAlign);
+	}
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_SUCCEEDED(status)) {
+		/* Update the node and stream resource status */
+		PRCS_GetCurrentHandle(&hProcess);
+		res_status = CFG_GetObject((u32 *)&hDrvObject,
+					  REG_DRV_OBJECT);
+		if (DSP_SUCCEEDED(res_status)) {
+			if (DRV_GetProcContext(hProcess, hDrvObject, &pCtxt,
+			   NULL, (u32) pMpuAddr) != DSP_ENOTFOUND) {
+				DRV_InsertDMMResElement(&dmmRes, pCtxt);
+				DRV_UpdateDMMResElement(dmmRes, (u32) pMpuAddr,
+						ulSize, (u32) pReqAddr,
+						(u32)*ppMapAddr, hProcessor);
+			}
+		}
+	}
+#endif
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_Map [0x%x]", status);
+	return status;
+}
+
+/*
+ *  ======== PROC_RegisterNotify ========
+ *  Purpose:
+ *      Register to be notified of specific processor events.
+ */
+DSP_STATUS PROC_RegisterNotify(DSP_HPROCESSOR hProcessor, u32 uEventMask,
+			      u32 uNotifyType, struct DSP_NOTIFICATION
+			      *hNotification)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct DEH_MGR *hDehMgr;
+
+	DBC_Require(hNotification != NULL);
+	DBC_Require(cRefs > 0);
+
+	GT_4trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_RegisterNotify, args:\n\t"
+		 "hProcessor:  0x%x\n\tuEventMask:  0x%x\n\tuNotifyMask:"
+		 " 0x%x\n\t hNotification 0x%x\n", hProcessor, uEventMask,
+		 uNotifyType, hNotification);
+
+	/* Check processor handle */
+	if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_RegsiterNotify Invalid "
+			 "ProcessorHandle 0x%x\n", hProcessor);
+		goto func_end;
+	}
+	/* Check if event mask is a valid processor related event */
+	if (uEventMask & ~(DSP_PROCESSORSTATECHANGE | DSP_PROCESSORATTACH |
+	   DSP_PROCESSORDETACH | DSP_PROCESSORRESTART | DSP_MMUFAULT |
+	   DSP_SYSERROR))
+		status = DSP_EVALUE;
+
+	/* Check if notify type is valid */
+	if (uNotifyType != DSP_SIGNALEVENT)
+		status = DSP_EVALUE;
+
+	if (DSP_SUCCEEDED(status)) {
+		/* * If event mask is not DSP_SYSERROR or DSP_MMUFAULT,
+		 * then register event immediately.  */
+		if (uEventMask & ~(DSP_SYSERROR | DSP_MMUFAULT)) {
+			status = NTFY_Register(pProcObject->hNtfy,
+				 hNotification,	uEventMask, uNotifyType);
+			/* * Special case alert, special case alert!
+			 * If we're trying to *deregister* (i.e. uEventMask
+			 * is 0), a DSP_SYSERROR or DSP_MMUFAULT notification,
+			 * we have to deregister with the DEH manager.
+			 * There's no way to know, based on uEventMask which
+			 * manager the notification event was registered with,
+			 * so if we're trying to deregister and NTFY_Register
+			 * failed, we'll give the deh manager a shot.
+			 */
+			if ((uEventMask == 0) && DSP_FAILED(status)) {
+				status = DEV_GetDehMgr(pProcObject->hDevObject,
+					 &hDehMgr);
+				DBC_Assert(pProcObject->pIntfFxns->
+					   pfnDehRegisterNotify);
+				status = (*pProcObject->pIntfFxns->
+					 pfnDehRegisterNotify)
+					 (hDehMgr, uEventMask, uNotifyType,
+					 hNotification);
+			}
+		} else {
+			status = DEV_GetDehMgr(pProcObject->hDevObject,
+					      &hDehMgr);
+			DBC_Assert(pProcObject->pIntfFxns->
+				  pfnDehRegisterNotify);
+			status = (*pProcObject->pIntfFxns->pfnDehRegisterNotify)
+				 (hDehMgr, uEventMask, uNotifyType,
+				 hNotification);
+			if (DSP_FAILED(status))
+				status = DSP_EFAIL;
+
+		}
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== PROC_ReserveMemory ========
+ *  Purpose:
+ *      Reserve a virtually contiguous region of DSP address space.
+ */
+DSP_STATUS PROC_ReserveMemory(DSP_HPROCESSOR hProcessor, u32 ulSize,
+			     void **ppRsvAddr)
+{
+	struct DMM_OBJECT *hDmmMgr;
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+	GT_3trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_ReserveMemory, args:\n\t"
+		 "hProcessor: 0x%x ulSize: 0x%x ppRsvAddr: 0x%x\n", hProcessor,
+		 ulSize, ppRsvAddr);
+	status = DMM_GetHandle(pProcObject, &hDmmMgr);
+	if (DSP_FAILED(status)) {
+		GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_ReserveMemory: "
+			 "Failed to get DMM Mgr handle: 0x%x\n", status);
+	} else {
+		status = DMM_ReserveMemory(hDmmMgr, ulSize, (u32 *)ppRsvAddr);
+	}
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Leaving PROC_ReserveMemory [0x%x]",
+		 status);
+	return status;
+}
+
+/*
+ *  ======== PROC_Start ========
+ *  Purpose:
+ *      Start a processor running.
+ */
+DSP_STATUS PROC_Start(DSP_HPROCESSOR hProcessor)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct COD_MANAGER *hCodMgr;	/* Code manager handle    */
+	u32 dwDspAddr;	/* Loaded code's entry point.    */
+#ifdef DEBUG
+	BRD_STATUS uBrdState;
+#endif
+	DBC_Require(cRefs > 0);
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Start, args:\n\t"
+		 "hProcessor:  0x%x\n", hProcessor);
+	if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Start :InValid Handle \n");
+		goto func_end;
+	}
+	/* Call the WMD_BRD_Start */
+	if (pProcObject->sState != PROC_LOADED) {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Start :Wrong state \n");
+		status = DSP_EWRONGSTATE;
+		goto func_end;
+	}
+	status = DEV_GetCodMgr(pProcObject->hDevObject, &hCodMgr);
+	if (DSP_FAILED(status)) {
+		status = DSP_EFAIL;
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "Processor Start DSP_FAILED "
+			 "in Getting DEV_GetCodMgr status 0x%x\n", status);
+		goto func_cont;
+	}
+	status = COD_GetEntry(hCodMgr, &dwDspAddr);
+	if (DSP_FAILED(status)) {
+		status = DSP_EFAIL;
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "Processor Start  DSP_FAILED in "
+			 "Getting COD_GetEntry status 0x%x\n", status);
+		goto func_cont;
+	}
+	status = (*pProcObject->pIntfFxns->pfnBrdStart)
+		 (pProcObject->hWmdContext, dwDspAddr);
+	if (DSP_FAILED(status)) {
+		status = DSP_EFAIL;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Start Failed to Start the board\n");
+		goto func_cont;
+	}
+	/* Call DEV_Create2 */
+	status = DEV_Create2(pProcObject->hDevObject);
+	if (DSP_SUCCEEDED(status)) {
+		pProcObject->sState = PROC_RUNNING;
+		/* Deep sleep switces off the peripheral clocks.
+		 * we just put the DSP CPU in idle in the idle loop.
+		 * so there is no need to send a command to DSP */
+
+		if (pProcObject->hNtfy) {
+			PROC_NotifyClients(pProcObject,
+					  DSP_PROCESSORSTATECHANGE);
+		}
+		GT_0trace(PROC_DebugMask, GT_1CLASS, "PROC_Start: Processor "
+			 "Started and running \n");
+	} else {
+		/* Failed to Create Node Manager and DISP Object
+		 * Stop the Processor from running. Put it in STOPPED State */
+		(void)(*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
+			hWmdContext);
+		status = DSP_EFAIL;
+		pProcObject->sState = PROC_STOPPED;
+		GT_0trace(PROC_DebugMask, GT_7CLASS, "PROC_Start "
+			 "Failed to Create the Node Manager\n");
+	}
+func_cont:
+#ifdef DEBUG
+	if (DSP_SUCCEEDED(status)) {
+		if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+		   (pProcObject->hWmdContext, &uBrdState))) {
+			GT_0trace(PROC_DebugMask, GT_1CLASS,
+				 "PROC_Start: Processor State is RUNNING \n");
+			DBC_Assert(uBrdState != BRD_HIBERNATION);
+		}
+	}
+#endif
+func_end:
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Exiting PROC_Start, status  0x%x\n", status);
+	DBC_Ensure((DSP_SUCCEEDED(status) && pProcObject->sState ==
+		  PROC_RUNNING)	|| DSP_FAILED(status));
+	return status;
+}
+
+/*
+ *  ======== PROC_Stop ========
+ *  Purpose:
+ *      Stop a processor running.
+ */
+DSP_STATUS PROC_Stop(DSP_HPROCESSOR hProcessor)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct MSG_MGR *hMsgMgr;
+	struct NODE_MGR *hNodeMgr;
+	DSP_HNODE hNode;
+	u32 uNodeTabSize = 1;
+	u32 uNumNodes = 0;
+	u32 uNodesAllocated = 0;
+#ifdef DEBUG
+	BRD_STATUS uBrdState;
+#endif
+	DBC_Require(cRefs > 0);
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Stop, args:\n\t"
+		 "hProcessor:  0x%x\n", hProcessor);
+	if (!MEM_IsValidHandle(pProcObject, PROC_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Stop :InValid Handle \n");
+		goto func_end;
+	}
+	/* check if there are any running nodes */
+	status = DEV_GetNodeManager(pProcObject->hDevObject, &hNodeMgr);
+	if (DSP_SUCCEEDED(status) && hNodeMgr) {
+		status = NODE_EnumNodes(hNodeMgr, &hNode, uNodeTabSize,
+					&uNumNodes, &uNodesAllocated);
+		if ((status == DSP_ESIZE) || (uNodesAllocated > 0)) {
+			GT_1trace(PROC_DebugMask, GT_7CLASS,
+				 "Can't stop device, Active "
+				 "nodes = 0x%x \n", uNodesAllocated);
+			return DSP_EWRONGSTATE;
+		}
+	}
+	/* Call the WMD_BRD_Stop */
+	/* It is OK to stop a device that does n't have nodes OR not started */
+	status = (*pProcObject->pIntfFxns->pfnBrdStop)(pProcObject->
+		 hWmdContext);
+	if (DSP_SUCCEEDED(status)) {
+		GT_0trace(PROC_DebugMask, GT_1CLASS,
+			 "PROC_Stop: Processor Stopped, "
+			 "i.e in standby mode \n");
+		pProcObject->sState = PROC_STOPPED;
+		/* Destory the Node Manager, MSG Manager */
+		if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
+			/* Destroy the MSG by calling MSG_Delete */
+			DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+			if (hMsgMgr) {
+				MSG_Delete(hMsgMgr);
+				DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
+			}
+#ifdef DEBUG
+			if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->
+			   pfnBrdStatus)(pProcObject->hWmdContext,
+			   &uBrdState))) {
+				GT_0trace(PROC_DebugMask, GT_1CLASS,
+					 "PROC_Monitor:Processor Stopped \n");
+				DBC_Assert(uBrdState == BRD_STOPPED);
+			}
+#endif
+		} else {
+			GT_0trace(PROC_DebugMask, GT_7CLASS,
+				 "PROC_Stop Couldn't delete node manager \n");
+		}
+	} else {
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Stop Failed to Stop the processor/device \n");
+	}
+func_end:
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Exiting PROC_Stop, status  0x%x\n",
+		 status);
+
+	return status;
+}
+
+/*
+ *  ======== PROC_UnMap ========
+ *  Purpose:
+ *      Removes a MPU buffer mapping from the DSP address space.
+ */
+DSP_STATUS PROC_UnMap(DSP_HPROCESSOR hProcessor, void *pMapAddr)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+	struct DMM_OBJECT *hDmmMgr;
+	u32 vaAlign;
+	u32 sizeAlign;
+#ifndef RES_CLEANUP_DISABLE
+	HANDLE	      hProcess;
+	HANDLE	      pCtxt = NULL;
+	HANDLE	      hDrvObject;
+	HANDLE	      dmmRes;
+	DSP_STATUS res_status = DSP_SOK;
+#endif
+	GT_2trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_UnMap, args:\n\thProcessor:"
+		 "0x%x pMapAddr: 0x%x\n", hProcessor, pMapAddr);
+
+	vaAlign = PG_ALIGN_LOW((u32) pMapAddr, PG_SIZE_4K);
+
+	status = DMM_GetHandle(hProcessor, &hDmmMgr);
+	if (DSP_FAILED(status)) {
+		GT_1trace(PROC_DebugMask, GT_7CLASS, "PROC_UnMap: "
+			 "Failed to get DMM Mgr handle: 0x%x\n", status);
+	} else {
+		/* Update DMM structures. Get the size to unmap.
+		 This function returns error if the VA is not mapped */
+		status = DMM_UnMapMemory(hDmmMgr, (u32) vaAlign, &sizeAlign);
+	}
+
+	/* Remove mapping from the page tables. */
+	if (DSP_SUCCEEDED(status)) {
+		status = (*pProcObject->pIntfFxns->pfnBrdMemUnMap)
+			 (pProcObject->hWmdContext, vaAlign, sizeAlign);
+	}
+#ifndef RES_CLEANUP_DISABLE
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		   "PROC_UnMap DRV_GetDMMResElement "
+		   "pMapAddr:[0x%x]", pMapAddr);
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Update the node and stream resource status */
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_FAILED(res_status))
+		goto func_end;
+
+	DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, (u32)pMapAddr);
+	if (pCtxt != NULL) {
+		if (DRV_GetDMMResElement((u32)pMapAddr, &dmmRes, pCtxt) !=
+		   DSP_ENOTFOUND)
+			DRV_RemoveDMMResElement(dmmRes, pCtxt);
+	}
+func_end:
+#endif
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Leaving PROC_UnMap [0x%x]", status);
+	return status;
+}
+
+/*
+ *  ======== PROC_UnReserveMemory ========
+ *  Purpose:
+ *      Frees a previously reserved region of DSP address space.
+ */
+DSP_STATUS PROC_UnReserveMemory(DSP_HPROCESSOR hProcessor, void *pRsvAddr)
+{
+	struct DMM_OBJECT *hDmmMgr;
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcessor;
+
+	GT_2trace(PROC_DebugMask, GT_ENTER,
+		 "Entered PROC_UnReserveMemory, args:\n\t"
+		 "hProcessor: 0x%x pRsvAddr: 0x%x\n", hProcessor, pRsvAddr);
+
+	status = DMM_GetHandle(pProcObject, &hDmmMgr);
+	if (DSP_FAILED(status))
+		GT_1trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Map: Failed to get DMM Mgr "
+			 "handle: 0x%x\n", status);
+	else
+		status = DMM_UnReserveMemory(hDmmMgr, (u32) pRsvAddr);
+
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Leaving PROC_UnReserveMemory [0x%x]",
+		 status);
+
+	return status;
+}
+
+/*
+ *  ======== = PROC_Monitor ======== ==
+ *  Purpose:
+ *      Place the Processor in Monitor State. This is an internal
+ *      function and a requirement before Processor is loaded.
+ *      This does a WMD_BRD_Stop, DEV_Destroy2 and WMD_BRD_Monitor.
+ *      In DEV_Destroy2 we delete the node manager.
+ *  Parameters:
+ *      hProcObject:    Handle to Processor Object
+ *  Returns:
+ *      DSP_SOK:	Processor placed in monitor mode.
+ *      !DSP_SOK:       Failed to place processor in monitor mode.
+ *  Requires:
+ *      Valid Processor Handle
+ *  Ensures:
+ *      Success:	ProcObject state is PROC_IDLE
+ */
+static DSP_STATUS PROC_Monitor(struct PROC_OBJECT *hProcObject)
+{
+	DSP_STATUS status = DSP_EFAIL;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProcObject;
+	struct MSG_MGR *hMsgMgr;
+#ifdef DEBUG
+	BRD_STATUS uBrdState;
+#endif
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+
+	GT_1trace(PROC_DebugMask, GT_ENTER, "Entered PROC_Monitor, args:\n\t"
+		 "hProcessor: 0x%x\n", hProcObject);
+	/* This is needed only when Device is loaded when it is
+	 * already 'ACTIVE' */
+	/* Destory the Node Manager, MSG Manager */
+	if (DSP_SUCCEEDED(DEV_Destroy2(pProcObject->hDevObject))) {
+		/* Destroy the MSG by calling MSG_Delete */
+		DEV_GetMsgMgr(pProcObject->hDevObject, &hMsgMgr);
+		if (hMsgMgr) {
+			MSG_Delete(hMsgMgr);
+			DEV_SetMsgMgr(pProcObject->hDevObject, NULL);
+		}
+	}
+	/* Place the Board in the Monitor State */
+	if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdMonitor)
+	   (pProcObject->hWmdContext))) {
+		status = DSP_SOK;
+#ifdef DEBUG
+		if (DSP_SUCCEEDED((*pProcObject->pIntfFxns->pfnBrdStatus)
+		   (pProcObject->hWmdContext, &uBrdState))) {
+			GT_0trace(PROC_DebugMask, GT_1CLASS,
+				 "PROC_Monitor:Processor in "
+				 "Monitor State\n");
+			DBC_Assert(uBrdState == BRD_IDLE);
+		}
+#endif
+	} else {
+		/* Monitor Failure */
+		GT_0trace(PROC_DebugMask, GT_7CLASS,
+			 "PROC_Monitor: Processor Could not"
+			 "be put in Monitor mode \n");
+	}
+	GT_1trace(PROC_DebugMask, GT_ENTER,
+		 "Exiting PROC_Monitor, status  0x%x\n",
+		 status);
+#ifdef DEBUG
+	DBC_Ensure((DSP_SUCCEEDED(status) && uBrdState == BRD_IDLE) ||
+		  DSP_FAILED(status));
+#endif
+	return status;
+}
+
+/*
+ *  ======== GetEnvpCount ========
+ *  Purpose:
+ *      Return the number of elements in the envp array, including the
+ *      terminating NULL element.
+ */
+static s32 GetEnvpCount(char **envp)
+{
+	s32 cRetval = 0;
+	if (envp) {
+		while (*envp++)
+			cRetval++;
+
+		cRetval += 1;	/* Include the terminating NULL in the count. */
+	}
+
+	return cRetval;
+}
+
+/*
+ *  ======== PrependEnvp ========
+ *  Purpose:
+ *      Prepend an environment variable=value pair to the new envp array, and
+ *      copy in the existing var=value pairs in the old envp array.
+ */
+static char **PrependEnvp(char **newEnvp, char **envp, s32 cEnvp, s32 cNewEnvp,
+			 char *szVar)
+{
+	char **ppEnvp = newEnvp;
+
+	DBC_Require(newEnvp);
+
+	/* Prepend new environ var=value string */
+	*newEnvp++ = szVar;
+
+	/* Copy user's environment into our own. */
+	while (cEnvp--)
+		*newEnvp++ = *envp++;
+
+	/* Ensure NULL terminates the new environment strings array. */
+	if (cEnvp == 0)
+		*newEnvp = NULL;
+
+	return ppEnvp;
+}
+
+/*
+ *  ======== PROC_NotifyClients ========
+ *  Purpose:
+ *      Notify the processor the events.
+ */
+DSP_STATUS PROC_NotifyClients(DSP_HPROCESSOR hProc, u32 uEvents)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+	DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+	DBC_Require(IsValidProcEvent(uEvents));
+	DBC_Require(cRefs > 0);
+
+	NTFY_Notify(pProcObject->hNtfy, uEvents);
+	GT_0trace(PROC_DebugMask, GT_1CLASS,
+		 "PROC_NotifyClients :Signaled. \n");
+
+	return status;
+}
+
+/*
+ *  ======== PROC_NotifyAllClients ========
+ *  Purpose:
+ *      Notify the processor the events. This includes notifying all clients
+ *      attached to a particulat DSP.
+ */
+DSP_STATUS PROC_NotifyAllClients(DSP_HPROCESSOR hProc, u32 uEvents)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+	DBC_Require(MEM_IsValidHandle(pProcObject, PROC_SIGNATURE));
+	DBC_Require(IsValidProcEvent(uEvents));
+	DBC_Require(cRefs > 0);
+
+	DEV_NotifyClients(pProcObject->hDevObject, uEvents);
+
+	GT_0trace(PROC_DebugMask, GT_1CLASS,
+		 "PROC_NotifyAllClients :Signaled. \n");
+
+	return status;
+}
+
+/*
+ *  ======== PROC_GetProcessorId ========
+ *  Purpose:
+ *      Retrieves the processor ID.
+ */
+DSP_STATUS PROC_GetProcessorId(DSP_HPROCESSOR hProc, u32 *procID)
+{
+	DSP_STATUS status = DSP_SOK;
+	struct PROC_OBJECT *pProcObject = (struct PROC_OBJECT *)hProc;
+
+	*procID = pProcObject->uProcessor;
+
+	return status;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/pwr.c b/drivers/dsp/bridge/rmgr/pwr.c
new file mode 100644
index 0000000..3984b00
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/pwr.c
@@ -0,0 +1,184 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/pwr.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== PWR.c ========
+ *  PWR API for controlling DSP power states.
+ *
+ *  Public Functions:
+ *      PWR_SleepDSP
+ *      PWR_WakeDSP
+ *
+ *! Revision History
+ *! ================
+ *! 18-Feb-2003 vp  Code review updates.
+ *! 18-Oct-2002 vp  Ported to Linux platform.
+ *! 22-May-2002 sg  Do PWR-to-IOCTL code mapping in PWR_SleepDSP.
+ *! 29-Apr-2002 sg  Initial.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- This */
+#include <pwr.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <devdefs.h>
+#include <drv.h>
+
+/*  ----------------------------------- Platform Manager */
+#include <dev.h>
+
+/*  ----------------------------------- Link Driver */
+#include <wmdioctl.h>
+
+/*
+ *  ======== PWR_SleepDSP ========
+ *    Send command to DSP to enter sleep state.
+ */
+DSP_STATUS PWR_SleepDSP(IN CONST u32 sleepCode, IN CONST u32 timeout)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct WMD_DEV_CONTEXT *dwContext;
+	DSP_STATUS status = DSP_EFAIL;
+	struct DEV_OBJECT *hDevObject = NULL;
+	u32 ioctlcode = 0;
+	u32 arg = timeout;
+
+	for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+			  hDevObject != 0;
+			hDevObject =
+				(struct DEV_OBJECT *)DRV_GetNextDevObject
+				((u32)hDevObject)) {
+		if (DSP_FAILED(DEV_GetWMDContext(hDevObject,
+		   (struct WMD_DEV_CONTEXT **)&dwContext))) {
+			continue;
+		}
+		if (DSP_FAILED(DEV_GetIntfFxns(hDevObject,
+		   (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+			continue;
+		}
+		if (sleepCode == PWR_DEEPSLEEP)
+			ioctlcode = WMDIOCTL_DEEPSLEEP;
+		else if (sleepCode == PWR_EMERGENCYDEEPSLEEP)
+			ioctlcode = WMDIOCTL_EMERGENCYSLEEP;
+		else
+			status = DSP_EINVALIDARG;
+
+		if (status != DSP_EINVALIDARG) {
+			status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+				 ioctlcode, (void *)&arg);
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== PWR_WakeDSP ========
+ *    Send command to DSP to wake it from sleep.
+ */
+DSP_STATUS PWR_WakeDSP(IN CONST u32 timeout)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct WMD_DEV_CONTEXT *dwContext;
+	DSP_STATUS status = DSP_EFAIL;
+	struct DEV_OBJECT *hDevObject = NULL;
+	u32 arg = timeout;
+
+	for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+	     hDevObject != 0;
+	     hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+			  ((u32)hDevObject)) {
+		if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+		   (struct WMD_DEV_CONTEXT **)&dwContext))) {
+			if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+			   (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+				status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+					 WMDIOCTL_WAKEUP, (void *)&arg);
+			}
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== PWR_PM_PreScale========
+ *    Sends pre-notification message to DSP.
+ */
+DSP_STATUS PWR_PM_PreScale(IN u16 voltage_domain, u32 level)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct WMD_DEV_CONTEXT *dwContext;
+	DSP_STATUS status = DSP_EFAIL;
+	struct DEV_OBJECT *hDevObject = NULL;
+	u32 arg[2];
+
+	arg[0] = voltage_domain;
+	arg[1] = level;
+
+	for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+	    hDevObject != 0;
+	    hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+			 ((u32)hDevObject)) {
+		if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+		   (struct WMD_DEV_CONTEXT **)&dwContext))) {
+			if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+			   (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+				status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+					 WMDIOCTL_PRESCALE_NOTIFY,
+					 (void *)&arg);
+			}
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== PWR_PM_PostScale========
+ *    Sends post-notification message to DSP.
+ */
+DSP_STATUS PWR_PM_PostScale(IN u16 voltage_domain, u32 level)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct WMD_DEV_CONTEXT *dwContext;
+	DSP_STATUS status = DSP_EFAIL;
+	struct DEV_OBJECT *hDevObject = NULL;
+	u32 arg[2];
+
+	arg[0] = voltage_domain;
+	arg[1] = level;
+
+	for (hDevObject = (struct DEV_OBJECT *)DRV_GetFirstDevObject();
+	     hDevObject != 0;
+	     hDevObject = (struct DEV_OBJECT *)DRV_GetNextDevObject
+			  ((u32)hDevObject)) {
+		if (DSP_SUCCEEDED(DEV_GetWMDContext(hDevObject,
+		   (struct WMD_DEV_CONTEXT **)&dwContext))) {
+			if (DSP_SUCCEEDED(DEV_GetIntfFxns(hDevObject,
+			   (struct WMD_DRV_INTERFACE **)&pIntfFxns))) {
+				status = (*pIntfFxns->pfnDevCntrl)(dwContext,
+					WMDIOCTL_POSTSCALE_NOTIFY,
+					(void *)&arg);
+			}
+		}
+	}
+	return status;
+
+}
+
+
diff --git a/drivers/dsp/bridge/rmgr/rmm.c b/drivers/dsp/bridge/rmgr/rmm.c
new file mode 100644
index 0000000..af12982
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/rmm.c
@@ -0,0 +1,604 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/rmm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== rmm.c ========
+ *  Description:
+ *
+ *  This memory manager provides general heap management and arbitrary
+ *  alignment for any number of memory segments.
+ *
+ *  Notes:
+ *
+ *  Memory blocks are allocated from the end of the first free memory
+ *  block large enough to satisfy the request.  Alignment requirements
+ *  are satisfied by "sliding" the block forward until its base satisfies
+ *  the alignment specification; if this is not possible then the next
+ *  free block large enough to hold the request is tried.
+ *
+ *  Since alignment can cause the creation of a new free block - the
+ *  unused memory formed between the start of the original free block
+ *  and the start of the allocated block - the memory manager must free
+ *  this memory to prevent a memory leak.
+ *
+ *  Overlay memory is managed by reserving through RMM_alloc, and freeing
+ *  it through RMM_free. The memory manager prevents DSP code/data that is
+ *  overlayed from being overwritten as long as the memory it runs at has
+ *  been allocated, and not yet freed.
+ *
+ *! Revision History
+ *! ================
+ *! 18-Feb-2003 vp  Code review updates.
+ *! 18-Oct-2002 vp  Ported to Linux Platform.
+ *! 24-Sep-2002 map Updated from Code Review
+ *! 25-Jun-2002 jeh     Free from segid passed to RMM_free().
+ *! 24-Apr-2002 jeh     Determine segid based on address in RMM_free(). (No way
+ *!                     to keep track of segid with dynamic loader library.)
+ *! 16-Oct-2001 jeh     Based on gen tree rm.c. Added support for overlays.
+ */
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <list.h>
+#include <mem.h>
+
+/*  ----------------------------------- This */
+#include <rmm.h>
+
+#define RMM_TARGSIGNATURE   0x544d4d52	/* "TMMR" */
+
+/*
+ *  ======== RMM_Header ========
+ *  This header is used to maintain a list of free memory blocks.
+ */
+struct RMM_Header {
+	struct RMM_Header *next;	/* form a free memory link list */
+	u32 size;		/* size of the free memory */
+	u32 addr;		/* DSP address of memory block */
+} ;
+
+/*
+ *  ======== RMM_OvlySect ========
+ *  Keeps track of memory occupied by overlay section.
+ */
+struct RMM_OvlySect {
+	struct LST_ELEM listElem;
+	u32 addr;		/* Start of memory section */
+	u32 size;		/* Length (target MAUs) of section */
+	s32 page;		/* Memory page */
+};
+
+/*
+ *  ======== RMM_TargetObj ========
+ */
+struct RMM_TargetObj {
+	u32 dwSignature;
+	struct RMM_Segment *segTab;
+	struct RMM_Header **freeList;
+	u32 numSegs;
+	struct LST_LIST *ovlyList;	/* List of overlay memory in use */
+};
+
+#if GT_TRACE
+static struct GT_Mask RMM_debugMask = { NULL, NULL };	/* GT trace variable */
+#endif
+
+static u32 cRefs;		/* module reference count */
+
+static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
+		      u32 align, u32 *dspAddr);
+static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
+		     u32 size);
+
+/*
+ *  ======== RMM_alloc ========
+ */
+DSP_STATUS RMM_alloc(struct RMM_TargetObj *target, u32 segid, u32 size,
+		    u32 align, u32 *dspAddr, bool reserve)
+{
+	struct RMM_OvlySect *sect;
+	struct RMM_OvlySect *prevSect = NULL;
+	struct RMM_OvlySect *newSect;
+	u32 addr;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+	DBC_Require(dspAddr != NULL);
+	DBC_Require(size > 0);
+	DBC_Require(reserve || (target->numSegs > 0));
+	DBC_Require(cRefs > 0);
+
+	GT_6trace(RMM_debugMask, GT_ENTER,
+		 "RMM_alloc(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+		 "0x%lx, 0x%lx)\n", target, segid, size, align, dspAddr,
+		 reserve);
+	if (!reserve) {
+		if (!allocBlock(target, segid, size, align, dspAddr)) {
+			status = DSP_EMEMORY;
+		} else {
+			/* Increment the number of allocated blocks in this
+			 * segment */
+			target->segTab[segid].number++;
+		}
+		goto func_end;
+	}
+	/* An overlay section - See if block is already in use. If not,
+	 * insert into the list in ascending address size.  */
+	addr = *dspAddr;
+	sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
+	/*  Find place to insert new list element. List is sorted from
+	 *  smallest to largest address. */
+	while (sect != NULL) {
+		if (addr <= sect->addr) {
+			/* Check for overlap with sect */
+			if ((addr + size > sect->addr) || (prevSect &&
+			   (prevSect->addr + prevSect->size > addr))) {
+				status = DSP_EOVERLAYMEMORY;
+			}
+			break;
+		}
+		prevSect = sect;
+		sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
+			(struct LST_ELEM *)sect);
+	}
+	if (DSP_SUCCEEDED(status)) {
+		/* No overlap - allocate list element for new section. */
+		newSect = MEM_Calloc(sizeof(struct RMM_OvlySect), MEM_PAGED);
+		if (newSect == NULL) {
+			status = DSP_EMEMORY;
+		} else {
+			LST_InitElem((struct LST_ELEM *)newSect);
+			newSect->addr = addr;
+			newSect->size = size;
+			newSect->page = segid;
+			if (sect == NULL) {
+				/* Put new section at the end of the list */
+				LST_PutTail(target->ovlyList,
+					   (struct LST_ELEM *)newSect);
+			} else {
+				/* Put new section just before sect */
+				LST_InsertBefore(target->ovlyList,
+						(struct LST_ELEM *)newSect,
+						(struct LST_ELEM *)sect);
+			}
+		}
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== RMM_create ========
+ */
+DSP_STATUS RMM_create(struct RMM_TargetObj **pTarget,
+		     struct RMM_Segment segTab[], u32 numSegs)
+{
+	struct RMM_Header *hptr;
+	struct RMM_Segment *sptr, *tmp;
+	struct RMM_TargetObj *target;
+	s32 i;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(pTarget != NULL);
+	DBC_Require(numSegs == 0 || segTab != NULL);
+
+	GT_3trace(RMM_debugMask, GT_ENTER,
+		 "RMM_create(0x%lx, 0x%lx, 0x%lx)\n",
+		 pTarget, segTab, numSegs);
+
+	/* Allocate DBL target object */
+	MEM_AllocObject(target, struct RMM_TargetObj, RMM_TARGSIGNATURE);
+
+	if (target == NULL) {
+		GT_0trace(RMM_debugMask, GT_6CLASS,
+			 "RMM_create: Memory allocation failed\n");
+		status = DSP_EMEMORY;
+	}
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	target->numSegs = numSegs;
+	if (!(numSegs > 0))
+		goto func_cont;
+
+	/* Allocate the memory for freelist from host's memory */
+	target->freeList = MEM_Calloc(numSegs * sizeof(struct RMM_Header *),
+				     MEM_PAGED);
+	if (target->freeList == NULL) {
+		GT_0trace(RMM_debugMask, GT_6CLASS,
+			 "RMM_create: Memory allocation failed\n");
+		status = DSP_EMEMORY;
+	} else {
+		/* Allocate headers for each element on the free list */
+		for (i = 0; i < (s32) numSegs; i++) {
+			target->freeList[i] =
+					MEM_Calloc(sizeof(struct RMM_Header),
+					MEM_PAGED);
+			if (target->freeList[i] == NULL) {
+				GT_0trace(RMM_debugMask, GT_6CLASS,
+					 "RMM_create: Memory "
+					 "allocation failed\n");
+				status = DSP_EMEMORY;
+				break;
+			}
+		}
+		/* Allocate memory for initial segment table */
+		target->segTab = MEM_Calloc(numSegs *
+				 sizeof(struct RMM_Segment), MEM_PAGED);
+		if (target->segTab == NULL) {
+			GT_0trace(RMM_debugMask, GT_6CLASS,
+				 "RMM_create: Memory allocation failed\n");
+			status = DSP_EMEMORY;
+		} else {
+			/* Initialize segment table and free list */
+			sptr = target->segTab;
+			for (i = 0, tmp = segTab; numSegs > 0; numSegs--, i++) {
+				*sptr = *tmp;
+				hptr = target->freeList[i];
+				hptr->addr = tmp->base;
+				hptr->size = tmp->length;
+				hptr->next = NULL;
+				tmp++;
+				sptr++;
+			}
+		}
+	}
+func_cont:
+	/* Initialize overlay memory list */
+	if (DSP_SUCCEEDED(status)) {
+		target->ovlyList = LST_Create();
+		if (target->ovlyList == NULL) {
+			GT_0trace(RMM_debugMask, GT_6CLASS,
+				 "RMM_create: Memory allocation failed\n");
+			status = DSP_EMEMORY;
+		}
+	}
+
+	if (DSP_SUCCEEDED(status)) {
+		*pTarget = target;
+	} else {
+		*pTarget = NULL;
+		if (target)
+			RMM_delete(target);
+
+	}
+
+	DBC_Ensure((DSP_SUCCEEDED(status) && MEM_IsValidHandle((*pTarget),
+		  RMM_TARGSIGNATURE)) || (DSP_FAILED(status) && *pTarget ==
+		  NULL));
+
+	return status;
+}
+
+/*
+ *  ======== RMM_delete ========
+ */
+void RMM_delete(struct RMM_TargetObj *target)
+{
+	struct RMM_OvlySect *pSect;
+	struct RMM_Header *hptr;
+	struct RMM_Header *next;
+	u32 i;
+
+	DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+
+	GT_1trace(RMM_debugMask, GT_ENTER, "RMM_delete(0x%lx)\n", target);
+
+	if (target->segTab != NULL)
+		MEM_Free(target->segTab);
+
+	if (target->ovlyList) {
+		while ((pSect = (struct RMM_OvlySect *)LST_GetHead
+		      (target->ovlyList))) {
+			MEM_Free(pSect);
+		}
+		DBC_Assert(LST_IsEmpty(target->ovlyList));
+		LST_Delete(target->ovlyList);
+	}
+
+	if (target->freeList != NULL) {
+		/* Free elements on freelist */
+		for (i = 0; i < target->numSegs; i++) {
+			hptr = next = target->freeList[i];
+			while (next) {
+				hptr = next;
+				next = hptr->next;
+				MEM_Free(hptr);
+			}
+		}
+		MEM_Free(target->freeList);
+	}
+
+	MEM_FreeObject(target);
+}
+
+/*
+ *  ======== RMM_exit ========
+ */
+void RMM_exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(RMM_debugMask, GT_5CLASS, "RMM_exit() ref count: 0x%x\n",
+		 cRefs);
+
+	if (cRefs == 0)
+		MEM_Exit();
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== RMM_free ========
+ */
+bool RMM_free(struct RMM_TargetObj *target, u32 segid, u32 addr, u32 size,
+	bool reserved)
+
+{
+	struct RMM_OvlySect *sect;
+	bool retVal = true;
+
+	DBC_Require(MEM_IsValidHandle(target, RMM_TARGSIGNATURE));
+
+	DBC_Require(reserved || segid < target->numSegs);
+	DBC_Require(reserved || (addr >= target->segTab[segid].base &&
+		   (addr + size) <= (target->segTab[segid].base +
+		   target->segTab[segid].length)));
+
+	GT_5trace(RMM_debugMask, GT_ENTER,
+		 "RMM_free(0x%lx, 0x%lx, 0x%lx, 0x%lx, "
+		 "0x%lx)\n", target, segid, addr, size, reserved);
+	/*
+	 *  Free or unreserve memory.
+	 */
+	if (!reserved) {
+		retVal = freeBlock(target, segid, addr, size);
+		if (retVal)
+			target->segTab[segid].number--;
+
+	} else {
+		/* Unreserve memory */
+		sect = (struct RMM_OvlySect *)LST_First(target->ovlyList);
+		while (sect != NULL) {
+			if (addr == sect->addr) {
+				DBC_Assert(size == sect->size);
+				/* Remove from list */
+				LST_RemoveElem(target->ovlyList,
+					      (struct LST_ELEM *)sect);
+				MEM_Free(sect);
+				break;
+			}
+			sect = (struct RMM_OvlySect *)LST_Next(target->ovlyList,
+			       (struct LST_ELEM *)sect);
+		}
+		if (sect == NULL)
+			retVal = false;
+
+	}
+	return retVal;
+}
+
+/*
+ *  ======== RMM_init ========
+ */
+bool RMM_init(void)
+{
+	bool retVal = true;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+		DBC_Assert(!RMM_debugMask.flags);
+		GT_create(&RMM_debugMask, "RM");	/* "RM" for RMm */
+
+		retVal = MEM_Init();
+
+		if (!retVal)
+			MEM_Exit();
+
+	}
+
+	if (retVal)
+		cRefs++;
+
+	GT_1trace(RMM_debugMask, GT_5CLASS,
+		 "RMM_init(), ref count:  0x%x\n",
+		 cRefs);
+
+	DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0)));
+
+	return retVal;
+}
+
+/*
+ *  ======== RMM_stat ========
+ */
+bool RMM_stat(struct RMM_TargetObj *target, enum DSP_MEMTYPE segid,
+	     struct DSP_MEMSTAT *pMemStatBuf)
+{
+	struct RMM_Header *head;
+	bool retVal = false;
+	u32 maxFreeSize = 0;
+	u32 totalFreeSize = 0;
+	u32 freeBlocks = 0;
+
+	DBC_Require(pMemStatBuf != NULL);
+	DBC_Assert(target != NULL);
+
+	if ((u32) segid < target->numSegs) {
+		head = target->freeList[segid];
+
+		/* Collect data from freeList */
+		while (head != NULL) {
+			maxFreeSize = max(maxFreeSize, head->size);
+			totalFreeSize += head->size;
+			freeBlocks++;
+			head = head->next;
+		}
+
+		/* ulSize */
+		pMemStatBuf->ulSize = target->segTab[segid].length;
+
+		/* ulNumFreeBlocks */
+		pMemStatBuf->ulNumFreeBlocks = freeBlocks;
+
+		/* ulTotalFreeSize */
+		pMemStatBuf->ulTotalFreeSize = totalFreeSize;
+
+		/* ulLenMaxFreeBlock */
+		pMemStatBuf->ulLenMaxFreeBlock = maxFreeSize;
+
+		/* ulNumAllocBlocks */
+		pMemStatBuf->ulNumAllocBlocks = target->segTab[segid].number;
+
+		retVal = true;
+	}
+
+	return retVal;
+}
+
+/*
+ *  ======== balloc ========
+ *  This allocation function allocates memory from the lowest addresses
+ *  first.
+ */
+static bool allocBlock(struct RMM_TargetObj *target, u32 segid, u32 size,
+		      u32 align, u32 *dspAddr)
+{
+	struct RMM_Header *head;
+	struct RMM_Header *prevhead = NULL;
+	struct RMM_Header *next;
+	u32 tmpalign;
+	u32 alignbytes;
+	u32 hsize;
+	u32 allocsize;
+	u32 addr;
+
+	alignbytes = (align == 0) ? 1 : align;
+	prevhead = NULL;
+	head = target->freeList[segid];
+
+	do {
+		hsize = head->size;
+		next = head->next;
+
+		addr = head->addr;	/* alloc from the bottom */
+
+		/* align allocation */
+		(tmpalign = (u32) addr % alignbytes);
+		if (tmpalign != 0)
+			tmpalign = alignbytes - tmpalign;
+
+		allocsize = size + tmpalign;
+
+		if (hsize >= allocsize) {	/* big enough */
+			if (hsize == allocsize && prevhead != NULL) {
+				prevhead->next = next;
+				MEM_Free(head);
+			} else {
+				head->size = hsize - allocsize;
+				head->addr += allocsize;
+			}
+
+			/* free up any hole created by alignment */
+			if (tmpalign)
+				freeBlock(target, segid, addr, tmpalign);
+
+			*dspAddr = addr + tmpalign;
+			return true;
+		}
+
+		prevhead = head;
+		head = next;
+
+	} while (head != NULL);
+
+	return false;
+}
+
+/*
+ *  ======== freeBlock ========
+ *  TO DO: freeBlock() allocates memory, which could result in failure.
+ *  Could allocate an RMM_Header in RMM_alloc(), to be kept in a pool.
+ *  freeBlock() could use an RMM_Header from the pool, freeing as blocks
+ *  are coalesced.
+ */
+static bool freeBlock(struct RMM_TargetObj *target, u32 segid, u32 addr,
+		     u32 size)
+{
+	struct RMM_Header *head;
+	struct RMM_Header *thead;
+	struct RMM_Header *rhead;
+	bool retVal = true;
+
+	/* Create a memory header to hold the newly free'd block. */
+	rhead = MEM_Calloc(sizeof(struct RMM_Header), MEM_PAGED);
+	if (rhead == NULL) {
+		retVal = false;
+	} else {
+		/* search down the free list to find the right place for addr */
+		head = target->freeList[segid];
+
+		if (addr >= head->addr) {
+			while (head->next != NULL && addr > head->next->addr)
+				head = head->next;
+
+			thead = head->next;
+
+			head->next = rhead;
+			rhead->next = thead;
+			rhead->addr = addr;
+			rhead->size = size;
+		} else {
+			*rhead = *head;
+			head->next = rhead;
+			head->addr = addr;
+			head->size = size;
+			thead = rhead->next;
+		}
+
+		/* join with upper block, if possible */
+		if (thead != NULL && (rhead->addr + rhead->size) ==
+		   thead->addr) {
+			head->next = rhead->next;
+			thead->size = size + thead->size;
+			thead->addr = addr;
+			MEM_Free(rhead);
+			rhead = thead;
+		}
+
+		/* join with the lower block, if possible */
+		if ((head->addr + head->size) == rhead->addr) {
+			head->next = rhead->next;
+			head->size = head->size + rhead->size;
+			MEM_Free(rhead);
+		}
+	}
+
+	return retVal;
+}
+
diff --git a/drivers/dsp/bridge/rmgr/strm.c b/drivers/dsp/bridge/rmgr/strm.c
new file mode 100644
index 0000000..1069dac
--- /dev/null
+++ b/drivers/dsp/bridge/rmgr/strm.c
@@ -0,0 +1,1053 @@
+/*
+ * linux/drivers/dsp/bridge/rmgr/strm.c
+ *
+ * DSP-BIOS Bridge driver support functions for TI OMAP processors.
+ *
+ * Copyright (C) 2005-2006 Texas Instruments, Inc.
+ *
+ * This package is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+
+/*
+ *  ======== strm.c ========
+ *  Description:
+ *      DSP/BIOS Bridge Stream Manager.
+ *
+ *  Public Functions:
+ *      STRM_AllocateBuffer
+ *      STRM_Close
+ *      STRM_Create
+ *      STRM_Delete
+ *      STRM_Exit
+ *      STRM_FreeBuffer
+ *      STRM_GetEventHandle
+ *      STRM_GetInfo
+ *      STRM_Idle
+ *      STRM_Init
+ *      STRM_Issue
+ *      STRM_Open
+ *      STRM_PrepareBuffer
+ *      STRM_Reclaim
+ *      STRM_RegisterNotify
+ *      STRM_Select
+ *      STRM_UnprepareBuffer
+ *
+ *  Notes:
+ *
+ *! Revision History:
+ *! =================
+ *! 18-Feb-2003 vp  Code review updates.
+ *! 18-Oct-2002 vp  Ported to Linux platform.
+ *! 13-Mar-2002 map    pStrm init'd to NULL in STRM_Open to prevent error
+ *! 12-Mar-2002 map Changed return var to WSX "wStatus" instead of "status"
+ *!		    in DEV and CMM function calls to avoid confusion.
+ *!		    Return DSP_SOK instead of S_OK from API fxns.
+ *! 12-Mar-2002 map    Changed FAILED(..) to DSP_FAILED(..)
+ *! 25-Jan-2002 ag  Allow neg seg ids(e.g. DSP_SHMSEG0) to denote SM.
+ *! 15-Nov-2001 ag  Added STRMMODE & SM for DMA/ZCopy streaming.
+ *!		 Changed DSP_STREAMINFO to STRM_INFO in STRM_GetInfo().
+ *!		 Use strm timeout value for dma flush timeout.
+ *! 09-May-2001 jeh Code review cleanup.
+ *! 06-Feb-2001 kc  Updated DBC_Ensure in STRM_Select to check timeout.
+ *! 23-Oct-2000 jeh Allow NULL STRM_ATTRS passed to STRM_Open() for DLL
+ *!		 tests to pass.
+ *! 25-Sep-2000 jeh Created.
+ */
+
+/*  ----------------------------------- Host OS */
+#include <host_os.h>
+
+/*  ----------------------------------- DSP/BIOS Bridge */
+#include <std.h>
+#include <dbdefs.h>
+#include <errbase.h>
+
+/*  ----------------------------------- Trace & Debug */
+#include <dbc.h>
+#include <gt.h>
+
+/*  ----------------------------------- OS Adaptation Layer */
+#include <mem.h>
+#include <sync.h>
+
+/*  ----------------------------------- Mini Driver */
+#include <wmd.h>
+
+/*  ----------------------------------- Resource Manager */
+#include <nodepriv.h>
+
+/*  ----------------------------------- Others */
+#include <cmm.h>
+
+/*  ----------------------------------- This */
+#include <strm.h>
+
+#ifndef RES_CLEANUP_DISABLE
+#include <cfg.h>
+#include <prcs.h>
+#include <dbreg.h>
+#include <resourcecleanup.h>
+#endif
+
+/*  ----------------------------------- Defines, Data Structures, Typedefs */
+#define STRM_SIGNATURE      0x4d525453	/* "MRTS" */
+#define STRMMGR_SIGNATURE   0x5254534d	/* "RTSM" */
+
+#define DEFAULTTIMEOUT      10000
+#define DEFAULTNUMBUFS      2
+
+/*
+ *  ======== STRM_MGR ========
+ *  The STRM_MGR contains device information needed to open the underlying
+ *  channels of a stream.
+ */
+struct STRM_MGR {
+	u32 dwSignature;
+	struct DEV_OBJECT *hDev;	/* Device for this processor */
+	struct CHNL_MGR *hChnlMgr;	/* Channel manager */
+	struct WMD_DRV_INTERFACE *pIntfFxns;	/* Function interface to WMD */
+	struct SYNC_CSOBJECT *hSync;	/* For critical sections */
+} ;
+
+/*
+ *  ======== STRM_OBJECT ========
+ *  This object is allocated in STRM_Open().
+ */
+ struct STRM_OBJECT {
+	u32 dwSignature;
+	struct STRM_MGR *hStrmMgr;
+	struct CHNL_OBJECT *hChnl;
+	u32 uDir;		/* DSP_TONODE or DSP_FROMNODE */
+	u32 uTimeout;
+	u32 uNumBufs;		/* Max # of bufs allowed in stream */
+	u32 uNBufsInStrm;	/* Current # of bufs in stream */
+	u32 ulNBytes;		/* bytes transferred since idled */
+	enum DSP_STREAMSTATE strmState;	/* STREAM_IDLE, STREAM_READY, ... */
+	HANDLE hUserEvent;	/* Saved for STRM_GetInfo() */
+	enum DSP_STRMMODE lMode;	/* STRMMODE_[PROCCOPY][ZEROCOPY]... */
+	u32 uDMAChnlId;	/* DMA chnl id */
+	u32 uDMAPriority;	/* DMA priority:DMAPRI_[LOW][HIGH] */
+	u32 uSegment;		/* >0 is SM segment.=0 is local heap */
+	u32 uAlignment;	/* Alignment for stream bufs */
+	struct CMM_XLATOROBJECT *hXlator;  /* Stream's SM address translator */
+} ;
+
+/*  ----------------------------------- Globals */
+#if GT_TRACE
+static struct GT_Mask STRM_debugMask = { NULL, NULL };	/* GT trace variable */
+#endif
+static u32 cRefs;		/* module reference count */
+
+/*  ----------------------------------- Function Prototypes */
+static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm);
+static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr);
+
+/*
+ *  ======== STRM_AllocateBuffer ========
+ *  Purpose:
+ *      Allocates buffers for a stream.
+ */
+DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize,
+				OUT u8 **apBuffer, u32 uNumBufs)
+{
+	DSP_STATUS status = DSP_SOK;
+	u32 uAllocated = 0;
+	u32 i;
+	#ifndef RES_CLEANUP_DISABLE
+	DSP_STATUS res_status = DSP_SOK;
+	HANDLE	     hProcess;
+	HANDLE	     pCtxt = NULL;
+	HANDLE	     hDrvObject;
+	HANDLE hSTRMRes;
+	#endif
+	DBC_Require(cRefs > 0);
+	DBC_Require(apBuffer != NULL);
+
+	GT_4trace(STRM_debugMask, GT_ENTER, "STRM_AllocateBuffer: hStrm: 0x%x\t"
+		 "uSize: 0x%x\tapBuffer: 0x%x\tuNumBufs: 0x%x\n",
+		 hStrm, uSize, apBuffer, uNumBufs);
+	if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		/*
+		 * Allocate from segment specified at time of stream open.
+		 */
+		if (uSize == 0)
+			status = DSP_ESIZE;
+
+	}
+	if (DSP_FAILED(status)) {
+		status = DSP_EHANDLE;
+		goto func_end;
+	}
+	for (i = 0; i < uNumBufs; i++) {
+		DBC_Assert(hStrm->hXlator != NULL);
+		(void)CMM_XlatorAllocBuf(hStrm->hXlator, &apBuffer[i], uSize);
+		if (apBuffer[i] == NULL) {
+			GT_0trace(STRM_debugMask, GT_7CLASS,
+				 "STRM_AllocateBuffer: "
+				 "DSP_FAILED to alloc shared memory.\n");
+			status = DSP_EMEMORY;
+			uAllocated = i;
+			break;
+		}
+	}
+	if (DSP_FAILED(status))
+		STRM_FreeBuffer(hStrm, apBuffer, uAllocated);
+
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_FAILED(res_status))
+		goto func_end;
+
+	DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
+	if (pCtxt != NULL) {
+		if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
+		   DSP_ENOTFOUND) {
+			DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes, pCtxt);
+		}
+	}
+#endif
+func_end:
+	return status;
+}
+
+/*
+ *  ======== STRM_Close ========
+ *  Purpose:
+ *      Close a stream opened with STRM_Open().
+ */
+DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct CHNL_INFO chnlInfo;
+	DSP_STATUS status = DSP_SOK;
+
+
+#ifndef RES_CLEANUP_DISABLE
+    HANDLE	      hProcess;
+    HANDLE	      pCtxt = NULL;
+    HANDLE	      hDrvObject;
+    HANDLE	      hSTRMRes;
+    DSP_STATUS	  res_status = DSP_SOK;
+#endif
+
+
+	DBC_Require(cRefs > 0);
+
+	GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm);
+
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		/* Have all buffers been reclaimed? If not, return
+		 * DSP_EPENDING */
+		pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+		status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
+		DBC_Assert(DSP_SUCCEEDED(status));
+
+		if (chnlInfo.cIOCs > 0 || chnlInfo.cIOReqs > 0) {
+			status = DSP_EPENDING;
+		} else {
+
+			status = DeleteStrm(hStrm);
+
+			if (DSP_FAILED(status)) {
+				/* we already validated the handle. */
+				DBC_Assert(status != DSP_EHANDLE);
+
+				/* make sure we return a documented result */
+				status = DSP_EFAIL;
+			}
+		}
+	}
+#ifndef RES_CLEANUP_DISABLE
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Update the node and stream resource status */
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_FAILED(res_status))
+		goto func_end;
+
+	DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
+	if (pCtxt != NULL) {
+		if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pCtxt) !=
+		   DSP_ENOTFOUND) {
+			DRV_ProcRemoveSTRMResElement(hSTRMRes, pCtxt);
+		}
+	}
+func_end:
+#endif
+	DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE ||
+		  status == DSP_EPENDING || status == DSP_EFAIL);
+
+	return status;
+}
+
+/*
+ *  ======== STRM_Create ========
+ *  Purpose:
+ *      Create a STRM manager object.
+ */
+DSP_STATUS STRM_Create(OUT struct STRM_MGR **phStrmMgr, struct DEV_OBJECT *hDev)
+{
+	struct STRM_MGR *pStrmMgr;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(phStrmMgr != NULL);
+	DBC_Require(hDev != NULL);
+
+	GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Create: phStrmMgr: "
+		 "0x%x\thDev: 0x%x\n", phStrmMgr, hDev);
+	*phStrmMgr = NULL;
+	/* Allocate STRM manager object */
+	MEM_AllocObject(pStrmMgr, struct STRM_MGR, STRMMGR_SIGNATURE);
+	if (pStrmMgr == NULL) {
+		status = DSP_EMEMORY;
+		GT_0trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
+			 "MEM_AllocObject() failed!\n ");
+	} else {
+		pStrmMgr->hDev = hDev;
+	}
+	/* Get Channel manager and WMD function interface */
+	if (DSP_SUCCEEDED(status)) {
+		status = DEV_GetChnlMgr(hDev, &(pStrmMgr->hChnlMgr));
+		if (DSP_SUCCEEDED(status)) {
+			(void) DEV_GetIntfFxns(hDev, &(pStrmMgr->pIntfFxns));
+			DBC_Assert(pStrmMgr->pIntfFxns != NULL);
+		} else {
+			GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Create: "
+				 "Failed to get channel manager! status = "
+				 "0x%x\n", status);
+		}
+	}
+	if (DSP_SUCCEEDED(status))
+		status = SYNC_InitializeCS(&pStrmMgr->hSync);
+
+	if (DSP_SUCCEEDED(status))
+		*phStrmMgr = pStrmMgr;
+	else
+		DeleteStrmMgr(pStrmMgr);
+
+	DBC_Ensure(DSP_SUCCEEDED(status) &&
+		  (MEM_IsValidHandle((*phStrmMgr), STRMMGR_SIGNATURE) ||
+		  (DSP_FAILED(status) && *phStrmMgr == NULL)));
+
+	return status;
+}
+
+/*
+ *  ======== STRM_Delete ========
+ *  Purpose:
+ *      Delete the STRM Manager Object.
+ */
+void STRM_Delete(struct STRM_MGR *hStrmMgr)
+{
+	DBC_Require(cRefs > 0);
+	DBC_Require(MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
+
+	GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Delete: hStrmMgr: 0x%x\n",
+		 hStrmMgr);
+
+	DeleteStrmMgr(hStrmMgr);
+
+	DBC_Ensure(!MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE));
+}
+
+/*
+ *  ======== STRM_Exit ========
+ *  Purpose:
+ *      Discontinue usage of STRM module.
+ */
+void STRM_Exit(void)
+{
+	DBC_Require(cRefs > 0);
+
+	cRefs--;
+
+	GT_1trace(STRM_debugMask, GT_5CLASS,
+		 "Entered STRM_Exit, ref count:  0x%x\n", cRefs);
+
+	DBC_Ensure(cRefs >= 0);
+}
+
+/*
+ *  ======== STRM_FreeBuffer ========
+ *  Purpose:
+ *      Frees the buffers allocated for a stream.
+ */
+DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer,
+			  u32 uNumBufs)
+{
+	DSP_STATUS status = DSP_SOK;
+	u32 i = 0;
+
+	#ifndef RES_CLEANUP_DISABLE
+	DSP_STATUS res_status = DSP_SOK;
+	HANDLE	     hProcess;
+	HANDLE	     pCtxt = NULL;
+	HANDLE	     hDrvObject;
+	HANDLE 		    hSTRMRes = NULL;
+	#endif
+	DBC_Require(cRefs > 0);
+	DBC_Require(apBuffer != NULL);
+
+	GT_3trace(STRM_debugMask, GT_ENTER, "STRM_FreeBuffer: hStrm: 0x%x\t"
+		 "apBuffer: 0x%x\tuNumBufs: 0x%x\n", hStrm, apBuffer, uNumBufs);
+
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE))
+		status = DSP_EHANDLE;
+
+	if (DSP_SUCCEEDED(status)) {
+		for (i = 0; i < uNumBufs; i++) {
+			DBC_Assert(hStrm->hXlator != NULL);
+			status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]);
+			if (DSP_FAILED(status)) {
+				GT_0trace(STRM_debugMask, GT_7CLASS,
+					 "STRM_FreeBuffer: DSP_FAILED"
+					 " to free shared memory.\n");
+				break;
+			}
+			apBuffer[i] = NULL;
+		}
+	}
+#ifndef RES_CLEANUP_DISABLE
+	/* Update the node and stream resource status */
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(res_status)) {
+		DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, NULL, 0);
+		if (pCtxt != NULL) {
+			if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
+			   DSP_ENOTFOUND) {
+				DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
+						     pCtxt);
+			}
+		}
+	}
+#endif
+	return status;
+}
+
+/*
+ *  ======== STRM_GetInfo ========
+ *  Purpose:
+ *      Retrieves information about a stream.
+ */
+DSP_STATUS STRM_GetInfo(struct STRM_OBJECT *hStrm,
+			OUT struct STRM_INFO *pStreamInfo,
+			u32 uStreamInfoSize)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct CHNL_INFO chnlInfo;
+	DSP_STATUS status = DSP_SOK;
+	void *pVirtBase = NULL;	/* NULL if no SM used */
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pStreamInfo != NULL);
+	DBC_Require(uStreamInfoSize >= sizeof(struct STRM_INFO));
+
+	GT_3trace(STRM_debugMask, GT_ENTER, "STRM_GetInfo: hStrm: 0x%x\t"
+		 "pStreamInfo: 0x%x\tuStreamInfoSize: 0x%x\n", hStrm,
+		 pStreamInfo, uStreamInfoSize);
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		if (uStreamInfoSize < sizeof(struct STRM_INFO)) {
+			/* size of users info */
+			status = DSP_ESIZE;
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+	status = (*pIntfFxns->pfnChnlGetInfo) (hStrm->hChnl, &chnlInfo);
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	if (hStrm->hXlator) {
+		/* We have a translator */
+		DBC_Assert(hStrm->uSegment > 0);
+		CMM_XlatorInfo(hStrm->hXlator, (u8 **)&pVirtBase, 0,
+			      hStrm->uSegment, false);
+	}
+	pStreamInfo->uSegment = hStrm->uSegment;
+	pStreamInfo->lMode = hStrm->lMode;
+	pStreamInfo->pVirtBase = pVirtBase;
+	pStreamInfo->pUser->uNumberBufsAllowed = hStrm->uNumBufs;
+	pStreamInfo->pUser->uNumberBufsInStream = chnlInfo.cIOCs +
+						 chnlInfo.cIOReqs;
+	/* # of bytes transferred since last call to DSPStream_Idle() */
+	pStreamInfo->pUser->ulNumberBytes = chnlInfo.cPosition;
+	pStreamInfo->pUser->hSyncObjectHandle = chnlInfo.hEvent;
+	/* Determine stream state based on channel state and info */
+	if (chnlInfo.dwState & CHNL_STATEEOS) {
+		pStreamInfo->pUser->ssStreamState = STREAM_DONE;
+	} else {
+		if (chnlInfo.cIOCs > 0)
+			pStreamInfo->pUser->ssStreamState = STREAM_READY;
+		else if (chnlInfo.cIOReqs > 0)
+			pStreamInfo->pUser->ssStreamState = STREAM_PENDING;
+		else
+			pStreamInfo->pUser->ssStreamState = STREAM_IDLE;
+
+	}
+func_end:
+	return status;
+}
+
+/*
+ *  ======== STRM_Idle ========
+ *  Purpose:
+ *      Idles a particular stream.
+ */
+DSP_STATUS STRM_Idle(struct STRM_OBJECT *hStrm, bool fFlush)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+
+	GT_2trace(STRM_debugMask, GT_ENTER, "STRM_Idle: hStrm: 0x%x\t"
+		 "fFlush: 0x%x\n", hStrm, fFlush);
+
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+		status = (*pIntfFxns->pfnChnlIdle) (hStrm->hChnl,
+			 hStrm->uTimeout, fFlush);
+	}
+	return status;
+}
+
+/*
+ *  ======== STRM_Init ========
+ *  Purpose:
+ *      Initialize the STRM module.
+ */
+bool STRM_Init(void)
+{
+	bool fRetVal = true;
+
+	DBC_Require(cRefs >= 0);
+
+	if (cRefs == 0) {
+#if GT_TRACE
+		DBC_Assert(!STRM_debugMask.flags);
+		GT_create(&STRM_debugMask, "ST");	/* "ST" for STrm */
+#endif
+	}
+
+	if (fRetVal)
+		cRefs++;
+
+	GT_1trace(STRM_debugMask, GT_5CLASS, "STRM_Init(), ref count: 0x%x\n",
+		 cRefs);
+
+	DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0)));
+
+	return fRetVal;
+}
+
+/*
+ *  ======== STRM_Issue ========
+ *  Purpose:
+ *      Issues a buffer on a stream
+ */
+DSP_STATUS STRM_Issue(struct STRM_OBJECT *hStrm, IN u8 *pBuf, u32 ulBytes,
+		     u32 ulBufSize, u32 dwArg)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+	void *pTmpBuf = NULL;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pBuf != NULL);
+
+	GT_4trace(STRM_debugMask, GT_ENTER, "STRM_Issue: hStrm: 0x%x\tpBuf: "
+		 "0x%x\tulBytes: 0x%x\tdwArg: 0x%x\n", hStrm, pBuf, ulBytes,
+		 dwArg);
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else {
+		pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+		if (hStrm->uSegment != 0) {
+			pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+					(void *)pBuf, CMM_VA2DSPPA);
+			if (pTmpBuf == NULL)
+				status = DSP_ETRANSLATE;
+
+		}
+		if (DSP_SUCCEEDED(status)) {
+			status = (*pIntfFxns->pfnChnlAddIOReq)
+				 (hStrm->hChnl, pBuf, ulBytes, ulBufSize,
+				 (u32) pTmpBuf, dwArg);
+		}
+		if (DSP_FAILED(status)) {
+			if (status == CHNL_E_NOIORPS)
+				status = DSP_ESTREAMFULL;
+			else
+				status = DSP_EFAIL;
+
+		}
+	}
+	return status;
+}
+
+/*
+ *  ======== STRM_Open ========
+ *  Purpose:
+ *      Open a stream for sending/receiving data buffers to/from a task or
+ *      XDAIS socket node on the DSP.
+ */
+DSP_STATUS STRM_Open(struct NODE_OBJECT *hNode, u32 uDir, u32 uIndex,
+		    IN struct STRM_ATTR *pAttr, OUT struct STRM_OBJECT **phStrm)
+{
+	struct STRM_MGR *hStrmMgr;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	u32 ulChnlId;
+	struct STRM_OBJECT *pStrm = NULL;
+	CHNL_MODE uMode;
+	struct CHNL_ATTRS chnlAttrs;
+	DSP_STATUS status = DSP_SOK;
+	struct CMM_OBJECT *hCmmMgr = NULL;	/* Shared memory manager hndl */
+
+	#ifndef RES_CLEANUP_DISABLE
+	DSP_STATUS res_status = DSP_SOK;
+	HANDLE	     hProcess;
+	HANDLE	     pCtxt = NULL;
+	HANDLE	     hDrvObject;
+	HANDLE 		    hSTRMRes;
+	#endif
+	DBC_Require(cRefs > 0);
+	DBC_Require(phStrm != NULL);
+	DBC_Require(pAttr != NULL);
+	GT_5trace(STRM_debugMask, GT_ENTER,
+		 "STRM_Open: hNode: 0x%x\tuDir: 0x%x\t"
+		 "uIndex: 0x%x\tpAttr: 0x%x\tphStrm: 0x%x\n",
+		 hNode, uDir, uIndex, pAttr, phStrm);
+	*phStrm = NULL;
+	if (uDir != DSP_TONODE && uDir != DSP_FROMNODE) {
+		status = DSP_EDIRECTION;
+	} else {
+		/* Get the channel id from the node (set in NODE_Connect()) */
+		status = NODE_GetChannelId(hNode, uDir, uIndex, &ulChnlId);
+	}
+	if (DSP_SUCCEEDED(status))
+		status = NODE_GetStrmMgr(hNode, &hStrmMgr);
+
+	if (DSP_SUCCEEDED(status)) {
+		MEM_AllocObject(pStrm, struct STRM_OBJECT, STRM_SIGNATURE);
+		if (pStrm == NULL) {
+			status = DSP_EMEMORY;
+			GT_0trace(STRM_debugMask, GT_6CLASS,
+				 "STRM_Open: MEM_AllocObject() failed!\n ");
+		} else {
+			pStrm->hStrmMgr = hStrmMgr;
+			pStrm->uDir = uDir;
+			pStrm->strmState = STREAM_IDLE;
+			pStrm->hUserEvent = pAttr->hUserEvent;
+			if (pAttr->pStreamAttrIn != NULL) {
+				pStrm->uTimeout = pAttr->pStreamAttrIn->
+						  uTimeout;
+				pStrm->uNumBufs = pAttr->pStreamAttrIn->
+						  uNumBufs;
+				pStrm->lMode = pAttr->pStreamAttrIn->lMode;
+				pStrm->uSegment = pAttr->pStreamAttrIn->
+						  uSegment;
+				pStrm->uAlignment = pAttr->pStreamAttrIn->
+						    uAlignment;
+				pStrm->uDMAChnlId = pAttr->pStreamAttrIn->
+						    uDMAChnlId;
+				pStrm->uDMAPriority = pAttr->pStreamAttrIn->
+						      uDMAPriority;
+				chnlAttrs.uIOReqs = pAttr->pStreamAttrIn->
+						    uNumBufs;
+			} else {
+				pStrm->uTimeout = DEFAULTTIMEOUT;
+				pStrm->uNumBufs = DEFAULTNUMBUFS;
+				pStrm->lMode = STRMMODE_PROCCOPY;
+				pStrm->uSegment = 0;	/* local memory */
+				pStrm->uAlignment = 0;
+				pStrm->uDMAChnlId = 0;
+				pStrm->uDMAPriority = 0;
+				chnlAttrs.uIOReqs = DEFAULTNUMBUFS;
+			}
+			chnlAttrs.hReserved1 = NULL;
+			/* DMA chnl flush timeout */
+			chnlAttrs.hReserved2 = pStrm->uTimeout;
+			chnlAttrs.hEvent = NULL;
+			if (pAttr->hUserEvent != NULL)
+				chnlAttrs.hEvent = pAttr->hUserEvent;
+
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_cont;
+
+	if ((pAttr->pVirtBase == NULL) || !(pAttr->ulVirtSize > 0))
+		goto func_cont;
+
+	DBC_Assert(pStrm->lMode != STRMMODE_LDMA);	/* no System DMA */
+	/* Get the shared mem mgr for this streams dev object */
+	status = DEV_GetCmmMgr(hStrmMgr->hDev, &hCmmMgr);
+	if (DSP_FAILED(status)) {
+		GT_1trace(STRM_debugMask, GT_6CLASS, "STRM_Open: Failed to get "
+			 "CMM Mgr handle: 0x%x\n", status);
+	} else {
+		/*Allocate a SM addr translator for this strm.*/
+		status = CMM_XlatorCreate(&pStrm->hXlator, hCmmMgr, NULL);
+		if (DSP_FAILED(status)) {
+			GT_1trace(STRM_debugMask, GT_6CLASS,
+				 "STRM_Open: Failed to "
+				 "create SM translator: 0x%x\n", status);
+		} else {
+			DBC_Assert(pStrm->uSegment > 0);
+			/*  Set translators Virt Addr attributes */
+			status = CMM_XlatorInfo(pStrm->hXlator,
+				 (u8 **)&pAttr->pVirtBase, pAttr->ulVirtSize,
+				 pStrm->uSegment, true);
+			if (status != DSP_SOK) {
+				GT_0trace(STRM_debugMask, GT_6CLASS,
+					 "STRM_Open: ERROR: "
+					 "in setting CMM_XlatorInfo.\n");
+			}
+		}
+	}
+func_cont:
+	if (DSP_SUCCEEDED(status)) {
+		/* Open channel */
+		uMode = (uDir == DSP_TONODE) ?
+			CHNL_MODETODSP : CHNL_MODEFROMDSP;
+		pIntfFxns = hStrmMgr->pIntfFxns;
+		status = (*pIntfFxns->pfnChnlOpen) (&(pStrm->hChnl),
+			 hStrmMgr->hChnlMgr, uMode, ulChnlId, &chnlAttrs);
+		if (DSP_FAILED(status)) {
+			/*
+			 * over-ride non-returnable status codes so we return
+			 * something documented
+			 */
+			if (status != DSP_EMEMORY && status !=
+			   DSP_EINVALIDARG && status != DSP_EFAIL) {
+				/*
+				 * We got a status that's not return-able.
+				 * Assert that we got something we were
+				 * expecting (DSP_EHANDLE isn't acceptable,
+				 * hStrmMgr->hChnlMgr better be valid or we
+				 * assert here), and then return DSP_EFAIL.
+				 */
+				DBC_Assert(status == CHNL_E_OUTOFSTREAMS ||
+					   status == CHNL_E_BADCHANID ||
+					   status == CHNL_E_CHANBUSY ||
+					   status == CHNL_E_NOIORPS);
+				status = DSP_EFAIL;
+			}
+			GT_2trace(STRM_debugMask, GT_6CLASS,
+				  "STRM_Open: Channel open failed, "
+				  "chnl id = %d, status = 0x%x\n", ulChnlId,
+				  status);
+		}
+	}
+	if (DSP_SUCCEEDED(status))
+		*phStrm = pStrm;
+	else
+		(void)DeleteStrm(pStrm);
+
+#ifndef RES_CLEANUP_DISABLE
+	PRCS_GetCurrentHandle(&hProcess);
+	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
+	if (DSP_SUCCEEDED(res_status)) {
+		DRV_GetProcContext(hProcess, hDrvObject, &pCtxt, hNode, 0);
+		if (pCtxt != NULL)
+			DRV_ProcInsertSTRMResElement(*phStrm, &hSTRMRes, pCtxt);
+
+	}
+#endif
+
+	 /* ensure we return a documented error code */
+	DBC_Ensure((DSP_SUCCEEDED(status) &&
+		  MEM_IsValidHandle((*phStrm), STRM_SIGNATURE)) ||
+		  (*phStrm == NULL && (status == DSP_EHANDLE ||
+		  status == DSP_EDIRECTION || status == DSP_EVALUE ||
+		  status == DSP_EFAIL)));
+	return status;
+}
+
+/*
+ *  ======== STRM_Reclaim ========
+ *  Purpose:
+ *      Relcaims a buffer from a stream.
+ */
+DSP_STATUS STRM_Reclaim(struct STRM_OBJECT *hStrm, OUT u8 **pBufPtr,
+			u32 *pulBytes, u32 *pulBufSize, u32 *pdwArg)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct CHNL_IOC chnlIOC;
+	DSP_STATUS status = DSP_SOK;
+	void *pTmpBuf = NULL;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(pBufPtr != NULL);
+	DBC_Require(pulBytes != NULL);
+	DBC_Require(pdwArg != NULL);
+
+	GT_4trace(STRM_debugMask, GT_ENTER,
+		 "STRM_Reclaim: hStrm: 0x%x\tpBufPtr: 0x%x"
+		 "\tpulBytes: 0x%x\tpdwArg: 0x%x\n", hStrm, pBufPtr, pulBytes,
+		 pdwArg);
+
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+		goto func_end;
+	}
+	pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+	status = (*pIntfFxns->pfnChnlGetIOC)(hStrm->hChnl, hStrm->uTimeout,
+		 &chnlIOC);
+	if (DSP_FAILED(status)) {
+		GT_1trace(STRM_debugMask, GT_6CLASS,
+			 "STRM_Reclaim: GetIOC failed! "
+			 "Status = 0x%x\n", status);
+	} else {
+		*pulBytes = chnlIOC.cBytes;
+		if (pulBufSize)
+			*pulBufSize = chnlIOC.cBufSize;
+
+		*pdwArg = chnlIOC.dwArg;
+		if (!CHNL_IsIOComplete(chnlIOC)) {
+			if (CHNL_IsTimedOut(chnlIOC)) {
+				status = DSP_ETIMEOUT;
+			} else {
+				/* Allow reclaims after idle to succeed */
+				if (!CHNL_IsIOCancelled(chnlIOC))
+					status = DSP_EFAIL;
+
+			}
+		}
+		/* Translate zerocopy buffer if channel not canceled. */
+		if (DSP_SUCCEEDED(status) && (!CHNL_IsIOCancelled(chnlIOC)) &&
+		   (hStrm->lMode == STRMMODE_ZEROCOPY)) {
+			/*
+			 *  This is a zero-copy channel so chnlIOC.pBuf
+			 *  contains the DSP address of SM. We need to
+			 *  translate it to a virtual address for the user
+			 *  thread to access.
+			 *  Note: Could add CMM_DSPPA2VA to CMM in the future.
+			 */
+			pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+					chnlIOC.pBuf, CMM_DSPPA2PA);
+			if (pTmpBuf != NULL) {
+				/* now convert this GPP Pa to Va */
+				pTmpBuf = CMM_XlatorTranslate(hStrm->hXlator,
+					  pTmpBuf, CMM_PA2VA);
+			}
+			if (pTmpBuf == NULL) {
+				GT_0trace(STRM_debugMask, GT_7CLASS,
+					 "STRM_Reclaim: Failed "
+					 "SM translation!\n");
+				status = DSP_ETRANSLATE;
+			}
+			chnlIOC.pBuf = pTmpBuf;
+		}
+		*pBufPtr = chnlIOC.pBuf;
+	}
+func_end:
+	/* ensure we return a documented return code */
+	DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
+		  status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
+		  status == DSP_EFAIL);
+	return status;
+}
+
+/*
+ *  ======== STRM_RegisterNotify ========
+ *  Purpose:
+ *      Register to be notified on specific events for this stream.
+ */
+DSP_STATUS STRM_RegisterNotify(struct STRM_OBJECT *hStrm, u32 uEventMask,
+			      u32 uNotifyType, struct DSP_NOTIFICATION
+			      *hNotification)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(hNotification != NULL);
+
+	GT_4trace(STRM_debugMask, GT_ENTER,
+		 "STRM_RegisterNotify: hStrm: 0x%x\t"
+		 "uEventMask: 0x%x\tuNotifyType: 0x%x\thNotification: 0x%x\n",
+		 hStrm, uEventMask, uNotifyType, hNotification);
+	if (!MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		status = DSP_EHANDLE;
+	} else if ((uEventMask & ~((DSP_STREAMIOCOMPLETION) |
+		 DSP_STREAMDONE)) != 0) {
+		status = DSP_EVALUE;
+	} else {
+		if (uNotifyType != DSP_SIGNALEVENT)
+			status = DSP_ENOTIMPL;
+
+	}
+	if (DSP_SUCCEEDED(status)) {
+		pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+
+		status = (*pIntfFxns->pfnChnlRegisterNotify)(hStrm->hChnl,
+			 uEventMask, uNotifyType, hNotification);
+	}
+	/* ensure we return a documented return code */
+	DBC_Ensure(DSP_SUCCEEDED(status) || status == DSP_EHANDLE ||
+		  status == DSP_ETIMEOUT || status == DSP_ETRANSLATE ||
+		  status == DSP_ENOTIMPL || status == DSP_EFAIL);
+	return status;
+}
+
+/*
+ *  ======== STRM_Select ========
+ *  Purpose:
+ *      Selects a ready stream.
+ */
+DSP_STATUS STRM_Select(IN struct STRM_OBJECT **aStrmTab, u32 nStrms,
+		      OUT u32 *pMask, u32 uTimeout)
+{
+	u32 uIndex;
+	struct CHNL_INFO chnlInfo;
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	struct SYNC_OBJECT **hSyncEvents = NULL;
+	u32 i;
+	DSP_STATUS status = DSP_SOK;
+
+	DBC_Require(cRefs > 0);
+	DBC_Require(aStrmTab != NULL);
+	DBC_Require(pMask != NULL);
+	DBC_Require(nStrms > 0);
+
+	GT_4trace(STRM_debugMask, GT_ENTER,
+		 "STRM_Select: aStrmTab: 0x%x \tnStrms: "
+		 "0x%x\tpMask: 0x%x\tuTimeout: 0x%x\n", aStrmTab,
+		 nStrms, pMask, uTimeout);
+	*pMask = 0;
+	for (i = 0; i < nStrms; i++) {
+		if (!MEM_IsValidHandle(aStrmTab[i], STRM_SIGNATURE)) {
+			status = DSP_EHANDLE;
+			break;
+		}
+	}
+	if (DSP_FAILED(status))
+		goto func_end;
+
+	/* Determine which channels have IO ready */
+	for (i = 0; i < nStrms; i++) {
+		pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
+		status = (*pIntfFxns->pfnChnlGetInfo)(aStrmTab[i]->hChnl,
+			 &chnlInfo);
+		if (DSP_FAILED(status)) {
+			break;
+		} else {
+			if (chnlInfo.cIOCs > 0)
+				*pMask |= (1 << i);
+
+		}
+	}
+	if (DSP_SUCCEEDED(status) && uTimeout > 0 && *pMask == 0) {
+		/* Non-zero timeout */
+		hSyncEvents = (struct SYNC_OBJECT **)MEM_Alloc(nStrms *
+			      sizeof(struct SYNC_OBJECT *), MEM_PAGED);
+		if (hSyncEvents == NULL) {
+			status = DSP_EMEMORY;
+		} else {
+			for (i = 0; i < nStrms; i++) {
+				pIntfFxns = aStrmTab[i]->hStrmMgr->pIntfFxns;
+				status = (*pIntfFxns->pfnChnlGetInfo)
+					 (aStrmTab[i]->hChnl, &chnlInfo);
+				if (DSP_FAILED(status))
+					break;
+				else
+					hSyncEvents[i] = chnlInfo.hSyncEvent;
+
+			}
+		}
+		if (DSP_SUCCEEDED(status)) {
+			status = SYNC_WaitOnMultipleEvents(hSyncEvents, nStrms,
+				uTimeout, &uIndex);
+			if (DSP_SUCCEEDED(status)) {
+				/* Since we waited on the event, we have to
+				 * reset it */
+				SYNC_SetEvent(hSyncEvents[uIndex]);
+				*pMask = 1 << uIndex;
+			}
+		}
+	}
+func_end:
+	if (hSyncEvents)
+		MEM_Free(hSyncEvents);
+
+	DBC_Ensure((DSP_SUCCEEDED(status) && (*pMask != 0 || uTimeout == 0)) ||
+		  (DSP_FAILED(status) && *pMask == 0));
+
+	return status;
+}
+
+/*
+ *  ======== DeleteStrm ========
+ *  Purpose:
+ *      Frees the resources allocated for a stream.
+ */
+static DSP_STATUS DeleteStrm(struct STRM_OBJECT *hStrm)
+{
+	struct WMD_DRV_INTERFACE *pIntfFxns;
+	DSP_STATUS status = DSP_SOK;
+
+	if (MEM_IsValidHandle(hStrm, STRM_SIGNATURE)) {
+		if (hStrm->hChnl) {
+			pIntfFxns = hStrm->hStrmMgr->pIntfFxns;
+			/* Channel close can fail only if the channel handle
+			 * is invalid. */
+			status = (*pIntfFxns->pfnChnlClose) (hStrm->hChnl);
+			/* Free all SM address translator resources */
+			if (DSP_SUCCEEDED(status)) {
+				if (hStrm->hXlator) {
+					/* force free */
+					(void)CMM_XlatorDelete(hStrm->hXlator,
+					true);
+				}
+			}
+		}
+		MEM_FreeObject(hStrm);
+	} else {
+		status = DSP_EHANDLE;
+	}
+	return status;
+}
+
+/*
+ *  ======== DeleteStrmMgr ========
+ *  Purpose:
+ *      Frees stream manager.
+ */
+static void DeleteStrmMgr(struct STRM_MGR *hStrmMgr)
+{
+	if (MEM_IsValidHandle(hStrmMgr, STRMMGR_SIGNATURE)) {
+
+		if (hStrmMgr->hSync)
+			SYNC_DeleteCS(hStrmMgr->hSync);
+
+		MEM_FreeObject(hStrmMgr);
+	}
+}
+
-- 
1.5.5.1.357.g1af8b

