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; }
/** ============================================================================ * @func KFILEDEF_Tell * * @desc Returns the current file pointer position for the specified * file handle. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS KFILEDEF_Tell (IN Void * fileHandle, OUT Int32 * pos) { DSP_STATUS status = DSP_SOK ; KFILEDEF_Object * fileObj = NULL ; TRC_2ENTER ("KFILEDEF_Tell", fileObj, pos) ; DBC_Require (fileHandle != NULL) ; DBC_Require (pos != NULL) ; if (pos == NULL) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else { fileObj = (KFILEDEF_Object *) fileHandle ; *pos = fileObj->curPos ; DBC_Assert (*pos == fileObj->fileDesc->f_pos) ; } DBC_Ensure ( (DSP_SUCCEEDED (status) && (pos != NULL) && (*pos >= 0)) || (DSP_FAILED (status))) ; TRC_1LEAVE ("KFILEDEF_Tell", status) ; return status ; }
/** ============================================================================ * @func LIST_PutTail * * @desc Adds the specified element to the tail of the list. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS LIST_PutTail (IN List * list, IN ListElement * element) { DSP_STATUS status = DSP_SOK ; TRC_2ENTER ("LIST_PutTail", list, element) ; DBC_Require (list != NULL) ; DBC_Require (element != NULL) ; if ((list == NULL) || (element == NULL)) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else { element->prev = list->head.prev ; element->next = &list->head ; list->head.prev = element ; element->prev->next = element ; } DBC_Assert ( (DSP_SUCCEEDED (status) && (!LIST_IsEmpty (list))) || (DSP_FAILED (status))); TRC_1LEAVE ("LIST_PutTail", status) ; return status ; }
/* * ======== NTFY_Delete ======== * Purpose: * Free resources allocated in NTFY_Create. */ void NTFY_Delete(struct NTFY_OBJECT *hNtfy) { struct NOTIFICATION *pNotify; DBC_Require(MEM_IsValidHandle(hNtfy, NTFY_SIGNATURE)); /* Remove any elements remaining in list */ if (hNtfy->notifyList) { (void) SYNC_EnterCS(hNtfy->hSync); while ((pNotify = (struct NOTIFICATION *)LST_GetHead(hNtfy-> notifyList))) { DeleteNotify(pNotify); } DBC_Assert(LST_IsEmpty(hNtfy->notifyList)); kfree(hNtfy->notifyList); (void) SYNC_LeaveCS(hNtfy->hSync); } if (hNtfy->hSync) (void)SYNC_DeleteCS(hNtfy->hSync); MEM_FreeObject(hNtfy); }
/* * ======== STRM_FreeBuffer ======== * Purpose: * Frees the buffers allocated for a stream. */ DSP_STATUS STRM_FreeBuffer(struct STRM_OBJECT *hStrm, u8 **apBuffer, u32 uNumBufs, struct PROCESS_CONTEXT *pr_ctxt) { DSP_STATUS status = DSP_SOK; u32 i = 0; HANDLE hSTRMRes = NULL; DBC_Require(cRefs > 0); DBC_Require(apBuffer != NULL); for (i = 0; i < uNumBufs; i++) { DBC_Assert(hStrm->hXlator != NULL); status = CMM_XlatorFreeBuf(hStrm->hXlator, apBuffer[i]); if (DSP_FAILED(status)) break; apBuffer[i] = NULL; } if (DSP_SUCCEEDED(status)) { if (DRV_GetSTRMResElement(hStrm, hSTRMRes, pr_ctxt) != DSP_ENOTFOUND) DRV_ProcUpdateSTRMRes(uNumBufs-i, hSTRMRes); } return status; }
/* * ======== MGR_Init ======== * Initialize MGR's private state, keeping a reference count on each call. */ bool 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; }
/* This function maps kernel space memory to user space memory. */ static 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); /* TODO: Check for valid size. */ /* It looks right now like this can map all of kernel memory if requested */ 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; }
/* * ======== WMD_CHNL_Close ======== * Purpose: * Ensures all pending I/O on this channel is cancelled, discards all * queued I/O completion notifications, then frees the resources allocated * for this channel, and makes the corresponding logical channel id * available for subsequent use. */ DSP_STATUS WMD_CHNL_Close(struct CHNL_OBJECT *hChnl) { DSP_STATUS status; struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl; /* Check args: */ if (!MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)) { status = DSP_EHANDLE; goto func_cont; } { /* Cancel IO: this ensures no further IO requests or * notifications.*/ status = WMD_CHNL_CancelIO(hChnl); } func_cont: if (DSP_SUCCEEDED(status)) { /* Assert I/O on this channel is now cancelled: Protects * from IO_DPC. */ DBC_Assert((pChnl->dwState & CHNL_STATECANCEL)); /* Invalidate channel object: Protects from * CHNL_GetIOCompletion(). */ pChnl->dwSignature = 0x0000; /* Free the slot in the channel manager: */ pChnl->pChnlMgr->apChannel[pChnl->uId] = NULL; pChnl->pChnlMgr->cOpenChannels -= 1; if (pChnl->hNtfy) { NTFY_Delete(pChnl->hNtfy); pChnl->hNtfy = NULL; } /* Reset channel event: (NOTE: hUserEvent freed in user * context.). */ if (pChnl->hSyncEvent) { SYNC_ResetEvent(pChnl->hSyncEvent); SYNC_CloseEvent(pChnl->hSyncEvent); pChnl->hSyncEvent = NULL; } /* Free I/O request and I/O completion queues: */ if (pChnl->pIOCompletions) { FreeChirpList(pChnl->pIOCompletions); pChnl->pIOCompletions = NULL; pChnl->cIOCs = 0; } if (pChnl->pIORequests) { FreeChirpList(pChnl->pIORequests); pChnl->pIORequests = NULL; pChnl->cIOReqs = 0; } if (pChnl->pFreeList) { FreeChirpList(pChnl->pFreeList); pChnl->pFreeList = NULL; } /* Release channel object. */ MEM_FreeObject(pChnl); pChnl = NULL; } DBC_Ensure(DSP_FAILED(status) || !MEM_IsValidHandle(pChnl, CHNL_SIGNATURE)); return status; }
/** ============================================================================ * @func LDRV_MPLIST_isEmpty * * @desc check for an empty list. * * @modif None. * ============================================================================ */ EXPORT_API Bool LDRV_MPLIST_isEmpty (IN ProcessorId dspId, IN List * list ) { Bool retVal = FALSE ; LDRV_MPLIST_Object * mplistState ; Uint32 temp ; TRC_2ENTER ("LDRV_MPLIST_isEmpty", dspId, list) ; DBC_Require (IS_VALID_PROCID(dspId)) ; DBC_Require (list != NULL) ; DBC_Assert (LDRV_MPLIST_IsInitialized [dspId] == TRUE) ; mplistState = &(LDRV_MPLIST_State [dspId]) ; temp = SWAP_LONG (DSP_addrConvert (dspId, (Uint32) &((list)->head), GppToDsp), mplistState->wordSwap) ; if ( ((Uint32) (list)->head.next) == temp) { retVal = TRUE ; } TRC_1LEAVE ("LDRV_MPLIST_isEmpty", retVal) ; return retVal ; }
/* * ======== DBLL_init ======== */ bool DBLL_init(void) { bool retVal = true; DBC_Require(cRefs >= 0); if (cRefs == 0) { DBC_Assert(!DBLL_debugMask.flags); GT_create(&DBLL_debugMask, "DL"); /* "DL" for dbDL */ GH_init(); retVal = MEM_Init(); if (!retVal) MEM_Exit(); } if (retVal) cRefs++; GT_1trace(DBLL_debugMask, GT_5CLASS, "DBLL_init(), ref count: 0x%x\n", cRefs); DBC_Ensure((retVal && (cRefs > 0)) || (!retVal && (cRefs >= 0))); return retVal; }
/* * ======== WMD_CHNL_Destroy ======== * Purpose: * Close all open channels, and destroy the channel manager. */ DSP_STATUS WMD_CHNL_Destroy(struct CHNL_MGR *hChnlMgr) { DSP_STATUS status = DSP_SOK; struct CHNL_MGR *pChnlMgr = hChnlMgr; u32 iChnl; if (MEM_IsValidHandle(hChnlMgr, CHNL_MGRSIGNATURE)) { /* Close all open channels: */ for (iChnl = 0; iChnl < pChnlMgr->cChannels; iChnl++) { if (DSP_SUCCEEDED (WMD_CHNL_Close(pChnlMgr->apChannel[iChnl]))) { DBC_Assert(pChnlMgr->apChannel[iChnl] == NULL); } } /* release critical section */ if (pChnlMgr->hCSObj) SYNC_DeleteCS(pChnlMgr->hCSObj); /* Free channel manager object: */ if (pChnlMgr->apChannel) MEM_Free(pChnlMgr->apChannel); /* Set hChnlMgr to NULL in device object. */ DEV_SetChnlMgr(pChnlMgr->hDevObject, NULL); /* Free this Chnl Mgr object: */ MEM_FreeObject(hChnlMgr); } else { status = DSP_EHANDLE; } return status; }
/** ============================================================================ * @func LIST_InsertBefore * * @desc Insert the element before the existing element. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS LIST_InsertBefore (IN List * list, IN ListElement * insertElement, IN ListElement * existingElement) { DSP_STATUS status = DSP_SOK ; TRC_3ENTER ("LIST_InsertBefore", list, insertElement, existingElement) ; DBC_Require(list != NULL) ; DBC_Require(insertElement != NULL) ; DBC_Require(existingElement != NULL) ; if ( (list == NULL) || (insertElement == NULL) || (existingElement == NULL)) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else { existingElement->prev->next = insertElement ; insertElement->prev = existingElement->prev ; insertElement->next = existingElement ; existingElement->prev = insertElement ; } DBC_Assert ( (DSP_SUCCEEDED (status) && (!LIST_IsEmpty (list))) || (DSP_FAILED (status))); TRC_1LEAVE ("LIST_InsertBefore", status) ; return status ; }
/* * ======== 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; }
/* * ======== WMD_CHNL_Create ======== * Create a channel manager object, responsible for opening new channels * and closing old ones for a given board. */ DSP_STATUS WMD_CHNL_Create(OUT struct CHNL_MGR **phChnlMgr, struct DEV_OBJECT *hDevObject, IN CONST struct CHNL_MGRATTRS *pMgrAttrs) { DSP_STATUS status = DSP_SOK; struct CHNL_MGR *pChnlMgr = NULL; s32 cChannels; /* Check DBC requirements: */ DBC_Require(phChnlMgr != NULL); DBC_Require(pMgrAttrs != NULL); DBC_Require(pMgrAttrs->cChannels > 0); DBC_Require(pMgrAttrs->cChannels <= CHNL_MAXCHANNELS); DBC_Require(pMgrAttrs->uWordSize != 0); /* Allocate channel manager object: */ MEM_AllocObject(pChnlMgr, struct CHNL_MGR, CHNL_MGRSIGNATURE); if (pChnlMgr) { /* The cChannels attr must equal the # of supported * chnls for each transport(# chnls for PCPY = DDMA = * ZCPY): i.e. pMgrAttrs->cChannels = CHNL_MAXCHANNELS = * DDMA_MAXDDMACHNLS = DDMA_MAXZCPYCHNLS. */ DBC_Assert(pMgrAttrs->cChannels == CHNL_MAXCHANNELS); cChannels = CHNL_MAXCHANNELS + CHNL_MAXCHANNELS * CHNL_PCPY; /* Create array of channels: */ pChnlMgr->apChannel = MEM_Calloc( sizeof(struct CHNL_OBJECT *) * cChannels, MEM_NONPAGED); if (pChnlMgr->apChannel) { /* Initialize CHNL_MGR object: */ /* Shared memory driver. */ pChnlMgr->dwType = CHNL_TYPESM; pChnlMgr->uWordSize = pMgrAttrs->uWordSize; /* total # chnls supported */ pChnlMgr->cChannels = cChannels; pChnlMgr->cOpenChannels = 0; pChnlMgr->dwOutputMask = 0; pChnlMgr->dwLastOutput = 0; pChnlMgr->hDevObject = hDevObject; if (DSP_SUCCEEDED(status)) status = SYNC_InitializeDPCCS( &pChnlMgr->hCSObj); } else { status = DSP_EMEMORY; } } else { status = DSP_EMEMORY; } if (DSP_FAILED(status)) { WMD_CHNL_Destroy(pChnlMgr); *phChnlMgr = NULL; } else { /* Return channel manager object to caller... */ *phChnlMgr = pChnlMgr; } return status; }
/** ============================================================================ * @func LDRV_MPLIST_removeElement * * @desc Removes (unlinks) the given element from the list, if the list is * not empty. Does not free the list element. This function works on * the list object and element fields in DSP address space.If the * element is from pool memory, it does the invalidate and writeback * operations on the element. If the element is from a non pool shared * memory, invalidate writeback operations are not performed. * * @modif None. * ============================================================================ */ EXPORT_API Void LDRV_MPLIST_removeElement (IN ProcessorId dspId, IN List * list, IN ListElement * element ) { PoolId poolId = POOL_INVALIDID ; LDRV_MPLIST_Object * mplistState ; ListElement * temp ; TRC_4ENTER ("LDRV_MPLIST_removeElement", dspId, list, element, poolId) ; DBC_Require (IS_VALID_PROCID (dspId)) ; DBC_Require (list != NULL) ; DBC_Require (element != NULL) ; DBC_Assert (LDRV_MPLIST_IsInitialized [dspId] == TRUE) ; mplistState = &(LDRV_MPLIST_State [dspId]) ; if (LDRV_MPLIST_isEmpty (dspId, list) == FALSE) { temp = (ListElement *) DSP_addrConvert (dspId, SWAP_LONG ((Uint32) (element->prev), mplistState->wordSwap), DspToGpp) ; LDRV_POOL_getPoolId (dspId, temp, AddrType_Knl, &poolId ); if (IS_VALID_POOLID (poolId)) { LDRV_POOL_invalidate (poolId, temp, sizeof (ListElement)) ; } temp->next = element->next ; if (IS_VALID_POOLID (poolId)) { LDRV_POOL_writeback (poolId, temp, sizeof (ListElement)) ; } temp = (ListElement *) DSP_addrConvert (dspId, SWAP_LONG ((Uint32) (element->next), mplistState->wordSwap), DspToGpp) ; LDRV_POOL_getPoolId (dspId, temp, AddrType_Knl, &poolId ); if (IS_VALID_POOLID (poolId)) { LDRV_POOL_invalidate (poolId, temp, sizeof (ListElement)) ; } temp->prev = element->prev ; if (IS_VALID_POOLID (poolId)) { LDRV_POOL_writeback (poolId, temp, sizeof (ListElement)) ; } } TRC_0LEAVE ("LDRV_MPLIST_removeElement") ; }
/* * ======== 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; }
/** ============================================================================ * @func KFILEDEF_Read * * @desc Reads a specified number of items of specified size * bytes from file to a buffer. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS KFILEDEF_Read (IN OUT Char8 * buffer, IN Uint32 size, IN Uint32 count, IN Void * fileHandle) { DSP_STATUS status = DSP_SOK ; Int32 bytesRead = 0 ; mm_segment_t fs ; KFILEDEF_Object * fileObj = NULL ; TRC_4ENTER ("KFILEDEF_Read", buffer, size, count, fileHandle) ; DBC_Require (fileHandle != NULL) ; DBC_Require (buffer != NULL) ; if (buffer == NULL) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else if ((size != 0) && (count != 0)) { fileObj = (KFILEDEF_Object *) fileHandle ; if ((fileObj->curPos + (size * count)) > fileObj->size) { status = DSP_ERANGE ; SET_FAILURE_REASON ; } else { /* read from file */ fs = get_fs () ; set_fs (KERNEL_DS) ; bytesRead = fileObj->fileDesc->f_op->read (fileObj->fileDesc, buffer, size * count, &(fileObj->fileDesc->f_pos)); set_fs (fs) ; if (bytesRead >= 0) { fileObj->curPos += bytesRead ; DBC_Assert ((bytesRead / size) == (Uint32) count) ; } else { status = DSP_EFILE; TRC_2PRINT (TRC_LEVEL1, "File Read failed with status [0x%x]\n" "Error value[0x%x]\n", status, bytesRead) ; } } } TRC_1LEAVE ("KFILEDEF_Read", status) ; return status ; }
/* * ======== 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; }
/* * ======== WMD_CHNL_CancelIO ======== * Return all I/O requests to the client which have not yet been * transferred. The channel's I/O completion object is * signalled, and all the I/O requests are queued as IOC's, with the * status field set to CHNL_IOCSTATCANCEL. * This call is typically used in abort situations, and is a prelude to * CHNL_Close(); */ DSP_STATUS WMD_CHNL_CancelIO(struct CHNL_OBJECT *hChnl) { DSP_STATUS status = DSP_SOK; struct CHNL_OBJECT *pChnl = (struct CHNL_OBJECT *)hChnl; u32 iChnl = -1; short int uMode; struct CHNL_IRP *pChirp; struct CHNL_MGR *pChnlMgr = NULL; /* Check args: */ if (MEM_IsValidHandle(pChnl, CHNL_SIGNATURE) && pChnl->pChnlMgr) { iChnl = pChnl->uId; uMode = pChnl->uMode; pChnlMgr = pChnl->pChnlMgr; } else { status = DSP_EHANDLE; } if (DSP_FAILED(status)) goto func_end; /* Mark this channel as cancelled, to prevent further IORequests or * IORequests or dispatching. */ SYNC_EnterCS(pChnlMgr->hCSObj); pChnl->dwState |= CHNL_STATECANCEL; if (LST_IsEmpty(pChnl->pIORequests)) goto func_cont; if (pChnl->uChnlType == CHNL_PCPY) { /* Indicate we have no more buffers available for transfer: */ if (CHNL_IsInput(pChnl->uMode)) { IO_CancelChnl(pChnlMgr->hIOMgr, iChnl); } else { /* Record that we no longer have output buffers * available: */ pChnlMgr->dwOutputMask &= ~(1 << iChnl); } } /* Move all IOR's to IOC queue: */ while (!LST_IsEmpty(pChnl->pIORequests)) { pChirp = (struct CHNL_IRP *)LST_GetHead(pChnl->pIORequests); if (pChirp) { pChirp->cBytes = 0; pChirp->status |= CHNL_IOCSTATCANCEL; LST_PutTail(pChnl->pIOCompletions, (struct list_head *)pChirp); pChnl->cIOCs++; pChnl->cIOReqs--; DBC_Assert(pChnl->cIOReqs >= 0); } } func_cont: SYNC_LeaveCS(pChnlMgr->hCSObj); func_end: return status; }
/* * ======== WMD_CHNL_RegisterNotify ======== * Registers for events on a particular channel. */ DSP_STATUS WMD_CHNL_RegisterNotify(struct CHNL_OBJECT *hChnl, u32 uEventMask, u32 uNotifyType, struct DSP_NOTIFICATION *hNotification) { DSP_STATUS status = DSP_SOK; DBC_Assert(!(uEventMask & ~(DSP_STREAMDONE | DSP_STREAMIOCOMPLETION))); status = NTFY_Register(hChnl->hNtfy, hNotification, uEventMask, uNotifyType); return status; }
/* * ======== WMD_MSG_Create ======== * Create an object to manage message queues. Only one of these objects * can exist per device object. */ DSP_STATUS WMD_MSG_Create(OUT struct MSG_MGR **phMsgMgr, struct DEV_OBJECT *hDevObject, MSG_ONEXIT msgCallback) { struct MSG_MGR *pMsgMgr; struct IO_MGR *hIOMgr; DSP_STATUS status = DSP_SOK; DBC_Require(phMsgMgr != NULL); DBC_Require(msgCallback != NULL); DBC_Require(hDevObject != NULL); DEV_GetIOMgr(hDevObject, &hIOMgr); DBC_Assert(hIOMgr != NULL); *phMsgMgr = NULL; /* Allocate MSG manager object */ MEM_AllocObject(pMsgMgr, struct MSG_MGR, MSGMGR_SIGNATURE); if (pMsgMgr) { pMsgMgr->onExit = msgCallback; pMsgMgr->hIOMgr = hIOMgr; /* List of MSG_QUEUEs */ pMsgMgr->queueList = LST_Create(); /* Queues of message frames for messages to the DSP. Message * frames will only be added to the free queue when a * MSG_QUEUE object is created. */ pMsgMgr->msgFreeList = LST_Create(); pMsgMgr->msgUsedList = LST_Create(); if (pMsgMgr->queueList == NULL || pMsgMgr->msgFreeList == NULL || pMsgMgr->msgUsedList == NULL) status = DSP_EMEMORY; if (DSP_SUCCEEDED(status)) status = SYNC_InitializeDPCCS(&pMsgMgr->hSyncCS); /* Create an event to be used by WMD_MSG_Put() in waiting * for an available free frame from the message manager. */ if (DSP_SUCCEEDED(status)) status = SYNC_OpenEvent(&pMsgMgr->hSyncEvent, NULL); if (DSP_SUCCEEDED(status)) *phMsgMgr = pMsgMgr; else DeleteMsgMgr(pMsgMgr); } else { status = DSP_EMEMORY; } return status; }
/* * ======== FreeMsgList ======== */ static void FreeMsgList(struct LST_LIST *msgList) { struct MSG_FRAME *pMsg; if (!msgList) goto func_end; while ((pMsg = (struct MSG_FRAME *)LST_GetHead(msgList)) != NULL) MEM_Free(pMsg); DBC_Assert(LST_IsEmpty(msgList)); LST_Delete(msgList); func_end: return; }
/* * ======== KFILE_Read ======== * Purpose: * Reads a specified number of bytes into a buffer. */ s32 KFILE_Read(void __user*pBuffer, s32 cSize, s32 cCount, struct KFILE_FileObj *hFile) { u32 dwBytesRead = 0; s32 cRetVal = 0; mm_segment_t fs; DBC_Require(pBuffer != NULL); GT_4trace(KFILE_debugMask, GT_4CLASS, "KFILE_Read: buffer 0x%x, cSize 0x%x," "cCount 0x%x, hFile 0x%x\n", pBuffer, cSize, cCount, hFile); /* check for valid file handle */ if (MEM_IsValidHandle(hFile, SIGNATURE)) { if ((cSize > 0) && (cCount > 0) && pBuffer) { /* read from file */ fs = get_fs(); set_fs(get_ds()); dwBytesRead = hFile->fileDesc->f_op->read(hFile-> fileDesc, pBuffer, cSize *cCount, &(hFile->fileDesc->f_pos)); set_fs(fs); if (dwBytesRead) { cRetVal = dwBytesRead / cSize; hFile->curPos += dwBytesRead; DBC_Assert((dwBytesRead / cSize) <= \ (u32)cCount); } else { cRetVal = E_KFILE_ERROR; GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Read: sys_read() failed\n"); } } else { cRetVal = DSP_EINVALIDARG; GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Read: Invalid argument(s)\n"); } } else { cRetVal = E_KFILE_INVALIDHANDLE; GT_0trace(KFILE_debugMask, GT_6CLASS, "KFILE_Read: invalid file handle\n"); } return cRetVal; }
/* * ======== 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; }
/* * ======== 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; }
/* * ======== MSG_Init ======== */ bool MSG_Init(void) { DBC_Require(cRefs >= 0); if (cRefs == 0) { DBC_Assert(!MSG_debugMask.flags); GT_create(&MSG_debugMask, "MS"); /* "MS" for MSg */ } cRefs++; GT_1trace(MSG_debugMask, GT_5CLASS, "MSG_Init(), ref count: 0x%x\n", cRefs); DBC_Ensure(cRefs >= 0); return true; }
/* * ======== STRM_AllocateBuffer ======== * Purpose: * Allocates buffers for a stream. */ DSP_STATUS STRM_AllocateBuffer(struct STRM_OBJECT *hStrm, u32 uSize, OUT u8 **apBuffer, u32 uNumBufs, struct PROCESS_CONTEXT *pr_ctxt) { DSP_STATUS status = DSP_SOK; u32 uAllocated = 0; u32 i; HANDLE hSTRMRes; DBC_Require(cRefs > 0); DBC_Require(apBuffer != NULL); /* * Allocate from segment specified at time of stream open. */ if (uSize == 0) status = DSP_ESIZE; if (DSP_FAILED(status)) 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) { status = DSP_EMEMORY; uAllocated = i; break; } } if (DSP_FAILED(status)) STRM_FreeBuffer(hStrm, apBuffer, uAllocated, pr_ctxt); if (DSP_FAILED(status)) goto func_end; if (DRV_GetSTRMResElement(hStrm, &hSTRMRes, pr_ctxt) != DSP_ENOTFOUND) DRV_ProcUpdateSTRMRes(uNumBufs, hSTRMRes); func_end: return status; }
/* * ======== 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; }
/* * ======== COD_Init ======== * Purpose: * Initialize the COD module's private state. * */ bool COD_Init(void) { bool fRetVal = true; DBC_Require(cRefs >= 0); if (cRefs == 0) { DBC_Assert(!COD_debugMask.flags); GT_create(&COD_debugMask, "CO"); } if (fRetVal) cRefs++; GT_1trace(COD_debugMask, GT_1CLASS, "Entered COD_Init, ref count: 0x%x\n", cRefs); DBC_Ensure((fRetVal && cRefs > 0) || (!fRetVal && cRefs >= 0)); return fRetVal; }
/* * ======== 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++; DBC_Ensure((fRetVal && (cRefs > 0)) || (!fRetVal && (cRefs >= 0))); return fRetVal; }