/* * ======== STRM_Close ======== * Purpose: * Close a stream opened with STRM_Open(). */ DSP_STATUS STRM_Close(struct STRM_OBJECT *hStrm, struct PROCESS_CONTEXT *pr_ctxt) { struct WMD_DRV_INTERFACE *pIntfFxns; struct CHNL_INFO chnlInfo; DSP_STATUS status = DSP_SOK; HANDLE hSTRMRes; DBC_Require(cRefs > 0); GT_1trace(STRM_debugMask, GT_ENTER, "STRM_Close: hStrm: 0x%x\n", hStrm); /* 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)) goto func_end; if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pr_ctxt) != DSP_ENOTFOUND) DRV_ProcRemoveSTRMResElement(hSTRMRes, pr_ctxt); func_end: DBC_Ensure(status == DSP_SOK || status == DSP_EHANDLE || status == DSP_EPENDING || 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; 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; }
/* * ======== 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; }