diff options
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/component/src/binder.c')
-rw-r--r-- | drivers/staging/nmf-cm/cm/engine/component/src/binder.c | 1313 |
1 files changed, 1313 insertions, 0 deletions
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c new file mode 100644 index 00000000000..5f08713833b --- /dev/null +++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder.c @@ -0,0 +1,1313 @@ +/* + * Copyright (C) ST-Ericsson SA 2010 + * Author: Jean-Philippe FASSINO <jean-philippe.fassino@stericsson.com> for ST-Ericsson. + * License terms: GNU General Public License (GPL) version 2. + */ +#include "../inc/bind.h" +#include "../inc/dspevent.h" +#include <cm/engine/communication/fifo/inc/nmf_fifo_arm.h> +#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h> +#include <cm/engine/component/inc/introspection.h> + +#include <cm/engine/trace/inc/trace.h> +#include <cm/engine/trace/inc/xtitrace.h> + +#include <cm/engine/utils/inc/string.h> + +#define CM_IT_NAME_MAX_LENGTH 8 + +t_nmf_table Host2MpcBindingTable; /**< list (table) of host2mpc bindings */ + +static void cm_fillItName(int interruptLine, char *itName); +static t_uint16 getNumberOfBind(t_component_instance* component); + +/* + * Bind virtual interface, here we assume that: + * - client component require this interface as last one and without collection, + * - server component provide only this interface and without collection. + * Fixed in loader.c. + */ +static void cm_bindVirtualInterface( + t_component_instance* client, + const t_component_instance* server) { + t_interface_require_description itfRequire; + + if(cm_getRequiredInterface(client, "coms", &itfRequire) == CM_OK) + { + t_interface_reference* itfRef = client->interfaceReferences[itfRequire.requireIndex]; + + /* + * Memorise this reference + */ + itfRef->provideIndex = 0; + itfRef->collectionIndex = 0; + itfRef->instance = server; + itfRef->bfInfoID = (t_bf_info_ID)0; + itfRef->bfInfo = (void*)-1; // TODO + } + else + { + ERROR("Internal Error in cm_bindVirtualInterface\n", 0, 0, 0, 0, 0, 0); + } +} + +static void cm_unbindVirtualInterface( + t_component_instance* client) { + t_interface_require_description itfRequire; + + if(cm_getRequiredInterface(client, "coms", &itfRequire) == CM_OK) + { + t_interface_reference* itfRef = client->interfaceReferences[itfRequire.requireIndex]; + itfRef->instance = NULL; + } + else + { + ERROR("Internal Error in cm_unbindVirtualInterface\n", 0, 0, 0, 0, 0, 0); + } +} + +/* + * Bind component + */ +static void cm_bindLowLevelInterface( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfLocalBC, /* On the same DSP */ + t_bf_info_ID bfInfoID, void* bfInfo) +{ + const t_component_instance* client = itfRequire->client; + t_component_instance* server = (t_component_instance*)itfLocalBC->server; + t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; + t_interface_provide* provide = &server->Template->provides[itfLocalBC->provideIndex]; + t_interface_provide_loaded* provideLoaded = &server->Template->providesLoaded[itfLocalBC->provideIndex]; + int k, j; + + if(require->indexes != NULL) + { + t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; + + for(k = 0; k < requireindex->numberOfClient; k++) { + t_uint32 *hostAddr; + + hostAddr = (t_uint32*)( + cm_DSP_GetHostLogicalAddress(client->memories[requireindex->memories[k].memory->id]) + + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); + + LOG_INTERNAL(2, "Fill ItfRef %s.%s mem=%s Off=%x @=%x\n", + client->pathname, require->name, + requireindex->memories[k].memory->memoryName, + requireindex->memories[k].offset, + hostAddr, 0); + + /* + * Fill the interface references. We start by This then methods in order to keep + * Unbinded panic as long as possible and not used method with wrong This. This is + * relevent only for optional since we must go in stop state before rebinding other + * required interface. + * + * Direct write to DSP memory without go through DSP abstraction since we know we are in 24bits + */ + // Write THIS reference into the Data field of the interface reference + // Write the interface methods reference + + if(((t_uint32)hostAddr & 0x7) == 0 && require->interface->methodNumber > 0) + { + // We are 64word byte aligned, combine this write with first method + *(volatile t_uint64*)hostAddr = + ((t_uint64)server->thisAddress << 0) | + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][0].methodAddresses << 32); + hostAddr += 2; + j = 1; + } + else + { + // We are not, write this which will align us + *hostAddr++ = (t_uint32)server->thisAddress; + j = 0; + } + + // Word align copy + for(; j < require->interface->methodNumber - 1; j+=2) { + *(volatile t_uint64*)hostAddr = + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses << 0) | + ((t_uint64)provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j+1].methodAddresses << 32); + hostAddr += 2; + } + + // Last word align if required + if(j < require->interface->methodNumber) + *hostAddr = provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses; + } + } + else + { + t_function_relocation *reloc = client->Template->delayedRelocation; + while(reloc != NULL) { + for(j = 0; j < provide->interface->methodNumber; j++) + { + if(provide->interface->methodNames[j] == reloc->symbol_name) { + cm_ELF_performRelocation( + reloc->type, + reloc->symbol_name, + provideLoaded->indexesLoaded[itfLocalBC->collectionIndex][j].methodAddresses, + reloc->reloc_addr); + break; + } + } + + reloc = reloc -> next; + } + } + + /* + * Memorise this reference + */ + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + itfRef->provideIndex = itfLocalBC->provideIndex; + itfRef->collectionIndex = itfLocalBC->collectionIndex; + itfRef->instance = itfLocalBC->server; + itfRef->bfInfoID = bfInfoID; + itfRef->bfInfo = bfInfo; + + /* + * Do not count binding from EE (ie interrupt line), as this will prevent + * cm_destroyInstance() of server to succeed (interrupt line bindings are + * destroyed after the check in cm_destroyInstance() + */ + if (client->Template->classe != FIRMWARE) + server->providedItfUsedCount++; + } +} + +static void cm_registerLowLevelInterfaceToConst( + const t_interface_require_description *itfRequire, + const t_component_instance* targetInstance) +{ + const t_component_instance* client = itfRequire->client; + + /* + * Memorise this no reference + */ + { + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + // This is an unbind from a true component (not to void) + // Do not count bindings from EE (ie interrupt line) + if ((targetInstance == NULL) + && (client->Template->classe != FIRMWARE) + && (itfRef->instance != (t_component_instance *)NMF_VOID_COMPONENT) + && (itfRef->instance != NULL)) + { + ((t_component_instance*)itfRef->instance)->providedItfUsedCount--; + } + + itfRef->instance = targetInstance; + itfRef->bfInfoID = BF_SYNCHRONOUS; // Just to memorize no Binding component used and unbind ToVoid happy ;-). + } +} + +static void cm_bindLowLevelInterfaceToConst( + const t_interface_require_description *itfRequire, + const t_dsp_address functionAddress, + const t_component_instance* targetInstance) { + const t_component_instance* client = itfRequire->client; + t_interface_require *require = &client->Template->requires[itfRequire->requireIndex]; + int j, k; + + + // If DSP is off/panic/... -> write nothing + if( + require->indexes != NULL + && cm_DSP_GetState(client->Template->dspId)->state == MPC_STATE_BOOTED) + { + t_interface_require_index *requireindex = &require->indexes[itfRequire->collectionIndex]; + + for(k = 0; k < requireindex->numberOfClient; k++) { + t_uint32 *hostAddr; + + hostAddr = (t_uint32*)( + cm_DSP_GetHostLogicalAddress(client->memories[requireindex->memories[k].memory->id]) + + requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize); + + /* + * Fill the interface references. We start by Methods then This in order to swith to + * Unbinded panic as fast as possible and not used method with wrong This. This is + * relevent only for optional since we must go in stop state before rebinding other + * required interface. + * + * Direct write to DSP memory without go through DSP abstraction since we know we are in 24bits + */ + /* + * Write THIS reference into the Data field of the interface reference + * Hack for simplifying debug just to keep THIS reference with caller one + * (could be removed if __return_address MMDSP intrinsec provided by compiler). + */ + // Write the interface methods reference + + if(((t_uint32)hostAddr & 0x7) == 0 && require->interface->methodNumber > 0) + { + // We are 64word byte aligned, combine this write with first method + *(volatile t_uint64*)hostAddr = + ((t_uint64)client->thisAddress << 0) | + ((t_uint64)functionAddress << 32); + hostAddr += 2; + j = 1; + } + else + { + // We are not, write this which will align us + *hostAddr++ = (t_uint32)client->thisAddress; + j = 0; + } + + // Word align copy + for(; j < require->interface->methodNumber - 1; j+=2) { + *(volatile t_uint64*)hostAddr = + ((t_uint64)functionAddress << 0) | + ((t_uint64)functionAddress << 32); + hostAddr += 2; + } + + // Last word align if required + if(j < require->interface->methodNumber) + *hostAddr = functionAddress; + } + } + + cm_registerLowLevelInterfaceToConst(itfRequire, targetInstance); +} + +/* + * Bind User component though primitive binding factory + */ +t_cm_error cm_bindInterface( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide) { + + LOG_INTERNAL(1, "\n##### Bind Synchronous %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + cm_bindLowLevelInterface( + itfRequire, + itfProvide, + BF_SYNCHRONOUS, NULL); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +/* + * + */ +void cm_unbindInterface( + const t_interface_require_description *itfRequire) { + + LOG_INTERNAL(1, "\n##### UnBind synchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + cm_bindLowLevelInterfaceToConst(itfRequire, + 0x0, + NULL); +} + +/* + * + */ +t_cm_error cm_bindInterfaceToVoid( + const t_interface_require_description *itfRequire) { + LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> Void #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_bindLowLevelInterfaceToConst(itfRequire, + cm_EEM_getExecutiveEngine(itfRequire->client->Template->dspId)->voidAddr, + (t_component_instance*)NMF_VOID_COMPONENT); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + return CM_OK; +} +/* + * Find the server and its interface inded to a given required interface for a given component + */ +t_cm_error cm_lookupInterface( + const t_interface_require_description *itfRequire, + t_interface_provide_description *itfProvide) { + const t_component_instance* client = itfRequire->client; + t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex]; + + if(itfRef->instance != NULL) + { + itfProvide->server = itfRef->instance; + itfProvide->provideIndex = itfRef->provideIndex; + itfProvide->collectionIndex = itfRef->collectionIndex; + + return CM_OK; + } else { + itfProvide->server = NULL; + return CM_INTERFACE_NOT_BINDED; + } +} + +/* + * + */ +t_cm_error cm_bindInterfaceTrace( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_elfdescription *elfhandleTrace) +{ + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; + t_interface_require_description bcitfRequire; + t_interface_provide_description bcitfProvide; + t_trace_bf_info *bfInfo; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind Synchronous Trace %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_trace_bf_info*)OSAL_Alloc(sizeof(t_trace_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* + * Instantiate related trace on dsp + */ + { + char traceTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(traceTemplateName,"_tr.", sizeof(traceTemplateName)); + cm_StringConcatenate(traceTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + traceTemplateName, + itfRequire->client->domainId, + itfProvide->server->priority, + traceDup, + elfhandleTrace, + &bfInfo->traceInstance)) != CM_OK) { + OSAL_Free(bfInfo); + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* Bind event to server interface (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->traceInstance, "target", &bcitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&bcitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + /* Get the event interface (Error must not occure) */ + CM_ASSERT(cm_getProvidedInterface(bfInfo->traceInstance, "target", &bcitfProvide) == CM_OK); + + /* Bind client to event (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &bcitfProvide, BF_TRACE, bfInfo); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_SYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindInterfaceTrace( + const t_interface_require_description *itfRequire, + t_trace_bf_info *bfInfo) +{ + t_interface_require_description traceitfRequire; + + LOG_INTERNAL(1, "\n##### UnBind trace synchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_SYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); + + /* Unbind explicitly Event from Server Binding Component */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->traceInstance, "target", &traceitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&traceitfRequire, NULL); + + /* Destroy Event Binding Component */ + cm_destroyInstance(bfInfo->traceInstance, DESTROY_WITHOUT_CHECK); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + + +/* + * + */ +t_cm_error cm_bindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleEvent) { + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; + t_interface_require_description eventitfRequire; + t_interface_provide_description eventitfProvide; + t_async_bf_info *bfInfo; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind Asynchronous %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_async_bf_info*)OSAL_Alloc(sizeof(t_async_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* + * Instantiate related event on dsp + */ + { + char eventTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(eventTemplateName,"_ev.", sizeof(eventTemplateName)); + cm_StringConcatenate(eventTemplateName, require->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + eventTemplateName, + itfRequire->client->domainId, + itfProvide->server->priority, + eventDup, + elfhandleEvent, + &bfInfo->eventInstance)) != CM_OK) { + OSAL_Free(bfInfo); + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* + * Initialize the event component + */ + { + unsigned int size; + + // Get fifo elem size (which was store in TOP by convention) + size = cm_readAttributeNoError(bfInfo->eventInstance, "TOP"); + LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", size, 0, 0, 0, 0, 0); + + // Allocate fifo + if ((error = dspevent_createDspEventFifo(bfInfo->eventInstance, + "TOP", + fifosize, size, + dspEventMemType, + &bfInfo->dspfifoHandle)) != CM_OK) + { + cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); + OSAL_Free(bfInfo); + return error; + } + } + + /* Bind event to server interface (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&eventitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + /* Get the event interface (Error must not occure) */ + CM_ASSERT(cm_getProvidedInterface(bfInfo->eventInstance, "target", &eventitfProvide) == CM_OK); + + /* Bind client to event (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &eventitfProvide, BF_ASYNCHRONOUS, bfInfo); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindInterfaceAsynchronous( + const t_interface_require_description *itfRequire, + t_async_bf_info *bfInfo) +{ + t_interface_require_description eventitfRequire; + + LOG_INTERNAL(1, "\n##### UnBind asynchronous %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, 0x0, NULL); + + /* Unbind explicitly Event from Server Binding Component */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->eventInstance, "target", &eventitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&eventitfRequire, NULL); + + /* Destroy Event fifo */ + dspevent_destroyDspEventFifo(bfInfo->dspfifoHandle); + + /* Destroy Event Binding Component */ + cm_destroyInstance(bfInfo->eventInstance, DESTROY_WITHOUT_CHECK); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + +/*! + * Create Shared FIFO and set stub and skeleton to it + */ +PRIVATE t_cm_error cm_createParamsFifo(t_component_instance *stub, + t_component_instance *skeleton, + t_cm_domain_id domainId, + t_uint32 fifosize, + t_nmf_fifo_arm_desc **fifo, + t_uint32 *fifoElemSize, + t_uint32 bcDescSize) +{ + t_nmf_core_id stubcore = (stub != NULL) ?(stub->Template->dspId): ARM_CORE_ID; + t_nmf_core_id skelcore = (skeleton != NULL) ?(skeleton->Template->dspId) : ARM_CORE_ID; + t_component_instance *bcnotnull = (stub != NULL) ? stub : skeleton; + int _fifoelemsize; + + CM_ASSERT(bcnotnull != NULL); + + /* Get fifo param elem size (which was store in FIFO by convention) */ + _fifoelemsize = cm_readAttributeNoError(bcnotnull, "FIFO"); + LOG_INTERNAL(3, "Fifo Params element size = %d\n", _fifoelemsize, 0, 0, 0, 0, 0); + if(fifoElemSize != NULL) + *fifoElemSize = _fifoelemsize; + + /* Allocation of the fifo params */ + *fifo = fifo_alloc(stubcore, skelcore, _fifoelemsize, fifosize, 1+bcDescSize, paramsLocation, extendedFieldLocation, domainId); /* 1+nbMethods fro hostBCThis_or_TOP space */ + if(*fifo == NULL) { + ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_createParamsFifo()\n", 0, 0, 0, 0, 0, 0); + return CM_NO_MORE_MEMORY; + } + + if(stub != NULL) + { + /* Set stub FIFO attribute (Error mut not occure) */ + cm_writeAttribute(stub, "FIFO", (*fifo)->dspAdress); + + LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); + } + + if(skeleton != NULL) + { + /* Set Skeleton FIFO attribute (Error mut not occure) */ + cm_writeAttribute(skeleton, "FIFO", (*fifo)->dspAdress); + + LOG_INTERNAL(2, " FIFO param %x:%x\n", *fifo, (*fifo)->dspAdress, 0, 0, 0, 0); + } + + return CM_OK; +} +/** + * + */ +static void cm_destroyParamsFifo(t_nmf_fifo_arm_desc *fifo) { + fifo_free(fifo); +} + +/*! + * Create DSP skeleton + */ +PRIVATE t_cm_error cm_createDSPSkeleton( + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, //INTERNAL_XRAM24 + t_elfdescription *elfhandleSkeleton, + t_dspskel_bf_info *bfInfo) +{ + t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; + t_interface_require_description skelitfRequire; + t_cm_error error; + unsigned int fifoeventsize = 0; + + /* Instantiate related stub on dsp */ + { + char stubTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(stubTemplateName,"_sk.", sizeof(stubTemplateName)); + cm_StringConcatenate(stubTemplateName, provide->interface->type, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + stubTemplateName, + itfProvide->server->domainId, + itfProvide->server->priority, + skeletonDup, + elfhandleSkeleton, + &bfInfo->skelInstance)) != CM_OK) { + return ((error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND:error); + } + } + + /* Get fifo elem size (which was store in TOP by convention) */ + fifoeventsize = cm_readAttributeNoError(bfInfo->skelInstance, "TOP"); + LOG_INTERNAL(3, "DspEvent Fifo element size = %d\n", fifoeventsize, 0, 0, 0, 0, 0); + + /* Allocation of the itf event dsp fifo */ + if ((error = dspevent_createDspEventFifo( + bfInfo->skelInstance, + "TOP", + fifosize, + fifoeventsize, + dspEventMemType, + &bfInfo->dspfifoHandle)) != CM_OK) + { + cm_destroyInstance(bfInfo->skelInstance, DESTROY_WITHOUT_CHECK); + return error; + } + + /* Bind stub to server component (Error must not occure) */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->skelInstance, "target", &skelitfRequire) == CM_OK); + + cm_bindLowLevelInterface(&skelitfRequire, itfProvide, BF_SYNCHRONOUS, NULL); + + return CM_OK; +} + +/** + * Destroy DSP Skeleton + */ +PRIVATE t_cm_error cm_destroyDSPSkeleton(t_dspskel_bf_info *bfInfo) { + t_interface_require_description skelitfRequire; + + /* Unbind explicitly stub from server component (Error must not occure) */ + /* This is mandatory to fix the providedItfUsedCount of the server */ + CM_ASSERT(cm_getRequiredInterface(bfInfo->skelInstance, "target", &skelitfRequire) == CM_OK); + + cm_registerLowLevelInterfaceToConst(&skelitfRequire, NULL); + + /* Destroy Event fifo */ + dspevent_destroyDspEventFifo(bfInfo->dspfifoHandle); + + /* Destroy Event Binding Component */ + return cm_destroyInstance(bfInfo->skelInstance, DESTROY_WITHOUT_CHECK); +} + +/* + * + */ +t_cm_error cm_bindComponentFromCMCore( + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_host2mpc_bf_info **bfInfo) { + t_interface_provide *provide = &itfProvide->server->Template->provides[itfProvide->provideIndex]; + t_dsp_offset shareVarOffset; + t_cm_error error; + + LOG_INTERNAL(1, "\n##### Bind HOST -> %s/%x.%s #####\n", + itfProvide->server->pathname, itfProvide->server, itfProvide->origName, 0, 0, 0); + + /* Allocate host2dsp binding factory information */ + *bfInfo = (t_host2mpc_bf_info*)OSAL_Alloc(sizeof(t_host2mpc_bf_info)); + if((*bfInfo) == 0) + return CM_NO_MORE_MEMORY; + + /* Create the Skeleton */ + if ((error = cm_createDSPSkeleton(itfProvide, + fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ + dspEventMemType, + elfhandleSkeleton, + &(*bfInfo)->dspskeleton)) != CM_OK) + { + OSAL_Free((*bfInfo)); + return error; + } + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo(NULL, + (*bfInfo)->dspskeleton.skelInstance, + itfProvide->server->domainId, + fifosize, + &(*bfInfo)->fifo, + NULL, + provide->interface->methodNumber)) != CM_OK) + { + cm_destroyDSPSkeleton(&(*bfInfo)->dspskeleton); + OSAL_Free((*bfInfo)); + return error; + } + + /* Set Target info in FIFO param to TOP */ + shareVarOffset = cm_getAttributeMpcAddress((*bfInfo)->dspskeleton.skelInstance, "TOP"); + + /* + * Set Target info in FIFO param to armThis + * Should not return any error + */ + fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); + + /* Initialise FIFO Param bcDesc with Skeleton methods */ + { + int i; + t_component_instance *skel = (*bfInfo)->dspskeleton.skelInstance; + for (i=0; i < provide->interface->methodNumber; i++) + { + /* should not return error */ + fifo_params_setSharedField( + (*bfInfo)->fifo, + 1+i, + skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses + ); + } + } + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + ARM_TRACE_COMPONENT, itfProvide->server, + NULL, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +void cm_unbindComponentFromCMCore( + t_host2mpc_bf_info* bfInfo) { + t_component_instance *skel = bfInfo->dspskeleton.skelInstance; + t_interface_reference* itfProvide = &skel->interfaceReferences[0][0]; + t_interface_provide *provide = &itfProvide->instance->Template->provides[itfProvide->provideIndex]; + + LOG_INTERNAL(1, "\n##### UnBind HOST -> %s/%x.%s #####\n", + itfProvide->instance->pathname, itfProvide->instance, provide->name, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + ARM_TRACE_COMPONENT, itfProvide->instance, + NULL, + itfProvide->instance->Template->provides[itfProvide->provideIndex].name); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destory Skeleton + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + + // Free BF info (which contains bcDecr(==dspfct) and arm This) + OSAL_Free(bfInfo); +} + +/** + * Create DSP Stub + */ +PRIVATE t_cm_error cm_createDSPStub( + const t_interface_require_description *itfRequire, + const char* itfType, + t_dspstub_bf_info* bfInfo, + t_elfdescription *elfhandleStub, + t_interface_provide_description *itfstubProvide) { + t_cm_error error; + + /* + * Instantiate related skel on dsp + */ + { + char skelTemplateName[4 + MAX_INTERFACE_TYPE_NAME_LENGTH + 1]; + + cm_StringCopy(skelTemplateName, "_st.", sizeof(skelTemplateName)); + cm_StringConcatenate(skelTemplateName, itfType, MAX_INTERFACE_TYPE_NAME_LENGTH); + + if ((error = cm_instantiateComponent( + skelTemplateName, + itfRequire->client->domainId, + itfRequire->client->priority, + stubDup, + elfhandleStub, + &bfInfo->stubInstance)) != CM_OK) { + return (error == CM_COMPONENT_NOT_FOUND)?CM_BINDING_COMPONENT_NOT_FOUND : error; + } + } + + /* Get the internal component that serve this interface (Error must not occure) */ + (void)cm_getProvidedInterface(bfInfo->stubInstance, "source", itfstubProvide); + + return CM_OK; +} + +PRIVATE t_cm_error cm_destroyDSPStub( + const t_interface_require_description *itfRequire, + t_dspstub_bf_info* bfInfo) { + + /* Unbind Client from Event Binding Component */ + cm_bindLowLevelInterfaceToConst(itfRequire, + 0x0, + NULL); + + /* Destroy Event Binding Component */ + return cm_destroyInstance(bfInfo->stubInstance, DESTROY_WITHOUT_CHECK); +} +/* + * + */ +t_cm_error cm_bindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_uint32 fifosize, + t_uint32 context, + t_elfdescription *elfhandleStub, + t_mpc2host_bf_info ** bfInfo) { + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; + t_interface_provide_description itfstubProvide; + t_cm_error error; + t_uint32 fifoelemsize; + + LOG_INTERNAL(1, "\n##### Bind %s/%x.%s -> HOST #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + /* Allocate dsp2host binding factory information */ + *bfInfo = (t_mpc2host_bf_info*)OSAL_Alloc(sizeof(t_mpc2host_bf_info)); + if(*bfInfo == 0) + return CM_NO_MORE_MEMORY; + (*bfInfo)->context = context; + + if ((error = cm_createDSPStub(itfRequire, + require->interface->type, + &(*bfInfo)->dspstub, + elfhandleStub, + &itfstubProvide)) != CM_OK) + { + OSAL_Free(*bfInfo); + return error; + } + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo( + (*bfInfo)->dspstub.stubInstance, + NULL, + itfRequire->client->domainId, + fifosize, + &(*bfInfo)->fifo, + &fifoelemsize, + 1)) != CM_OK) /* 1 => we used first field as max params size */ + { + cm_destroyDSPStub(itfRequire, &(*bfInfo)->dspstub); + OSAL_Free(*bfInfo); + return error; + } + + /* Bind client to stub component (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2HOST, *bfInfo); + + /* Bind stub component to host (virtual bind) */ + cm_bindVirtualInterface((*bfInfo)->dspstub.stubInstance, (t_component_instance*)NMF_HOST_COMPONENT); + + /* + * Set Target info in FIFO param to armThis + * Initialise FIFO Param bcDesc with Jumptable + * Should not return any error + */ + fifo_params_setSharedField((*bfInfo)->fifo, 0, (t_shared_field)context /* ArmBCThis_or_TOP */); + fifo_params_setSharedField((*bfInfo)->fifo, 1, (t_shared_field)fifoelemsize * 2/* bcDescRef */); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, ARM_TRACE_COMPONENT, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + return error; +} + +void cm_unbindComponentToCMCore( + const t_interface_require_description *itfRequire, + t_mpc2host_bf_info *bfInfo) +{ + LOG_INTERNAL(1, "\n##### UnBind %s/%x.%s -> HOST #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, ARM_TRACE_COMPONENT, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind virtual interface coms */ + cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destroy DSP Stub + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + + /* Free BF info */ + OSAL_Free(bfInfo); +} + +/*! + * + */ +t_cm_error cm_bindInterfaceDistributed( + const t_interface_require_description *itfRequire, + const t_interface_provide_description *itfProvide, + t_uint32 fifosize, + t_dsp_memory_type_id dspEventMemType, + t_elfdescription *elfhandleSkeleton, + t_elfdescription *elfhandleStub) { + t_interface_require *require = &itfRequire->client->Template->requires[itfRequire->requireIndex]; + t_interface_provide_description itfstubProvide; + t_cm_error error; + t_mpc2mpc_bf_info *bfInfo; + t_dsp_offset shareVarOffset; + + LOG_INTERNAL(1, "\n##### Bind Distributed %s/%x.%s -> %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server, itfProvide->origName); + + /* Allocate aynchronous binding factory information */ + bfInfo = (t_mpc2mpc_bf_info*)OSAL_Alloc(sizeof(t_mpc2mpc_bf_info)); + if(bfInfo == 0) + return CM_NO_MORE_MEMORY; + + /* Create the Skeleton */ + if ((error = cm_createDSPSkeleton(itfProvide, + fifo_normalizeDepth(fifosize), /* We SHALL create DSP Skeleton before creating the Params Fifo, but we need in advance the real depth of this fifo */ + dspEventMemType, + elfhandleSkeleton, + &bfInfo->dspskeleton)) != CM_OK) + { + OSAL_Free(bfInfo); + return error; + } + + // Create DSP Stub + if ((error = cm_createDSPStub(itfRequire, + require->interface->type, + &bfInfo->dspstub, + elfhandleStub, + &itfstubProvide)) != CM_OK) + { + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + OSAL_Free(bfInfo); + return error; + } + + /* Bind client to stub component (Error must not occure) */ + cm_bindLowLevelInterface(itfRequire, &itfstubProvide, BF_DSP2DSP, bfInfo); + + /* Create the FIFO Params */ + if ((error = cm_createParamsFifo( + bfInfo->dspstub.stubInstance, + bfInfo->dspskeleton.skelInstance, + itfProvide->server->domainId, + fifosize, + &bfInfo->fifo, + NULL, + require->interface->methodNumber)) != CM_OK) + { + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + OSAL_Free(bfInfo); + return error; + } + + /* Bind stub component to host (virtual bind) */ + cm_bindVirtualInterface(bfInfo->dspstub.stubInstance, bfInfo->dspskeleton.skelInstance); + + /* Set Target info in FIFO param to TOP */ + shareVarOffset = cm_getAttributeMpcAddress(bfInfo->dspskeleton.skelInstance, "TOP"); + + /* + * Set Target info in FIFO param to armThis + * Should not return any error + */ + fifo_params_setSharedField(bfInfo->fifo, 0, (t_shared_field)shareVarOffset /* ArmBCThis_or_TOP */); + + /* Initialise FIFO Param bcDesc with Skeleton methods */ + { + int i; + t_component_instance *skel = bfInfo->dspskeleton.skelInstance; + for (i=0; i < require->interface->methodNumber; i++) + { + /* should not return error */ + fifo_params_setSharedField( + bfInfo->fifo, + 1+i, + skel->Template->providesLoaded[0].indexesLoaded[0][i].methodAddresses + ); + } + } + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_BIND_ASYNCHRONOUS, + itfRequire->client, itfProvide->server, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + itfProvide->server->Template->provides[itfProvide->provideIndex].name); + + return CM_OK; +} + +/*! + * + */ +void cm_unbindInterfaceDistributed( + const t_interface_require_description *itfRequire, + t_mpc2mpc_bf_info *bfInfo) +{ + LOG_INTERNAL(1, "\n##### UnBind distributed %s/%x.%s #####\n", + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0, 0); + + cm_TRC_traceBinding(TRACE_BIND_COMMAND_UNBIND_ASYNCHRONOUS, + itfRequire->client, NULL, + itfRequire->client->Template->requires[itfRequire->requireIndex].name, + NULL); + + /* Unbind virtual interface */ + cm_unbindVirtualInterface(bfInfo->dspstub.stubInstance); + + // Destroy FIFO params + cm_destroyParamsFifo(bfInfo->fifo); + + // Destroy DSP Stub + cm_destroyDSPStub(itfRequire, &bfInfo->dspstub); + + // Destory DSP Skeleton + cm_destroyDSPSkeleton(&bfInfo->dspskeleton); + + // Destroy BF Info + OSAL_Free(bfInfo); +} + +t_cm_error cm_bindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine, + const t_component_instance *server, + const char* providedItfServerName +) +{ + char requiredItfClientName[CM_IT_NAME_MAX_LENGTH]; + t_component_instance *client = cm_EEM_getExecutiveEngine(coreId)->instance; + t_interface_require_description itfRequire; + t_interface_provide_description itfProvide; + t_cm_error error; + + //build it[%d] name + if (interruptLine < 0 || interruptLine > 255) {return CM_OUT_OF_LIMITS;} + cm_fillItName(interruptLine, requiredItfClientName); + + //do binding + if ((error = cm_getRequiredInterface(client,requiredItfClientName,&itfRequire)) != CM_OK) {return error;} + if ((error = cm_getProvidedInterface(server,providedItfServerName,&itfProvide)) != CM_OK) {return error;} + if((error = cm_bindInterface(&itfRequire, &itfProvide)) != CM_OK) {return error;} + + return CM_OK; +} + +t_cm_error cm_unbindInterfaceStaticInterrupt( + const t_nmf_core_id coreId, + const int interruptLine +) +{ + char requiredItfClientName[CM_IT_NAME_MAX_LENGTH]; + t_component_instance *client = cm_EEM_getExecutiveEngine(coreId)->instance; + t_interface_require_description itfRequire; + t_cm_error error; + + //build it[%d] name + if (interruptLine < 0 || interruptLine > 255) {return CM_OUT_OF_LIMITS;} + cm_fillItName(interruptLine, requiredItfClientName); + + //do unbinding + if ((error = cm_getRequiredInterface(client,requiredItfClientName,&itfRequire)) != CM_OK) {return error;} + cm_unbindInterface(&itfRequire); + + return CM_OK; +} + +void cm_destroyRequireInterface(t_component_instance* component, t_nmf_client_id clientId) +{ + int i, j; + + /* + * Special code for SINGLETON handling + */ + if(component->Template->classe == SINGLETON) + { + if(getNumberOfBind(component) > 0) + return; + } + + for(i = 0; i < component->Template->requireNumber; i++) + { + int nb = component->Template->requires[i].collectionSize; + for(j = 0; j < nb; j++) + { + if(component->interfaceReferences[i][j].instance != NULL) + { + t_interface_reference* itfRef = &component->interfaceReferences[i][j]; + t_interface_require_description itfRequire; + + itfRequire.client = component; + itfRequire.requireIndex = i; + itfRequire.collectionIndex = j; + itfRequire.origName = component->Template->requires[i].name; + + switch (itfRef->bfInfoID) { + case BF_SYNCHRONOUS: + /* Error ignored as it is always OK */ + cm_unbindInterface(&itfRequire); + break; + case BF_TRACE: + cm_unbindInterfaceTrace(&itfRequire, + (t_trace_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_ASYNCHRONOUS: + cm_unbindInterfaceAsynchronous(&itfRequire, + (t_async_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_DSP2HOST: + /* This 'mpc2host handle' is provided by the host at OS Integration level. + It must then be handled and released in OS specific part. + */ + cm_unbindComponentToCMCore(&itfRequire, + (t_mpc2host_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + case BF_HOST2DSP: + /* These bindings are from CM Core to DSP, they are not listed + here and must be handles/freed by host at OS Integration level + */ + break; + case BF_DSP2DSP: + cm_unbindInterfaceDistributed(&itfRequire, + (t_mpc2mpc_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo); + break; + default: + break; + } + } + } + } +} + +void cm_registerSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId) +{ + if(component->Template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfBind++; + + if(itfProvide != NULL) + LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> %s/%x\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server); + else + LOG_INTERNAL(1, " -> Singleton[%d] : Register binding %s/%x.%s -> ARM/VOID\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + } +} + +t_bool cm_unregisterSingletonBinding( + t_component_instance* component, + t_interface_require_description* itfRequire, + t_interface_provide_description* itfProvide, + t_nmf_client_id clientId) +{ + if(component->Template->classe == SINGLETON) + { + struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId); + if(cl != NULL) + cl->numberOfBind--; + + if(itfProvide->server == (t_component_instance *)NMF_VOID_COMPONENT) + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ARM/VOID\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + else if(itfProvide->server == NULL) + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> ?? <already unbound>\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, 0, 0); + else + LOG_INTERNAL(1, " -> Singleton[%d] : Unregister binding %s/%x.%s -> %s/%x\n", + clientId, + itfRequire->client->pathname, itfRequire->client, itfRequire->origName, + itfProvide->server->pathname, itfProvide->server); + + if(getNumberOfBind(component) == 0) + { + LOG_INTERNAL(1, " -> Singleton[%d] : All required of %s/%x logically unbound, perform physical unbind\n", + clientId, itfRequire->client->pathname, itfRequire->client, 0, 0, 0); + + (void)cm_EEM_ForceWakeup(component->Template->dspId); + + // This is the last binding unbind all !!! + cm_destroyRequireInterface(component, clientId); + + cm_EEM_AllowSleep(component->Template->dspId); + } + else if(itfProvide->server != NULL) + { + t_interface_require* itfReq; + itfReq = &itfRequire->client->Template->requires[itfRequire->requireIndex]; + if((itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0) + return TRUE; + } + + return FALSE; + } + + return TRUE; +} + +static t_uint16 getNumberOfBind(t_component_instance* component) +{ + t_uint16 bindNumber = 0; + struct t_client_of_singleton* cur = component->clientOfSingleton; + + for( ; cur != NULL ; cur = cur->next) + { + bindNumber += cur->numberOfBind; + } + + return bindNumber; +} + +static void cm_fillItName(int interruptLine, char *itName) +{ + int divider = 10000; + + *itName++ = 'i'; + *itName++ = 't'; + *itName++ = '['; + + // Find first significant divider + while(divider > interruptLine) + divider /= 10; + + // Compute number + do + { + *itName++ = "0123456789"[interruptLine / divider]; + interruptLine %= divider; + divider /= 10; + } while(divider != 0); + + *itName++ = ']'; + *itName++ = '\0'; +} |