/** ============================================================================ * @func MEM_Calloc * * @desc Allocates the specified number of bytes and memory is set to zero. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS MEM_Calloc (OUT Void ** ptr, IN Uint32 cBytes, IN OUT Pvoid arg) { DSP_STATUS status = DSP_SOK ; Uint32 i ; TRC_3ENTER ("MEM_Calloc", ptr, cBytes, arg) ; DBC_Require (ptr != NULL) ; DBC_Require (MEM_IsInitialized == TRUE) ; DBC_Require (cBytes != 0) ; status = MEM_Alloc (ptr, cBytes, arg) ; if (DSP_SUCCEEDED (status)) { for (i = 0 ; i < cBytes ; i++) { (*(Uint8 **) ptr)[i] = 0 ; } } DBC_Ensure ( ((ptr == NULL) && DSP_FAILED (status)) || ((ptr != NULL) && (*ptr != NULL) && DSP_SUCCEEDED (status)) || ((ptr != NULL) && (*ptr == NULL) && DSP_FAILED (status))) ; TRC_1LEAVE ("MEM_Calloc", status) ; return status ; }
/* * ======== NTFY_Create ======== * Purpose: * Create an empty list of notifications. */ DSP_STATUS NTFY_Create(struct NTFY_OBJECT **phNtfy) { struct NTFY_OBJECT *pNtfy; DSP_STATUS status = DSP_SOK; DBC_Require(phNtfy != NULL); *phNtfy = NULL; MEM_AllocObject(pNtfy, struct NTFY_OBJECT, NTFY_SIGNATURE); if (pNtfy) { status = SYNC_InitializeDPCCS(&pNtfy->hSync); if (DSP_SUCCEEDED(status)) { pNtfy->notifyList = MEM_Calloc(sizeof(struct LST_LIST), MEM_NONPAGED); if (pNtfy->notifyList == NULL) { (void) SYNC_DeleteCS(pNtfy->hSync); MEM_FreeObject(pNtfy); status = DSP_EMEMORY; } else { INIT_LIST_HEAD(&pNtfy->notifyList->head); *phNtfy = pNtfy; } } } else { status = DSP_EMEMORY; } DBC_Ensure((DSP_FAILED(status) && *phNtfy == NULL) || (DSP_SUCCEEDED(status) && MEM_IsValidHandle((*phNtfy), NTFY_SIGNATURE))); 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); 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; }
void DataStructuresTest (void) { printf("\n****************************\n"); printf("*** QOS Test version 1.0 ***\n"); printf("****************************\n"); printf ("\n*** TEST CASE 1: Creating and Deleting data structures ***\n"); printf("Calling data create..."); data = DSPData_Create(QOSDataType_Memory_DynAlloc); if (data) { printf("SUCCESS\n"); printf("Calling data delete..."); status = DSPData_Delete(data); if (DSP_SUCCEEDED(status)) printf("SUCCESS\n"); else printf("FAILED\n"); } else printf("FAILED\n"); if (data && DSP_SUCCEEDED(status)) { printf("\nPASSED: data structures can be created and deleted\n"); NumTestsPassed++; NumRegistryTestsPassed++; } else printf("\nFAILED: failed to create and delete data structures\n"); }
/* * ======== MGRWRAP_WaitForBridgeEvents ======== */ u32 MGRWRAP_WaitForBridgeEvents(union Trapped_Args *args, void *pr_ctxt) { DSP_STATUS status = DSP_SOK; struct DSP_NOTIFICATION *aNotifications[MAX_EVENTS]; struct DSP_NOTIFICATION notifications[MAX_EVENTS]; u32 uIndex, i; u32 uCount = args->ARGS_MGR_WAIT.uCount; GT_0trace(WCD_debugMask, GT_ENTER, "MGRWRAP_WaitForBridgeEvents: entered\n"); if (uCount > MAX_EVENTS) status = DSP_EINVALIDARG; /* get the array of pointers to user structures */ cp_fm_usr(aNotifications, args->ARGS_MGR_WAIT.aNotifications, status, uCount); /* get the events */ for (i = 0; i < uCount; i++) { cp_fm_usr(¬ifications[i], aNotifications[i], status, 1); if (DSP_SUCCEEDED(status)) { /* set the array of pointers to kernel structures*/ aNotifications[i] = ¬ifications[i]; } } if (DSP_SUCCEEDED(status)) { status = MGR_WaitForBridgeEvents(aNotifications, uCount, &uIndex, args->ARGS_MGR_WAIT.uTimeout); } cp_to_usr(args->ARGS_MGR_WAIT.puIndex, &uIndex, status, 1); return status; }
/** ============================================================================ * @func DSP_Delete * * @desc This function releases resources allocated earlier by call to * DSP_Create (). * During cleanup, the allocated resources are being freed * unconditionally. Actual applications may require stricter check * against return values for robustness. * * @modif LOOP_Buffers * ============================================================================ */ NORMAL_API Void DSP_Delete (Uint8 processorId) { DSP_STATUS status = DSP_SOK ; DSP_STATUS tmpStatus = DSP_SOK ; LOOP_0Print ("Entered DSP_Delete ()\n") ; status = PROC_stop (processorId) ; tmpStatus = POOL_close (POOL_makePoolId(processorId, 0)) ; if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) { LOOP_1Print ("POOL_close () failed. Status = [0x%x]\n", tmpStatus) ; } tmpStatus = PROC_detach (processorId) ; if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) { LOOP_1Print ("PROC_detach () failed. Status = [0x%x]\n", tmpStatus) ; } tmpStatus = PROC_destroy () ; if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) { LOOP_1Print ("PROC_destroy () failed. Status = [0x%x]\n", tmpStatus) ; } LOOP_0Print ("Leaving DSP_Delete ()\n") ; }
/** ============================================================================ * @func LDRV_init * * @desc Allocates resources and initializes the LDRV component for a DSP. * * @modif None * ============================================================================ */ EXPORT_API DSP_STATUS LDRV_init (IN ProcessorId procId, IN LINKCFG_DspConfig * dspCfg) { DSP_STATUS status = DSP_SOK ; Char8 * dspName = NULL ; TRC_2ENTER ("LDRV_init", procId, dspCfg) ; DBC_Require (LDRV_LinkCfgPtr != NULL) ; DBC_Require (IS_VALID_PROCID (procId)) ; /* ------------------------------------------------------------------------ * Get the pointer to kernel-side APUDRV configuration structure. * ------------------------------------------------------------------------ */ if (dspCfg != NULL) { if (LDRV_LinkCfgPtr->dspConfigs [procId] != NULL) { /* First free the previously read config values */ status = LDRV_freeLinkDspCfg (procId, LDRV_LinkCfgPtr) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; } } if (DSP_SUCCEEDED (status)) { status = LDRV_getLinkDspCfg (procId, dspCfg, LDRV_LinkCfgPtr) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; LDRV_exit (procId) ; } } } else { if (LDRV_LinkCfgPtr->dspConfigs [procId] == NULL) { PRINT_Printf ("For multi-app support, Please pass valid DSP") ; PRINT_Printf ("Config values through PROC_attach.\n") ; status = DSP_ECONFIG ; SET_FAILURE_REASON ; } } /* ------------------------------------------------------------------------ * Plug the correct configuration mapping information for APU DRIVER. * ------------------------------------------------------------------------ */ if (DSP_SUCCEEDED (status)) { dspName = LDRV_LinkCfgPtr->dspConfigs [procId]->dspObject->name ; status = CFGMAP_attachObject (procId, dspName) ; if (DSP_FAILED (status)) { SET_FAILURE_REASON ; LDRV_exit (procId) ; } } TRC_1LEAVE ("LDRV_init", status) ; return status ; }
/* * ======== cmm_create ======== * Purpose: * Create a communication memory manager object. */ int cmm_create(OUT struct cmm_object **ph_cmm_mgr, struct dev_object *hdev_obj, IN CONST struct cmm_mgrattrs *pMgrAttrs) { struct cmm_object *cmm_obj = NULL; int status = 0; struct util_sysinfo sys_info; DBC_REQUIRE(refs > 0); DBC_REQUIRE(ph_cmm_mgr != NULL); *ph_cmm_mgr = NULL; /* create, zero, and tag a cmm mgr object */ cmm_obj = kzalloc(sizeof(struct cmm_object), GFP_KERNEL); if (cmm_obj != NULL) { if (pMgrAttrs == NULL) pMgrAttrs = &cmm_dfltmgrattrs; /* set defaults */ /* 4 bytes minimum */ DBC_ASSERT(pMgrAttrs->ul_min_block_size >= 4); /* save away smallest block allocation for this cmm mgr */ cmm_obj->ul_min_block_size = pMgrAttrs->ul_min_block_size; /* save away the systems memory page size */ sys_info.dw_page_size = PAGE_SIZE; sys_info.dw_allocation_granularity = PAGE_SIZE; sys_info.dw_number_of_processors = 1; if (DSP_SUCCEEDED(status)) { cmm_obj->dw_page_size = sys_info.dw_page_size; } else { cmm_obj->dw_page_size = 0; status = -EPERM; } /* Note: DSP SM seg table(aDSPSMSegTab[]) zero'd by * MEM_ALLOC_OBJECT */ if (DSP_SUCCEEDED(status)) { /* create node free list */ cmm_obj->node_free_list_head = kzalloc(sizeof(struct lst_list), GFP_KERNEL); if (cmm_obj->node_free_list_head == NULL) status = -ENOMEM; else INIT_LIST_HEAD(&cmm_obj-> node_free_list_head->head); } if (DSP_SUCCEEDED(status)) mutex_init(&cmm_obj->cmm_lock); if (DSP_SUCCEEDED(status)) *ph_cmm_mgr = cmm_obj; else cmm_destroy(cmm_obj, true); } else { status = -ENOMEM; } return status; }
/** ============================================================================ * @func LIST_SearchElement * * @desc This function searchs for a element in the List. * * @modif None. * ============================================================================ */ EXPORT_API DSP_STATUS LIST_SearchElement (IN List * list, IN Pvoid data, OUT ListElement ** elem, IN ListMatchFunc matchFunc) { DSP_STATUS status = DSP_SOK ; ListElement * temp = NULL ; ListElement * temp1 = NULL ; Bool found = FALSE ; DBC_Require (list != NULL) ; DBC_Require (elem != NULL) ; DBC_Require (matchFunc != NULL) ; if ((list == NULL) || (elem == NULL)) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } else { if (LIST_IsEmpty (list)) { status = DSP_EINVALIDARG ; SET_FAILURE_REASON ; } if (DSP_SUCCEEDED (status)) { status = LIST_First (list, &temp) ; if (DSP_SUCCEEDED (status)) { while ((found == FALSE) && (temp != NULL)) { if ((*matchFunc) (temp, data) == TRUE) { found = TRUE ; } else { temp1 = temp ; LIST_Next (list, temp1, &temp) ; } } if (found == TRUE) { *elem = temp ; } else { *elem = NULL ; status = DSP_ENOTFOUND ; SET_FAILURE_REASON ; } } else { SET_FAILURE_REASON ; } } } 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; }
/* * ======== dbll_get_sect ======== * Get the base address and size (in bytes) of a COFF section. */ int dbll_get_sect(struct dbll_library_obj *lib, char *name, u32 *paddr, u32 *psize) { u32 byte_size; bool opened_doff = false; const struct ldr_section_info *sect = NULL; struct dbll_library_obj *zl_lib = (struct dbll_library_obj *)lib; int status = 0; DBC_REQUIRE(refs > 0); DBC_REQUIRE(name != NULL); DBC_REQUIRE(paddr != NULL); DBC_REQUIRE(psize != NULL); DBC_REQUIRE(zl_lib); /* If DOFF file is not open, we open it. */ if (zl_lib != NULL) { if (zl_lib->fp == NULL) { status = dof_open(zl_lib); if (DSP_SUCCEEDED(status)) opened_doff = true; } else { (*(zl_lib->target_obj->attrs.fseek)) (zl_lib->fp, zl_lib->ul_pos, SEEK_SET); } } else { status = -EFAULT; } if (DSP_SUCCEEDED(status)) { byte_size = 1; if (dload_get_section_info(zl_lib->desc, name, §)) { *paddr = sect->load_addr; *psize = sect->size * byte_size; /* Make sure size is even for good swap */ if (*psize % 2) (*psize)++; /* Align size */ *psize = DOFF_ALIGN(*psize); } else { status = -ENXIO; } } if (opened_doff) { dof_close(zl_lib); opened_doff = false; } dev_dbg(bridge, "%s: lib: %p name: %s paddr: %p psize: %p, " "status %i\n", __func__, lib, name, paddr, psize, status); return status; }
/* * ======== chnl_create ======== * Purpose: * Create a channel manager object, responsible for opening new channels * and closing old ones for a given 'Bridge board. */ int chnl_create(OUT struct chnl_mgr **phChnlMgr, struct dev_object *hdev_obj, IN CONST struct chnl_mgrattrs *pMgrAttrs) { int status; struct chnl_mgr *hchnl_mgr; struct chnl_mgr_ *chnl_mgr_obj = NULL; DBC_REQUIRE(refs > 0); DBC_REQUIRE(phChnlMgr != NULL); DBC_REQUIRE(pMgrAttrs != NULL); *phChnlMgr = NULL; /* Validate args: */ if ((0 < pMgrAttrs->max_channels) && (pMgrAttrs->max_channels <= CHNL_MAXCHANNELS)) status = 0; else if (pMgrAttrs->max_channels == 0) status = -EINVAL; else status = -ECHRNG; if (pMgrAttrs->word_size == 0) status = -EINVAL; if (DSP_SUCCEEDED(status)) { status = dev_get_chnl_mgr(hdev_obj, &hchnl_mgr); if (DSP_SUCCEEDED(status) && hchnl_mgr != NULL) status = -EEXIST; } if (DSP_SUCCEEDED(status)) { struct bridge_drv_interface *intf_fxns; dev_get_intf_fxns(hdev_obj, &intf_fxns); if (intf_fxns) { /* Let WMD channel module finish the create */ status = (*intf_fxns->pfn_chnl_create)(&hchnl_mgr, hdev_obj, pMgrAttrs); } if (DSP_SUCCEEDED(status)) { /* Fill in WCD channel module's fields of the * chnl_mgr structure */ chnl_mgr_obj = (struct chnl_mgr_ *)hchnl_mgr; chnl_mgr_obj->intf_fxns = intf_fxns; /* Finally, return the new channel manager handle: */ *phChnlMgr = hchnl_mgr; } } DBC_ENSURE(DSP_FAILED(status) || chnl_mgr_obj); return status; }
/* * ======== DBLL_getSect ======== * Get the base address and size (in bytes) of a COFF section. */ DSP_STATUS DBLL_getSect(struct DBLL_LibraryObj *lib, char *name, u32 *pAddr, u32 *pSize) { u32 uByteSize; bool fOpenedDoff = false; const struct LDR_SECTION_INFO *sect = NULL; struct DBLL_LibraryObj *zlLib = (struct DBLL_LibraryObj *)lib; DSP_STATUS status = DSP_SOK; DBC_Require(cRefs > 0); DBC_Require(name != NULL); DBC_Require(pAddr != NULL); DBC_Require(pSize != NULL); DBC_Require(MEM_IsValidHandle(zlLib, DBLL_LIBSIGNATURE)); GT_4trace(DBLL_debugMask, GT_ENTER, "DBLL_getSect: lib: 0x%x name: %s pAddr:" " 0x%x pSize: 0x%x\n", lib, name, pAddr, pSize); /* If DOFF file is not open, we open it. */ if (zlLib != NULL) { if (zlLib->fp == NULL) { status = dofOpen(zlLib); if (DSP_SUCCEEDED(status)) fOpenedDoff = true; } else { (*(zlLib->pTarget->attrs.fseek))(zlLib->fp, zlLib->ulPos, SEEK_SET); } } else { status = DSP_EHANDLE; } if (DSP_SUCCEEDED(status)) { uByteSize = 1; if (DLOAD_GetSectionInfo(zlLib->desc, name, §)) { *pAddr = sect->load_addr; *pSize = sect->size * uByteSize; /* Make sure size is even for good swap */ if (*pSize % 2) (*pSize)++; /* Align size */ *pSize = DOFF_ALIGN(*pSize); } else { status = DSP_ENOSECT; } } if (fOpenedDoff) { dofClose(zlLib); fOpenedDoff = false; } return status; }
/* * ======== cmm_destroy ======== * Purpose: * Release the communication memory manager resources. */ int cmm_destroy(struct cmm_object *hcmm_mgr, bool bForce) { struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr; struct cmm_info temp_info; int status = 0; s32 slot_seg; struct cmm_mnode *pnode; DBC_REQUIRE(refs > 0); if (!hcmm_mgr) { status = -EFAULT; return status; } mutex_lock(&cmm_mgr_obj->cmm_lock); /* If not force then fail if outstanding allocations exist */ if (!bForce) { /* Check for outstanding memory allocations */ status = cmm_get_info(hcmm_mgr, &temp_info); if (DSP_SUCCEEDED(status)) { if (temp_info.ul_total_in_use_cnt > 0) { /* outstanding allocations */ status = -EPERM; } } } if (DSP_SUCCEEDED(status)) { /* UnRegister SM allocator */ for (slot_seg = 0; slot_seg < CMM_MAXGPPSEGS; slot_seg++) { if (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] != NULL) { un_register_gppsm_seg (cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg]); /* Set slot to NULL for future reuse */ cmm_mgr_obj->pa_gppsm_seg_tab[slot_seg] = NULL; } } } if (cmm_mgr_obj->node_free_list_head != NULL) { /* Free the free nodes */ while (!LST_IS_EMPTY(cmm_mgr_obj->node_free_list_head)) { pnode = (struct cmm_mnode *) lst_get_head(cmm_mgr_obj->node_free_list_head); kfree(pnode); } /* delete NodeFreeList list */ kfree(cmm_mgr_obj->node_free_list_head); } mutex_unlock(&cmm_mgr_obj->cmm_lock); if (DSP_SUCCEEDED(status)) { /* delete CS & cmm mgr object */ mutex_destroy(&cmm_mgr_obj->cmm_lock); kfree(cmm_mgr_obj); } 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; if (!phMsgMgr || !msgCallback || !hDevObject) { status = DSP_EPOINTER; goto func_end; } DEV_GetIOMgr(hDevObject, &hIOMgr); if (!hIOMgr) { status = DSP_EPOINTER; goto func_end; } *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; } func_end: return status; }
/* * ======== NODEWRAP_Allocate ======== */ u32 NODEWRAP_Allocate(union Trapped_Args *args, void *pr_ctxt) { DSP_STATUS status = DSP_SOK; struct DSP_UUID nodeId; u32 cbDataSize = 0; u32 __user *pSize = (u32 __user *)args->ARGS_NODE_ALLOCATE.pArgs; u8 *pArgs = NULL; struct DSP_NODEATTRIN attrIn, *pAttrIn = NULL; struct NODE_OBJECT *hNode; GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Allocate: entered\n"); /* Optional argument */ if (pSize) { if (get_user(cbDataSize, pSize)) status = DSP_EFAIL; cbDataSize += sizeof(u32); if (DSP_SUCCEEDED(status)) { pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED); if (pArgs == NULL) status = DSP_EMEMORY; } cp_fm_usr(pArgs, args->ARGS_NODE_ALLOCATE.pArgs, status, cbDataSize); } cp_fm_usr(&nodeId, args->ARGS_NODE_ALLOCATE.pNodeID, status, 1); if (DSP_FAILED(status)) goto func_cont; /* Optional argument */ if (args->ARGS_NODE_ALLOCATE.pAttrIn) { cp_fm_usr(&attrIn, args->ARGS_NODE_ALLOCATE.pAttrIn, status, 1); if (DSP_SUCCEEDED(status)) pAttrIn = &attrIn; else status = DSP_EMEMORY; } if (DSP_SUCCEEDED(status)) { mutex_lock(&((struct PROCESS_CONTEXT *)pr_ctxt)->node_lock); status = NODE_Allocate(args->ARGS_NODE_ALLOCATE.hProcessor, &nodeId, (struct DSP_CBDATA *)pArgs, pAttrIn, &hNode, pr_ctxt); mutex_unlock(&((struct PROCESS_CONTEXT *)pr_ctxt)->node_lock); } cp_to_usr(args->ARGS_NODE_ALLOCATE.phNode, &hNode, status, 1); func_cont: if (pArgs) MEM_Free(pArgs); return status; }
/* * ======== NODEWRAP_Connect ======== */ u32 NODEWRAP_Connect(union Trapped_Args *args, void *pr_ctxt) { DSP_STATUS status = DSP_SOK; struct DSP_STRMATTR attrs; struct DSP_STRMATTR *pAttrs = NULL; u32 cbDataSize; u32 __user *pSize = (u32 __user *)args->ARGS_NODE_CONNECT.pConnParam; u8 *pArgs = NULL; GT_0trace(WCD_debugMask, GT_ENTER, "NODEWRAP_Connect: entered\n"); /* Optional argument */ if (pSize) { if (get_user(cbDataSize, pSize)) status = DSP_EFAIL; cbDataSize += sizeof(u32); if (DSP_SUCCEEDED(status)) { pArgs = MEM_Alloc(cbDataSize, MEM_NONPAGED); if (pArgs == NULL) { status = DSP_EMEMORY; goto func_cont; } } cp_fm_usr(pArgs, args->ARGS_NODE_CONNECT.pConnParam, status, cbDataSize); if (DSP_FAILED(status)) goto func_cont; } if (args->ARGS_NODE_CONNECT.pAttrs) { /* Optional argument */ cp_fm_usr(&attrs, args->ARGS_NODE_CONNECT.pAttrs, status, 1); if (DSP_SUCCEEDED(status)) pAttrs = &attrs; } if (DSP_SUCCEEDED(status)) { status = NODE_Connect(args->ARGS_NODE_CONNECT.hNode, args->ARGS_NODE_CONNECT.uStream, args->ARGS_NODE_CONNECT.hOtherNode, args->ARGS_NODE_CONNECT.uOtherStream, pAttrs, (struct DSP_CBDATA *)pArgs); } func_cont: if (pArgs) MEM_Free(pArgs); return status; }
/** ============================================================================ * @func helloDSP_Main * * @desc Entry point for the application * * @modif None * ============================================================================ */ NORMAL_API Void helloDSP_Main(IN Char8* dspExecutable, IN Char8* strNumIterations, IN Char8* strProcessorId) { DSP_STATUS status = DSP_SOK; Uint32 numIterations = 0; Uint8 processorId = 0; SYSTEM_0Print ("========== Sample Application : helloDSP ==========\n"); if ((dspExecutable != NULL) && (strNumIterations != NULL)) { numIterations = SYSTEM_Atoi(strNumIterations); if (numIterations > 0xFFFF) { status = DSP_EINVALIDARG; SYSTEM_1Print("ERROR! Invalid arguments specified for helloDSP application.\n Max iterations = %d\n", 0xFFFF); } else { processorId = SYSTEM_Atoi(strProcessorId); if (processorId >= MAX_DSPS) { SYSTEM_1Print("== Error: Invalid processor id %d specified ==\n", processorId); status = DSP_EFAIL; } /* Specify the dsp executable file name for message creation phase. */ if (DSP_SUCCEEDED(status)) { status = helloDSP_Create(dspExecutable, strNumIterations, processorId); /* Execute the message execute phase. */ if (DSP_SUCCEEDED(status)) { status = helloDSP_Execute(numIterations, processorId); } /* Perform cleanup operation. */ helloDSP_Delete(processorId); } } } else { status = DSP_EINVALIDARG; SYSTEM_0Print("ERROR! Invalid arguments specified for helloDSP application\n"); } SYSTEM_0Print ("====================================================\n"); }
/* To remove all process resources before removing the process from the * process context list*/ DSP_STATUS DRV_RemoveAllResources(HANDLE hPCtxt) { DSP_STATUS status; DSP_STATUS rc; struct PROCESS_CONTEXT *pCtxt = (struct PROCESS_CONTEXT *)hPCtxt; status = DRV_RemoveAllSTRMResElements(pCtxt); rc = DRV_RemoveAllNodeResElements(pCtxt); if (DSP_SUCCEEDED(status)) status = rc; rc = DRV_RemoveAllDMMResElements(pCtxt); if (DSP_SUCCEEDED(status)) status = rc; pCtxt->resState = PROC_RES_FREED; return status; }
/* * ======== bridge_chnl_flush_io ======== * purpose: * Flushes all the outstanding data requests on a channel. */ int bridge_chnl_flush_io(struct chnl_object *chnl_obj, u32 dwTimeOut) { int status = 0; struct chnl_object *pchnl = (struct chnl_object *)chnl_obj; s8 chnl_mode = -1; struct chnl_mgr *chnl_mgr_obj; struct chnl_ioc chnl_ioc_obj; /* Check args: */ if (pchnl) { if ((dwTimeOut == CHNL_IOCNOWAIT) && CHNL_IS_OUTPUT(pchnl->chnl_mode)) { status = -EINVAL; } else { chnl_mode = pchnl->chnl_mode; chnl_mgr_obj = pchnl->chnl_mgr_obj; } } else { status = -EFAULT; } if (DSP_SUCCEEDED(status)) { /* Note: Currently, if another thread continues to add IO * requests to this channel, this function will continue to * flush all such queued IO requests. */ if (CHNL_IS_OUTPUT(chnl_mode) && (pchnl->chnl_type == CHNL_PCPY)) { /* Wait for IO completions, up to the specified * timeout: */ while (!LST_IS_EMPTY(pchnl->pio_requests) && DSP_SUCCEEDED(status)) { status = bridge_chnl_get_ioc(chnl_obj, dwTimeOut, &chnl_ioc_obj); if (DSP_FAILED(status)) continue; if (chnl_ioc_obj.status & CHNL_IOCSTATTIMEOUT) status = -ETIMEDOUT; } } else { status = bridge_chnl_cancel_io(chnl_obj); /* Now, leave the channel in the ready state: */ pchnl->dw_state &= ~CHNL_STATECANCEL; } } DBC_ENSURE(DSP_FAILED(status) || LST_IS_EMPTY(pchnl->pio_requests)); return status; }
/* * ========= 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; }
/** ============================================================================ * @func LDRV_MPLIST_moduleExit * * @desc This function finalizes the LDRV_MPLIST module. * * @modif None. * ============================================================================ */ NORMAL_API DSP_STATUS LDRV_MPLIST_moduleExit (Void) { DSP_STATUS status = DSP_SOK ; DSP_STATUS tmpStatus = DSP_SOK ; Uint32 dspId ; TRC_0ENTER ("LDRV_MPLIST_moduleExit") ; /* Finalize the IsInitialized flags for all DSPs. */ for (dspId = 0 ; dspId < MAX_DSPS ; dspId++) { if (LDRV_MPLIST_IsInitialized [dspId] == TRUE) { tmpStatus = LDRV_MPLIST_exit (dspId) ; if (DSP_SUCCEEDED (status) && DSP_FAILED (tmpStatus)) { status = tmpStatus ; SET_FAILURE_REASON ; } } } TRC_1LEAVE ("LDRV_MPLIST_moduleExit", status) ; 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 ; }
/* * ======== 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; }
/** ---------------------------------------------------------------------------- * @func LOOP_HandleResultData * * @desc This function verifies the data-integrity of given buffer. * * @modif None * ---------------------------------------------------------------------------- */ STATIC NORMAL_API DSP_STATUS LOOP_HandleResultData (IN Char8 * buf) { DSP_STATUS status = DSP_SOK ; Int16 i ; Char8 data ; /* * Copy out the data from DSP. */ memcpy (&result_data[0], buf, 20 * sizeof(MYBUF_TYPE)); /* * Verify the data. */ for (i = 0 ; (i < 20) && (DSP_SUCCEEDED (status)) ; i++) { if (result_data[i] != expect_data[i]) { status = DSP_EFAIL ; } printf("result[%d] from dsp = %d (%d expected)\n", i, result_data[i], expect_data[i]); } 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 ; }
/* * ======== dbll_create ======== */ int dbll_create(struct dbll_tar_obj **target_obj, struct dbll_attrs *pattrs) { struct dbll_tar_obj *pzl_target; int status = 0; DBC_REQUIRE(refs > 0); DBC_REQUIRE(pattrs != NULL); DBC_REQUIRE(target_obj != NULL); /* Allocate DBL target object */ pzl_target = kzalloc(sizeof(struct dbll_tar_obj), GFP_KERNEL); if (target_obj != NULL) { if (pzl_target == NULL) { *target_obj = NULL; status = -ENOMEM; } else { pzl_target->attrs = *pattrs; *target_obj = (struct dbll_tar_obj *)pzl_target; } DBC_ENSURE((DSP_SUCCEEDED(status) && *target_obj) || (DSP_FAILED(status) && *target_obj == NULL)); } 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 ISR_Finalize * * @desc This function provides an interface to exit from the ISR module. * It frees up all the used ISRs and releases all the resources used by * this module. * * @modif ISR_InstalledIsrs, ISR_IsInitialized * ============================================================================ */ EXPORT_API DSP_STATUS ISR_Finalize () { DSP_STATUS status = DSP_SOK ; DSP_STATUS tmpStatus = DSP_SOK ; Uint32 index = 0 ; Uint32 procId = 0 ; TRC_0ENTER ("ISR_Finalize") ; DBC_Require (ISR_IsInitialized == TRUE) ; if (ISR_IsInitialized == TRUE) { for (procId = 0 ; procId < MAX_DSPS ; procId ++) { for (index = 0 ; index < MAX_ISR ; index ++) { if (ISR_InstalledIsrs [procId][index] != NULL) { tmpStatus = ISR_Uninstall ( ISR_InstalledIsrs [procId][index]) ; if (DSP_FAILED (tmpStatus) && DSP_SUCCEEDED (status)) { status = tmpStatus ; } } } } ISR_IsInitialized = FALSE ; } DBC_Ensure (ISR_IsInitialized == FALSE) ; TRC_1LEAVE ("ISR_Finalize", status) ; return status ; }
/* * ======== regsupGetValue ======== * Purpose: * Get the value of the entry having the given name. */ DSP_STATUS regsupGetValue(char *valName, void *pBuf, u32 *dataSize) { DSP_STATUS retVal = DSP_EFAIL; u32 i; /* Need to search through the entries looking for the right one. */ for (i = 0; i < pRegKey->numValueEntries; i++) { /* See if the name matches. */ if (strncmp(pRegKey->values[i].name, valName, BRIDGE_MAX_NAME_SIZE) == 0) { /* We have a match! Copy out the data. */ memcpy(pBuf, pRegKey->values[i].pData, pRegKey->values[i].dataSize); /* Get the size for the caller. */ *dataSize = pRegKey->values[i].dataSize; /* Set our status to good and exit. */ retVal = DSP_SOK; break; } } if (DSP_SUCCEEDED(retVal)) { GT_2trace(REG_debugMask, GT_2CLASS, "G %s DATA %x ", valName, *(u32 *)pBuf); printS((u8 *)pBuf); } else { GT_1trace(REG_debugMask, GT_3CLASS, "G %s FAILED\n", valName); } return retVal; }