Esempio n. 1
0
/*
 *  ======== 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;
}
Esempio n. 2
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;
       u32                  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 */
       /* Return PID instead of process handle */
       hProcess = current->pid;

	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_SUCCEEDED(res_status)) {
               DRV_GetProcContext(hProcess,
				 (struct DRV_OBJECT *)hDrvObject, &pCtxt,
				 NULL, 0);
		if (pCtxt != NULL) {
			if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pCtxt) !=
			   DSP_ENOTFOUND) {
				DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes,
						     pCtxt);
			}
		}
	}
#endif
	return status;
}
static int __devexit omap34xx_bridge_remove(struct platform_device *pdev)
{
	dev_t devno;
	bool ret;
	DSP_STATUS dsp_status = DSP_SOK;
	HANDLE hDrvObject = NULL;

	dsp_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_FAILED(dsp_status))
		goto func_cont;

#ifdef CONFIG_BRIDGE_DVFS
	if (clk_notifier_unregister(clk_handle, &iva_clk_notifier))
		pr_err("%s: clk_notifier_unregister failed for iva2_ck\n",
								__func__);
#endif /* #ifdef CONFIG_BRIDGE_DVFS */

	if (driverContext) {
		/* Put the DSP in reset state */
		ret = DSP_Deinit(driverContext);
		driverContext = 0;
		DBC_Assert(ret == true);
	}

#ifdef CONFIG_BRIDGE_DVFS
	clk_put(clk_handle);
	clk_handle = NULL;
#endif

func_cont:

#ifdef CONFIG_PM
	/* The suspend wait queue should not have anything waiting on it
	   since remove won't be called while the file is open */
	DBC_Assert(!waitqueue_active(&bridge_suspend_data.suspend_wq));
#endif
	MEM_ExtPhysPoolRelease();

	SERVICES_Exit();
	GT_exit();

	/* Remove driver sysfs entries */
	bridge_destroy_sysfs();

	devno = MKDEV(driver_major, 0);
	cdev_del(&bridge_cdev);
	unregister_chrdev_region(devno, 1);
	if (bridge_class) {
		/* remove the device from sysfs */
		device_destroy(bridge_class, MKDEV(driver_major, 0));
		class_destroy(bridge_class);

	}
	return 0;
}
Esempio n. 4
0
/*
 *  ======== 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;
       u32                  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
       /* Return PID instead of process handle */
       hProcess = current->pid;

	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_SUCCEEDED(res_status)) {
               DRV_GetProcContext(hProcess,
				 (struct DRV_OBJECT *)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;
}
Esempio n. 5
0
/*
 *  ======== 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
    u32                      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 */
       /* Return PID instead of process handle */
       hProcess = current->pid;

	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_FAILED(res_status))
		goto func_end;

       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)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;
}
Esempio n. 6
0
/*
 *  ======== 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;
       u32                  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;

       /* Return PID instead of process handle */
       hProcess = current->pid;

	res_status = CFG_GetObject((u32 *)&hDrvObject, REG_DRV_OBJECT);
	if (DSP_FAILED(res_status))
		goto func_end;

       DRV_GetProcContext(hProcess, (struct DRV_OBJECT *)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;
}
Esempio n. 7
0
/*
 *  ======== 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;
}
Esempio n. 8
0
/*
 *  ======== 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;
}