summaryrefslogtreecommitdiff
path: root/drivers/staging/nmf-cm/cm/engine/component/src
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/nmf-cm/cm/engine/component/src')
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/binder.c1313
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c205
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c1332
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c78
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/initializer.c383
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c829
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/introspection.c327
-rw-r--r--drivers/staging/nmf-cm/cm/engine/component/src/loader.c384
8 files changed, 4851 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';
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c
new file mode 100644
index 00000000000..373fea0cd47
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/binder_check.c
@@ -0,0 +1,205 @@
+/*
+ * 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 <cm/engine/trace/inc/trace.h>
+
+#include <cm/engine/utils/inc/string.h>
+
+t_cm_error cm_checkValidClient(
+ const t_component_instance* client,
+ const char* requiredItfClientName,
+ t_interface_require_description *itfRequire,
+ t_bool *bindable) {
+ t_cm_error error;
+
+ // Component LC state check
+ if (NULL == client)
+ return CM_INVALID_COMPONENT_HANDLE;
+
+ // Check if the requiredItfClientName is required by client component
+ if ((error = cm_getRequiredInterface(client, requiredItfClientName, itfRequire)) != CM_OK)
+ return error;
+
+ // Check required interface not already binded
+ {
+ t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex];
+
+ if(itfRef->instance != (t_component_instance*)NULL)
+ {
+ if(client->Template->classe == SINGLETON)
+ {
+ // Singleton is immutable thus we can't rebind it, nevertheless it's not an issue
+ *bindable = FALSE;
+ return CM_OK;
+ }
+ else
+ {
+ t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex];
+
+ if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT)
+ ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.%s) already bound to VOID\n",
+ client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0);
+ else
+ ERROR("CM_INTERFACE_ALREADY_BINDED(): Component (%s<%s>.%s) already bound to another server (%s<%s>.%s)\n",
+ client->pathname, client->Template->name, requiredItfClientName,
+ itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name);
+ return CM_INTERFACE_ALREADY_BINDED;
+ }
+ }
+ }
+
+ // Delayed Component LC state check done only if not optional required interface or intrinsic one that has been solved by loader
+ {
+ t_interface_require* itfReq = &client->Template->requires[itfRequire->requireIndex];
+
+ if((itfReq->requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0) {
+ if(client->state == STATE_RUNNABLE)
+ return CM_COMPONENT_NOT_STOPPED;
+ }
+ }
+
+ *bindable = TRUE;
+
+ return CM_OK;
+}
+
+t_cm_error cm_checkValidServer(
+ const t_component_instance* server,
+ const char* providedItfServerName,
+ t_interface_provide_description *itfProvide) {
+ t_cm_error error;
+
+ // Check if the components are initialized
+ //if (server->state == STATE_INSTANCIATED)
+ // return CM_COMPONENT_NOT_INITIALIZED;
+ if(NULL == server)
+ return CM_INVALID_COMPONENT_HANDLE;
+
+ // Check if the providedItfServerName is provided by server component
+ if((error = cm_getProvidedInterface(server, providedItfServerName, itfProvide)) != CM_OK)
+ return error;
+
+ return CM_OK;
+}
+
+t_cm_error cm_checkValidBinding(
+ const t_component_instance* client,
+ const char* requiredItfClientName,
+ const t_component_instance* server,
+ const char* providedItfServerName,
+ t_interface_require_description *itfRequire,
+ t_interface_provide_description *itfProvide,
+ t_bool *bindable) {
+ t_interface_require *require;
+ t_interface_provide *provide;
+ t_cm_error error;
+
+ // Check Server
+ if((error = cm_checkValidServer(server, providedItfServerName, itfProvide)) != CM_OK)
+ return error;
+
+ // Check Client
+ if((error = cm_checkValidClient(client, requiredItfClientName, itfRequire, bindable)) != CM_OK)
+ return error;
+
+ // If this is a singleton which has been already bound check that next binding is at the same server
+ if(*bindable == FALSE
+ && client->Template->classe == SINGLETON)
+ {
+ t_interface_reference* itfRef = &client->interfaceReferences[itfRequire->requireIndex][itfRequire->collectionIndex];
+ while( itfRef->instance != server
+ || itfRef->provideIndex != itfProvide->provideIndex
+ || itfRef->collectionIndex != itfProvide->collectionIndex )
+ {
+ if(itfRef->instance == (const t_component_instance*)NMF_VOID_COMPONENT)
+ {
+ ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.%s) already bound to VOID\n",
+ client->pathname, client->Template->name, requiredItfClientName, 0, 0, 0);
+ return CM_INTERFACE_ALREADY_BINDED;
+ }
+ else if(itfRef->bfInfoID == BF_ASYNCHRONOUS || itfRef->bfInfoID == BF_TRACE)
+ {
+ t_interface_require_description eventitfRequire;
+ CM_ASSERT(cm_getRequiredInterface(itfRef->instance, "target", &eventitfRequire) == CM_OK);
+ itfRef = &itfRef->instance->interfaceReferences[eventitfRequire.requireIndex][eventitfRequire.collectionIndex];
+
+ // Go to see client of event if the same
+ }
+ else
+ {
+ ERROR("CM_INTERFACE_ALREADY_BINDED(): Singleton (%s<%s>.%s) already bound to different server (%s<%s>.%s)\n",
+ client->pathname, client->Template->name, requiredItfClientName,
+ itfRef->instance->pathname, itfRef->instance->Template->name, itfRef->instance->Template->provides[itfRef->provideIndex].name);
+ return CM_INTERFACE_ALREADY_BINDED;
+ }
+ }
+ }
+
+ // Check if provided and required type matches
+ require = &client->Template->requires[itfRequire->requireIndex];
+ provide = &server->Template->provides[itfProvide->provideIndex];
+ if(require->interface != provide->interface)
+ {
+ ERROR("CM_ILLEGAL_BINDING(%s, %s)\n", require->interface->type, provide->interface->type, 0, 0, 0, 0);
+ return CM_ILLEGAL_BINDING;
+ }
+
+ // Check if static required interface binded to singleton component
+ if((require->requireTypes & STATIC_REQUIRE) &&
+ (server->Template->classe != SINGLETON))
+ {
+ ERROR("CM_ILLEGAL_BINDING(): Can't bind static required interface to not singleton component\n",
+ 0, 0, 0, 0, 0, 0);
+ return CM_ILLEGAL_BINDING;
+ }
+
+ return CM_OK;
+}
+
+t_cm_error cm_checkValidUnbinding(
+ const t_component_instance* client,
+ const char* requiredItfClientName,
+ t_interface_require_description *itfRequire,
+ t_interface_provide_description *itfProvide) {
+ t_cm_error error;
+ t_interface_require* itfReq;
+
+ // Component LC state check
+ if (NULL == client)
+ return CM_INVALID_COMPONENT_HANDLE;
+
+ // Check if the requiredItfClientName is required by client component
+ if ((error = cm_getRequiredInterface(client, requiredItfClientName, itfRequire)) != CM_OK)
+ return error;
+
+ itfReq = &client->Template->requires[itfRequire->requireIndex];
+
+ // Check if the requiredItfClientName is required by client component
+ if ((error = cm_lookupInterface(itfRequire, itfProvide)) != CM_OK)
+ {
+ // We allow to unbind optional required of singleton even if not binded, since it could have been unbound previously but we don't
+ // want to break bind singleton reference counter
+ if((client->Template->classe == SINGLETON) &&
+ (itfReq->requireTypes & OPTIONAL_REQUIRE) != 0x0)
+ return CM_OK;
+
+ return error;
+ }
+
+ // Singleton is immutable, don't unbind it
+ if(client->Template->classe == SINGLETON)
+ return CM_OK;
+
+ /* if interface is optionnal then allow unbinding even if not stop */
+ if((itfReq->requireTypes & OPTIONAL_REQUIRE) == 0x0)
+ {
+ if(client->state == STATE_RUNNABLE)
+ return CM_COMPONENT_NOT_STOPPED;
+ }
+
+ return CM_OK;
+}
+
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c
new file mode 100644
index 00000000000..d593950cd97
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/component_wrapper.c
@@ -0,0 +1,1332 @@
+/*
+ * 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 <cm/engine/api/component_engine.h>
+#include <cm/engine/api/communication_engine.h>
+
+#include <cm/engine/component/inc/bind.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/component/inc/introspection.h>
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/memory/inc/domain.h>
+
+#include <cm/engine/configuration/inc/configuration.h>
+#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h>
+
+/*
+ * Component mangement wrapping.
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_InstantiateComponent(
+ const char* templateName,
+ t_cm_domain_id domainId,
+ t_nmf_client_id clientId,
+ t_nmf_ee_priority priority,
+ const char localName[MAX_COMPONENT_NAME_LENGTH],
+ const char *dataFile,
+ t_cm_instance_handle *instance) {
+ t_cm_error error;
+ t_nmf_core_id coreId;
+ t_component_instance *comp;
+ t_elfdescription *elfhandle = NULL;
+
+ OSAL_LOCK_API();
+
+ /*
+ * Load Elf File
+ */
+ if(dataFile != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFile,
+ TRUE,
+ &elfhandle)) != CM_OK)
+ goto out;
+
+ //only allow instantiation in non-scratch domains (ie. DOMAIN_NORMAL)!
+ if ((error = cm_DM_CheckDomainWithClient(domainId, DOMAIN_NORMAL, clientId)) != CM_OK)
+ goto out;
+
+ coreId = cm_DM_GetDomainCoreId(domainId);
+
+ if(coreId < FIRST_MPC_ID || coreId > LAST_CORE_ID)
+ {
+ error = CM_INVALID_PARAMETER;
+ goto out;
+ }
+
+ if ((error = cm_CFG_CheckMpcStatus(coreId)) != CM_OK)
+ goto out;
+
+ if ((error = cm_EEM_ForceWakeup(coreId)) != CM_OK)
+ goto out;
+
+ error = cm_instantiateComponent(
+ templateName,
+ domainId,
+ priority,
+ localName,
+ elfhandle,
+ &comp);
+ if(error == CM_OK)
+ *instance = comp->instance;
+
+ cm_EEM_AllowSleep(coreId);
+
+out:
+ cm_ELF_CloseFile(TRUE, elfhandle);
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_StartComponent(
+ t_cm_instance_handle instance,
+ t_nmf_client_id clientId) {
+ t_cm_error error;
+ t_component_instance *component;
+
+ OSAL_LOCK_API();
+
+ component = cm_lookupComponent(instance);
+ if (NULL == component)
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else
+ {
+ error = cm_startComponent(component, clientId);
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_StopComponent(
+ t_cm_instance_handle instance,
+ t_nmf_client_id clientId) {
+ t_cm_error error;
+ t_component_instance *component;
+
+ OSAL_LOCK_API();
+
+ component = cm_lookupComponent(instance);
+ if (NULL == component)
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else
+ {
+ error = cm_stopComponent(component, clientId);
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_DestroyComponent(
+ t_cm_instance_handle instance,
+ t_nmf_client_id clientId)
+{
+ t_cm_error error;
+ t_component_instance *component;
+
+ OSAL_LOCK_API();
+
+ component = cm_lookupComponent(instance);
+ if (NULL == component)
+ {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ }
+ else
+ {
+ t_nmf_core_id coreId = component->Template->dspId;
+
+ (void)cm_EEM_ForceWakeup(coreId);
+
+ error = cm_destroyInstanceForClient(component, DESTROY_NORMAL, clientId);
+
+ cm_CFG_ReleaseMpc(coreId);
+
+ cm_EEM_AllowSleep(coreId);
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_FlushComponents(t_nmf_client_id clientId)
+{
+ t_cm_error error = CM_OK;
+ t_component_instance *instance;
+ t_uint32 i;
+
+ if (clientId == 0)
+ return CM_INVALID_PARAMETER;
+
+ OSAL_LOCK_API();
+
+ // We don't know exactly where components will be, wake up everybody !!
+ (void)cm_EEM_ForceWakeup(SVA_CORE_ID);
+ (void)cm_EEM_ForceWakeup(SIA_CORE_ID);
+
+ /* Destroy all host2mpc bindings */
+ OSAL_LOCK_COM();
+ for (i=0; i<Host2MpcBindingTable.idxMax; i++)
+ {
+ t_host2mpc_bf_info* bfInfo;
+ bfInfo = Host2MpcBindingTable.entries[i];
+ if ((bfInfo != NULL) && (bfInfo->clientId == clientId)) {
+ cm_delEntry(&Host2MpcBindingTable, i);
+ OSAL_UNLOCK_COM();
+ cm_unbindComponentFromCMCore(bfInfo);
+ OSAL_LOCK_COM();
+ }
+ }
+ OSAL_UNLOCK_COM();
+
+ /* First, stop all remaining components for this client */
+ for (i=0; i<ComponentTable.idxMax; i++)
+ {
+ if ((instance = componentEntry(i)) == NULL)
+ continue;
+ if (/* skip EE */
+ (instance->Template->classe == FIRMWARE) ||
+ /* Skip all binding components */
+ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0))
+ continue;
+
+ /*
+ * Special code for SINGLETON handling
+ */
+ if(instance->Template->classe == SINGLETON)
+ {
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId);
+ if(cl == NULL)
+ continue;
+
+ cl->numberOfStart = 1; // == 1 since it will go to 0 in cm_stopComponent
+ cl->numberOfInstance = 1; // == 1 since it will go to 0 in cm_destroyInstanceForClient
+ cl->numberOfBind = 0; // == 0 since we don't want anymore binding for this component
+ }
+ else if(domainDesc[instance->domainId].client != clientId)
+ /* Skip all components not belonging to our client */
+ continue;
+
+ // Stop the component
+ error = cm_stopComponent(instance, clientId);
+ if (error != CM_OK && error != CM_COMPONENT_NOT_STARTED)
+ LOG_INTERNAL(0, "Error stopping component %s/%x (%s, error=%d, client=%u)\n", instance->pathname, instance, instance->Template->name, error, clientId, 0);
+
+ // Destroy dependencies
+ cm_destroyRequireInterface(instance, clientId);
+ }
+
+ /* Destroy all remaining components for this client */
+ for (i=0; i<ComponentTable.idxMax; i++)
+ {
+ if ((instance = componentEntry(i)) == NULL)
+ continue;
+ if (/* skip EE */
+ (instance->Template->classe == FIRMWARE) ||
+ /* Skip all binding components */
+ (cm_StringCompare(instance->Template->name, "_ev.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_st.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_sk.", 4) == 0) ||
+ (cm_StringCompare(instance->Template->name, "_tr.", 4) == 0)) {
+ continue;
+ }
+
+
+ /*
+ * Special code for SINGLETON handling
+ */
+ if(instance->Template->classe == SINGLETON)
+ {
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(instance, FALSE, clientId);
+ if(cl == NULL)
+ continue;
+ }
+ else if(domainDesc[instance->domainId].client != clientId)
+ /* Skip all components not belonging to our client */
+ continue;
+
+
+ // Destroy the component
+ error = cm_destroyInstanceForClient(instance, DESTROY_WITHOUT_CHECK, clientId);
+
+ if (error != CM_OK)
+ {
+ /* FIXME : add component name instance in log message but need to make a copy before cm_flushComponent()
+ * because it's no more available after.
+ */
+ LOG_INTERNAL(0, "Error flushing component (error=%d, client=%u)\n", error, clientId, 0, 0, 0, 0);
+ }
+ }
+
+ cm_CFG_ReleaseMpc(SVA_CORE_ID);
+ cm_CFG_ReleaseMpc(SIA_CORE_ID);
+
+ cm_EEM_AllowSleep(SVA_CORE_ID);
+ cm_EEM_AllowSleep(SIA_CORE_ID);
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+/*
+ * Component binding wrapping.
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponent(
+ const t_cm_instance_handle clientInstance,
+ const char* requiredItfClientName,
+ const t_cm_instance_handle serverInstance,
+ const char* providedItfServerName,
+ t_bool traced,
+ t_nmf_client_id clientId,
+ const char *dataFileTrace) {
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_bool bindable;
+ t_cm_error error;
+ t_component_instance *client, *server;
+ t_elfdescription *elfhandleTrace = NULL;
+
+ OSAL_LOCK_API();
+
+ /*
+ * Load Elf File
+ */
+ if(dataFileTrace != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFileTrace,
+ TRUE,
+ &elfhandleTrace)) != CM_OK)
+ goto out;
+
+ client = cm_lookupComponent(clientInstance);
+ server = cm_lookupComponent(serverInstance);
+ // Sanity check
+ if((error = cm_checkValidBinding(client, requiredItfClientName,
+ server, providedItfServerName,
+ &itfRequire, &itfProvide, &bindable)) != CM_OK)
+ goto out;
+
+ // Check that client and server component run on same DSP
+ if (itfRequire.client->Template->dspId != itfProvide.server->Template->dspId)
+ {
+ error = CM_ILLEGAL_BINDING;
+ goto out;
+ }
+
+ // Check if we really need to bind
+ if(bindable)
+ {
+ if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK)
+ goto out;
+
+ /*
+ * Synchronous binding, so no binding component
+ */
+ if(traced)
+ error = cm_bindInterfaceTrace(&itfRequire, &itfProvide, elfhandleTrace);
+ else
+ error = cm_bindInterface(&itfRequire, &itfProvide);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ }
+
+ cm_registerSingletonBinding(client, &itfRequire, &itfProvide, clientId);
+
+out:
+ cm_ELF_CloseFile(TRUE, elfhandleTrace);
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponent(
+ const t_cm_instance_handle clientInstance,
+ const char* requiredItfClientName,
+ t_nmf_client_id clientId) {
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_bf_info_ID bfInfoID;
+ t_cm_error error;
+ t_component_instance *client;
+
+ OSAL_LOCK_API();
+
+ client = cm_lookupComponent(clientInstance);
+ // Sanity check
+ if((error = cm_checkValidUnbinding(client, requiredItfClientName,
+ &itfRequire, &itfProvide)) != CM_OK)
+ goto out;
+
+ // Check if this is a Primitive binding
+ bfInfoID = itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID;
+ if(bfInfoID != BF_SYNCHRONOUS && bfInfoID != BF_TRACE)
+ {
+ error = CM_ILLEGAL_UNBINDING;
+ goto out;
+ }
+
+ // Check if we really need to unbind
+ if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId))
+ {
+ (void)cm_EEM_ForceWakeup(itfRequire.client->Template->dspId);
+
+ if(bfInfoID == BF_SYNCHRONOUS)
+ cm_unbindInterface(&itfRequire);
+ else
+ cm_unbindInterfaceTrace(
+ &itfRequire,
+ (t_trace_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+
+ error = CM_OK;
+ }
+
+out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToVoid(
+ const t_cm_instance_handle clientInstance,
+ const char requiredItfClientName[MAX_INTERFACE_NAME_LENGTH],
+ t_nmf_client_id clientId)
+{
+ t_interface_require_description itfRequire;
+ t_bool bindable;
+ t_cm_error error;
+ t_component_instance *client;
+
+ OSAL_LOCK_API();
+
+ client = cm_lookupComponent(clientInstance);
+ // Check invalid binding
+ if((error = cm_checkValidClient(client, requiredItfClientName,
+ &itfRequire, &bindable)) != CM_OK)
+ goto out;
+
+ // Check if we really need to bind
+ if(bindable)
+ {
+ if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK)
+ goto out;
+
+ error = cm_bindInterfaceToVoid(&itfRequire);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ }
+
+ cm_registerSingletonBinding(client, &itfRequire, NULL, clientId);
+
+out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentAsynchronous(
+ const t_cm_instance_handle clientInstance,
+ const char* requiredItfClientName,
+ const t_cm_instance_handle serverInstance,
+ const char* providedItfServerName,
+ t_uint32 fifosize,
+ t_cm_mpc_memory_type eventMemType,
+ t_nmf_client_id clientId,
+ const char *dataFileSkeletonOrEvent,
+ const char *dataFileStub) {
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_dsp_memory_type_id dspEventMemType;
+ t_bool bindable;
+ t_cm_error error;
+ t_component_instance *client, *server;
+ t_elfdescription *elfhandleSkeletonOrEvent = NULL;
+ t_elfdescription *elfhandleStub = NULL;
+
+ OSAL_LOCK_API();
+
+ /*
+ * Load Elf File
+ */
+ if(dataFileSkeletonOrEvent != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFileSkeletonOrEvent,
+ TRUE,
+ &elfhandleSkeletonOrEvent)) != CM_OK)
+ goto out;
+ if(dataFileStub != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFileStub,
+ TRUE,
+ &elfhandleStub)) != CM_OK)
+ goto out;
+
+ client = cm_lookupComponent(clientInstance);
+ server = cm_lookupComponent(serverInstance);
+ // Check invalid binding
+ if((error = cm_checkValidBinding(client, requiredItfClientName,
+ server, providedItfServerName,
+ &itfRequire, &itfProvide, &bindable)) != CM_OK)
+ goto out;
+
+ switch(eventMemType)
+ {
+ case CM_MM_MPC_TCM24_X:
+ dspEventMemType = INTERNAL_XRAM24;
+ break;
+ case CM_MM_MPC_ESRAM24:
+ dspEventMemType = ESRAM_EXT24;
+ break;
+ case CM_MM_MPC_SDRAM24:
+ dspEventMemType = SDRAM_EXT24;
+ break;
+ default:
+ error = CM_INVALID_PARAMETER;
+ goto out;
+ }
+
+ // Check if we really need to bind
+ if(bindable)
+ {
+ // Create the binding and bind it to the client (or all sub-components clients ....)
+ if (itfRequire.client->Template->dspId != itfProvide.server->Template->dspId)
+ {
+ if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK)
+ goto out;
+ if ((error = cm_EEM_ForceWakeup(itfProvide.server->Template->dspId)) != CM_OK)
+ {
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ goto out;
+ }
+
+ // This is a distribute communication
+ error = cm_bindInterfaceDistributed(
+ &itfRequire,
+ &itfProvide,
+ fifosize,
+ dspEventMemType,
+ elfhandleSkeletonOrEvent,
+ elfhandleStub);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ cm_EEM_AllowSleep(itfProvide.server->Template->dspId);
+ }
+ else
+ {
+ if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK)
+ goto out;
+
+ // This is a acynchronous communication
+ error = cm_bindInterfaceAsynchronous(
+ &itfRequire,
+ &itfProvide,
+ fifosize,
+ dspEventMemType,
+ elfhandleSkeletonOrEvent);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ }
+ }
+
+ cm_registerSingletonBinding(client, &itfRequire, &itfProvide, clientId);
+
+out:
+ cm_ELF_CloseFile(TRUE, elfhandleSkeletonOrEvent);
+ cm_ELF_CloseFile(TRUE, elfhandleStub);
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentAsynchronous(
+ const t_cm_instance_handle instance,
+ const char* requiredItfClientName,
+ t_nmf_client_id clientId) {
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_bf_info_ID bfInfoID;
+ t_cm_error error;
+ t_component_instance *client;
+
+ OSAL_LOCK_API();
+
+ client = cm_lookupComponent(instance);
+ // Sanity check
+ if((error = cm_checkValidUnbinding(client, requiredItfClientName,
+ &itfRequire, &itfProvide)) != CM_OK)
+ goto out;
+
+ bfInfoID = itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID;
+
+ // Check if we really need to unbind
+ if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId))
+ {
+ // Check if this is a Asynchronous binding
+ if(bfInfoID == BF_DSP2DSP)
+ {
+ t_nmf_core_id clientDsp = itfRequire.client->Template->dspId;
+ t_nmf_core_id serverDsp = itfProvide.server->Template->dspId;
+
+ (void)cm_EEM_ForceWakeup(clientDsp);
+ (void)cm_EEM_ForceWakeup(serverDsp);
+
+ cm_unbindInterfaceDistributed(
+ &itfRequire,
+ (t_mpc2mpc_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo);
+
+ cm_EEM_AllowSleep(clientDsp);
+ cm_EEM_AllowSleep(serverDsp);
+
+ error = CM_OK;
+ }
+ else if(bfInfoID == BF_ASYNCHRONOUS)
+ {
+ t_nmf_core_id clientDsp = itfRequire.client->Template->dspId;
+
+ (void)cm_EEM_ForceWakeup(clientDsp);
+
+ cm_unbindInterfaceAsynchronous(
+ &itfRequire,
+ (t_async_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo);
+
+ cm_EEM_AllowSleep(clientDsp);
+
+ error = CM_OK;
+ }
+ else
+ error = CM_ILLEGAL_UNBINDING;
+ }
+
+ out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentFromCMCore(
+ const t_cm_instance_handle server,
+ const char* providedItfServerName,
+ t_uint32 fifosize,
+ t_cm_mpc_memory_type eventMemType,
+ t_cm_bf_host2mpc_handle *bfHost2mpcHdl,
+ t_nmf_client_id clientId,
+ const char *dataFileSkeleton) {
+ t_interface_provide_description itfProvide;
+ t_dsp_memory_type_id dspEventMemType;
+ t_cm_error error;
+ t_component_instance* component;
+ t_host2mpc_bf_info *bfInfo;
+ t_elfdescription *elfhandleSkeleton = NULL;
+
+ OSAL_LOCK_API();
+
+ /*
+ * Load Elf File
+ */
+ if(dataFileSkeleton != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFileSkeleton,
+ TRUE,
+ &elfhandleSkeleton)) != CM_OK)
+ goto out;
+
+ component = cm_lookupComponent(server);
+ // Check server validity
+ if((error = cm_checkValidServer(component, providedItfServerName,
+ &itfProvide)) != CM_OK)
+ goto out;
+
+ if ((error = cm_EEM_ForceWakeup(itfProvide.server->Template->dspId)) != CM_OK)
+ goto out;
+
+ switch(eventMemType)
+ {
+ case CM_MM_MPC_TCM24_X:
+ dspEventMemType = INTERNAL_XRAM24;
+ break;
+ case CM_MM_MPC_ESRAM24:
+ dspEventMemType = ESRAM_EXT24;
+ break;
+ case CM_MM_MPC_SDRAM24:
+ dspEventMemType = SDRAM_EXT24;
+ break;
+ default:
+ error = CM_INVALID_PARAMETER;
+ goto out;
+ }
+
+ error = cm_bindComponentFromCMCore(&itfProvide,
+ fifosize,
+ dspEventMemType,
+ elfhandleSkeleton,
+ &bfInfo);
+
+ cm_EEM_AllowSleep(itfProvide.server->Template->dspId);
+
+out:
+ cm_ELF_CloseFile(TRUE, elfhandleSkeleton);
+ OSAL_UNLOCK_API();
+
+ if (error == CM_OK) {
+ bfInfo->clientId = clientId;
+ OSAL_LOCK_COM();
+ *bfHost2mpcHdl = cm_addEntry(&Host2MpcBindingTable, bfInfo);
+ if (*bfHost2mpcHdl == 0)
+ error = CM_NO_MORE_MEMORY;
+ OSAL_UNLOCK_COM();
+
+ if (error != CM_OK) {
+ OSAL_LOCK_API();
+ (void)cm_EEM_ForceWakeup(itfProvide.server->Template->dspId);
+ cm_unbindComponentFromCMCore(bfInfo);
+ cm_EEM_AllowSleep(itfProvide.server->Template->dspId);
+ OSAL_UNLOCK_API();
+ }
+ }
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentFromCMCore(
+ t_cm_bf_host2mpc_handle bfHost2mpcId) {
+ t_host2mpc_bf_info* bfInfo;
+ t_nmf_core_id coreId;
+
+ OSAL_LOCK_COM();
+ bfInfo = cm_lookupEntry(&Host2MpcBindingTable, bfHost2mpcId);
+ if (bfInfo)
+ cm_delEntry(&Host2MpcBindingTable, bfHost2mpcId & INDEX_MASK);
+ OSAL_UNLOCK_COM();
+ if (NULL == bfInfo)
+ return CM_INVALID_PARAMETER;
+
+ OSAL_LOCK_API();
+
+ // Check if this is a DSP to Host binding
+ //if(bfInfo->id != BF_HOST2DSP)
+ // return CM_ILLEGAL_UNBINDING;
+ coreId = bfInfo->dspskeleton.skelInstance->Template->dspId;
+
+ (void)cm_EEM_ForceWakeup(coreId);
+
+ cm_unbindComponentFromCMCore(bfInfo);
+
+ cm_EEM_AllowSleep(coreId);
+
+ OSAL_UNLOCK_API();
+ return CM_OK;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_BindComponentToCMCore(
+ const t_cm_instance_handle instance,
+ const char *requiredItfClientName,
+ t_uint32 fifosize,
+ t_nmf_mpc2host_handle upLayerThis,
+ const char *dataFileStub,
+ t_cm_bf_mpc2host_handle *mpc2hostId,
+ t_nmf_client_id clientId) {
+ t_interface_require_description itfRequire;
+ t_bool bindable;
+ t_cm_error error;
+ t_component_instance* client;
+ t_elfdescription *elfhandleStub = NULL;
+
+ OSAL_LOCK_API();
+
+ /*
+ * Load Elf File
+ */
+ if(dataFileStub != NULL &&
+ (error = cm_ELF_CheckFile(
+ dataFileStub,
+ TRUE,
+ &elfhandleStub)) != CM_OK)
+ goto out;
+
+ client = cm_lookupComponent(instance);
+ // Check invalid binding
+ if((error = cm_checkValidClient(client, requiredItfClientName,
+ &itfRequire, &bindable)) != CM_OK)
+ goto out;
+
+ // Check if we really need to bind
+ if(bindable)
+ {
+ if ((error = cm_EEM_ForceWakeup(itfRequire.client->Template->dspId)) != CM_OK)
+ goto out;
+
+ error = cm_bindComponentToCMCore(
+ &itfRequire,
+ fifosize,
+ upLayerThis,
+ elfhandleStub,
+ (t_mpc2host_bf_info**)mpc2hostId);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+ }
+
+ cm_registerSingletonBinding(client, &itfRequire, NULL, clientId);
+
+out:
+ cm_ELF_CloseFile(TRUE, elfhandleStub);
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_UnbindComponentToCMCore(
+ const t_cm_instance_handle instance,
+ const char *requiredItfClientName,
+ t_nmf_mpc2host_handle *upLayerThis,
+ t_nmf_client_id clientId) {
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_cm_error error;
+ t_mpc2host_bf_info *bfInfo;
+ t_component_instance* client;
+
+ OSAL_LOCK_API();
+
+ client = cm_lookupComponent(instance);
+ // Sanity check
+ if((error = cm_checkValidUnbinding(client, requiredItfClientName,
+ &itfRequire, &itfProvide)) != CM_OK)
+ goto out;
+
+ // Check if this is a DSP to Host binding
+ if(itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfoID != BF_DSP2HOST)
+ {
+ error = CM_ILLEGAL_UNBINDING;
+ goto out;
+ }
+
+ bfInfo = (t_mpc2host_bf_info*)itfRequire.client->interfaceReferences[itfRequire.requireIndex][itfRequire.collectionIndex].bfInfo;
+
+ // Get client information
+ *upLayerThis = bfInfo->context;
+
+ // Check if we really need to unbind
+ if(cm_unregisterSingletonBinding(client, &itfRequire, &itfProvide, clientId))
+ {
+ (void)cm_EEM_ForceWakeup(itfRequire.client->Template->dspId);
+
+ cm_unbindComponentToCMCore(&itfRequire, bfInfo);
+
+ cm_EEM_AllowSleep(itfRequire.client->Template->dspId);
+
+ error = CM_OK;
+ }
+out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_event_params_handle CM_ENGINE_AllocEvent(t_cm_bf_host2mpc_handle host2mpcId) {
+ t_host2mpc_bf_info* bfInfo;
+ t_event_params_handle eventHandle;
+
+ OSAL_LOCK_COM();
+ bfInfo = cm_lookupEntry(&Host2MpcBindingTable, host2mpcId);
+ if (NULL == bfInfo) {
+ OSAL_UNLOCK_COM();
+ return NULL;
+ }
+
+ if(bfInfo->dspskeleton.skelInstance->interfaceReferences[0][0].instance->state != STATE_RUNNABLE) {
+ ERROR("CM_COMPONENT_NOT_STARTED: Call interface before start component %s<%s>\n",
+ bfInfo->dspskeleton.skelInstance->pathname,
+ bfInfo->dspskeleton.skelInstance->Template->name, 0, 0, 0, 0);
+ }
+
+ eventHandle = cm_AllocEvent(bfInfo->fifo);
+
+ OSAL_UNLOCK_COM();
+
+ return eventHandle;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_PushEvent(t_cm_bf_host2mpc_handle host2mpcId, t_event_params_handle h, t_uint32 methodIndex) {
+ t_host2mpc_bf_info* bfInfo;
+ t_cm_error error;
+
+ OSAL_LOCK_COM();
+ bfInfo = cm_lookupEntry(&Host2MpcBindingTable, host2mpcId);
+ if (NULL == bfInfo) {
+ OSAL_UNLOCK_COM();
+ return CM_INVALID_PARAMETER;
+ }
+ error = cm_PushEvent(bfInfo->fifo, h, methodIndex);
+ OSAL_UNLOCK_COM();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED void CM_ENGINE_AcknowledgeEvent(t_cm_bf_mpc2host_handle mpc2hostId) {
+ t_mpc2host_bf_info* bfInfo = (t_mpc2host_bf_info*)mpc2hostId;
+
+ //t_dsp2host_bf_info* bfInfo = (t_host2mpc_bf_info*)mpc2hostId;
+ OSAL_LOCK_COM();
+ cm_AcknowledgeEvent(bfInfo->fifo);
+ OSAL_UNLOCK_COM();
+}
+
+/*
+ * Get a reference on a given attribute of a given component
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_ReadComponentAttribute(
+ const t_cm_instance_handle instance,
+ const char* attrName,
+ t_uint24 *attrValue)
+{
+ t_cm_error error;
+ t_component_instance* component;
+
+ OSAL_LOCK_API();
+
+ component = cm_lookupComponent(instance);
+ if (NULL == component)
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else
+ {
+ if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK)
+ goto out;
+
+ // t_uint24 -> t_uint32 possible since we know it same size
+ error = cm_readAttribute(component, attrName, (t_uint32*)attrValue);
+
+ cm_EEM_AllowSleep(component->Template->dspId);
+ }
+
+out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+/*
+ * Get a reference on a given attribute of a given component
+ */
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_WriteComponentAttribute(
+ const t_cm_instance_handle instance,
+ const char* attrName,
+ t_uint24 attrValue)
+{
+ t_cm_error error;
+ t_component_instance* component;
+
+ OSAL_LOCK_API();
+
+ component = cm_lookupComponent(instance);
+ if (NULL == component)
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else
+ {
+ if ((error = cm_EEM_ForceWakeup(component->Template->dspId)) != CM_OK)
+ goto out;
+
+ //t_uint24 -> t_uint32 possible since we know it same size
+ error = cm_writeAttribute(component, attrName, attrValue);
+
+ cm_EEM_AllowSleep(component->Template->dspId);
+ }
+
+out:
+ OSAL_UNLOCK_API();
+ return error;
+}
+
+/*===============================================================================
+ * Introspection API
+ *===============================================================================*/
+/*
+ * Component
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListHeader(
+ const t_nmf_client_id client,
+ t_cm_instance_handle *headerComponent) {
+ t_uint32 i;
+
+ OSAL_LOCK_API();
+
+ *headerComponent = 0;
+ for (i=0; i < ComponentTable.idxMax; i++) {
+ if ((componentEntry(i) != NULL) &&
+ (componentEntry(i)->Template->classe != FIRMWARE) &&
+ (domainDesc[componentEntry(i)->domainId].client == client)) {
+ *headerComponent = ENTRY2HANDLE(componentEntry(i), i);;
+ break;
+ }
+ }
+
+ OSAL_UNLOCK_API();
+
+ return CM_OK;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentListNext(
+ const t_nmf_client_id client,
+ const t_cm_instance_handle prevComponent,
+ t_cm_instance_handle *nextComponent){
+ t_cm_error error;
+ t_uint32 i = prevComponent & INDEX_MASK;
+
+ OSAL_LOCK_API();
+
+ // Sanity check
+ if ((i >= ComponentTable.idxMax)
+ || (((unsigned int)componentEntry(i) << INDEX_SHIFT) != (prevComponent & ~INDEX_MASK)))
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else {
+ *nextComponent = 0;
+ for (i++; i < ComponentTable.idxMax; i++) {
+ if ((componentEntry(i) != NULL) &&
+ (componentEntry(i)->Template->classe != FIRMWARE) &&
+ (domainDesc[componentEntry(i)->domainId].client == client)) {
+ *nextComponent = ENTRY2HANDLE(componentEntry(i), i);;
+ break;
+ }
+ }
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentDescription(
+ const t_cm_instance_handle instance,
+ char *templateName,
+ t_uint32 templateNameLength,
+ t_nmf_core_id *coreId,
+ char *localName,
+ t_uint32 localNameLength,
+ t_nmf_ee_priority *priority) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else {
+ cm_StringCopy(
+ templateName,
+ comp->Template->name,
+ templateNameLength);
+ *coreId = comp->Template->dspId;
+ cm_StringCopy(
+ localName,
+ comp->pathname,
+ localNameLength);
+ if (priority)
+ *priority = comp->priority;
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+/*
+ * Require interface
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceNumber(
+ const t_cm_instance_handle instance,
+ t_uint8 *numberRequiredInterfaces) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else {
+ *numberRequiredInterfaces = comp->Template->requireNumber;
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterface(
+ const t_cm_instance_handle instance,
+ const t_uint8 index,
+ char *itfName,
+ t_uint32 itfNameLength,
+ char *itfType,
+ t_uint32 itfTypeLength,
+ t_cm_require_state *requireState,
+ t_sint16 *collectionSize) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else if(index >= comp->Template->requireNumber) {
+ error = CM_NO_SUCH_REQUIRED_INTERFACE;
+ } else {
+ cm_StringCopy(
+ itfName,
+ comp->Template->requires[index].name,
+ itfNameLength);
+ cm_StringCopy(
+ itfType,
+ comp->Template->requires[index].interface->type,
+ itfTypeLength);
+ if(comp->Template->requires[index].requireTypes & COLLECTION_REQUIRE)
+ *collectionSize = comp->Template->requires[index].collectionSize;
+ else
+ *collectionSize = -1;
+
+ if(requireState != NULL) {
+ *requireState = 0;
+ if(comp->Template->requires[index].requireTypes & COLLECTION_REQUIRE)
+ *requireState |= CM_REQUIRE_COLLECTION;
+ if(comp->Template->requires[index].requireTypes & OPTIONAL_REQUIRE)
+ *requireState |= CM_REQUIRE_OPTIONAL;
+ if(comp->Template->requires[index].requireTypes & STATIC_REQUIRE)
+ *requireState |= CM_REQUIRE_STATIC;
+ }
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentRequiredInterfaceBinding(
+ const t_cm_instance_handle instance,
+ const char *itfName,
+ t_cm_instance_handle *server,
+ char *serverItfName,
+ t_uint32 serverItfNameLength) {
+ t_component_instance *comp;
+ t_interface_require_description itfRequire;
+ t_interface_provide_description itfProvide;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if(NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else if ((error = cm_getRequiredInterface(comp, itfName, &itfRequire)) != CM_OK) {
+ // Check if the requiredItfClientName is required by client component
+ } else if ((error = cm_lookupInterface(&itfRequire, &itfProvide)) != CM_OK) {
+ // Check if the requiredItfClientName is required by client component
+ } else {
+ if ((t_cm_instance_handle)itfProvide.server == NMF_HOST_COMPONENT
+ || (t_cm_instance_handle)itfProvide.server == NMF_VOID_COMPONENT)
+ *server = (t_cm_instance_handle)itfProvide.server;
+ else
+ *server = itfProvide.server->instance;
+ if(*server == NMF_HOST_COMPONENT) {
+ cm_StringCopy(
+ serverItfName,
+ "unknown",
+ serverItfNameLength);
+ } else if(*server == NMF_VOID_COMPONENT) {
+ cm_StringCopy(
+ serverItfName,
+ "void",
+ serverItfNameLength);
+ } else if(*server != 0) {
+ cm_StringCopy(
+ serverItfName,
+ itfProvide.server->Template->provides[itfProvide.provideIndex].name,
+ serverItfNameLength);
+ if(itfProvide.server->Template->provides[itfProvide.provideIndex].provideTypes & COLLECTION_PROVIDE) {
+ int len = cm_StringLength(serverItfName, serverItfNameLength);
+ serverItfName[len++] = '[';
+ if(itfProvide.collectionIndex >= 100)
+ serverItfName[len++] = '0' + (itfProvide.collectionIndex / 100);
+ if(itfProvide.collectionIndex >= 10)
+ serverItfName[len++] = '0' + ((itfProvide.collectionIndex % 100) / 10);
+ serverItfName[len++] = '0' + (itfProvide.collectionIndex % 10);
+ serverItfName[len++] = ']';
+ serverItfName[len] = 0;
+ }
+ }
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+/*
+ * Provide interface
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterfaceNumber(
+ const t_cm_instance_handle instance,
+ t_uint8 *numberProvidedInterfaces) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else {
+ *numberProvidedInterfaces = comp->Template->provideNumber;
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentProvidedInterface(
+ const t_cm_instance_handle instance,
+ const t_uint8 index,
+ char *itfName,
+ t_uint32 itfNameLength,
+ char *itfType,
+ t_uint32 itfTypeLength,
+ t_sint16 *collectionSize) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else if(index >= comp->Template->provideNumber) {
+ error = CM_NO_SUCH_PROVIDED_INTERFACE;
+ } else {
+ cm_StringCopy(
+ itfName,
+ comp->Template->provides[index].name,
+ itfNameLength);
+ cm_StringCopy(
+ itfType,
+ comp->Template->provides[index].interface->type,
+ itfTypeLength);
+ if(comp->Template->provides[index].provideTypes & COLLECTION_PROVIDE)
+ *collectionSize = comp->Template->provides[index].collectionSize;
+ else
+ *collectionSize = -1;
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+/*
+ * Component Property
+ */
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyNumber(
+ const t_cm_instance_handle instance,
+ t_uint8 *numberProperties) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else {
+ *numberProperties = comp->Template->propertyNumber;
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyName(
+ const t_cm_instance_handle instance,
+ const t_uint8 index,
+ char *propertyName,
+ t_uint32 propertyNameLength) {
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ // Sanity check
+ if (NULL == comp) {
+ error = CM_INVALID_COMPONENT_HANDLE;
+ } else if(index >= comp->Template->propertyNumber) {
+ error = CM_NO_SUCH_PROPERTY;
+ } else {
+ cm_StringCopy(
+ propertyName,
+ comp->Template->properties[index].name,
+ propertyNameLength);
+
+ error = CM_OK;
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
+
+PUBLIC EXPORT_SHARED t_cm_error CM_ENGINE_GetComponentPropertyValue(
+ const t_cm_instance_handle instance,
+ const char *propertyName,
+ char *propertyValue,
+ t_uint32 propertyValueLength)
+{
+ t_component_instance *comp;
+ t_cm_error error;
+
+ OSAL_LOCK_API();
+
+ comp = cm_lookupComponent(instance);
+ if (NULL == comp)
+ error = CM_INVALID_COMPONENT_HANDLE;
+ else
+ {
+ error = cm_getComponentProperty(
+ comp,
+ propertyName,
+ propertyValue,
+ propertyValueLength);
+
+ if(error == CM_NO_SUCH_PROPERTY)
+ ERROR("CM_NO_SUCH_PROPERTY(%s, %s)\n", comp->pathname, propertyName, 0, 0, 0, 0);
+ }
+
+ OSAL_UNLOCK_API();
+
+ return error;
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c
new file mode 100644
index 00000000000..0d5e89e0515
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/dspevent.c
@@ -0,0 +1,78 @@
+/*
+ * 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 <cm/inc/cm_type.h>
+#include <cm/engine/component/inc/introspection.h>
+#include <cm/engine/communication/inc/communication.h>
+#include <cm/engine/memory/inc/memory.h>
+#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h>
+#include <cm/engine/trace/inc/trace.h>
+#include "../inc/dspevent.h"
+
+
+#define DSP_REMOTE_EVENT_SIZE_IN_BYTE (4*DSP_REMOTE_EVENT_SIZE_IN_DSPWORD)
+#define DSP_REMOTE_EVENT_NEXT_FIELD_OFFSET 0
+#define DSP_REMOTE_EVENT_REACTION_FIELD_OFFSET 1
+#define DSP_REMOTE_EVENT_THIS_FIELD_OFFSET 2
+#define DSP_REMOTE_EVENT_PRIORITY_FIELD_OFFSET 3
+#define DSP_REMOTE_EVENT_DATA_FIELD_OFFSET 4
+
+t_cm_error dspevent_createDspEventFifo(
+ const t_component_instance *pComp,
+ const char* nameOfTOP,
+ t_uint32 fifoNbElem,
+ t_uint32 fifoElemSizeInWord,
+ t_dsp_memory_type_id dspEventMemType,
+ t_memory_handle *pHandle)
+{
+ t_uint32 dspElementAddr;
+ t_uint32 *elemAddr32;
+ int i;
+
+ // Allocate fifo
+ *pHandle = cm_DM_Alloc(pComp->domainId, dspEventMemType, fifoNbElem*fifoElemSizeInWord, CM_MM_ALIGN_2WORDS, TRUE);
+ if(*pHandle == INVALID_MEMORY_HANDLE) {
+ ERROR("CM_NO_MORE_MEMORY: dspevent_createDspEventFifo()\n", 0, 0, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ cm_DSP_GetDspAddress(*pHandle, &dspElementAddr);
+
+ elemAddr32 = (t_uint32*)cm_DSP_GetHostLogicalAddress(*pHandle);
+
+ LOG_INTERNAL(2, "\n##### FIFO (dsp event): ARM=0x%x DSP=0x%x\n", elemAddr32, dspElementAddr, 0, 0, 0, 0);
+
+ // Read attribute addr (we assume that variable in XRAM)
+ cm_writeAttribute(pComp, nameOfTOP, dspElementAddr);
+
+ // Initialise the linked list (next...)
+ for (i = 0; i < fifoNbElem - 1; i++)
+ {
+ dspElementAddr += fifoElemSizeInWord;
+
+ /* Write next field */
+ *elemAddr32 = dspElementAddr;
+ /* Write THIS field & priority field */
+ *(volatile t_uint64*)&elemAddr32[DSP_REMOTE_EVENT_THIS_FIELD_OFFSET] =
+ ((t_uint64)pComp->thisAddress | (((t_uint64)pComp->priority) << 32));
+
+ elemAddr32 += fifoElemSizeInWord;
+ }
+
+ /* Last element: Write next field */
+ *elemAddr32 = 0x0 /* NULL */;
+ /* Last element: Write THIS field & priority field */
+ *(volatile t_uint64*)&elemAddr32[DSP_REMOTE_EVENT_THIS_FIELD_OFFSET] =
+ ((t_uint64)pComp->thisAddress | (((t_uint64)pComp->priority) << 32));
+
+ return CM_OK;
+}
+
+
+
+void dspevent_destroyDspEventFifo(t_memory_handle handle)
+{
+ (void)cm_DM_Free(handle, TRUE);
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
new file mode 100644
index 00000000000..7f99b710401
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/initializer.c
@@ -0,0 +1,383 @@
+/*
+ * 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 <cm/inc/cm_type.h>
+#include <cm/engine/component/inc/introspection.h>
+#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h>
+#include <cm/engine/communication/inc/communication.h>
+#include <cm/engine/dsp/inc/dsp.h>
+#include <cm/engine/dsp/mmdsp/inc/mmdsp_hwp.h>
+
+#include <cm/engine/power_mgt/inc/power.h>
+#include <cm/engine/os_adaptation_layer/inc/os_adaptation_layer.h>
+
+#include <cm/engine/trace/inc/trace.h>
+
+#include "../inc/dspevent.h"
+#include "../inc/initializer.h"
+
+// Since now due to semaphore use call is synchrone so we only need a fifo size of three
+// (due to updateStack + (InstructionCacheLock or InstructionCacheUnlock))
+#define DEFAULT_INITIALIZER_FIFO_SIZE 3
+
+/* private prototype */
+PRIVATE t_cm_error cm_COMP_generic(t_nmf_core_id coreId, t_event_params_handle paramArray, t_uint32 paramNumber, t_uint32 serviceIndex);
+PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId);
+
+/*
+ * This module is tightly coupled with cm_DSP_components one (communication/initializer)
+ */
+static struct {
+ t_nmf_fifo_arm_desc* downlinkFifo;
+ t_nmf_fifo_arm_desc* uplinkFifo;
+ t_memory_handle dspfifoHandle;
+ t_nmf_osal_sem_handle fifoSemHandle;
+ t_uint32 servicePending; // TODO : Use sem counter instead of defining such variable (need to create new OSAL)
+} initializerDesc[NB_CORE_IDS];
+
+PUBLIC t_cm_error cm_COMP_INIT_Init(t_nmf_core_id coreId)
+{
+ t_uint32 i;
+ t_cm_error error;
+ t_component_instance *ee;
+ t_dsp_offset sharedVarOffset;
+ t_interface_provide_description itfProvide;
+ t_interface_provide* provide;
+ t_interface_provide_loaded* provideLoaded;
+
+ ee = cm_EEM_getExecutiveEngine(coreId)->instance;
+
+ // Get interface description
+ if((error = cm_getProvidedInterface(ee, "service", &itfProvide)) != CM_OK)
+ return error;
+ provide = &ee->Template->provides[itfProvide.provideIndex];
+ provideLoaded = &ee->Template->providesLoaded[itfProvide.provideIndex];
+
+
+ if ((error = dspevent_createDspEventFifo(
+ ee, "comms/TOP",
+ DEFAULT_INITIALIZER_FIFO_SIZE,
+ DSP_REMOTE_EVENT_SIZE_IN_DSPWORD,
+ INTERNAL_XRAM24,
+ &initializerDesc[coreId].dspfifoHandle)) != CM_OK)
+ return error;
+
+ /* create fifo semaphore */
+ initializerDesc[coreId].servicePending = 0;
+ initializerDesc[coreId].fifoSemHandle = OSAL_CreateSemaphore(DEFAULT_INITIALIZER_FIFO_SIZE);
+ if (initializerDesc[coreId].fifoSemHandle == 0) {
+ dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ /* static armTHis initialisation */
+ /*
+ * In the two next fifo_alloc call (1+n) means that we want to manage the hostThis_or_TOP and one method for each params fifos */
+ initializerDesc[coreId].downlinkFifo =
+ fifo_alloc(ARM_CORE_ID, coreId,
+ INIT_COMPONENT_CMD_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE,
+ (1+provide->interface->methodNumber), paramsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE);
+ if (initializerDesc[coreId].downlinkFifo == NULL)
+ {
+ OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);
+ dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
+ ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ initializerDesc[coreId].uplinkFifo =
+ fifo_alloc(coreId, ARM_CORE_ID,
+ INIT_COMPONENT_ACK_SIZE, DEFAULT_INITIALIZER_FIFO_SIZE,
+ (1), paramsLocation, extendedFieldLocation, cm_DSP_GetState(coreId)->domainEE); /* 1 is mandatory to compute internally the indexMask */
+ /* this statement is acceptable only written by skilled man ;) */
+ /* We don't used bcDescRef, since we assume that we don't need params size */
+ if (initializerDesc[coreId].uplinkFifo == NULL)
+ {
+ OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);
+ fifo_free(initializerDesc[coreId].downlinkFifo);
+ dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
+ ERROR("CM_NO_MORE_MEMORY: fifo_alloc() failed in cm_COMP_INIT_Init()\n", 0, 0, 0, 0, 0, 0);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ cm_writeAttribute(ee, "comms/FIFOcmd", initializerDesc[coreId].downlinkFifo->dspAdress);
+
+ cm_writeAttribute(ee, "comms/FIFOack", initializerDesc[coreId].uplinkFifo->dspAdress);
+
+ sharedVarOffset = cm_getAttributeMpcAddress(ee, "comms/TOP");
+
+ /* HOST->DSP ParamsFifo extended fields initialisation */
+ fifo_params_setSharedField(
+ initializerDesc[coreId].downlinkFifo,
+ 0,
+ (t_shared_field)sharedVarOffset /* TOP DSP Address */
+ );
+ for(i=0; i<provide->interface->methodNumber; i++)
+ {
+ fifo_params_setSharedField(
+ initializerDesc[coreId].downlinkFifo,
+ i + 1,
+ provideLoaded->indexesLoaded[itfProvide.collectionIndex][i].methodAddresses);
+ }
+
+ /* DSP->HOST ParamsFifo extended fields initialisation */
+ fifo_params_setSharedField(
+ initializerDesc[coreId].uplinkFifo,
+ 0,
+ (t_shared_field)NMF_INTERNAL_USERTHIS
+ );
+
+ return CM_OK;
+}
+
+
+PUBLIC t_cm_error cm_COMP_CallService(
+ int serviceIndex,
+ t_component_instance *pComp,
+ t_uint32 methodAddress) {
+ t_cm_error error;
+ t_uint16 params[INIT_COMPONENT_CMD_SIZE];
+ t_bool isSynchronous = (serviceIndex == NMF_CONSTRUCT_SYNC_INDEX ||
+ serviceIndex == NMF_START_SYNC_INDEX ||
+ serviceIndex == NMF_STOP_SYNC_INDEX ||
+ serviceIndex == NMF_DESTROY_INDEX)?TRUE:FALSE;
+
+ params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)((unsigned int)pComp & 0xFFFF);
+ params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] = (t_uint16)((unsigned int)pComp >> 16);
+ params[INIT_COMPONENT_CMD_THIS_INDEX] = (t_uint16)(pComp->thisAddress & 0xFFFF);
+ params[INIT_COMPONENT_CMD_THIS_INDEX+1] = (t_uint16)(pComp->thisAddress >> 16);
+ params[INIT_COMPONENT_CMD_METHOD_INDEX] = (t_uint16)(methodAddress & 0xFFFF);
+ params[INIT_COMPONENT_CMD_METHOD_INDEX+1] = (t_uint16)(methodAddress >> 16);
+
+ error = cm_COMP_generic(pComp->Template->dspId, params, sizeof(params) / sizeof(t_uint16), serviceIndex);
+
+ if (isSynchronous == TRUE && error == CM_OK) {
+ if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) {
+ cm_COMP_generatePanic(pComp->Template->dspId);
+ error = CM_MPC_NOT_RESPONDING;
+ }
+ }
+
+ return error;
+}
+
+PUBLIC void cm_COMP_Flush(t_nmf_core_id coreId) {
+
+ if(initializerDesc[coreId].servicePending > 0)
+ {
+ t_uint16 params[INIT_COMPONENT_CMD_SIZE];
+ t_uint32 methodAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr;
+
+ // If service still pending on MMDSP side, send a flush command (today, we reuse Destroy to not create new empty service)
+ // When we receive the result, this mean that we have flushed all previous request.
+
+ params[INIT_COMPONENT_CMD_HANDLE_INDEX] = (t_uint16)(0x0 & 0xFFFF);
+ params[INIT_COMPONENT_CMD_HANDLE_INDEX+1] = (t_uint16)(0x0 >> 16);
+ params[INIT_COMPONENT_CMD_THIS_INDEX] = (t_uint16)(0x0 & 0xFFFF);
+ params[INIT_COMPONENT_CMD_THIS_INDEX+1] = (t_uint16)(0x0 >> 16);
+ params[INIT_COMPONENT_CMD_METHOD_INDEX] = (t_uint16)(methodAddress & 0xFFFF);
+ params[INIT_COMPONENT_CMD_METHOD_INDEX+1] = (t_uint16)(methodAddress >> 16);
+
+ if (cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_DESTROY_INDEX) != CM_OK ||
+ OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK)
+ {
+ cm_COMP_generatePanic(coreId);
+ ERROR("CM_MPC_NOT_RESPONDING: can't call flush service\n", 0, 0, 0, 0, 0, 0);
+ }
+ }
+}
+
+PUBLIC void cm_COMP_INIT_Close(t_nmf_core_id coreId)
+{
+ unsigned int i;
+
+ /* wait for semaphore to be sure it would not be touch later on */
+ /* in case of timeout we break and try to clean everythink */
+ for(i = 0; i < DEFAULT_INITIALIZER_FIFO_SIZE; i++) {
+ if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK)
+ break;
+ }
+
+ /* destroy semaphore */
+ OSAL_DestroySemaphore(initializerDesc[coreId].fifoSemHandle);
+
+ /* Unallocate initializerDesc[index].uplinkFifo */
+ /* (who is used in this particular case to store dummy (with no data space (only descriptor)) DSP->HOST params fifo */
+ fifo_free(initializerDesc[coreId].uplinkFifo);
+
+ /* Unallocate initializerDesc[index].downlinkFifo */
+ fifo_free(initializerDesc[coreId].downlinkFifo);
+
+ /* Unallocate initializerDesc[index].dspfifoHandle */
+ dspevent_destroyDspEventFifo(initializerDesc[coreId].dspfifoHandle);
+}
+
+PUBLIC void processAsyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam)
+{
+ cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo);
+
+ initializerDesc[coreId].servicePending--;
+ OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1);
+}
+
+PUBLIC void processSyncAcknowledge(t_nmf_core_id coreId, t_event_params_handle pParam)
+{
+ cm_AcknowledgeEvent(initializerDesc[coreId].uplinkFifo);
+
+ initializerDesc[coreId].servicePending--;
+ OSAL_SemaphorePost(initializerDesc[coreId].fifoSemHandle,1);
+ OSAL_SemaphorePost(semHandle,1);
+}
+
+PUBLIC t_cm_error cm_COMP_UpdateStack(
+ t_nmf_core_id coreId,
+ t_uint32 stackSize
+)
+{
+ t_uint16 params[2];
+
+ // Marshall parameter
+ params[0] = (t_uint16)((unsigned int)stackSize & 0xFFFF);
+ params[1] = (t_uint16)((unsigned int)stackSize >> 16);
+
+ return cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UPDATE_STACK);
+}
+
+PUBLIC t_cm_error cm_COMP_ULPForceWakeup(
+ t_nmf_core_id coreId
+)
+{
+ t_cm_error error;
+
+ error = cm_COMP_generic(coreId, NULL, 0, NMF_ULP_FORCEWAKEUP);
+
+ if (error == CM_OK) {
+ if (OSAL_SEMAPHORE_WAIT_TIMEOUT(semHandle) != SYNC_OK) {
+ cm_COMP_generatePanic(coreId);
+ error = CM_MPC_NOT_RESPONDING;
+ }
+ }
+
+ return error;
+}
+
+PUBLIC t_cm_error cm_COMP_ULPAllowSleep(
+ t_nmf_core_id coreId
+)
+{
+ return cm_COMP_generic(coreId, NULL, 0, NMF_ULP_ALLOWSLEEP);
+}
+
+PUBLIC t_cm_error cm_COMP_InstructionCacheLock(
+ t_nmf_core_id coreId,
+ t_uint32 mmdspAddr,
+ t_uint32 mmdspSize
+)
+{
+ t_uint16 params[4];
+ t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset;
+ int way;
+
+ for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++)
+ {
+ if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE)
+ {
+ t_cm_error error;
+
+ // Marshall parameter
+ params[0] = (t_uint16)((unsigned int)startAddr & 0xFFFF);
+ params[1] = (t_uint16)((unsigned int)startAddr >> 16);
+ params[2] = (t_uint16)((unsigned int)way & 0xFFFF);
+ params[3] = (t_uint16)((unsigned int)way >> 16);
+
+ if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_LOCK_CACHE)) != CM_OK)
+ return error;
+ }
+ }
+
+ return CM_OK;
+}
+
+PUBLIC t_cm_error cm_COMP_InstructionCacheUnlock(
+ t_nmf_core_id coreId,
+ t_uint32 mmdspAddr,
+ t_uint32 mmdspSize
+)
+{
+ t_uint16 params[2];
+ t_uint32 startAddr = cm_DSP_GetState(coreId)->locked_offset;
+ int way;
+
+ for(way = 1; startAddr < mmdspAddr + mmdspSize; startAddr += MMDSP_CODE_CACHE_WAY_SIZE, way++)
+ {
+ if(mmdspAddr < startAddr + MMDSP_CODE_CACHE_WAY_SIZE)
+ {
+ t_cm_error error;
+
+ // Marshall parameter
+ params[0] = (t_uint16)((unsigned int)way & 0xFFFF);
+ params[1] = (t_uint16)((unsigned int)way >> 16);
+
+ if((error = cm_COMP_generic(coreId, params, sizeof(params) / sizeof(t_uint16), NMF_UNLOCK_CACHE)) != CM_OK)
+ return error;
+ }
+ }
+
+ return CM_OK;
+}
+
+/* private method */
+PRIVATE t_cm_error cm_COMP_generic(
+ t_nmf_core_id coreId,
+ t_event_params_handle paramArray,
+ t_uint32 paramNumber,
+ t_uint32 serviceIndex
+)
+{
+ t_event_params_handle _xyuv_data;
+ t_cm_error error;
+ t_uint32 i;
+
+ // wait for an event in fifo
+ if (OSAL_SEMAPHORE_WAIT_TIMEOUT(initializerDesc[coreId].fifoSemHandle) != SYNC_OK) {
+ cm_COMP_generatePanic(coreId);
+ return CM_MPC_NOT_RESPONDING;
+ }
+
+
+ // AllocEvent
+ if((_xyuv_data = cm_AllocEvent(initializerDesc[coreId].downlinkFifo)) == NULL)
+ {
+ ERROR("CM_INTERNAL_FIFO_OVERFLOW: service FIFO full\n", 0, 0, 0, 0, 0, 0);
+ error = CM_INTERNAL_FIFO_OVERFLOW;
+ goto unlock;
+ }
+
+ // Copy param
+ for(i=0;i<paramNumber;i++)
+ _xyuv_data[i] = paramArray[i];
+
+ OSAL_LOCK_COM();
+
+ // Send Command
+ error = cm_PushEventTrace(initializerDesc[coreId].downlinkFifo, _xyuv_data, serviceIndex,0);
+ if(error == CM_OK)
+ initializerDesc[coreId].servicePending++;
+
+unlock:
+ OSAL_UNLOCK_COM();
+
+ return error;
+}
+
+PRIVATE void cm_COMP_generatePanic(t_nmf_core_id coreId)
+{
+ const t_dsp_desc* pDspDesc = cm_DSP_GetState(coreId);
+
+ if (pDspDesc->state != MPC_STATE_PANIC) {
+ cm_DSP_SetStatePanic(coreId);
+ OSAL_GeneratePanic(coreId, 0);
+ }
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c
new file mode 100644
index 00000000000..92c28b63171
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/instantiater.c
@@ -0,0 +1,829 @@
+/*
+ * 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 <cm/engine/component/inc/instance.h>
+#include <cm/engine/component/inc/bind.h>
+#include <cm/engine/component/inc/initializer.h>
+
+#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h>
+#include <cm/engine/configuration/inc/configuration_status.h>
+
+#include <cm/engine/dsp/inc/dsp.h>
+
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/trace/inc/xtitrace.h>
+
+#include <cm/engine/memory/inc/domain.h>
+
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/utils/inc/mem.h>
+#include <cm/engine/utils/inc/convert.h>
+
+#include <cm/engine/power_mgt/inc/power.h>
+
+
+t_nmf_table ComponentTable; /**< list (table) of components */
+
+static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent);
+static t_uint16 getNumberOfInstance(t_component_instance* component);
+static t_uint16 getNumberOfStart(t_component_instance* component);
+
+
+t_cm_error cm_COMP_Init(void) {
+ t_cm_error error;
+ error = cm_initTable(&ComponentTable);
+ if (error == CM_OK)
+ error = cm_initTable(&Host2MpcBindingTable);
+ return error;
+}
+
+void cm_COMP_Destroy(void) {
+ cm_destroyTable(&ComponentTable);
+ cm_destroyTable(&Host2MpcBindingTable);
+}
+
+/** cm_addComponent - Add an internal handler to the list
+ *
+ * 1. Increase the size of the list if it's full
+ * 2. Search an empty entry
+ * 3. Add the element to the list
+ * 4. Compute and return the "user handle" (= t_cm_instance_handle)
+ */
+static t_cm_instance_handle cm_addComponent(t_component_instance *comp)
+{
+ OSAL_DisableServiceMessages();
+ comp->instance = cm_addEntry(&ComponentTable, comp);
+ OSAL_EnableServiceMessages();
+
+ return comp->instance;
+}
+
+/** cm_delComponent - remove the given component from the list
+ *
+ * 1. Check if the handle is valid
+ * 2. Search the entry and free it
+ */
+static void cm_delComponent(t_component_instance *comp)
+{
+ if (comp == NULL)
+ return;
+
+ OSAL_DisableServiceMessages();
+ cm_delEntry(&ComponentTable, comp->instance & INDEX_MASK);
+ OSAL_EnableServiceMessages();
+}
+
+/** cm_lookupComponent - search the component corresponding to
+ * the component instance.
+ *
+ * 1. Check if the instance is valid
+ * 2. Return a pointer to the component
+ */
+t_component_instance *cm_lookupComponent(const t_cm_instance_handle hdl)
+{
+ return cm_lookupEntry(&ComponentTable, hdl);
+}
+
+static void cm_DestroyComponentMemory(t_component_instance *component)
+{
+ int i;
+
+ /*
+ * Remove instance from list
+ */
+ cm_delComponent(component);
+
+ /*
+ * Destroy instance
+ */
+ {
+ struct t_client_of_singleton* cur = component->clientOfSingleton;
+
+ for( ; cur != NULL ; )
+ {
+ struct t_client_of_singleton* tmp = cur;
+ cur = cur->next;
+
+ OSAL_Free(tmp);
+ }
+ }
+
+ for(i = 0; i < component->Template->requireNumber; i++)
+ {
+ OSAL_Free(component->interfaceReferences[i]);
+ }
+
+ cm_StringRelease(component->pathname);
+
+ cm_ELF_FreeInstance(component->Template->dspId, component->Template->memories, component->memories);
+
+ cm_unloadComponent(component->Template);
+ OSAL_Free(component);
+}
+
+/**
+ * Non-Require:
+ * - MMDSP could be sleep (Since we access it only through HSEM)
+ */
+void cm_delayedDestroyComponent(t_component_instance *component) {
+ int i;
+
+ if (osal_debug_ops.component_destroy)
+ osal_debug_ops.component_destroy(component);
+
+ /*
+ * Remove component from load map here
+ */
+ cm_DSPABI_RemoveLoadMap(
+ component->domainId,
+ component->Template->name,
+ component->memories,
+ component->pathname,
+ component);
+
+ // Generate XTI/STM trace
+ cm_TRC_traceLoadMap(TRACE_COMPONENT_COMMAND_REMOVE, component);
+
+ /*
+ * disconnect interrupt handler if needed
+ */
+ for(i = 0; i < component->Template->provideNumber; i++)
+ {
+ if(component->Template->provides[i].interruptLine)
+ {
+ cm_unbindInterfaceStaticInterrupt(component->Template->dspId, component->Template->provides[i].interruptLine);
+ }
+ }
+
+ /*
+ * Update dsp stack size if needed
+ */
+ if (component->Template->minStackSize > MIN_STACK_SIZE)
+ {
+ if (cm_EEM_isStackUpdateNeed(component->Template->dspId, component->priority, FALSE, component->Template->minStackSize))
+ {
+ t_uint32 newStackValue;
+ t_uint32 maxComponentStackSize;
+
+ maxComponentStackSize = cm_getMaxStackValue(component);
+ cm_EEM_UpdateStack(component->Template->dspId, component->priority, maxComponentStackSize, &newStackValue);
+ if (cm_DSP_GetState(component->Template->dspId)->state == MPC_STATE_BOOTED)
+ cm_COMP_UpdateStack(component->Template->dspId, newStackValue);
+ }
+ }
+
+ cm_DestroyComponentMemory(component);
+}
+
+/**
+ * Pre-Require:
+ * - MMDSP wakeup (when loading in TCM)
+ */
+t_cm_error cm_instantiateComponent(const char* templateName,
+ t_cm_domain_id domainId,
+ t_nmf_ee_priority priority,
+ const char* pathName,
+ t_elfdescription *elfhandle,
+ t_component_instance** refcomponent)
+{
+ t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId);
+ t_dup_char templateNameDup;
+ t_component_template* template;
+ t_component_instance *component;
+ /* coverity[var_decl] */
+ t_cm_error error;
+ int i, j, k;
+
+ *refcomponent = NULL;
+
+ templateNameDup = cm_StringDuplicate(templateName);
+ if(templateNameDup == NULL)
+ return CM_NO_MORE_MEMORY;
+
+ /*
+ * Lookup in template list
+ */
+ template = cm_lookupTemplate(coreId, templateNameDup);
+ if(template != NULL)
+ {
+ if(template->classe == SINGLETON)
+ {
+ // Return same handle for singleton component
+ struct t_client_of_singleton* cl;
+
+ cm_StringRelease(templateNameDup);
+
+ cl = cm_getClientOfSingleton(template->singletonIfAvaliable, TRUE, domainDesc[domainId].client);
+ if(cl == NULL)
+ return CM_NO_MORE_MEMORY;
+ cl->numberOfInstance++;
+
+ *refcomponent = template->singletonIfAvaliable;
+ LOG_INTERNAL(1, "##### Singleton : New handle of %s/%x component on %s provItf=%d#####\n",
+ template->singletonIfAvaliable->pathname, template->singletonIfAvaliable, cm_getDspName(coreId),
+ template->singletonIfAvaliable->providedItfUsedCount, 0, 0);
+ return CM_OK;
+ }
+ }
+
+ // Get the dataFile (identity if already pass as parameter)
+ if((elfhandle = cm_REP_getComponentFile(templateNameDup, elfhandle)) == NULL)
+ {
+ cm_StringRelease(templateNameDup);
+ return CM_COMPONENT_NOT_FOUND;
+ }
+
+ // Load template
+ if((error = cm_loadComponent(templateNameDup, domainId, elfhandle, &template)) != CM_OK)
+ {
+ cm_StringRelease(templateNameDup);
+ return error;
+ }
+
+ // templateNameDup no more used, release it
+ cm_StringRelease(templateNameDup);
+
+ // Allocated component
+ component = (t_component_instance*)OSAL_Alloc_Zero(
+ sizeof(t_component_instance) +
+ sizeof(t_interface_reference*) * template->requireNumber);
+ if(component == NULL)
+ {
+ cm_unloadComponent(template);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ component->interfaceReferences = (t_interface_reference**)((char*)component + sizeof(t_component_instance));
+ component->Template = template;
+
+ /*
+ * Update linked list
+ */
+ if (cm_addComponent(component) == 0) {
+ cm_unloadComponent(template);
+ OSAL_Free(component);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ // NOTE: From here use cm_DestroyComponentMemory
+
+ component->pathname = pathName ? cm_StringDuplicate(pathName) : cm_StringReference(anonymousDup);
+ if(component->pathname == NULL)
+ {
+ cm_DestroyComponentMemory(component);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ LOG_INTERNAL(1, "\n##### Instantiate %s/%x (%s) component on %s at priority %d #####\n", component->pathname, component, template->name, cm_getDspName(coreId), priority, 0);
+
+ if((error = cm_ELF_LoadInstance(domainId, elfhandle, template->memories, component->memories, template->classe == SINGLETON)) != CM_OK)
+ {
+ cm_DestroyComponentMemory(component);
+ return error;
+ }
+
+ if((error = cm_ELF_relocatePrivateSegments(
+ component->memories,
+ elfhandle,
+ template)) != CM_OK)
+ {
+ cm_DestroyComponentMemory(component);
+ return error;
+ }
+
+ cm_ELF_FlushInstance(coreId, template->memories, component->memories);
+
+ /*
+ * Create a new component instance
+ */
+ component->priority = priority;
+ component->thisAddress = 0xFFFFFFFF;
+ component->state = STATE_NONE;
+
+ if(component->Template->classe == SINGLETON)
+ { // Return same handle for singleton component
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, TRUE, domainDesc[domainId].client);
+ if(cl == NULL)
+ {
+ cm_DestroyComponentMemory(component);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ cl->numberOfInstance = 1;
+ template->singletonIfAvaliable = component;
+ if (cm_DM_GetDomainCoreId(domainId) == SVA_CORE_ID)
+ component->domainId = DEFAULT_SVA_DOMAIN;
+ else
+ component->domainId = DEFAULT_SIA_DOMAIN;
+ } else {
+ component->domainId = domainId;
+ }
+
+ if(component->memories[template->thisMemory->id] != INVALID_MEMORY_HANDLE)
+ cm_DSP_GetDspAddress(component->memories[template->thisMemory->id], &component->thisAddress);
+ else {
+ // In case of singleton or component without data
+ component->thisAddress = 0;
+ }
+
+ /*
+ * Create empty required interfaces array and set method interface to Panic
+ */
+ for(i = 0; i < template->requireNumber; i++) // For all required interface
+ {
+ component->interfaceReferences[i] =
+ (t_interface_reference*)OSAL_Alloc_Zero(sizeof(t_interface_reference) * template->requires[i].collectionSize);
+ if(component->interfaceReferences[i] == NULL)
+ {
+ cm_DestroyComponentMemory(component);
+ return CM_NO_MORE_MEMORY;
+ }
+
+ for(j = 0; j < template->requires[i].collectionSize; j++) // ... and for each index in collection (set THIS&method for each client)
+ {
+ component->interfaceReferences[i][j].instance = NULL;
+ component->interfaceReferences[i][j].bfInfoID = BF_SYNCHRONOUS; // Just to memorize no Binding component used and unbind ToVoid happy ;-).
+
+ if(template->classe == COMPONENT && template->requires[i].indexes != NULL)
+ {
+ // If component, fill THIS to itself to detect UNBINDED panic with rigth DSP
+ t_interface_require_index *requireindex = &template->requires[i].indexes[j];
+ for(k = 0; k < requireindex->numberOfClient; k++)
+ {
+ t_uint32 *hostAddr;
+
+ hostAddr = (t_uint32*)(
+ cm_DSP_GetHostLogicalAddress(
+ component->memories[requireindex->memories[k].memory->id]) +
+ requireindex->memories[k].offset * requireindex->memories[k].memory->memEntSize);
+ *hostAddr++ = (t_uint32)component->thisAddress;
+ }
+ }
+ }
+ }
+
+ /*
+ * Inform debugger about new component
+ */
+ if ((error = cm_DSPABI_AddLoadMap(
+ domainId,
+ template->name,
+ component->pathname,
+ component->memories,
+ component)) != CM_OK)
+ {
+ cm_DestroyComponentMemory(component);
+ return error;
+ }
+
+ // Generate XTI/STM trace
+ cm_TRC_traceLoadMap(TRACE_COMPONENT_COMMAND_ADD, component);
+
+ // NOTE: From here use cm_delayedDestroyComponent
+
+ /*
+ * Relocate interrupt if this is an interrupt
+ */
+ for(i = 0; i < template->provideNumber; i++)
+ {
+ if(template->provides[i].interruptLine)
+ {
+ if ((error = cm_bindInterfaceStaticInterrupt(coreId,
+ template->provides[i].interruptLine,
+ component,
+ template->provides[i].name)) != CM_OK)
+ {
+ cm_delayedDestroyComponent(component);
+ return error;
+ }
+ }
+ }
+
+ /*
+ * For first instance of a component; Update ee stack size if needed
+ */
+ if(template->classe != FIRMWARE && template->numberOfInstance == 1 && template->minStackSize > MIN_STACK_SIZE)
+ {
+ t_uint32 newStackValue;
+
+ if (cm_EEM_isStackUpdateNeed(template->dspId, priority, TRUE, template->minStackSize))
+ {
+ error = cm_EEM_UpdateStack(template->dspId, priority, template->minStackSize, &newStackValue);
+ if (error != CM_OK)
+ {
+ cm_delayedDestroyComponent(component);
+ return error;
+ }
+ cm_COMP_UpdateStack(template->dspId, newStackValue);
+ }
+ }
+
+
+ /*
+ * For component or first instance
+ */
+ if(template->classe == SINGLETON || template->classe == COMPONENT)
+ {
+ /*
+ * Call init function generated by the compiler (one per .elf)
+ */
+ LOG_INTERNAL(2, "constructor call(s) <%s>\n", template->name, 0, 0, 0, 0, 0);
+ if (cm_DSP_GetState(template->dspId)->state != MPC_STATE_BOOTED)
+ {
+ cm_delayedDestroyComponent(component);
+ return CM_MPC_NOT_RESPONDING;
+ }
+ else if ((error = cm_COMP_CallService(
+ (priority > cm_EEM_getExecutiveEngine(coreId)->instance->priority)?NMF_CONSTRUCT_SYNC_INDEX:NMF_CONSTRUCT_INDEX,
+ component,
+ template->LCCConstructAddress)) != CM_OK)
+ {
+ if (error == CM_MPC_NOT_RESPONDING)
+ ERROR("CM_MPC_NOT_RESPONDING: can't call constructor '%s'\n", component->pathname, 0, 0, 0, 0, 0);
+ cm_delayedDestroyComponent(component);
+ return error;
+ }
+ }
+ else
+ {
+ /* be sure everything is write into memory, not required elsewhere since will be done by cm_COMP_CallService */
+ OSAL_mb();
+ }
+
+ // For firmware; Directly switch to STARTED state, don't need to start it
+ if (template->classe == FIRMWARE)
+ component->state = STATE_RUNNABLE;
+ else
+ component->state = STATE_STOPPED;
+
+ if (osal_debug_ops.component_create)
+ osal_debug_ops.component_create(component);
+
+ *refcomponent = component;
+ return CM_OK;
+}
+
+struct t_client_of_singleton* cm_getClientOfSingleton(t_component_instance* component, t_bool createdIfNotExist, t_nmf_client_id clientId)
+{
+ struct t_client_of_singleton* cur = component->clientOfSingleton;
+
+ for( ; cur != NULL ; cur = cur->next)
+ {
+ if(cur->clientId == clientId)
+ {
+ return cur;
+ }
+ }
+
+ //if(createdIfNotExist)
+ {
+ cur = OSAL_Alloc(sizeof(struct t_client_of_singleton));
+ if(cur != NULL)
+ {
+ cur->clientId = clientId;
+ cur->next = component->clientOfSingleton;
+ cur->numberOfBind = 0;
+ cur->numberOfInstance= 0;
+ cur->numberOfStart = 0;
+ component->clientOfSingleton = cur;
+ }
+ }
+ return cur;
+}
+
+/**
+ * Non-Require:
+ * - MMDSP could be sleep (Since we access it only through HSEM)
+ */
+t_cm_error cm_startComponent(t_component_instance* component, t_nmf_client_id clientId)
+{
+ t_cm_error error;
+ char value[MAX_PROPERTY_VALUE_LENGTH];
+ int i;
+
+ /*
+ * Special code for SINGLETON handling
+ */
+ if(component->Template->classe == SINGLETON)
+ {
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId);
+ if(cl != NULL)
+ cl->numberOfStart++;
+ // A singleton could be started twice, thus start it only if first client starter
+ if(getNumberOfStart(component) > 1)
+ return CM_OK;
+
+ // Fall through and start really the singleton.
+ }
+
+ if(component->state == STATE_RUNNABLE)
+ return CM_COMPONENT_NOT_STOPPED;
+
+ // CM_ASSERT component->state == STATE_STOPPED
+
+ /*
+ * Check that all required binding have been binded!
+ */
+ for(i = 0; i < component->Template->requireNumber; i++)
+ {
+ int nb = component->Template->requires[i].collectionSize, j;
+ for(j = 0; j < nb; j++)
+ {
+ if(component->interfaceReferences[i][j].instance == NULL &&
+ (component->Template->requires[i].requireTypes & (OPTIONAL_REQUIRE | INTRINSEC_REQUIRE)) == 0)
+ {
+ ERROR("CM_REQUIRE_INTERFACE_UNBINDED: Required interface '%s'.'%s' binded\n", component->pathname, component->Template->requires[i].name, 0, 0, 0, 0);
+ return CM_REQUIRE_INTERFACE_UNBINDED;
+ }
+ }
+ }
+
+ component->state = STATE_RUNNABLE;
+
+ /*
+ * Power on, HW resources if required
+ */
+ if(cm_getComponentProperty(
+ component,
+ "hardware",
+ value,
+ sizeof(value)) == CM_OK)
+ {
+ error = cm_PWR_EnableMPC(MPC_PWR_HWIP, component->Template->dspId);
+ if(error != CM_OK)
+ return error;
+ }
+
+ /*
+ * Call starter if available
+ */
+ if(component->Template->LCCStartAddress != 0)
+ {
+ if (cm_DSP_GetState(component->Template->dspId)->state != MPC_STATE_BOOTED)
+ {
+ return CM_MPC_NOT_RESPONDING;
+ }
+ else if ((error = cm_COMP_CallService(
+ (component->priority > cm_EEM_getExecutiveEngine(component->Template->dspId)->instance->priority)?NMF_START_SYNC_INDEX:NMF_START_INDEX,
+ component,
+ component->Template->LCCStartAddress)) != CM_OK)
+ {
+ if (error == CM_MPC_NOT_RESPONDING)
+ ERROR("CM_MPC_NOT_RESPONDING: can't call starter '%s'\n", component->pathname, 0, 0, 0, 0, 0);
+ return error;
+ }
+ }
+
+ return CM_OK;
+}
+
+/**
+ * Non-Require:
+ * - MMDSP could be sleep (Since we access it only through HSEM)
+ */
+t_cm_error cm_stopComponent(t_component_instance* component, t_nmf_client_id clientId)
+{
+ char value[MAX_PROPERTY_VALUE_LENGTH];
+ t_cm_error error = CM_OK;
+ t_bool isHwProperty;
+
+ /*
+ * Special code for SINGLETON handling
+ */
+ if(component->Template->classe == SINGLETON)
+ {
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId);
+ if(cl != NULL)
+ cl->numberOfStart--;
+ // A singleton could be started twice, thus stop it only if no more client starter
+ if(getNumberOfStart(component) > 0)
+ return CM_OK;
+
+ // Fall through and stop really the singleton.
+ }
+
+ /*
+ * Component life cycle sanity check
+ */
+ if(component->state == STATE_STOPPED)
+ return CM_COMPONENT_NOT_STARTED;
+
+ // CM_ASSERT component->state == STATE_RUNNABLE
+ component->state = STATE_STOPPED;
+
+ isHwProperty = (cm_getComponentProperty(
+ component,
+ "hardware",
+ value,
+ sizeof(value)) == CM_OK);
+
+ if (cm_DSP_GetState(component->Template->dspId)->state != MPC_STATE_BOOTED)
+ {
+ error = CM_MPC_NOT_RESPONDING;
+ }
+ else
+ {
+ /*
+ * Call stopper if available
+ */
+ if(component->Template->LCCStopAddress != 0)
+ {
+ if ((error = cm_COMP_CallService(
+ isHwProperty ? NMF_STOP_SYNC_INDEX : NMF_STOP_INDEX,
+ component,
+ component->Template->LCCStopAddress)) != CM_OK)
+ {
+ if (error == CM_MPC_NOT_RESPONDING)
+ ERROR("CM_MPC_NOT_RESPONDING: can't call stopper '%s'\n", component->pathname, 0, 0, 0, 0, 0);
+ }
+ }
+ }
+
+ /*
+ * Power on, HW resources if required
+ */
+ if(isHwProperty)
+ {
+ cm_PWR_DisableMPC(MPC_PWR_HWIP, component->Template->dspId);
+ }
+
+ return error;
+}
+
+t_cm_error cm_destroyInstance(t_component_instance* component, t_destroy_state forceDestroy)
+{
+ int i, j;
+
+ LOG_INTERNAL(1, "\n##### Destroy %s/%x (%s) component on %s #####\n",
+ component->pathname, component, component->Template->name, cm_getDspName(component->Template->dspId), 0, 0);
+
+ /*
+ * Component life cycle sanity check; do it only when destroying last reference.
+ */
+ if(forceDestroy == DESTROY_NORMAL)
+ {
+ if (component->state == STATE_RUNNABLE)
+ return CM_COMPONENT_NOT_STOPPED;
+
+ // CM_ASSERT component->state == STATE_STOPPED
+
+ // Check that all required binding have been unbound!
+ 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)
+ {
+ ERROR("CM_COMPONENT_NOT_UNBINDED: Required interface %s/%x.%s still binded\n",
+ component->pathname, component, component->Template->requires[i].name, 0, 0, 0);
+ return CM_COMPONENT_NOT_UNBINDED;
+ }
+ }
+ }
+
+ // Check that all provided bindings have been unbound!
+ if (component->providedItfUsedCount != 0)
+ {
+ unsigned idx;
+
+ ERROR("CM_COMPONENT_NOT_UNBINDED: Still %d binding to %s/%x provided interface\n",
+ component->providedItfUsedCount, component->pathname, component, 0, 0, 0);
+
+ /* Find which interface is still bound to gracefully print an error message */
+ for (idx=0; idx<ComponentTable.idxMax; idx++)
+ {
+ if ((componentEntry(idx) == NULL) || (componentEntry(idx) == component))
+ continue;
+ for (i = 0; i < componentEntry(idx)->Template->requireNumber; i++)
+ {
+ for (j = 0; j < componentEntry(idx)->Template->requires[i].collectionSize; j++)
+ {
+ if(componentEntry(idx)->interfaceReferences[i][j].instance == component
+ && component->Template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].interruptLine == 0)
+ {
+ ERROR(" -> %s/%x.%s still used by %s/%x.%s\n",
+ component->pathname, component,
+ component->Template->provides[componentEntry(idx)->interfaceReferences[i][j].provideIndex].name,
+ componentEntry(idx)->pathname,
+ componentEntry(idx),
+ componentEntry(idx)->Template->requires[i].name);
+ }
+ }
+ }
+ }
+
+ return CM_COMPONENT_NOT_UNBINDED;
+ }
+ }
+
+ // Sanity check finished, here, we will do the JOB whatever error
+
+ if (cm_DSP_GetState(component->Template->dspId)->state == MPC_STATE_BOOTED)
+ {
+ /*
+ * Call destroy if available
+ */
+ /* Call the destructor only if we don't want to force the destruction */
+ if(forceDestroy != DESTROY_WITHOUT_CHECK_CALL && component->Template->LCCDestroyAddress != 0)
+ {
+ if (cm_COMP_CallService(
+ NMF_DESTROY_INDEX,
+ component,
+ component->Template->LCCDestroyAddress) != CM_OK)
+ {
+ ERROR("CM_MPC_NOT_RESPONDING: can't call destroy '%s'\n", component->pathname, 0, 0, 0, 0, 0);
+ }
+ }
+ else
+ {
+ cm_COMP_Flush(component->Template->dspId);
+ }
+ }
+
+ cm_delayedDestroyComponent(component);
+
+ return CM_OK;
+}
+
+/**
+ * Pre-Require:
+ * - MMDSP wakeup (when accessing loadmap)
+ */
+t_cm_error cm_destroyInstanceForClient(t_component_instance* component, t_destroy_state forceDestroy, t_nmf_client_id clientId)
+{
+ /*
+ * Special code for SINGLETON handling
+ */
+ if(component->Template->classe == SINGLETON)
+ {
+ struct t_client_of_singleton* cl = cm_getClientOfSingleton(component, FALSE, clientId);
+ int nbinstance;
+ if(cl != NULL)
+ cl->numberOfInstance--;
+
+ // A singleton could be instantiate twice, thus destroy it only if no more client constructor
+ nbinstance = getNumberOfInstance(component);
+ if(nbinstance > 0)
+ {
+ LOG_INTERNAL(1, "##### Singleton : Delete handle of %s/%x (%s) component on %s [%d] provItf=%d #####\n",
+ component->pathname, component, component->Template->name, cm_getDspName(component->Template->dspId),
+ nbinstance, component->providedItfUsedCount);
+ return CM_OK;
+ }
+
+ // Fall through
+ }
+
+ return cm_destroyInstance(component, forceDestroy);
+}
+
+
+static t_uint32 cm_getMaxStackValue(t_component_instance *pComponent)
+{
+ t_nmf_executive_engine_id executiveEngineId = cm_EEM_getExecutiveEngine(pComponent->Template->dspId)->executiveEngineId;
+ t_uint32 res = MIN_STACK_SIZE;
+ unsigned int i;
+
+ for (i=0; i<ComponentTable.idxMax; i++)
+ {
+ if ((componentEntry(i) != NULL) &&
+ (componentEntry(i) != pComponent) &&
+ (pComponent->Template->dspId == componentEntry(i)->Template->dspId) &&
+ (executiveEngineId == SYNCHRONOUS_EXECUTIVE_ENGINE || componentEntry(i)->priority == pComponent->priority))
+ {
+ if (componentEntry(i)->Template->minStackSize > res)
+ res = componentEntry(i)->Template->minStackSize;
+ }
+ }
+
+ return res;
+}
+
+static t_uint16 getNumberOfInstance(t_component_instance* component)
+{
+ t_uint16 instanceNumber = 0;
+ struct t_client_of_singleton* cur = component->clientOfSingleton;
+
+ for( ; cur != NULL ; cur = cur->next)
+ {
+ instanceNumber += cur->numberOfInstance;
+ }
+
+ return instanceNumber;
+}
+
+static t_uint16 getNumberOfStart(t_component_instance* component)
+{
+ t_uint16 startNumber = 0;
+ struct t_client_of_singleton* cur = component->clientOfSingleton;
+
+ for( ; cur != NULL ; cur = cur->next)
+ {
+ startNumber += cur->numberOfStart;
+ }
+
+ return startNumber;
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c
new file mode 100644
index 00000000000..7e2f7cd65d0
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/introspection.c
@@ -0,0 +1,327 @@
+/*
+ * 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 <cm/engine/component/inc/introspection.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/utils/inc/string.h>
+
+/*
+ *
+ */
+t_cm_error cm_getComponentProperty(
+ const t_component_instance *component,
+ const char *propName,
+ char value[MAX_PROPERTY_VALUE_LENGTH],
+ t_uint32 valueLength){
+ t_component_template* template = component->Template;
+ int i;
+
+ for(i = 0; i < template->propertyNumber; i++) {
+ if(cm_StringCompare(template->properties[i].name, propName, MAX_PROPERTY_NAME_LENGTH) == 0) {
+ cm_StringCopy(
+ value,
+ template->properties[i].value,
+ valueLength);
+ return CM_OK;
+ }
+ }
+
+ return CM_NO_SUCH_PROPERTY;
+}
+
+/**
+ *
+ */
+static t_attribute* cm_getAttributeDescriptor(
+ const t_component_instance *component,
+ const char *attrName)
+{
+ int i;
+
+ for(i = 0; i < component->Template->attributeNumber; i++)
+ {
+ if(cm_StringCompare(component->Template->attributes[i].name, attrName, MAX_ATTRIBUTE_NAME_LENGTH) == 0)
+ {
+ return &component->Template->attributes[i];
+ }
+ }
+
+ return NULL;
+}
+
+t_dsp_address cm_getAttributeMpcAddress(
+ const t_component_instance *component,
+ const char *attrName)
+{
+ t_attribute* attribute;
+ t_uint32 dspAddress;
+
+ if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL)
+ return 0x0;
+
+ cm_DSP_GetDspAddress(component->memories[attribute->memory.memory->id], &dspAddress);
+
+ return (dspAddress +
+ attribute->memory.offset);
+}
+
+t_cm_logical_address cm_getAttributeHostAddr(
+ const t_component_instance *component,
+ const char *attrName)
+{
+ t_attribute* attribute;
+
+ if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL)
+ return 0x0;
+
+ // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load
+ return cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) +
+ attribute->memory.offset * attribute->memory.memory->memEntSize;
+}
+
+
+t_cm_error cm_readAttribute(
+ const t_component_instance* component,
+ const char* attrName,
+ t_uint32* value)
+{
+ t_attribute* attribute;
+ t_cm_logical_address hostAddr;
+
+ if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL)
+ {
+ ERROR("CM_NO_SUCH_ATTRIBUTE(%s, %s)\n", component->pathname, attrName, 0, 0, 0, 0);
+ return CM_NO_SUCH_ATTRIBUTE;
+ }
+
+ // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load
+ hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) +
+ attribute->memory.offset * attribute->memory.memory->memEntSize;
+
+ if(attribute->memory.memory->memEntSize != 2)
+ *value = *((t_uint32 *)hostAddr) & ~MASK_BYTE3;
+ else
+ *value = *((t_uint16 *)hostAddr);
+
+ LOG_INTERNAL(3, "cm_readAttribute: [%s:%s, %x]=%x\n",
+ component->pathname, attrName, hostAddr, *value, 0, 0);
+
+ return CM_OK;
+}
+
+t_uint32 cm_readAttributeNoError(
+ const t_component_instance* component,
+ const char* attrName)
+{
+ t_uint32 value;
+
+ if(cm_readAttribute(component, attrName, &value) != CM_OK)
+ value = 0;
+
+ return value;
+}
+
+t_cm_error cm_writeAttribute(
+ const t_component_instance* component,
+ const char* attrName,
+ t_uint32 value)
+{
+ t_attribute* attribute;
+ t_cm_logical_address hostAddr;
+
+ if((attribute = cm_getAttributeDescriptor(component, attrName)) == NULL)
+ {
+ ERROR("CM_NO_SUCH_ATTRIBUTE(%s, %s)\n", component->pathname, attrName, 0, 0, 0, 0);
+ return CM_NO_SUCH_ATTRIBUTE;
+ }
+
+ // TODO JPF: component->Template->attributes[i].memory.offset could be converted in byte during load
+ hostAddr = cm_DSP_GetHostLogicalAddress(component->memories[attribute->memory.memory->id]) +
+ attribute->memory.offset * attribute->memory.memory->memEntSize;
+
+ if(attribute->memory.memory->memEntSize != 2)
+ *((t_uint32 *)hostAddr) = value & ~MASK_BYTE3;
+ else
+ *((t_uint16 *)hostAddr) = value;
+
+ /* be sure attribute is write into memory */
+ OSAL_mb();
+
+ LOG_INTERNAL(3, "cm_writeAttribute: [%s:%s, %x]=%x\n",
+ component->pathname, attrName, hostAddr, value, 0, 0);
+
+ return CM_OK;
+}
+
+
+/**
+ *
+ */
+t_dsp_address cm_getFunction(
+ const t_component_instance* component,
+ const char* interfaceName,
+ const char* methodName)
+{
+ t_interface_provide_description itfProvide;
+ t_interface_provide* provide;
+ t_interface_provide_loaded* provideLoaded;
+ t_cm_error error;
+ int i;
+
+ // Get interface description
+ if((error = cm_getProvidedInterface(component, interfaceName, &itfProvide)) != CM_OK)
+ return error;
+
+ provide = &component->Template->provides[itfProvide.provideIndex];
+ provideLoaded = &component->Template->providesLoaded[itfProvide.provideIndex];
+
+ for(i = 0; i < provide->interface->methodNumber; i++)
+ {
+ if(cm_StringCompare(provide->interface->methodNames[i], methodName, MAX_INTERFACE_METHOD_NAME_LENGTH) == 0)
+ {
+ return provideLoaded->indexesLoaded[itfProvide.collectionIndex][i].methodAddresses;
+ }
+ }
+
+ return 0x0;
+}
+
+/**
+ *
+ */
+PRIVATE t_uint8 compareItfName(const char* simplename, const char* complexname, int *collectionIndex) {
+ int i;
+
+ // Search if simplename is a prefix of complexname ??
+ for(i = 0; simplename[i] != 0; i++) {
+ if(simplename[i] != complexname[i])
+ return 1; // NO
+ }
+
+ // YES
+ if(complexname[i] == '[') {
+ // This is a collection
+ int value = 0;
+ i++;
+ if(complexname[i] < '0' || complexname[i] > '9') {
+ return 1;
+ }
+ for(; complexname[i] >= '0' && complexname[i] <= '9'; i++) {
+ value = value * 10 + (complexname[i] - '0');
+ }
+ if(complexname[i++] != ']')
+ return 1;
+ *collectionIndex = value;
+ } else
+ *collectionIndex = -1;
+
+ if(complexname[i] != 0) {
+ // Complexe name has not been fully parsed -> different name
+ return 1;
+ }
+
+ return 0;
+}
+
+
+/**
+ *
+ */
+PUBLIC t_cm_error cm_getProvidedInterface(const t_component_instance* server,
+ const char* itfName,
+ t_interface_provide_description *itfProvide){
+ int i;
+
+ for(i = 0; i < server->Template->provideNumber; i++)
+ {
+ int collectionIndex;
+ if(compareItfName(server->Template->provides[i].name, itfName, &collectionIndex) == 0)
+ {
+ t_interface_provide *provide = &server->Template->provides[i];
+ if(collectionIndex >= 0)
+ {
+ if(! (provide->provideTypes & COLLECTION_PROVIDE)) {
+ ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s)\n",
+ server->pathname, itfName, 0, 0, 0, 0);
+ goto out;
+ }
+ if(collectionIndex >= provide->collectionSize) {
+ ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s): out of range [0..%d[\n",
+ server->pathname, itfName, provide->collectionSize,
+ 0, 0, 0);
+ goto out;
+ }
+ }
+ else
+ {
+ if(provide->provideTypes & COLLECTION_PROVIDE) {
+ ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s): interface is a collection [0..%d[\n",
+ server->pathname, itfName, provide->collectionSize,
+ 0, 0, 0);
+ goto out;
+ }
+ collectionIndex = 0;
+ }
+ itfProvide->provideIndex = i;
+ itfProvide->server = server;
+ itfProvide->collectionIndex = collectionIndex;
+ itfProvide->origName = itfName;
+ return CM_OK;
+ }
+ }
+
+ ERROR("CM_NO_SUCH_PROVIDED_INTERFACE(%s, %s)\n", server->pathname, itfName, 0, 0, 0, 0);
+out:
+ itfProvide->provideIndex = 0;
+ itfProvide->server = NULL;
+ itfProvide->collectionIndex = 0;
+ itfProvide->origName = NULL;
+ return CM_NO_SUCH_PROVIDED_INTERFACE;
+}
+
+/**
+ *
+ */
+t_cm_error cm_getRequiredInterface(const t_component_instance* client,
+ const char* itfName,
+ t_interface_require_description *itfRequire){
+ int i;
+
+ for(i = 0; i < client->Template->requireNumber; i++) {
+ int collectionIndex;
+ if(compareItfName(client->Template->requires[i].name, itfName, &collectionIndex) == 0) {
+ t_interface_require *require = &client->Template->requires[i];
+ if(collectionIndex >= 0) {
+ if(! (require->requireTypes & COLLECTION_REQUIRE)) {
+ ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s)\n",
+ client->pathname, itfName, 0, 0, 0, 0);
+ return CM_NO_SUCH_REQUIRED_INTERFACE;
+ }
+ if(collectionIndex >= require->collectionSize) {
+ ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s): out of range [0..%d[\n",
+ client->pathname, itfName, require->collectionSize,
+ 0, 0, 0);
+ return CM_NO_SUCH_REQUIRED_INTERFACE;
+ }
+ } else {
+ if(require->requireTypes & COLLECTION_REQUIRE) {
+ ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s): interface is a collection [0..%d[\n",
+ client->pathname, itfName, require->collectionSize,
+ 0, 0, 0);
+ return CM_NO_SUCH_REQUIRED_INTERFACE;
+ }
+ collectionIndex = 0;
+ }
+ itfRequire->client = client;
+ itfRequire->requireIndex = i;
+ itfRequire->collectionIndex = collectionIndex;
+ itfRequire->origName = itfName;
+ return CM_OK;
+ }
+ }
+
+ ERROR("CM_NO_SUCH_REQUIRED_INTERFACE(%s, %s)\n", client->pathname, itfName, 0, 0, 0, 0);
+ return CM_NO_SUCH_REQUIRED_INTERFACE;
+}
diff --git a/drivers/staging/nmf-cm/cm/engine/component/src/loader.c b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c
new file mode 100644
index 00000000000..3d81e8308f9
--- /dev/null
+++ b/drivers/staging/nmf-cm/cm/engine/component/src/loader.c
@@ -0,0 +1,384 @@
+/*
+ * 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 <cm/engine/component/inc/instance.h>
+#include <cm/engine/memory/inc/memory.h>
+#include <cm/engine/executive_engine_mgt/inc/executive_engine_mgt.h>
+#include <cm/engine/component/inc/bind.h>
+
+#include <cm/engine/utils/inc/string.h>
+#include <cm/engine/trace/inc/trace.h>
+#include <cm/engine/utils/inc/convert.h>
+
+void START(void);
+void END(char*);
+
+#undef NHASH
+#define NHASH 79 //Use a prime number!
+#define MULT 17
+
+static t_component_template *templates[NB_CORE_IDS][NHASH];
+
+static unsigned int templateHash(const char *str)
+{
+ unsigned int h = 0;
+ for(; *str; str++)
+ h = MULT * h + *str;
+ return h % NHASH;
+}
+
+static void templateAdd(t_component_template *template)
+{
+ unsigned int h = templateHash(template->name);
+
+ if(templates[template->dspId][h] != NULL)
+ templates[template->dspId][h]->prev = template;
+ template->next = templates[template->dspId][h];
+ template->prev = NULL;
+ templates[template->dspId][h] = template;
+}
+
+static void templateRemove(t_component_template *template)
+{
+ unsigned int h = templateHash(template->name);
+
+ if(template->prev != NULL)
+ template->prev->next = template->next;
+ if(template->next != NULL)
+ template->next->prev = template->prev;
+ if(template == templates[template->dspId][h])
+ templates[template->dspId][h] = template->next;
+}
+
+
+t_component_template* cm_lookupTemplate(t_nmf_core_id dspId, t_dup_char str)
+{
+ t_component_template *template;
+
+ for(template = templates[dspId][templateHash(str)]; template != NULL; template = template->next)
+ {
+ if(str == template->name)
+ return template;
+ }
+
+ return NULL;
+}
+
+t_bool cm_isComponentOnCoreId(t_nmf_core_id coreId) {
+ t_uint32 i;
+
+ for(i = 0; i < NHASH; i++)
+ {
+ if ((templates[coreId][i] != NULL)
+ && (templates[coreId][i]->classe != FIRMWARE)) // Skip firmware
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+static t_dsp_address MemoryToDspAdress(t_component_template *template, t_memory_reference *memory)
+{
+ if(memory->memory == NULL)
+ return (t_dsp_address)memory->offset;
+ else
+ {
+ t_dsp_address address;
+
+ cm_DSP_GetDspAddress(template->memories[memory->memory->id], &address);
+
+ return (t_dsp_address)(address + memory->offset);
+ }
+}
+
+/*
+ * Method callback
+ */
+t_uint32 cm_resolvSymbol(
+ void* context,
+ t_uint32 type,
+ t_dup_char symbolName,
+ char* reloc_addr)
+{
+ t_component_template *template = (t_component_template*)context;
+ t_component_instance* ee = cm_EEM_getExecutiveEngine(template->dspId)->instance;
+ int i, j;
+
+ // Search if this method is provided by EE and resolve it directly
+ for(i = 0; i < ee->Template->provideNumber; i++)
+ {
+ t_interface_provide* provide = &ee->Template->provides[i];
+ t_interface_provide_loaded* provideLoaded = &ee->Template->providesLoaded[i];
+
+ for(j = 0; j < provide->interface->methodNumber; j++)
+ {
+ if(provide->interface->methodNames[j] == symbolName)
+ {
+ return provideLoaded->indexesLoaded[0][j].methodAddresses; // Here we assume no collection provided !!
+ }
+ }
+ }
+
+ // Lookup if the method is statically required, ands delay relocation when bind occur
+ for(i = 0; i < template->requireNumber; i++)
+ {
+ if((template->requires[i].requireTypes & STATIC_REQUIRE) == 0)
+ continue;
+
+ for(j = 0; j < template->requires[i].interface->methodNumber; j++)
+ {
+ if(template->requires[i].interface->methodNames[j] == symbolName)
+ {
+ t_function_relocation* delayedRelocation = (t_function_relocation*)OSAL_Alloc(sizeof(t_function_relocation));
+ if(delayedRelocation == NULL)
+ return 0xFFFFFFFE;
+
+ delayedRelocation->type = type;
+ delayedRelocation->symbol_name = cm_StringReference(symbolName);
+ delayedRelocation->reloc_addr = reloc_addr;
+ delayedRelocation->next = template->delayedRelocation;
+ template->delayedRelocation = delayedRelocation;
+
+ return 0xFFFFFFFF;
+ }
+ }
+ }
+
+ //Symbol not found
+ return 0x0;
+}
+
+/*
+ * Template Management
+ */
+t_cm_error cm_loadComponent(
+ t_dup_char templateName,
+ t_cm_domain_id domainId,
+ t_elfdescription* elfhandle,
+ t_component_template **reftemplate)
+{
+ t_nmf_core_id coreId = cm_DM_GetDomainCoreId(domainId);
+ t_cm_error error;
+ int i, j, k;
+
+ /*
+ * Allocate new component template if first instance
+ */
+ if(*reftemplate == NULL)
+ {
+ t_component_template *template;
+
+ LOG_INTERNAL(1, "\n##### Load template %s on %s #####\n", templateName, cm_getDspName(coreId), 0, 0, 0, 0);
+
+ /*
+ * Sanity check
+ */
+ if(elfhandle->foundedTemplateName != templateName)
+ {
+ ERROR("CM_INVALID_ELF_FILE: template name %s != %s\n", templateName, elfhandle->foundedTemplateName, 0, 0, 0, 0);
+ return CM_INVALID_ELF_FILE;
+ }
+
+ // Alloc & Reset variable in order to use unloadComponent either with partial constructed template
+ *reftemplate = template = (t_component_template*)OSAL_Alloc_Zero(sizeof(t_component_template));
+ if(template == NULL)
+ return CM_NO_MORE_MEMORY;
+ template->name = cm_StringReference(elfhandle->foundedTemplateName);
+
+ // Get information from elfhandle
+ template->descriptionAssociatedWithTemplate = elfhandle->temporaryDescription;
+ template->requireNumber = elfhandle->requireNumber;
+ template->requires = elfhandle->requires;
+ template->attributeNumber = elfhandle->attributeNumber;
+ template->attributes = elfhandle->attributes;
+ template->propertyNumber = elfhandle->propertyNumber;
+ template->properties = elfhandle->properties;
+ template->provideNumber = elfhandle->provideNumber;
+ template->provides = elfhandle->provides;
+ if(template->descriptionAssociatedWithTemplate)
+ {
+ elfhandle->requires = NULL;
+ elfhandle->attributes = NULL;
+ elfhandle->properties = NULL;
+ elfhandle->provides = NULL;
+ }
+
+ // Compute simple information
+ template->numberOfInstance = 1;
+ template->dspId = coreId;
+ LOG_INTERNAL(3, "load<%x> = %s\n", (int)template, template->name, 0, 0, 0, 0);
+ switch(elfhandle->magicNumber) {
+ case MAGIC_COMPONENT:
+ template->classe = COMPONENT;
+ break;
+ case MAGIC_SINGLETON:
+ template->classe = SINGLETON;
+ break;
+ case MAGIC_FIRMWARE:
+ template->classe = FIRMWARE;
+ break;
+ }
+ template->minStackSize = elfhandle->minStackSize;
+
+ /*
+ * Load shared memory from file
+ */
+ // START();
+ if((error = cm_ELF_LoadTemplate(domainId, elfhandle, template->memories, template->classe == SINGLETON)) != CM_OK)
+ goto out;
+ MMDSP_serializeMemories(elfhandle->instanceProperty, &template->codeMemory, &template->thisMemory);
+ // END("cm_ELF_LoadTemplate");
+
+ /*
+ * Copy LCC functions information
+ * Since MMDSP require Constructor & Destructor (for cache flush and debug purpose) to be called
+ * either if not provided by user for allowing defered breakpoint, we use Void method if not provided.
+ */
+ template->LCCConstructAddress = MemoryToDspAdress(template, &elfhandle->memoryForConstruct);
+ template->LCCStartAddress = MemoryToDspAdress(template, &elfhandle->memoryForStart);
+ template->LCCStopAddress = MemoryToDspAdress(template, &elfhandle->memoryForStop);
+ template->LCCDestroyAddress = MemoryToDspAdress(template, &elfhandle->memoryForDestroy);
+ if(template->LCCConstructAddress == 0 && template->classe != FIRMWARE)
+ template->LCCConstructAddress = cm_EEM_getExecutiveEngine(coreId)->voidAddr;
+
+ // Compute provide methodIndex
+ if(template->provideNumber != 0)
+ {
+ template->providesLoaded =
+ (t_interface_provide_loaded*)OSAL_Alloc_Zero(sizeof(t_interface_provide_loaded) * template->provideNumber);
+ if(template->providesLoaded == NULL)
+ goto oom;
+
+ for(i = 0; i < template->provideNumber; i++)
+ {
+ template->providesLoaded[i].indexesLoaded = (t_interface_provide_index_loaded**)OSAL_Alloc_Zero(
+ sizeof(t_interface_provide_index_loaded*) * template->provides[i].collectionSize);
+ if(template->providesLoaded[i].indexesLoaded == NULL)
+ goto oom;
+
+ if(template->provides[i].interface->methodNumber != 0)
+ {
+ for(j = 0; j < template->provides[i].collectionSize; j++)
+ {
+ template->providesLoaded[i].indexesLoaded[j] = (t_interface_provide_index_loaded*)OSAL_Alloc(
+ sizeof(t_interface_provide_index_loaded) * template->provides[i].interface->methodNumber);
+ if(template->providesLoaded[i].indexesLoaded[j] == NULL)
+ goto oom;
+
+ for(k = 0; k < template->provides[i].interface->methodNumber; k++)
+ {
+ template->providesLoaded[i].indexesLoaded[j][k].methodAddresses =
+ MemoryToDspAdress(template, &template->provides[i].indexes[j][k].memory);
+
+ LOG_INTERNAL(2, " [%d, %d] method '%s' @ %x\n",
+ j, k, template->provides[i].interface->methodNames[k],
+ template->providesLoaded[i].indexesLoaded[j][k].methodAddresses, 0, 0);
+ }
+
+ }
+ }
+ }
+ }
+
+ /*
+ * TODO
+
+ if((error = elfhandle->errorOccured) != CM_OK)
+ goto out;
+ */
+
+ // START();
+ if(template->classe != FIRMWARE)
+ {
+ if((error = cm_ELF_relocateSharedSegments(
+ template->memories,
+ elfhandle,
+ template)) != CM_OK)
+ goto out;
+ }
+ // END("cm_ELF_relocateSharedSegments");
+
+ cm_ELF_FlushTemplate(coreId, template->memories);
+
+ templateAdd(template);
+
+ return CM_OK;
+ oom:
+ error = CM_NO_MORE_MEMORY;
+ out:
+ cm_unloadComponent(template);
+ return error;
+ }
+ else
+ {
+ (*reftemplate)->numberOfInstance++;
+ }
+
+ return CM_OK;
+}
+
+PUBLIC t_cm_error cm_unloadComponent(
+ t_component_template *template)
+{
+ /*
+ * Destroy template if last instance
+ */
+ if(--template->numberOfInstance == 0) {
+ t_function_relocation* reloc;
+
+ LOG_INTERNAL(3, "unload<%s>\n", template->name, 0, 0, 0, 0, 0);
+
+ templateRemove(template);
+
+ // Free delayedRelocation
+ reloc = template->delayedRelocation;
+ while(reloc != NULL)
+ {
+ t_function_relocation *tofree = reloc;
+ reloc = reloc->next;
+ cm_StringRelease(tofree->symbol_name);
+ OSAL_Free(tofree);
+ }
+
+ if(template->providesLoaded != NULL)
+ {
+ int i, j;
+
+ for(i = 0; i < template->provideNumber; i++)
+ {
+ if(template->providesLoaded[i].indexesLoaded != NULL)
+ {
+ for(j = 0; j < template->provides[i].collectionSize; j++)
+ {
+ OSAL_Free(template->providesLoaded[i].indexesLoaded[j]);
+ }
+ OSAL_Free(template->providesLoaded[i].indexesLoaded);
+ }
+ }
+
+ OSAL_Free(template->providesLoaded);
+ }
+
+ if(template->descriptionAssociatedWithTemplate)
+ {
+ cm_ELF_ReleaseDescription(
+ template->requireNumber, template->requires,
+ template->attributeNumber, template->attributes,
+ template->propertyNumber, template->properties,
+ template->provideNumber, template->provides);
+ }
+
+ // Free shared memories
+ cm_ELF_FreeTemplate(template->dspId, template->memories);
+
+ cm_StringRelease(template->name);
+
+ OSAL_Free(template);
+ }
+
+ return CM_OK;
+}
+