]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
MLK-9707-2 mcc: mcc version 2.0 base common codes
authorRichard Zhu <richard.zhu@freescale.com>
Mon, 20 Oct 2014 06:34:34 +0000 (14:34 +0800)
committerNitin Garg <nitin.garg@freescale.com>
Fri, 16 Jan 2015 03:19:02 +0000 (21:19 -0600)
This is the base line of the mcc version 2.0.

Acked-by: Shawn Guo
Signed-off-by: Richard Zhu <richard.zhu@freescale.com>
(cherry picked from commit cfd44c266e3b8a833ac624b86be627efbda6aaa9)

arch/arm/mach-imx/mcc_api.c [new file with mode: 0755]
arch/arm/mach-imx/mcc_common.c [new file with mode: 0755]
arch/arm/mach-imx/mcc_config.h [new file with mode: 0755]
include/linux/mcc_api.h [new file with mode: 0755]
include/linux/mcc_common.h [new file with mode: 0755]

diff --git a/arch/arm/mach-imx/mcc_api.c b/arch/arm/mach-imx/mcc_api.c
new file mode 100755 (executable)
index 0000000..dafc8c1
--- /dev/null
@@ -0,0 +1,946 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Freescale IMX Linux-specific MCC implementation.
+ * MCC library API functions implementation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <string.h>
+#include "mcc_config.h"
+#include "mcc_common.h"
+#include "mcc_api.h"
+
+#if (MCC_OS_USED == MCC_MQX)
+#include "mcc_mqx.h"
+#endif
+
+const char * const init_string    = MCC_INIT_STRING;
+const char * const version_string = MCC_VERSION_STRING;
+
+static int mcc_recv_common_part(MCC_ENDPOINT *endpoint, unsigned int timeout_ms, MCC_RECEIVE_LIST **list);
+static int mcc_get_buffer_internal(void **buffer, MCC_MEM_SIZE *buf_size, unsigned int timeout_ms);
+static int mcc_free_buffer_internal(void *buffer);
+/*!
+ * \brief This function initializes the Multi Core Communication subsystem for a given node.
+ *
+ * This function should only be called once per node (once in MQX, once per a process in Linux).
+ * It tries to initialize the bookkeeping structure when the init_string member of this structure
+ * is not equal to MCC_INIT_STRING, i.e. when no other core had performed the initialization yet.
+ * Note, that this way of bookkeeping data re-initialization protection is not powerful enough and
+ * the user application should not rely on this method. Instead, the application should be designed 
+ * to unambiguously assign the core that will perform the MCC initialization. 
+ * Clear the shared memory before the first core is attempting to initialize the MCC 
+ * (in some cases MCC_INIT_STRING remains in the shared memory after the application reset and could
+ * cause that the bookkeeping data structure is not initialized correctly). 
+ *
+ * \param[in] node Node number that will be used in endpoints created by this process.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_INT (interrupt registration error)
+ * \return MCC_ERR_VERSION (incorrect MCC version used - compatibility issue)
+ * \return MCC_ERR_OSSYNC (OS synchronization module(s) initialization failed)
+ *
+ * \see mcc_destroy
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+int mcc_initialize(MCC_NODE node)
+{
+    int i,j = 0;
+    int return_value = MCC_SUCCESS;
+    MCC_SIGNAL tmp_signals_received = {(MCC_SIGNAL_TYPE)0, (MCC_CORE)0, (MCC_NODE)0, (MCC_PORT)0};
+
+    /* Initialize synchronization module for shared data protection */
+    return_value = mcc_init_semaphore(MCC_SHMEM_SEMAPHORE_NUMBER);
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Initialize all necessary OS synchronization module(s) 
+       (for unblocking tasks waiting for new received data and for unblocking tasks waiting for a free buffer) */
+    return_value = mcc_init_os_sync();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Register CPU-to-CPU interrupt for inter-core signaling */
+    //mcc_register_cpu_to_cpu_isr(MCC_CORE0_CPU_TO_CPU_VECTOR);
+    return_value = mcc_register_cpu_to_cpu_isr();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Initialize the bookeeping structure */
+    bookeeping_data = (MCC_BOOKEEPING_STRUCT *)MCC_BASE_ADDRESS;
+    MCC_DCACHE_INVALIDATE_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT));
+    if(strcmp(bookeeping_data->init_string, init_string) != 0) {
+        /* MCC not initialized yet, do it now */
+        /* Zero it all - no guarantee Linux or uboot didnt touch it before it was reserved */
+        _mem_zero((void*) bookeeping_data, (_mem_size) sizeof(struct mcc_bookeeping_struct));
+
+        /* Set init_string in case it has not been set yet by another core */
+        mcc_memcpy((void*)init_string, bookeeping_data->init_string, (unsigned int)sizeof(bookeeping_data->init_string));
+
+        /* Set version_string */
+        mcc_memcpy((void*)version_string, bookeeping_data->version_string, (unsigned int)sizeof(bookeeping_data->version_string));
+
+        /* Initialize the free list */
+        bookeeping_data->free_list.head = &bookeeping_data->r_buffers[0];
+        bookeeping_data->free_list.tail = &bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1];
+
+        /* Initialize receive buffers */
+        for(i=0; i<MCC_ATTR_NUM_RECEIVE_BUFFERS-1; i++) {
+            bookeeping_data->r_buffers[i].next = &bookeeping_data->r_buffers[i+1];
+        }
+        bookeeping_data->r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS-1].next = null;
+
+        /* Initialize signal queues */
+        for(i=0; i<MCC_NUM_CORES; i++) {
+            for(j=0; j<MCC_MAX_OUTSTANDING_SIGNALS; j++) {
+                bookeeping_data->signals_received[i][j] = tmp_signals_received;
+            }
+            bookeeping_data->signal_queue_head[i] = 0;
+            bookeeping_data->signal_queue_tail[i] = 0;
+        }
+
+        /* Mark all endpoint ports as free */
+        for(i=0; i<MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) {
+            bookeeping_data->endpoint_table[i].endpoint.port = MCC_RESERVED_PORT_NUMBER;
+        }
+    }
+    else {
+        /* MCC already initialized - check the major number of the version string to ensure compatibility */
+        if(strncmp(bookeeping_data->version_string, version_string, 4) != 0) {
+            return_value = MCC_ERR_VERSION;
+        }
+    }
+    
+    MCC_DCACHE_FLUSH_MLINES(bookeeping_data, sizeof(MCC_BOOKEEPING_STRUCT));
+    return return_value;
+}
+
+/*!
+ * \brief This function de-initializes the Multi Core Communication subsystem for a given node.
+ *
+ * The function frees all resources of the node. Deletes all endpoints and frees any buffers that may have been queued there.
+ *
+ * \param[in] node Node number to be deinitialized.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_OSSYNC (OS synchronization module(s) deinitialization failed)
+ *
+ * \see mcc_initialize
+ */
+int mcc_destroy(MCC_NODE node)
+{
+    int i = 0, return_value;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* All endpoints of the particular node have to be removed from the endpoint table */
+    MCC_DCACHE_INVALIDATE_MLINES(&bookeeping_data->endpoint_table[0], MCC_ATTR_MAX_RECEIVE_ENDPOINTS * sizeof(MCC_ENDPOINT_MAP_ITEM));
+    for(i = 0; i < MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) {
+        if (bookeeping_data->endpoint_table[i].endpoint.node == node) {
+            /* Remove the endpoint from the table */
+            mcc_remove_endpoint(bookeeping_data->endpoint_table[i].endpoint);
+        }
+    }
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Deinitialize synchronization module */
+    mcc_deinit_semaphore(MCC_SHMEM_SEMAPHORE_NUMBER);
+
+    /* De-initialize OS synchronization module(s) 
+       (for unblocking tasks waiting for new data and for unblocking tasks waiting for a free buffer */
+    return_value = mcc_deinit_os_sync();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+
+/*!
+ * \brief This function creates an endpoint.
+ *
+ * The function creates an endpoint on the local node with the specified port number.
+ * The core and node provided in the endpoint must match the caller's core and
+ * node, and the port argument must match the endpoint port.
+ *
+ * \param[out] endpoint Pointer to the endpoint triplet to be created.
+ * \param[in] port Port number.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_NOMEM (maximum number of endpoints exceeded)
+ * \return MCC_ERR_ENDPOINT (invalid value for port or endpoint already registered)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see mcc_destroy_endpoint
+ * \see MCC_ENDPOINT
+ */
+int mcc_create_endpoint(MCC_ENDPOINT *endpoint, MCC_PORT port)
+{
+    int return_value = MCC_SUCCESS;
+
+    /* Fill the endpoint structure */
+    endpoint->core = (MCC_CORE)MCC_CORE_NUMBER;
+    endpoint->node = (MCC_NODE)MCC_MQX_NODE_NUMBER;
+    endpoint->port = (MCC_PORT)port;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Add new endpoint data into the book-keeping structure */
+    return_value = mcc_register_endpoint(*endpoint);
+    if(return_value != MCC_SUCCESS) {
+        mcc_release_semaphore();
+        return return_value;
+    }
+
+    /* Semaphore-protected section end */
+    return_value =  mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+
+/*!
+ * \brief This function destroys an endpoint.
+ *
+ * The function destroys an endpoint on the local node and frees any buffers that may be queued.
+ *
+ * \param[in] endpoint Pointer to the endpoint triplet to be deleted.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint doesn't exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see mcc_create_endpoint
+ * \see MCC_ENDPOINT
+ */
+int mcc_destroy_endpoint(MCC_ENDPOINT *endpoint)
+{
+    int return_value = MCC_SUCCESS;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Remove the endpoint data from the book-keeping structure */
+    return_value = mcc_remove_endpoint(*endpoint);
+    if(return_value != MCC_SUCCESS) {
+        mcc_release_semaphore();
+        return return_value;
+    }
+
+    /* Clear OS synchronization module parts associated with the endpoint to be destroyed */
+    mcc_clear_os_sync_for_ep(endpoint);
+    
+    /* Semaphore-protected section end */
+    return_value =  mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+
+/*!
+ * \brief This function sends a message to an endpoint.
+ *
+ * The message is copied into the MCC buffer and the destination core is signaled.
+ *
+ * \param[in] src_endpoint Pointer to the local endpoint identifying the source endpoint.
+ * \param[in] dest_endpoint Pointer to the destination endpoint to send the message to.
+ * \param[in] msg Pointer to the message to be sent.
+ * \param[in] msg_size Size of the message to be sent in bytes.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_INVAL (the msg_size exceeds the size of a data buffer)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a buffer became available)
+ * \return MCC_ERR_NOMEM (no free buffer available and timeout_ms set to 0)
+ * \return MCC_ERR_SQ_FULL (signal queue is full)
+ *
+ * \see mcc_recv
+ * \see mcc_recv_nocopy
+ * \see MCC_ENDPOINT
+ */
+int mcc_send(MCC_ENDPOINT *src_endpoint, MCC_ENDPOINT *dest_endpoint, void *msg, MCC_MEM_SIZE msg_size, unsigned int timeout_ms)
+{
+    int return_value;
+    MCC_RECEIVE_LIST *list;
+    MCC_RECEIVE_BUFFER * buf;
+    MCC_SIGNAL affiliated_signal;
+    MCC_MEM_SIZE buffer_size;
+
+    /* Reuse the mcc_get_buffer_internal() function to get the MCC buffer pointer. */
+    return_value = mcc_get_buffer_internal((void**)&buf, &buffer_size, timeout_ms);
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* As the mcc_get_buffer_internal() returns the pointer to the data field, it
+       is necessary to adjust the pointer to point at the MCC buffer structure beginning. */
+    buf = (MCC_RECEIVE_BUFFER *)((unsigned int)buf - (unsigned int)(&(((MCC_RECEIVE_BUFFER*)0)->data)));
+    
+    /* Check if the size of the message to be sent does not exceed the size of the mcc buffer */
+    if(msg_size > buffer_size) {
+        while(MCC_SUCCESS != mcc_free_buffer_internal(buf)) {};
+        return MCC_ERR_INVAL;
+    }
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Copy the message into the MCC receive buffer */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)buf, sizeof(MCC_RECEIVE_BUFFER));
+    mcc_memcpy(msg, (void*)buf->data, (unsigned int)msg_size);
+    mcc_memcpy((void*)src_endpoint, (void*)&buf->source, sizeof(MCC_ENDPOINT));
+    buf->data_len = msg_size;
+    MCC_DCACHE_FLUSH_MLINES((void*)buf, sizeof(MCC_RECEIVE_BUFFER));
+
+    /* Get list of buffers kept by the particular endpoint */
+    list = mcc_get_endpoint_list(*dest_endpoint);
+
+    if(list == null) {
+        /* The endpoint does not exists (has not been registered so far),
+         free the buffer and return immediately - error */
+        /* Enqueue the buffer back into the free list */
+        MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->free_list, sizeof(MCC_RECEIVE_LIST*));
+        mcc_queue_buffer(&bookeeping_data->free_list, buf);
+      
+        mcc_release_semaphore();
+        return MCC_ERR_ENDPOINT;
+    }
+
+    /* Write the signal type into the signal queue of the particular core */
+    affiliated_signal.type = BUFFER_QUEUED;
+    affiliated_signal.destination = *dest_endpoint;
+    return_value = mcc_queue_signal(dest_endpoint->core, affiliated_signal);
+    if(return_value != MCC_SUCCESS) {
+        /* Signal queue is full, free the buffer and return immediately - error */
+        MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->free_list, sizeof(MCC_RECEIVE_LIST*));
+        mcc_queue_buffer(&bookeeping_data->free_list, buf);
+
+        mcc_release_semaphore();
+        return return_value;
+    }
+
+    /* Enqueue the buffer into the endpoint buffer list */
+    mcc_queue_buffer(list, buf);
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Signal the other core by generating the CPU-to-CPU interrupt */
+    return_value = mcc_generate_cpu_to_cpu_interrupt();
+
+    return return_value;
+}
+
+/*!
+ * \private
+ *  
+ * \brief This function dequeues a buffer from the free list.
+ *
+ * This is an internal implementation of the mcc_get_buffer() function. It is called
+ * either from the mcc_send() or from mcc_get_buffer() when the non-copy-send
+ * mechanism is enabled by the MCC_SEND_RECV_NOCOPY_API_ENABLED macro in mcc_config.h. 
+ *
+ * \param[out] buffer Pointer to the MCC buffer dequeued from the free list.
+ * \param[out] buf_size Pointer to an MCC_MEM_SIZE that is used for passing the size of the dequeued MCC buffer to the application.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a buffer became available)
+ * \return MCC_ERR_NOMEM (no free buffer available and timeout_ms set to 0)
+ *
+ * \see mcc_send_nocopy
+ * \see mcc_send
+ * \see mcc_get_buffer 
+ */
+static int mcc_get_buffer_internal(void **buffer, MCC_MEM_SIZE *buf_size, unsigned int timeout_ms)
+{
+    int return_value;
+    MCC_RECEIVE_BUFFER * buf = null;
+
+    *buffer = null;
+    
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Dequeue the buffer from the free list */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->free_list, sizeof(MCC_RECEIVE_LIST*));
+    buf = mcc_dequeue_buffer(&bookeeping_data->free_list);
+
+    /* Semaphore-protected section end */
+    mcc_release_semaphore();
+
+    if(buf == null) {
+        /* Non-blocking call */
+        if(timeout_ms == 0) {
+            return MCC_ERR_NOMEM;
+        } else {
+            /* Wait for the buffer freed event */
+            return_value = mcc_wait_for_buffer_freed((MCC_RECEIVE_BUFFER **)&buf, timeout_ms);
+            if(MCC_SUCCESS != return_value) {
+                return return_value;
+            }
+        }
+    }
+
+    /* Return the MCC buffer size and the pointer to the dequeued MCC buffer */
+    *buf_size = (MCC_MEM_SIZE)sizeof(bookeeping_data->r_buffers[0].data);
+    *buffer = (void*)buf->data;
+    return MCC_SUCCESS;
+}
+
+#if MCC_SEND_RECV_NOCOPY_API_ENABLED
+/*!
+ * \brief This function dequeues a buffer from the free list.
+ *
+ * The application has take the responsibility for MCC buffer de-allocation and 
+ * filling the data to be sent into the pre-allocated MCC buffer.
+ *
+ * \param[out] buffer Pointer to the MCC buffer dequeued from the free list.
+ * \param[out] buf_size Pointer to an MCC_MEM_SIZE that is used for passing the size of the dequeued MCC buffer to the application.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a buffer became available)
+ * \return MCC_ERR_NOMEM (no free buffer available and timeout_ms set to 0)
+ *
+ * \see mcc_send_nocopy
+ */
+int mcc_get_buffer(void **buffer, MCC_MEM_SIZE *buf_size, unsigned int timeout_ms)
+{
+    return mcc_get_buffer_internal(buffer, buf_size, timeout_ms);
+}
+
+/*!
+ * \brief This function sends a message to an endpoint. The data is NOT copied 
+ * from the user-app. buffer but the pointer to already filled message buffer is
+ * provided.  
+ *
+ * The application has to take the responsibility for:
+ *  1. MCC buffer de-allocation
+ *  2. filling the data to be sent into the pre-allocated MCC buffer
+ *  3. not exceeding the buffer size when filling the data (MCC_ATTR_BUFFER_SIZE_IN_BYTES) 
+ * 
+ * Once the data cache is used on the target platform it is good to have MCC buffers 
+ * in shared RAM aligned to the cache line size in order not to corrupt entities placed 
+ * just before and just after the MCC buffer when flushing the MCC buffer content into
+ * the shared RAM. It is also the application responsibility to flush the data in
+ * that case. If the alignment condition is not fulfilled the application
+ * has to take care about the data cache coherency. 
+ * The following scenarios can happen:
+ * A. Data cache is OFF:
+ *    - No cache operation needs to be done, the application just 
+ *     1. calls the mcc_get_buffer() function, 
+ *     2. fills data into the provided MCC buffer,
+ *     3. and finally issues the mcc_send_nocopy() function.
+ * B. Data cache is ON, shared RAM MCC buffers ALIGNED to the cache line size:
+ *    - The application has to perform following steps: 
+ *     1. call the mcc_get_buffer() to get the pointer to a free message buffer 
+ *     2. copy data to be sent into the message buffer
+ *     3. flush all cache lines occupied by the message buffer new data
+ *       (maximum of MCC_ATTR_BUFFER_SIZE_IN_BYTES bytes).
+ *     4. call the mcc_send_nocopy() with the correct buffer pointer and the message size passed 
+ * C. Data cache is ON, shared RAM MCC buffers NOT ALIGNED:
+ *    - The application has to perform following steps: 
+ *     1. call the mcc_get_buffer() to get the pointer to a free message buffer 
+ *     2. grab the hw semaphore by calling the mcc_get_semaphore() low level MCC function.
+ *     3. invalidate all cache lines occupied by data to be filled into the free message buffer.
+ *       (maximum of MCC_ATTR_BUFFER_SIZE_IN_BYTES bytes).
+ *     4. copy data to be sent into the message buffer.
+ *     5. flush all cache lines occupied by the message buffer new data 
+ *       (maximum of MCC_ATTR_BUFFER_SIZE_IN_BYTES bytes).
+ *     6. release the hw semaphore by calling the mcc_release_semaphore() low level MCC function.
+ *     7. call the mcc_send_nocopy() with the correct buffer pointer and the message size passed.
+ * 
+ * After the mcc_send_nocopy() function is issued the message buffer is no more owned 
+ * by the sending task and must not be touched anymore unless the mcc_send_nocopy() 
+ * function fails and returns an error. In that case the application should try 
+ * to re-issue the mcc_send_nocopy() again and if it is still not possible to send 
+ * the message and the application wants to give it up from whatever reasons 
+ * (for instance the MCC_ERR_ENDPOINT error is returned meaning the endpoint 
+ * has not been created yet) the mcc_free_buffer() function could be called, 
+ * passing the pointer to the buffer to be freed as a parameter.     
+ *
+ * \param[in] src_endpoint Pointer to the local endpoint identifying the source endpoint.
+ * \param[in] dest_endpoint Pointer to the destination endpoint to send the message to.
+ * \param[in] buffer_p Pointer to the MCC buffer of the shared memory where the 
+ *            data to be sent is stored.
+ * \param[in] msg_size Size of the message to be sent in bytes.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_INVAL (the msg_size exceeds the size of a data buffer)
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_SQ_FULL (signal queue is full)
+ *
+ * \see mcc_send
+ * \see mcc_get_buffer
+ * \see MCC_ENDPOINT
+ */
+int mcc_send_nocopy(MCC_ENDPOINT *src_endpoint, MCC_ENDPOINT *dest_endpoint, void *buffer_p, MCC_MEM_SIZE msg_size)
+{
+    int return_value;
+    MCC_RECEIVE_BUFFER * buf;
+    MCC_RECEIVE_LIST *list;
+    MCC_SIGNAL affiliated_signal;
+
+    /* Check if the size of the message to be sent does not exceed the size of the mcc buffer */
+    if(msg_size > sizeof(bookeeping_data->r_buffers[0].data)) {
+        return MCC_ERR_INVAL;
+    }
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Get list of buffers kept by the particular endpoint */
+    list = mcc_get_endpoint_list(*dest_endpoint);
+
+    if(list == null) {
+        /* The endpoint does not exists (has not been registered so far) */
+        mcc_release_semaphore();
+        return MCC_ERR_ENDPOINT;
+    }
+
+    /* Store the message size and the source endpoint in the MCC_RECEIVE_BUFFER structure */
+    buf = (MCC_RECEIVE_BUFFER *)((unsigned int)buffer_p - (unsigned int)(&(((MCC_RECEIVE_BUFFER*)0)->data)));
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&buf->source, sizeof(MCC_ENDPOINT) + sizeof(MCC_MEM_SIZE));
+    ((MCC_RECEIVE_BUFFER*)buf)->data_len = msg_size;
+    mcc_memcpy((void*)src_endpoint, (void*)&buf->source, sizeof(MCC_ENDPOINT));
+    MCC_DCACHE_FLUSH_MLINES((void*)(void*)&buf->source, sizeof(MCC_ENDPOINT) + sizeof(MCC_MEM_SIZE));
+
+
+    /* Write the signal type into the signal queue of the particular core */
+    affiliated_signal.type = BUFFER_QUEUED;
+    affiliated_signal.destination = *dest_endpoint;
+    return_value = mcc_queue_signal(dest_endpoint->core, affiliated_signal);
+    if(return_value != MCC_SUCCESS) {
+        /* Signal queue is full - error */
+        mcc_release_semaphore();
+        return return_value;
+    }
+
+    /* Enqueue the buffer into the endpoint buffer list */
+    mcc_queue_buffer(list, (MCC_RECEIVE_BUFFER*)buf);
+
+    /* Semaphore-protected section end */
+    mcc_release_semaphore();
+
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Signal the other core by generating the CPU-to-CPU interrupt */
+    return_value = mcc_generate_cpu_to_cpu_interrupt();
+
+    return return_value;
+}
+#endif /* MCC_SEND_RECV_NOCOPY_API_ENABLED */
+
+/*!
+ * \brief This function receives a message from the specified endpoint if one is available.
+ *        The data is copied from the receive buffer into the user supplied buffer.
+ *
+ * This is the "receive with copy" version of the MCC receive function. This version is simple
+ * to use but it requires copying data from shared memory into the user space buffer.
+ * The user has no obligation or burden to manage the shared memory buffers.
+ *
+ * \param[out] src_endpoint Pointer to the MCC_ENDPOINT structure to be filled by the endpoint identifying the message sender.
+ * \param[in] dest_endpoint Pointer to the local receiving endpoint to receive from.
+ * \param[in] buffer Pointer to the user-app. buffer where data will be copied into.
+ * \param[in] buffer_size The maximum number of bytes to copy.
+ * \param[out] recv_size Pointer to an MCC_MEM_SIZE that will contain the number of bytes actually copied into the buffer.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a new message came)
+ *
+ * \see mcc_send
+ * \see mcc_recv_nocopy
+ * \see MCC_ENDPOINT
+ */
+int mcc_recv(MCC_ENDPOINT *src_endpoint, MCC_ENDPOINT *dest_endpoint, void *buffer, MCC_MEM_SIZE buffer_size, MCC_MEM_SIZE *recv_size, unsigned int timeout_ms)
+{
+    MCC_RECEIVE_LIST *list = null;
+    MCC_RECEIVE_BUFFER * buf;
+    MCC_SIGNAL affiliated_signal;
+    MCC_ENDPOINT tmp_destination = {(MCC_CORE)0, (MCC_NODE)0, (MCC_PORT)0};
+    int return_value, i = 0;
+
+    return_value = mcc_recv_common_part(dest_endpoint, timeout_ms, (MCC_RECEIVE_LIST**)&list);
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+    
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    MCC_DCACHE_INVALIDATE_MLINES((void*)list, sizeof(MCC_RECEIVE_LIST*));
+
+    if(list->head == (MCC_RECEIVE_BUFFER*)0) {
+        /* Buffer not dequeued before the timeout */
+        mcc_release_semaphore();
+        return MCC_ERR_TIMEOUT;
+    }
+
+    /* Copy the message from the MCC receive buffer into the user-app. buffer */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&list->head->source, sizeof(MCC_ENDPOINT) + sizeof(MCC_MEM_SIZE));
+    mcc_memcpy((void*)&list->head->source, (void*)src_endpoint, sizeof(MCC_ENDPOINT));
+    if (list->head->data_len > buffer_size) {
+        list->head->data_len = buffer_size;
+    }
+    *recv_size = (MCC_MEM_SIZE)(list->head->data_len);
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&list->head->data, list->head->data_len);
+    mcc_memcpy((void*)list->head->data, buffer, list->head->data_len);
+
+    /* Dequeue the buffer from the endpoint list */
+    buf = mcc_dequeue_buffer(list);
+
+    /* Enqueue the buffer into the free list */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->free_list, sizeof(MCC_RECEIVE_LIST*));
+    mcc_queue_buffer(&bookeeping_data->free_list, buf);
+
+    /* Notify all cores (except of itself) via CPU-to-CPU interrupt that a buffer has been freed */
+    affiliated_signal.type = BUFFER_FREED;
+    affiliated_signal.destination = tmp_destination;
+    for (i=0; i<MCC_NUM_CORES; i++) {
+        if(i != MCC_CORE_NUMBER) {
+            mcc_queue_signal(i, affiliated_signal);
+        }
+    }
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+
+    mcc_generate_cpu_to_cpu_interrupt();
+
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+
+#if MCC_SEND_RECV_NOCOPY_API_ENABLED
+/*!
+ * \brief This function receives a message from the specified endpoint if one is available. The data is NOT copied into the user-app. buffer.
+ *
+ * This is the "zero-copy receive" version of the MCC receive function. No data is copied. 
+ * Only the pointer to the data is returned. This version is fast, but it requires the user to manage
+ * buffer allocation. Specifically, the user must decide when a buffer is no longer in use and
+ * make the appropriate API call to free it, see mcc_free_buffer.
+ *
+ * \param[out] src_endpoint Pointer to the MCC_ENDPOINT structure to be filled by the endpoint identifying the message sender.
+ * \param[in] dest_endpoint Pointer to the local receiving endpoint to receive from.
+ * \param[out] buffer_p Pointer to the MCC buffer of the shared memory where the received data is stored.
+ * \param[out] recv_size Pointer to an MCC_MEM_SIZE that will contain the number of valid bytes in the buffer.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a new message came)
+ *
+ * \see mcc_send
+ * \see mcc_recv
+ * \see MCC_ENDPOINT
+ */
+int mcc_recv_nocopy(MCC_ENDPOINT *src_endpoint, MCC_ENDPOINT *dest_endpoint, void **buffer_p, MCC_MEM_SIZE *recv_size, unsigned int timeout_ms)
+{
+    MCC_RECEIVE_LIST *list = null;
+    int return_value;
+
+    return_value = mcc_recv_common_part(dest_endpoint, timeout_ms, (MCC_RECEIVE_LIST**)&list);
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+    
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    MCC_DCACHE_INVALIDATE_MLINES((void*)list, sizeof(MCC_RECEIVE_LIST*));
+
+    if(list->head == (MCC_RECEIVE_BUFFER*)0) {
+        /* Buffer not dequeued before the timeout */
+        mcc_release_semaphore();
+        return MCC_ERR_TIMEOUT;
+    }
+
+    /* Get the message pointer from the head of the receive buffer list */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&list->head->data, list->head->data_len);
+    *buffer_p = (void*)&list->head->data;
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&list->head->source, sizeof(MCC_ENDPOINT) + sizeof(MCC_MEM_SIZE));
+    mcc_memcpy((void*)&list->head->source, (void*)src_endpoint, sizeof(MCC_ENDPOINT));
+    *recv_size = (MCC_MEM_SIZE)(list->head->data_len);
+
+    /* Dequeue the buffer from the endpoint list */
+    mcc_dequeue_buffer(list);
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+#endif /* MCC_SEND_RECV_NOCOPY_API_ENABLED */
+
+/*!
+ * \private
+ *
+ * \brief This function is common part for mcc_recv() and mcc_recv_nocopy() function.
+ *
+ * It tries to get the list of buffers kept by the particular endpoint. If the list is empty
+ * it waits for a new message until the timeout expires. 
+ *
+ * \param[in] endpoint Pointer to the receiving endpoint to receive from.
+ * \param[in] timeout_ms Timeout, in milliseconds, to wait for a free buffer. A value of 0 means don't wait (non-blocking call). A value of 0xffffffff means wait forever (blocking call).
+ * \param[out] list Pointer to the list of buffers kept by the particular endpoint.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ * \return MCC_ERR_TIMEOUT (timeout exceeded before a new message came)
+ *
+ * \see mcc_recv
+ * \see mcc_recv_nocopy
+ * \see MCC_ENDPOINT
+ */
+static int mcc_recv_common_part(MCC_ENDPOINT *endpoint, unsigned int timeout_ms, MCC_RECEIVE_LIST **list)
+{
+    MCC_RECEIVE_LIST *tmp_list;
+    int return_value;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Get list of buffers kept by the particular endpoint */
+    tmp_list = mcc_get_endpoint_list(*endpoint);
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* The endpoint is not valid */
+    if(tmp_list == null) {
+        return MCC_ERR_ENDPOINT;
+    }
+
+    if(tmp_list->head == (MCC_RECEIVE_BUFFER*)0) {
+        /* Non-blocking call */
+        if(timeout_ms == 0) {
+            return MCC_ERR_TIMEOUT;
+        }
+        /* Blocking call */
+        else {
+            /* Wait for the buffer queued event */
+            mcc_wait_for_buffer_queued(endpoint, timeout_ms);
+            if(MCC_SUCCESS != return_value) {
+                return return_value;
+            }
+        }
+    }
+    
+    /* Clear event bit specified for the particular endpoint */
+    mcc_clear_os_sync_for_ep(endpoint);
+
+    *list = (MCC_RECEIVE_LIST*)tmp_list;
+    return MCC_SUCCESS;
+}
+
+/*!
+ * \brief This function returns the number of buffers currently queued at the endpoint.
+ *
+ * The function checks if messages are available on a receive endpoint. While the call only checks the
+ * availability of messages, it does not dequeue them.
+ *
+ * \param[in] endpoint Pointer to the endpoint structure.
+ * \param[out] num_msgs Pointer to an unsigned int that will contain the number of buffers queued.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (the endpoint does not exist)
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see mcc_recv
+ * \see mcc_recv_nocopy
+ * \see MCC_ENDPOINT
+ */
+int mcc_msgs_available(MCC_ENDPOINT *endpoint, unsigned int *num_msgs)
+{
+    unsigned int count = 0;
+    MCC_RECEIVE_LIST *list;
+    MCC_RECEIVE_BUFFER * buf;
+    int return_value;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Get list of buffers kept by the particular endpoint */
+    list = mcc_get_endpoint_list(*endpoint);
+    if(list == null) {
+        /* The endpoint does not exists (has not been registered so far), return immediately - error */
+        mcc_release_semaphore();
+        return MCC_ERR_ENDPOINT;
+    }
+
+    buf = list->head;
+    while(buf != (MCC_RECEIVE_BUFFER*)0) {
+        count++;
+        MCC_DCACHE_INVALIDATE_MLINES((void*)&buf->next, sizeof(MCC_RECEIVE_BUFFER*));
+        buf = (MCC_RECEIVE_BUFFER*)buf->next;
+    }
+    *num_msgs = count;
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+
+/*!
+ * \private
+ *  
+ * \brief This function frees a buffer previously returned by mcc_recv_nocopy().
+ *
+ * Once the zero-copy mechanism of receiving data is used, this function
+ * has to be called to free a buffer and to make it available for the next data
+ * transfer.
+ *
+ * \param[in] buffer Pointer to the buffer to be freed.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see mcc_recv_nocopy
+ */
+static int mcc_free_buffer_internal(void *buffer)
+{
+    MCC_SIGNAL affiliated_signal;
+    MCC_ENDPOINT tmp_destination = {(MCC_CORE)0, (MCC_NODE)0, (MCC_PORT)0};
+    int return_value, i = 0;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    /* Enqueue the buffer into the free list */
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->free_list, sizeof(MCC_RECEIVE_LIST*));
+    mcc_queue_buffer(&bookeeping_data->free_list, (MCC_RECEIVE_BUFFER *)((unsigned int)buffer - (unsigned int)(&(((MCC_RECEIVE_BUFFER*)0)->data))));
+
+    /* Notify all cores (except of itself) via CPU-to-CPU interrupt that a buffer has been freed */
+    affiliated_signal.type = BUFFER_FREED;
+    affiliated_signal.destination = tmp_destination;
+    for (i=0; i<MCC_NUM_CORES; i++) {
+        if(i != MCC_CORE_NUMBER) {
+            mcc_queue_signal(i, affiliated_signal);
+        }
+    }
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+
+    mcc_generate_cpu_to_cpu_interrupt();
+
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
+#if MCC_SEND_RECV_NOCOPY_API_ENABLED
+/*!
+ * \brief This function frees a buffer previously returned by mcc_recv_nocopy().
+ *
+ * Once the zero-copy mechanism of receiving data is used, this function
+ * has to be called to free a buffer and to make it available for the next data
+ * transfer.
+ *
+ * \param[in] buffer Pointer to the buffer to be freed.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see mcc_recv_nocopy
+ */
+int mcc_free_buffer(void *buffer)
+{
+    return mcc_free_buffer_internal(buffer);
+}
+#endif /* MCC_SEND_RECV_NOCOPY_API_ENABLED */
+
+/*!
+ * \brief This function returns information about the MCC sub system.
+ *
+ * The function returns implementation-specific information.
+ *
+ * \param[in] node Node number.
+ * \param[out] info_data Pointer to the MCC_INFO_STRUCT structure to hold returned data.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SEMAPHORE (semaphore handling error)
+ *
+ * \see MCC_INFO_STRUCT
+ */
+int mcc_get_info(MCC_NODE node, MCC_INFO_STRUCT* info_data)
+{
+    int return_value;
+
+    /* Semaphore-protected section start */
+    return_value = mcc_get_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    mcc_memcpy(bookeeping_data->version_string, (void*)info_data->version_string, (unsigned int)sizeof(bookeeping_data->version_string));
+
+    /* Semaphore-protected section end */
+    return_value = mcc_release_semaphore();
+    if(return_value != MCC_SUCCESS)
+        return return_value;
+
+    return return_value;
+}
diff --git a/arch/arm/mach-imx/mcc_common.c b/arch/arm/mach-imx/mcc_common.c
new file mode 100755 (executable)
index 0000000..d766976
--- /dev/null
@@ -0,0 +1,259 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Freescale IMX Linux-specific MCC implementation.
+ * MCC library common functions
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "mcc_config.h"
+#include "mcc_common.h"
+
+#if (MCC_OS_USED == MCC_LINUX)
+#include "linux/mcc_linux.h"
+#include "linux/mcc_shm_linux.h"
+#include <mach/hardware.h>
+#include <linux/kernel.h>
+#elif (MCC_OS_USED == MCC_MQX)
+#include "mcc_mqx.h"
+#endif
+
+
+/*!
+ * \brief This function registers an endpoint.
+ *
+ * Register an endpoint with specified structure / params (core, node and port).
+ *
+ * \param[in] endpoint Pointer to the endpoint structure.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_NOMEM (maximum number of endpoints exceeded)
+ * \return MCC_ERR_ENDPOINT (invalid value for port or endpoint already registered)
+ */
+int mcc_register_endpoint(MCC_ENDPOINT endpoint)
+{
+    int i;
+
+    /* must be valid */
+    if(endpoint.port == MCC_RESERVED_PORT_NUMBER)
+        return MCC_ERR_ENDPOINT;
+
+    /* check not already registered */
+    if(mcc_get_endpoint_list(endpoint))
+        return MCC_ERR_ENDPOINT;
+
+    MCC_DCACHE_INVALIDATE_MLINES(&bookeeping_data->endpoint_table[0], MCC_ATTR_MAX_RECEIVE_ENDPOINTS * sizeof(MCC_ENDPOINT_MAP_ITEM));
+    for(i = 0; i < MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) {
+        if(bookeeping_data->endpoint_table[i].endpoint.port == MCC_RESERVED_PORT_NUMBER) {
+            bookeeping_data->endpoint_table[i].endpoint.core = endpoint.core;
+            bookeeping_data->endpoint_table[i].endpoint.node = endpoint.node;
+            bookeeping_data->endpoint_table[i].endpoint.port = endpoint.port;
+            MCC_DCACHE_FLUSH_MLINES(&bookeeping_data->endpoint_table[i], sizeof(MCC_ENDPOINT_MAP_ITEM));
+            return MCC_SUCCESS;
+        }
+    }
+    return MCC_ERR_NOMEM;
+}
+
+/*!
+ * \brief This function removes an endpoint.
+ *
+ * Removes an endpoint with specified structure / params (core, node and port).
+ *
+ * \param[in] endpoint Pointer to the endpoint structure.
+ *
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_ENDPOINT (invalid value for port or the endpoint doesn't exist)
+ */
+int mcc_remove_endpoint(MCC_ENDPOINT endpoint)
+{
+    int i=0;
+
+    /* must be valid */
+    if(endpoint.port == MCC_RESERVED_PORT_NUMBER)
+        return MCC_ERR_ENDPOINT;
+
+    MCC_DCACHE_INVALIDATE_MLINES(&bookeeping_data->endpoint_table[0], MCC_ATTR_MAX_RECEIVE_ENDPOINTS * sizeof(MCC_ENDPOINT_MAP_ITEM));
+    for(i = 0; i < MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) {
+
+        if(MCC_ENDPOINTS_EQUAL(bookeeping_data->endpoint_table[i].endpoint, endpoint)) {
+            /* clear the queue */
+            MCC_RECEIVE_BUFFER * buffer = mcc_dequeue_buffer((MCC_RECEIVE_LIST *)MCC_MEM_PHYS_TO_VIRT(&bookeeping_data->endpoint_table[i].list));
+            while(buffer) {
+                mcc_queue_buffer((MCC_RECEIVE_LIST *)MCC_MEM_PHYS_TO_VIRT(&bookeeping_data->free_list), buffer);
+                buffer = mcc_dequeue_buffer((MCC_RECEIVE_LIST *)MCC_MEM_PHYS_TO_VIRT(&bookeeping_data->endpoint_table[i].list));
+            }
+            /* indicate free */
+            bookeeping_data->endpoint_table[i].endpoint.port = MCC_RESERVED_PORT_NUMBER;
+            MCC_DCACHE_FLUSH_MLINES((void*)&bookeeping_data->endpoint_table[i].endpoint.port, sizeof(MCC_PORT));
+            return MCC_SUCCESS;
+        }
+    }
+    return MCC_ERR_ENDPOINT;
+}
+
+/*!
+ * \brief This function dequeues the buffer.
+ *
+ * Dequeues the buffer from the list.
+ *
+ * \param[in] list Pointer to the MCC_RECEIVE_LIST structure.
+ *  
+ * \return Pointer to MCC_RECEIVE_BUFFER
+ */
+MCC_RECEIVE_BUFFER * mcc_dequeue_buffer(MCC_RECEIVE_LIST *list)
+{
+    MCC_DCACHE_INVALIDATE_MLINES((void*)list, sizeof(MCC_RECEIVE_LIST));
+    MCC_RECEIVE_BUFFER * next_buf = list->head;
+
+    MCC_RECEIVE_BUFFER * next_buf_virt = (MCC_RECEIVE_BUFFER *)MCC_MEM_PHYS_TO_VIRT(next_buf);
+    if(next_buf) {
+        MCC_DCACHE_INVALIDATE_MLINES((void*)&next_buf_virt->next, sizeof(MCC_RECEIVE_BUFFER*));
+        list->head = next_buf_virt->next;
+        if(list->tail == next_buf)
+            list->tail = null;
+    }
+    MCC_DCACHE_FLUSH_MLINES(list, sizeof(MCC_RECEIVE_LIST));
+    return next_buf_virt;
+}
+
+/*!
+ * \brief This function queues the buffer.
+ *
+ * Queues the buffer in the list.
+ *
+ * \param[in] list Pointer to the MCC_RECEIVE_LIST structure.
+ * \param[in] r_buffer Pointer to MCC_RECEIVE_BUFFER.
+ *  
+ * \return none
+ */
+void mcc_queue_buffer(MCC_RECEIVE_LIST *list, MCC_RECEIVE_BUFFER * r_buffer)
+{
+    MCC_DCACHE_INVALIDATE_MLINES((void*)list, sizeof(MCC_RECEIVE_LIST));
+
+    MCC_RECEIVE_BUFFER * last_buf = (MCC_RECEIVE_BUFFER *)MCC_MEM_PHYS_TO_VIRT(list->tail);
+    MCC_RECEIVE_BUFFER * r_buffer_phys = (MCC_RECEIVE_BUFFER *)MCC_MEM_VIRT_TO_PHYS(r_buffer);
+    if(last_buf) {
+        last_buf->next = r_buffer_phys;
+        MCC_DCACHE_FLUSH_MLINES((void*)&last_buf->next, sizeof(MCC_RECEIVE_BUFFER*));
+    }
+    else {
+        list->head = r_buffer_phys;
+    }
+    r_buffer->next = null;
+    list->tail = r_buffer_phys;
+    MCC_DCACHE_FLUSH_MLINES(list, sizeof(MCC_RECEIVE_LIST));
+    MCC_DCACHE_FLUSH_MLINES((void*)&r_buffer->next, sizeof(MCC_RECEIVE_BUFFER*));
+}
+
+/*!
+ * \brief This function returns the endpoint list.
+ *
+ * Returns the MCC_RECEIVE_LIST respective to the endpoint structure provided.
+ *
+ * \param[in] endpoint Pointer to the MCC_ENDPOINT structure.
+ *  
+ * \return MCC_RECEIVE_LIST pointer 
+ * \return null pointer
+ */
+MCC_RECEIVE_LIST * mcc_get_endpoint_list(MCC_ENDPOINT endpoint)
+{
+    int i=0;
+
+    /* must be valid */
+    if(endpoint.port == MCC_RESERVED_PORT_NUMBER)
+        return null;
+
+    MCC_DCACHE_INVALIDATE_MLINES(&bookeeping_data->endpoint_table[0], MCC_ATTR_MAX_RECEIVE_ENDPOINTS * sizeof(MCC_ENDPOINT_MAP_ITEM));
+    for(i = 0; i<MCC_ATTR_MAX_RECEIVE_ENDPOINTS; i++) {
+
+        if(MCC_ENDPOINTS_EQUAL(bookeeping_data->endpoint_table[i].endpoint, endpoint)) {
+            return (MCC_RECEIVE_LIST *)MCC_MEM_PHYS_TO_VIRT(&bookeeping_data->endpoint_table[i].list);
+        }
+    }
+    return null;
+}
+
+/*!
+ * \brief This function queues a signal
+ *  
+ * Signal circular queue rules:
+ *     tail points to next free slot
+ *     head points to first occupied slot
+ *     head == tail indicates empty
+ *     (tail + 1) % len = fill
+ * This method costs 1 slot since you need to differentiate
+ * between full and empty (if you fill the last slot it looks
+ * like empty since h == t)
+ *
+ * \param[in] core Core number.
+ * \param[in] signal Signal to be queued.
+ *  
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SQ_FULL (signal queue is full - no more that MCC_MAX_OUTSTANDING_SIGNALS items allowed)
+ */
+int mcc_queue_signal(MCC_CORE core, MCC_SIGNAL signal)
+{
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signal_queue_head[core], sizeof(unsigned int));
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signal_queue_tail[core], sizeof(unsigned int));
+    int tail = bookeeping_data->signal_queue_tail[core];
+    int new_tail = tail == (MCC_MAX_OUTSTANDING_SIGNALS-1) ? 0 : tail+1;
+
+    if(MCC_SIGNAL_QUEUE_FULL(core))
+        return MCC_ERR_SQ_FULL;
+
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signals_received[core][tail], sizeof(MCC_SIGNAL));
+    bookeeping_data->signals_received[core][tail].type = signal.type;
+    bookeeping_data->signals_received[core][tail].destination.core = signal.destination.core;
+    bookeeping_data->signals_received[core][tail].destination.node = signal.destination.node;
+    bookeeping_data->signals_received[core][tail].destination.port = signal.destination.port;
+
+    bookeeping_data->signal_queue_tail[core] = new_tail;
+    MCC_DCACHE_FLUSH_MLINES((void*)&bookeeping_data->signal_queue_tail[core], sizeof(unsigned int));
+    MCC_DCACHE_FLUSH_MLINES((void*)&bookeeping_data->signals_received[core][tail], sizeof(MCC_SIGNAL));
+
+    return MCC_SUCCESS;
+}
+
+/*!
+ * \brief This function dequeues a signal
+ * 
+ * It dequeues a signal from the signal queue for the particular core.
+ *    
+ * \param[in] core Core number.
+ * \param[in] signal Signal to be dequeued.
+ *  
+ * \return MCC_SUCCESS
+ * \return MCC_ERR_SQ_EMPTY (signal queue is empty, nothing to dequeue)
+ */
+int mcc_dequeue_signal(MCC_CORE core, MCC_SIGNAL *signal)
+{
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signal_queue_head[core], sizeof(unsigned int));
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signal_queue_tail[core], sizeof(unsigned int));
+    int head = bookeeping_data->signal_queue_head[core];
+
+    if(MCC_SIGNAL_QUEUE_EMPTY(core))
+        return MCC_ERR_SQ_EMPTY;
+
+    MCC_DCACHE_INVALIDATE_MLINES((void*)&bookeeping_data->signals_received[core][head], sizeof(MCC_SIGNAL));
+    signal->type = bookeeping_data->signals_received[core][head].type;
+    signal->destination.core = bookeeping_data->signals_received[core][head].destination.core;
+    signal->destination.node = bookeeping_data->signals_received[core][head].destination.node;
+    signal->destination.port = bookeeping_data->signals_received[core][head].destination.port;
+
+    bookeeping_data->signal_queue_head[core] = head == (MCC_MAX_OUTSTANDING_SIGNALS-1) ? 0 : head+1;
+    MCC_DCACHE_FLUSH_MLINES((void*)&bookeeping_data->signal_queue_head[core], sizeof(unsigned int));
+
+    return MCC_SUCCESS;
+}
+
diff --git a/arch/arm/mach-imx/mcc_config.h b/arch/arm/mach-imx/mcc_config.h
new file mode 100755 (executable)
index 0000000..c07d99f
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Freescale IMX Linux-specific MCC implementation.
+ * The main MCC configuration file
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MCC_CONFIG__
+#define __MCC_CONFIG__
+
+/* used OS */
+#define MCC_OS_USED                    (MCC_MQX)
+
+/* base address of shared memory */
+#define MCC_BASE_ADDRESS               (BSP_SHARED_RAM_START)
+
+/* size (in bytes) and number of receive buffers */
+#define MCC_ATTR_NUM_RECEIVE_BUFFERS   (10)
+#define MCC_ATTR_BUFFER_SIZE_IN_BYTES  (1024)
+
+/* maximum number of receive endpoints (application specific setting),
+ * do not assign it to a value greater than 255 ! */
+#define MCC_ATTR_MAX_RECEIVE_ENDPOINTS (5)
+
+/* size of the signal queue */
+#define MCC_MAX_OUTSTANDING_SIGNALS    (10)
+
+/* number of cores */
+#define MCC_NUM_CORES                  (2)
+
+/* core number */
+#define MCC_CORE_NUMBER                (_psp_core_num())
+
+/* semaphore number */
+#define MCC_SHMEM_SEMAPHORE_NUMBER      (1)
+#define MCC_PRINTF_SEMAPHORE_NUMBER     (2)
+#define MCC_I2C_SEMAPHORE_NUMBER        (3)
+#define MCC_RESERVED1_SEMAPHORE_NUMBER  (4)
+#define MCC_RESERVED2_SEMAPHORE_NUMBER  (5)
+
+/* data non-copy mechanisms enabled  */
+#define MCC_SEND_RECV_NOCOPY_API_ENABLED (1)
+
+#endif /* __MCC_CONFIG__ */
diff --git a/include/linux/mcc_api.h b/include/linux/mcc_api.h
new file mode 100755 (executable)
index 0000000..1048a10
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Freescale IMX Linux-specific MCC implementation.
+ * MCC library API functions implementation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __MCC_API__
+#define __MCC_API__
+
+int mcc_initialize(MCC_NODE);
+int mcc_destroy(MCC_NODE);
+int mcc_create_endpoint(MCC_ENDPOINT*, MCC_PORT);
+int mcc_destroy_endpoint(MCC_ENDPOINT*);
+int mcc_send(MCC_ENDPOINT*, MCC_ENDPOINT*, void*, MCC_MEM_SIZE, unsigned int);
+int mcc_recv(MCC_ENDPOINT*, MCC_ENDPOINT*, void*, MCC_MEM_SIZE, MCC_MEM_SIZE*, unsigned int);
+int mcc_msgs_available(MCC_ENDPOINT*, unsigned int*);
+int mcc_get_info(MCC_NODE, MCC_INFO_STRUCT*);
+
+#if MCC_SEND_RECV_NOCOPY_API_ENABLED
+int mcc_get_buffer(void**, MCC_MEM_SIZE*, unsigned int);
+int mcc_send_nocopy(MCC_ENDPOINT*, MCC_ENDPOINT*, void*, MCC_MEM_SIZE);
+int mcc_recv_nocopy(MCC_ENDPOINT*, MCC_ENDPOINT*, void**, MCC_MEM_SIZE*, unsigned int);
+int mcc_free_buffer(void*);
+#endif /* MCC_SEND_RECV_NOCOPY_API_ENABLED */
+
+#endif /* __MCC_API__ */
+
diff --git a/include/linux/mcc_common.h b/include/linux/mcc_common.h
new file mode 100755 (executable)
index 0000000..47dc2fc
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright (C) 2014 Freescale Semiconductor, Inc.
+ * Freescale IMX Linux-specific MCC implementation.
+ * MCC library header file
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef __MCC_COMMON__
+#define __MCC_COMMON__
+
+#define MCC_INIT_STRING    "mccisrd"
+#define MCC_VERSION_STRING "002.000"
+#define null ((void*)0)
+
+/*!
+ * \brief MCC_BOOLEAN type.
+ *
+ * Boolean type definiton for the MCC library.
+ */
+typedef unsigned int MCC_BOOLEAN;
+
+/*!
+ * \brief MCC_MEM_SIZE type.
+ *
+ * Mem size type definiton for the MCC library.
+ */
+typedef unsigned int MCC_MEM_SIZE;
+
+/*!
+ * \brief MCC_CORE type.
+ *
+ * This unsigned integer value specifies the core number for the endpoint definition.
+ *
+ * \see MCC_NODE
+ * \see MCC_PORT
+ * \see MCC_ENDPOINT
+ */
+typedef unsigned int MCC_CORE;
+
+/*!
+ * \brief MCC_NODE type.
+ *
+ * This unsigned integer value specifies the node number for the endpoint definition.
+ *
+ * \see MCC_CORE
+ * \see MCC_PORT
+ * \see MCC_ENDPOINT
+ */
+typedef unsigned int MCC_NODE;
+
+/*!
+ * \brief MCC_PORT type.
+ *
+ * This unsigned integer value specifies the port number for the endpoint definition.
+ *
+ * \see MCC_CORE
+ * \see MCC_NODE
+ * \see MCC_ENDPOINT
+ */
+typedef unsigned int MCC_PORT;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief Endpoint structure.
+ *
+ * Endpoints are receive buffer queues, implemented in shared RAM, 
+ * and are addressed by a triplet containing core, node, and port.
+ *
+ * \see MCC_BOOKEEPING_STRUCT
+ * \see MCC_CORE
+ * \see MCC_NODE
+ * \see MCC_PORT
+ */
+struct mcc_endpoint {
+    /*! \brief Core number - identifies the core within the processor */
+    MCC_CORE core;
+
+    /*! \brief Node number - in Linux any user process participating in MCC is a unique node;
+    MQX has only one node */
+    MCC_NODE node;
+
+    /*! \brief Port number - both Linux and MQX can have an arbitrary number of ports per node */
+    MCC_PORT port;
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_endpoint MCC_ENDPOINT;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief Receive buffer structure.
+ *
+ * This is the receive buffer structure used for exchanging data.
+ *
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+struct mcc_receive_buffer {
+    /*! \brief Pointer to the next receive buffer */
+    struct mcc_receive_buffer *next;
+
+    /*! \brief Source endpoint */
+    MCC_ENDPOINT source;
+
+    /*! \brief Length of data stored in this buffer */
+    MCC_MEM_SIZE data_len;
+
+    /*! \brief Space for data storage */
+    char data [MCC_ATTR_BUFFER_SIZE_IN_BYTES];
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_receive_buffer MCC_RECEIVE_BUFFER;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief List of buffers.
+ *
+ * Each endpoint keeps the list of received buffers.
+ * The list of free buffers is kept in bookkeeping data structure. 
+ *
+ * \see MCC_RECEIVE_BUFFER
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+struct mcc_receive_list {
+    /*! \brief Head of a buffers list */
+    MCC_RECEIVE_BUFFER * head;
+
+    /*! \brief Tail of a buffers list */
+    MCC_RECEIVE_BUFFER * tail;
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_receive_list MCC_RECEIVE_LIST;
+
+#define BUFFER_QUEUED (0)
+#define BUFFER_FREED  (1)
+typedef unsigned int MCC_SIGNAL_TYPE;
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief Signals and signal queues.
+ *
+ * This is one item of a signal queue.
+ *
+ * \see MCC_SIGNAL_TYPE
+ * \see MCC_ENDPOINT
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+struct mcc_signal {
+    /*! \brief Signal type - BUFFER_QUEUED or BUFFER_FREED */
+    MCC_SIGNAL_TYPE type;
+
+    /*! \brief Destination endpoint */
+    MCC_ENDPOINT    destination;
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_signal MCC_SIGNAL;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief Endpoint registration table.
+ *
+ * This is used for matching each endpoint structure with it's list of received buffers.
+ *
+ * \see MCC_ENDPOINT
+ * \see MCC_RECEIVE_LIST
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+struct mcc_endpoint_map_item {
+    /*! \brief Endpoint tripplet */
+    MCC_ENDPOINT      endpoint;
+
+    /*! \brief List of received buffers */
+    MCC_RECEIVE_LIST  list;
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_endpoint_map_item MCC_ENDPOINT_MAP_ITEM;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief MCC info structure.
+ *
+ * This is used for additional information about the MCC implementation.
+ *
+ * \see MCC_BOOKEEPING_STRUCT
+ */
+struct mcc_info_struct {
+    /*! \brief <major>.<minor> - minor is changed whenever patched, major indicates compatibility */
+    char version_string[sizeof(MCC_VERSION_STRING)];
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_info_struct MCC_INFO_STRUCT;
+
+#if defined(__IAR_SYSTEMS_ICC__)
+__packed
+#endif
+/*!
+ * \brief Share Memory data - Bookkeeping data and buffers.
+ *
+ * This is used for "bookkeeping data" such as endpoint and signal queue head 
+ * and tail pointers and fixed size data buffers. The whole mcc_bookeeping_struct
+ * as well as each individual structure members has to be defined and stored in the
+ * memory as packed structure. This way, the same structure member offsets will be ensured
+ * on all cores/OSes/compilers. Compiler-specific pragmas for data packing have to be applied.
+ *
+ * \see MCC_RECEIVE_LIST
+ * \see MCC_SIGNAL
+ * \see MCC_ENDPOINT_MAP_ITEM
+ * \see MCC_RECEIVE_BUFFER
+ */
+struct mcc_bookeeping_struct {
+    /*! \brief String that indicates if this structure has been already initialized */
+    char init_string[sizeof(MCC_INIT_STRING)];
+
+    /*! \brief String that indicates the MCC library version */
+    char version_string[sizeof(MCC_VERSION_STRING)];
+
+    /*! \brief List of free buffers */
+    MCC_RECEIVE_LIST free_list;
+
+    /*! \brief Each core has it's own queue of received signals */
+    MCC_SIGNAL signals_received[MCC_NUM_CORES][MCC_MAX_OUTSTANDING_SIGNALS];
+
+    /*! \brief Signal queue head for each core */
+    unsigned int signal_queue_head[MCC_NUM_CORES];
+
+    /*! \brief Signal queue tail for each core */
+    unsigned int signal_queue_tail[MCC_NUM_CORES];
+
+    /*! \brief Endpoint map */
+    MCC_ENDPOINT_MAP_ITEM endpoint_table[MCC_ATTR_MAX_RECEIVE_ENDPOINTS];
+
+    /*! \brief Receive buffers, the number is defined in mcc_config.h (MCC_ATTR_NUM_RECEIVE_BUFFERS) */
+    MCC_RECEIVE_BUFFER r_buffers[MCC_ATTR_NUM_RECEIVE_BUFFERS];
+#if defined(__IAR_SYSTEMS_ICC__)
+};
+#else
+}__attribute__((packed));
+#endif
+typedef struct mcc_bookeeping_struct MCC_BOOKEEPING_STRUCT;
+
+extern MCC_BOOKEEPING_STRUCT * bookeeping_data;
+
+/*
+ * Common Macros
+ */
+#define MCC_RESERVED_PORT_NUMBER        (0)
+#define MCC_MAX_RECEIVE_ENDPOINTS_COUNT (255)
+
+/*
+ * Errors
+ */
+#define MCC_SUCCESS         (0) /* function returned successfully */
+#define MCC_ERR_TIMEOUT     (1) /* blocking function timed out before completing */
+#define MCC_ERR_INVAL       (2) /* invalid input parameter */
+#define MCC_ERR_NOMEM       (3) /* out of shared memory for message transmission */
+#define MCC_ERR_ENDPOINT    (4) /* invalid endpoint / endpoint doesn't exist */
+#define MCC_ERR_SEMAPHORE   (5) /* semaphore handling error */
+#define MCC_ERR_DEV         (6) /* Device Open Error */
+#define MCC_ERR_INT         (7) /* Interrupt Error */
+#define MCC_ERR_SQ_FULL     (8) /* Signal queue is full */
+#define MCC_ERR_SQ_EMPTY    (9) /* Signal queue is empty */
+#define MCC_ERR_VERSION     (10) /* Incorrect MCC version used - compatibility issue */
+#define MCC_ERR_OSSYNC      (11) /* OS-dependent synchronization module issue */
+
+/*
+ * OS Selection
+ */
+#define MCC_LINUX         (1) /* Linux OS used */
+#define MCC_MQX           (2) /* MQX RTOS used */
+
+MCC_RECEIVE_LIST * mcc_get_endpoint_list(MCC_ENDPOINT endpoint);
+MCC_RECEIVE_BUFFER * mcc_dequeue_buffer(MCC_RECEIVE_LIST *list);
+void mcc_queue_buffer(MCC_RECEIVE_LIST *list, MCC_RECEIVE_BUFFER * r_buffer);
+int mcc_remove_endpoint(MCC_ENDPOINT endpoint);
+int mcc_register_endpoint(MCC_ENDPOINT endpoint);
+int mcc_queue_signal(MCC_CORE core, MCC_SIGNAL signal);
+int mcc_dequeue_signal(MCC_CORE core, MCC_SIGNAL *signal);
+
+#define MCC_SIGNAL_QUEUE_FULL(core)  (((bookeeping_data->signal_queue_tail[core] + 1) % MCC_MAX_OUTSTANDING_SIGNALS) == bookeeping_data->signal_queue_head[core])
+#define MCC_SIGNAL_QUEUE_EMPTY(core) (bookeeping_data->signal_queue_head[core] == bookeeping_data->signal_queue_tail[core])
+#define MCC_ENDPOINTS_EQUAL(e1, e2)  ((e1.core == e2.core) && (e1.node == e2.node) && (e1.port == e2.port))
+
+#if (MCC_ATTR_MAX_RECEIVE_ENDPOINTS > MCC_MAX_RECEIVE_ENDPOINTS_COUNT)
+#error User-defined maximum number of endpoints can not exceed the value of MCC_MAX_RECEIVE_ENDPOINTS_COUNT
+#endif
+
+#endif /* __MCC_COMMON__ */
+