示例#1
0
/*
 *  ======== 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));


	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;
}
示例#2
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;
}