MessageQCopy: Pulled in from sysbios-rpmsg repo on omapzoom.org.
authorG Anthony <a0783926@ti.com>
Thu, 14 Feb 2013 02:23:21 +0000 (18:23 -0800)
committerG Anthony <a0783926@ti.com>
Tue, 26 Feb 2013 18:09:24 +0000 (10:09 -0800)
      The source code is located in git.omapzoom.org

      branch: master
      tag: 2.00.11.31
      commit-id: 91f6379282230ef5d1818ce8363ce1e64f23cda2

      (The commit history is there)

      patches applied on top for Qnx can be found at:
      \\dta0866189\SHARE\sl3\patches\sl3_1.05.23\sysbios-rpmsg
      0001-IPC-Protect-Message-Sending-to-Serialize-Messages.patch
      0002-WIP-Add-j5-and-j5eco-support.patch
      0003-Resources-Update-ti811x-resource-table-for-shmem-car.patch
      0004-Update-number-of-HwSpinlocks.patch

Signed-off-by: G Anthony <a0783926@ti.com>
src/ti/ipc/rpmsg/MessageQCopy.c [new file with mode: 0644]
src/ti/ipc/rpmsg/MessageQCopy.h [new file with mode: 0644]
src/ti/ipc/rpmsg/package.bld
src/ti/ipc/rpmsg/package.xdc

diff --git a/src/ti/ipc/rpmsg/MessageQCopy.c b/src/ti/ipc/rpmsg/MessageQCopy.c
new file mode 100644 (file)
index 0000000..4f11221
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** ============================================================================
+ *  @file       MessageQCopy.c
+ *
+ *  @brief      A simple copy-based MessageQ, to work with Linux virtio_rp_msg.
+ *
+ *  ============================================================================
+ */
+
+/* this define must precede inclusion of any xdc header file */
+#define Registry_CURDESC ti_ipc_rpmsg_MessageQCopy__Desc
+#define MODULE_NAME "ti.ipc.rpmsg.MessageQCopy"
+
+#include <xdc/std.h>
+#include <xdc/runtime/System.h>
+#include <xdc/runtime/Error.h>
+#include <xdc/runtime/Assert.h>
+#include <xdc/runtime/Memory.h>
+#include <xdc/runtime/Main.h>
+#include <xdc/runtime/Registry.h>
+#include <xdc/runtime/Log.h>
+#include <xdc/runtime/Diags.h>
+
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Swi.h>
+#include <ti/sysbios/knl/Semaphore.h>
+#include <ti/sysbios/heaps/HeapBuf.h>
+#include <ti/sysbios/gates/GateSwi.h>
+
+#include <ti/sdo/utils/List.h>
+#include <ti/ipc/MultiProc.h>
+
+#include "MessageQCopy.h"
+#include "VirtQueue.h"
+
+/* =============================================================================
+ * Structures & Enums
+ * =============================================================================
+ */
+
+/* Various arbitrary limits: */
+#define MAXMESSAGEQOBJECTS     256
+#define MAXMESSAGEBUFFERS      512
+#define MSGBUFFERSIZE          512   // Max payload + sizeof(ListElem)
+#define MAXHEAPSIZE            (MAXMESSAGEBUFFERS * MSGBUFFERSIZE)
+#define HEAPALIGNMENT          8
+
+/* The MessageQCopy Object */
+typedef struct MessageQCopy_Object {
+    UInt32           queueId;      /* Unique id (procId | queueIndex)       */
+    Semaphore_Handle semHandle;    /* I/O Completion                        */
+    List_Handle      queue;        /* Queue of pending messages             */
+    Bool             unblocked;    /* Use with signal to unblock _receive() */
+} MessageQCopy_Object;
+
+/* Module_State */
+typedef struct MessageQCopy_Module {
+    /* Instance gate: */
+    GateSwi_Handle gateSwi;
+    /* Array of messageQObjects in the system: */
+    struct MessageQCopy_Object  *msgqObjects[MAXMESSAGEQOBJECTS];
+    /* Heap from which to allocate free messages for copying: */
+    HeapBuf_Handle              heap;
+} MessageQCopy_Module;
+
+/* Message Header: Must match mp_msg_hdr in virtio_rp_msg.h on Linux side. */
+typedef struct MessageQCopy_MsgHeader {
+    Bits32 srcAddr;                 /* source endpoint addr               */
+    Bits32 dstAddr;                 /* destination endpoint addr          */
+    Bits32 reserved;                /* reserved                           */
+    Bits16 dataLen;                 /* data length                        */
+    Bits16 flags;                   /* bitmask of different flags         */
+    UInt8  payload[];               /* Data payload                       */
+} MessageQCopy_MsgHeader;
+
+typedef MessageQCopy_MsgHeader *MessageQCopy_Msg;
+
+/* Element to hold payload copied onto receiver's queue.                  */
+typedef struct Queue_elem {
+    List_Elem    elem;              /* Allow list linking.                */
+    UInt         len;               /* Length of data                     */
+    UInt32       src;               /* Src address/endpt of the msg       */
+    Char         data[];            /* payload begins here                */
+} Queue_elem;
+
+/* Combine transport related objects into a struct for future migration: */
+typedef struct MessageQCopy_Transport  {
+    Swi_Handle       swiHandle;
+    VirtQueue_Handle virtQueue_toHost;
+    VirtQueue_Handle virtQueue_fromHost;
+    Semaphore_Handle semHandle_toHost;
+} MessageQCopy_Transport;
+
+
+/* module diags mask */
+Registry_Desc Registry_CURDESC;
+
+static MessageQCopy_Module      module;
+static MessageQCopy_Transport   transport;
+
+/* We create a fixed size heap over this memory for copying received msgs */
+#pragma DATA_ALIGN (recv_buffers, HEAPALIGNMENT)
+static UInt8 recv_buffers[MAXHEAPSIZE];
+
+/* Module ref count: */
+static Int curInit = 0;
+extern Semaphore_Handle MessageQCopy_semHandle;
+
+/*
+ *  ======== MessageQCopy_swiFxn ========
+ */
+#define FXNN "MessageQCopy_swiFxn"
+static Void MessageQCopy_swiFxn(UArg arg0, UArg arg1)
+{
+    Int16             token;
+    MessageQCopy_Msg  msg;
+    UInt16            dstProc = MultiProc_self();
+    Bool              usedBufAdded = FALSE;
+    Int               len;
+
+    Log_print0(Diags_ENTRY, "--> "FXNN);
+
+    /* Process all available buffers: */
+    while ((token = VirtQueue_getAvailBuf(transport.virtQueue_fromHost,
+                                         (Void **)&msg, &len)) >= 0) {
+
+        Log_print3(Diags_INFO, FXNN": \n\tReceived msg: from: 0x%x, "
+                   "to: 0x%x, dataLen: %d",
+                  (IArg)msg->srcAddr, (IArg)msg->dstAddr, (IArg)msg->dataLen);
+
+        /* Pass to desitination queue (which is on this proc): */
+        MessageQCopy_send(dstProc, msg->dstAddr, msg->srcAddr,
+                         (Ptr)msg->payload, msg->dataLen);
+
+        VirtQueue_addUsedBuf(transport.virtQueue_fromHost, token,
+                                                            RP_MSG_BUF_SIZE);
+        usedBufAdded = TRUE;
+    }
+
+    if (usedBufAdded)  {
+       /* Tell host we've processed the buffers: */
+       VirtQueue_kick(transport.virtQueue_fromHost);
+    }
+    Log_print0(Diags_EXIT, "<-- "FXNN);
+}
+#undef FXNN
+
+
+#define FXNN "callback_availBufReady"
+static Void callback_availBufReady(VirtQueue_Handle vq)
+{
+
+    if (vq == transport.virtQueue_fromHost)  {
+       /* Post a SWI to process all incoming messages */
+        Log_print0(Diags_INFO, FXNN": virtQueue_fromHost kicked");
+        Swi_post(transport.swiHandle);
+    }
+    else if (vq == transport.virtQueue_toHost) {
+       /* Note: We post nothing for transport.virtQueue_toHost, as we assume the
+        * host has already made all buffers available for sending.
+        */
+        Semaphore_post(transport.semHandle_toHost);
+        Log_print0(Diags_INFO, FXNN": virtQueue_toHost kicked");
+    }
+}
+#undef FXNN
+
+/* =============================================================================
+ *  MessageQCopy Functions:
+ * =============================================================================
+ */
+
+/*
+ *  ======== MessasgeQCopy_init ========
+ *
+ *
+ */
+#define FXNN "MessageQCopy_init"
+Void MessageQCopy_init(UInt16 remoteProcId)
+{
+    GateSwi_Params gatePrms;
+    HeapBuf_Params prms;
+    int     i;
+    Registry_Result result;
+
+    Semaphore_pend(MessageQCopy_semHandle, BIOS_WAIT_FOREVER);
+    if (curInit++) {
+        Log_print1(Diags_ENTRY, "--> "FXNN": (remoteProcId=%d)",
+                    (IArg)remoteProcId);
+        goto exit;  /* module already initialized */
+    }
+
+    /* register with xdc.runtime to get a diags mask */
+    result = Registry_addModule(&Registry_CURDESC, MODULE_NAME);
+    Assert_isTrue(result == Registry_SUCCESS, (Assert_Id)NULL);
+
+    /* Log should be after the Registry_CURDESC is initialized */
+    Log_print1(Diags_ENTRY, "--> "FXNN": (remoteProcId=%d)",
+                (IArg)remoteProcId);
+
+    /* Gate to protect module object and lists: */
+    GateSwi_Params_init(&gatePrms);
+    module.gateSwi = GateSwi_create(&gatePrms, NULL);
+
+    /* Initialize Module State: */
+    for (i = 0; i < MAXMESSAGEQOBJECTS; i++) {
+       module.msgqObjects[i] = NULL;
+    }
+
+    HeapBuf_Params_init(&prms);
+    prms.blockSize    = MSGBUFFERSIZE;
+    prms.numBlocks    = MAXMESSAGEBUFFERS;
+    prms.buf          = recv_buffers;
+    prms.bufSize      = MAXHEAPSIZE;
+    prms.align        = HEAPALIGNMENT;
+    module.heap       = HeapBuf_create(&prms, NULL);
+    if (module.heap == 0) {
+       System_abort("MessageQCopy_init: HeapBuf_create returned 0\n");
+    }
+    transport.semHandle_toHost = Semaphore_create(0, NULL, NULL);
+
+    /* Initialize Transport related objects: */
+
+    /*
+     * Plug Vring Interrupts, and create a pair VirtQueues (one for sending,
+     * one for receiving).
+     */
+    VirtQueue_startup();
+
+    /*
+     * Note: order of these calls determines the virtqueue indices identifying
+     * the vrings toHost and fromHost:  toHost is first!
+     */
+    transport.virtQueue_toHost   = VirtQueue_create(callback_availBufReady,
+                                                    remoteProcId,
+                                                    ID_SELF_TO_A9);
+    transport.virtQueue_fromHost = VirtQueue_create(callback_availBufReady,
+                                                    remoteProcId,
+                                                    ID_A9_TO_SELF);
+
+    /* construct the Swi to process incoming messages: */
+    transport.swiHandle = Swi_create(MessageQCopy_swiFxn, NULL, NULL);
+
+exit:
+    Semaphore_post(MessageQCopy_semHandle);
+
+    Log_print0(Diags_EXIT, "<-- "FXNN);
+}
+#undef FXNN
+
+/*
+ *  ======== MessasgeQCopy_finalize ========
+ */
+#define FXNN "MessageQCopy_finalize"
+Void MessageQCopy_finalize()
+{
+    Log_print0(Diags_ENTRY, "--> "FXNN);
+
+    Semaphore_pend(MessageQCopy_semHandle, BIOS_WAIT_FOREVER);
+    if (!curInit || --curInit) {
+         goto exit; /* module still in use, or uninitialized */
+    }
+
+    /* Tear down Module */
+    HeapBuf_delete(&(module.heap));
+
+    Swi_delete(&(transport.swiHandle));
+
+    GateSwi_delete(&module.gateSwi);
+
+exit:
+    Semaphore_post(MessageQCopy_semHandle);
+
+    Log_print0(Diags_EXIT, "<-- "FXNN);
+}
+#undef FXNN
+
+/*
+ *  ======== MessageQCopy_create ========
+ */
+#define FXNN "MessageQCopy_create"
+MessageQCopy_Handle MessageQCopy_create(UInt32 reserved, UInt32 * endpoint)
+{
+    MessageQCopy_Object    *obj = NULL;
+    Bool                   found = FALSE;
+    Int                    i;
+    UInt16                 queueIndex = 0;
+    IArg key;
+
+    Log_print2(Diags_ENTRY, "--> "FXNN": (reserved=%d, endpoint=0x%x)",
+                (IArg)reserved, (IArg)endpoint);
+
+    Assert_isTrue((curInit > 0) , NULL);
+
+    key = GateSwi_enter(module.gateSwi);
+
+    if (reserved == MessageQCopy_ASSIGN_ANY)  {
+       /* Search the array for a free slot above reserved: */
+       for (i = MessageQCopy_MAX_RESERVED_ENDPOINT + 1;
+           (i < MAXMESSAGEQOBJECTS) && (found == FALSE) ; i++) {
+           if (module.msgqObjects[i] == NULL) {
+            queueIndex = i;
+            found = TRUE;
+            break;
+           }
+       }
+    }
+    else if ((queueIndex = reserved) <= MessageQCopy_MAX_RESERVED_ENDPOINT) {
+       if (module.msgqObjects[queueIndex] == NULL) {
+           found = TRUE;
+       }
+    }
+
+    if (found)  {
+       obj = Memory_alloc(NULL, sizeof(MessageQCopy_Object), 0, NULL);
+       if (obj != NULL) {
+           /* Allocate a semaphore to signal when messages received: */
+           obj->semHandle = Semaphore_create(0, NULL, NULL);
+
+           /* Create our queue of to be received messages: */
+           obj->queue = List_create(NULL, NULL);
+
+           /* Store our endpoint, and object: */
+           obj->queueId = queueIndex;
+           module.msgqObjects[queueIndex] = obj;
+
+           /* See MessageQCopy_unblock() */
+           obj->unblocked = FALSE;
+
+           *endpoint    = queueIndex;
+           Log_print1(Diags_LIFECYCLE, FXNN": endPt created: %d",
+                        (IArg)queueIndex);
+       }
+    }
+
+    GateSwi_leave(module.gateSwi, key);
+
+    Log_print1(Diags_EXIT, "<-- "FXNN": 0x%x", (IArg)obj);
+    return (obj);
+}
+#undef FXNN
+
+/*
+ *  ======== MessageQCopy_delete ========
+ */
+#define FXNN "MessageQCopy_delete"
+Int MessageQCopy_delete(MessageQCopy_Handle *handlePtr)
+{
+    Int                    status = MessageQCopy_S_SUCCESS;
+    MessageQCopy_Object    *obj;
+    Queue_elem             *payload;
+    IArg                   key;
+
+    Log_print1(Diags_ENTRY, "--> "FXNN": (handlePtr=0x%x)", (IArg)handlePtr);
+
+    Assert_isTrue((curInit > 0) , NULL);
+
+    if (handlePtr && (obj = (MessageQCopy_Object *)(*handlePtr)))  {
+
+       Semaphore_delete(&(obj->semHandle));
+
+       /* Free/discard all queued message buffers: */
+       while ((payload = (Queue_elem *)List_get(obj->queue)) != NULL) {
+           HeapBuf_free(module.heap, (Ptr)payload, MSGBUFFERSIZE);
+       }
+
+       List_delete(&(obj->queue));
+
+       /* Null out our slot: */
+       key = GateSwi_enter(module.gateSwi);
+       module.msgqObjects[obj->queueId] = NULL;
+       GateSwi_leave(module.gateSwi, key);
+
+       Log_print1(Diags_LIFECYCLE, FXNN": endPt deleted: %d",
+                        (IArg)obj->queueId);
+
+       /* Now free the obj */
+       Memory_free(NULL, obj, sizeof(MessageQCopy_Object));
+
+       *handlePtr = NULL;
+    }
+
+    Log_print1(Diags_EXIT, "<-- "FXNN": %d", (IArg)status);
+    return(status);
+}
+#undef FXNN
+
+/*
+ *  ======== MessageQCopy_recv ========
+ */
+#define FXNN "MessageQCopy_recv"
+Int MessageQCopy_recv(MessageQCopy_Handle handle, Ptr data, UInt16 *len,
+                      UInt32 *rplyEndpt, UInt timeout)
+{
+    Int                 status = MessageQCopy_S_SUCCESS;
+    MessageQCopy_Object *obj = (MessageQCopy_Object *)handle;
+    Bool                semStatus;
+    Queue_elem          *payload;
+
+    Log_print5(Diags_ENTRY, "--> "FXNN": (handle=0x%x, data=0x%x, len=0x%x,"
+               "rplyEndpt=0x%x, timeout=%d)", (IArg)handle, (IArg)data,
+               (IArg)len, (IArg)rplyEndpt, (IArg)timeout);
+
+    Assert_isTrue((curInit > 0) , NULL);
+
+    /* Check vring for pending messages before we block: */
+    Swi_post(transport.swiHandle);
+
+    /*  Block until notified. */
+    semStatus = Semaphore_pend(obj->semHandle, timeout);
+
+    if (semStatus == FALSE)  {
+       status = MessageQCopy_E_TIMEOUT;
+       Log_print0(Diags_STATUS, FXNN": Sem pend timeout!");
+    }
+    else if (obj->unblocked) {
+       status = MessageQCopy_E_UNBLOCKED;
+    }
+    else  {
+       payload = (Queue_elem *)List_get(obj->queue);
+
+       if (!payload) {
+           System_abort("MessageQCopy_recv: got a NULL payload\n");
+       }
+    }
+
+    if (status == MessageQCopy_S_SUCCESS)  {
+       /* Now, copy payload to client and free our internal msg */
+       memcpy(data, payload->data, payload->len);
+       *len = payload->len;
+       *rplyEndpt = payload->src;
+
+       HeapBuf_free(module.heap, (Ptr)payload,
+                    (payload->len + sizeof(Queue_elem)));
+    }
+
+    Log_print1(Diags_EXIT, "<-- "FXNN": %d", (IArg)status);
+    return (status);
+}
+#undef FXNN
+
+/*
+ *  ======== MessageQCopy_send ========
+ */
+#define FXNN "MessageQCopy_send"
+Int MessageQCopy_send(UInt16 dstProc,
+                      UInt32 dstEndpt,
+                      UInt32 srcEndpt,
+                      Ptr    data,
+                      UInt16 len)
+{
+    Int               status = MessageQCopy_S_SUCCESS;
+    MessageQCopy_Object   *obj;
+    Int16             token = 0;
+    MessageQCopy_Msg  msg;
+    Queue_elem        *payload;
+    UInt              size;
+    IArg              key;
+    Int               length;
+
+    Log_print5(Diags_ENTRY, "--> "FXNN": (dstProc=%d, dstEndpt=%d, "
+               "srcEndpt=%d, data=0x%x, len=%d", (IArg)dstProc, (IArg)dstEndpt,
+               (IArg)srcEndpt, (IArg)data, (IArg)len);
+
+    Assert_isTrue((curInit > 0) , NULL);
+
+    if (dstProc != MultiProc_self()) {
+        /* Send to remote processor: */
+        do {
+            key = GateSwi_enter(module.gateSwi);  /* Protect vring structs */
+            Semaphore_reset(transport.semHandle_toHost, 0);
+            token = VirtQueue_getAvailBuf(transport.virtQueue_toHost,
+                    (Void **)&msg, &length);
+        } while (token < 0 && Semaphore_pend(transport.semHandle_toHost,
+                                             BIOS_WAIT_FOREVER));
+        if (token >= 0) {
+            /* Copy the payload and set message header: */
+            memcpy(msg->payload, data, len);
+            msg->dataLen = len;
+            msg->dstAddr = dstEndpt;
+            msg->srcAddr = srcEndpt;
+            msg->flags = 0;
+            msg->reserved = 0;
+
+            VirtQueue_addUsedBuf(transport.virtQueue_toHost, token,
+                                                            RP_MSG_BUF_SIZE);
+            VirtQueue_kick(transport.virtQueue_toHost);
+        }
+        else {
+            status = MessageQCopy_E_FAIL;
+            Log_print0(Diags_STATUS, FXNN": getAvailBuf failed!");
+        }
+        GateSwi_leave(module.gateSwi, key);
+    }
+    else {
+        /* Put on a Message queue on this processor: */
+
+        /* Protect from MessageQCopy_delete */
+        key = GateSwi_enter(module.gateSwi);
+        obj = module.msgqObjects[dstEndpt];
+        GateSwi_leave(module.gateSwi, key);
+
+        if (obj == NULL) {
+            Log_print1(Diags_STATUS, FXNN": no object for endpoint: %d",
+                   (IArg)dstEndpt);
+            status = MessageQCopy_E_NOENDPT;
+            return status;
+        }
+
+        /* Allocate a buffer to copy the payload: */
+        size = len + sizeof(Queue_elem);
+
+        /* HeapBuf_alloc() is non-blocking, so needs protection: */
+        key = GateSwi_enter(module.gateSwi);
+        payload = (Queue_elem *)HeapBuf_alloc(module.heap, size, 0, NULL);
+        GateSwi_leave(module.gateSwi, key);
+
+        if (payload != NULL)  {
+            memcpy(payload->data, data, len);
+            payload->len = len;
+            payload->src = srcEndpt;
+
+            /* Put on the endpoint's queue and signal: */
+            List_put(obj->queue, (List_Elem *)payload);
+            Semaphore_post(obj->semHandle);
+        }
+        else {
+            status = MessageQCopy_E_MEMORY;
+            Log_print0(Diags_STATUS, FXNN": HeapBuf_alloc failed!");
+        }
+    }
+
+    Log_print1(Diags_EXIT, "<-- "FXNN": %d", (IArg)status);
+    return (status);
+}
+#undef FXNN
+
+/*
+ *  ======== MessageQCopy_unblock ========
+ */
+#define FXNN "MessageQCopy_unblock"
+Void MessageQCopy_unblock(MessageQCopy_Handle handle)
+{
+    MessageQCopy_Object *obj = (MessageQCopy_Object *)handle;
+
+    Log_print1(Diags_ENTRY, "--> "FXNN": (handle=0x%x)", (IArg)handle);
+
+    /* Set instance to 'unblocked' state, and post */
+    obj->unblocked = TRUE;
+    Semaphore_post(obj->semHandle);
+    Log_print0(Diags_EXIT, "<-- "FXNN);
+}
+#undef FXNN
diff --git a/src/ti/ipc/rpmsg/MessageQCopy.h b/src/ti/ipc/rpmsg/MessageQCopy.h
new file mode 100644 (file)
index 0000000..7378553
--- /dev/null
@@ -0,0 +1,281 @@
+/*
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/** ============================================================================
+ *  @file       MessageQCopy.h
+ *
+ *  @brief      A simple copy-based MessageQ, to work with Linux virtio_rp_msg.
+ *
+ *  The following are key features of the MessageQCopy module:
+ *  - Multiple writers, single reader.
+ *  - Timeouts are allowed when receiving messages.
+ *  - Supports processor copy transfers only.
+ *  - Sending/receiving also works between enpoints on the same processor.
+ *
+ *  Non-Features (as compared to MessageQ):
+ *  - zero copy messaging, using registered heaps.
+ *  - Dependence on a NameServer (Client furnishes the endpoint IDs)
+ *  - Arbitrary reply endpoints can be embedded in message header.
+ *  - Priority Queues.
+ *
+ *  Conceptually, the reader thread owns a message queue. The reader thread
+ *  creates a message queue. The writer threads opens a created message queue
+ *  to get access to it.
+ *
+ *  Message queues are identified by a system-wide unique 32 bit queueID,
+ *  which encodes the (MultiProc) 16 bit core ID and a local 16 bit index ID.
+ *
+ *  The MessageQCopy header should be included in an application as follows:
+ *  @code
+ *  #include <ti/ipc/rpmsg/MessageQCopy.h>
+ *  @endcode
+ *
+ *  Questions:
+ *  - Workout how connections exist: how does Ducati side cleanup when Linux
+ *    side goes down?
+ *  - Client needs to know max size of data buffer to allocate for receive.
+ *  - Do we need procID's buried in the message header addresses anymore, or
+ *    isn't that now implicit in the vrings/transport.
+ *  - Do we want MessageQ_Unblock in this version?  (Normally used in RCM).
+ *  - Do we want the generic ISync ability to create our own synchronizers,
+ *    or just hard-code semaphore usage or callbacks for simplicity?
+ *
+ *  ============================================================================
+ */
+
+#ifndef ti_ipc_MessageQCopy__include
+#define ti_ipc_MessageQCopy__include
+
+#if defined (__cplusplus)
+extern "C" {
+#endif
+
+
+/* =============================================================================
+ *  Structures & Definitions
+ * =============================================================================
+ */
+
+/*!
+ *  @brief      Used as the timeout value to specify wait forever
+ */
+#define MessageQCopy_FOREVER                ~(0)
+
+/*!
+   *  @def    MessageQCopy_S_SUCCESS
+ *  @brief  Operation is successful.
+ */
+#define MessageQCopy_S_SUCCESS              0
+
+/*!
+ *  @def    MessageQCopy_E_FAIL
+ *  @brief  Operation is not successful.
+ */
+#define MessageQCopy_E_FAIL                 -1
+
+/*!
+ *  @def    MessageQCopy_E_MEMORY
+ *  @brief  Operation resulted in memory failure.
+ */
+#define MessageQCopy_E_MEMORY               -3
+
+/*!
+ *  @def    MessageQCopy_E_TIMEOUT
+ *  @brief  Operation timed out.
+ */
+#define MessageQCopy_E_TIMEOUT              -6
+
+/*!
+ *  @def    MessageQCopy_E_NOENDPT
+ *  @brief  No endpoint for a message.
+ */
+#define MessageQCopy_E_NOENDPT              -7
+
+/*!
+ *  @def    MessageQ_E_UNBLOCKED
+ *  @brief  MessageQ was unblocked
+ */
+#define MessageQCopy_E_UNBLOCKED            -19
+
+/*!
+ *  @def    MessageQCopy_MAX_RESERVED_ENDPOINT
+ *  @brief  Maximum Value for System Reserved Endpoints.
+ */
+#define MessageQCopy_MAX_RESERVED_ENDPOINT  100
+
+/*!
+ *  @def    MessageQCopy_MAX_RESERVED_ENDPOINT
+ *  @brief  Maximum Value for System Reserved Endpoints.
+ */
+#define MessageQCopy_ASSIGN_ANY             0xFFFFFFFF
+/*!
+ *  @brief  MessageQCopy_Handle type
+ */
+typedef struct MessageQCopy_Object *MessageQCopy_Handle;
+
+/* =============================================================================
+ *  MessageQCopy Functions:
+ * =============================================================================
+ */
+
+
+/*!
+ *  @brief      Initialize MessageQCopy Module
+ *
+ *  Note: Multiple clients must serialize calls to this function.
+ *
+ *  @param[in]  remoteProcId      MultiProc ID of the peer.
+ */
+Void MessageQCopy_init(UInt16 remoteProcId);
+
+/*!
+ *  @brief      Tear down MessageQCopy Module
+ *
+ */
+Void MessageQCopy_finalize();
+
+
+/*!
+ *  @brief      Create a MessageQ instance for receiving.
+ *
+ *  The returned handle is to an object containing a queue for receiving
+ *  messages from the transport, and a 32 bit endpoint ID unique to this local
+ *  processor.
+ *
+ *  @param[in]   reserved     If value is MessageQCopy_ASSIGN_ANY, then
+ *                            any Endpoint can be assigned; otherwise, value is
+ *                            a reserved Endpoint ID, which must be less than
+ *                            or equal to MessageQCopy_MAX_RESERVED_ENDPOINT.
+ *  @param[out]  endpoint     Endpoint ID for this side of the connection.
+ *
+ *
+ *  @return     MessageQ Handle, or NULL if:
+ *                            - reserved endpoint already taken;
+ *                            - could not allocate object
+ */
+MessageQCopy_Handle MessageQCopy_create(UInt32 reserved, UInt32 * endpoint);
+
+/*!
+ *  @brief      Receives a message from a message queue
+ *
+ *  This function returns a status. It also copies data to the client.
+ *  If no message is available, it blocks on the semaphore object
+ *  until the semaphore is signaled or a timeout occurs.
+ *  The semaphore is signaled, when Message_send is called to deliver a message
+ *  to this endpoint. If a timeout occurs, len is set to zero and the status is
+ *  #MessageQCopy_E_TIMEOUT. If a timeout of zero is specified, the function
+ *  returns immediately and if no message is available, the len is set to zero
+ *  and the status is #MessageQCopy_E_TIMEOUT.
+ *  The #MessageQCopy_E_UNBLOCKED status is returned, if MessageQ_unblock is called
+ *  on the MessageQCopy handle.
+ *  If a message is successfully retrieved, the message
+ *  data is copied into the data pointer, and a #MessageQCopy_S_SUCCESS
+ *  status is returned.
+ *
+ *  @param[in]  handle      MessageQ handle
+ *  @param[out] data        Pointer to the client's data buffer.
+ *  @param[out] len         Amount of data received.
+ *  @param[out] rplyEndpt   Endpoint of source (for replies).
+ *  @param[in]  timeout     Maximum duration to wait for a message in
+ *                          microseconds.
+ *
+ *  @return     MessageQ status:
+ *              - #MessageQCopy_S_SUCCESS: Message successfully returned
+ *              - #MessageQCopy_E_TIMEOUT: MessageQCopy_recv timed out
+ *              - #MessageQCopy_E_UNBLOCKED: MessageQ_get was unblocked
+ *              - #MessageQCopy_E_FAIL:    A general failure has occurred
+ *
+ *  @sa         MessageQCopy_send MessageQCopy_unblock
+ */
+Int MessageQCopy_recv(MessageQCopy_Handle handle, Ptr data, UInt16 *len,
+                      UInt32 *rplyEndpt, UInt timeout);
+
+/*!
+ *  @brief      Sends data to a remote processor, or copies onto a local
+ *              messageQ.
+ *
+ *  If the message is placed onto a local Message queue, the queue's
+ *  #MessageQCopy_Params::semaphore signal function is called.
+ *
+ *  @param[in]  dstProc     Destination ProcId.
+ *  @param[in]  dstEndpt    Destination Endpoint.
+ *  @param[in]  srcEndpt    Source Endpoint.
+ *  @param[in]  data        Data payload to be copied and sent.
+ *  @param[in]  len         Amount of data to be copied, including Msg header.
+ *
+ *  @return     Status of the call.
+ *              - #MessageQCopy_S_SUCCESS denotes success.
+ *              - #MessageQCopy_E_FAIL denotes failure.
+ *                The send was not successful.
+ */
+Int MessageQCopy_send(UInt16 dstProc,
+                      UInt32 dstEndpt,
+                      UInt32 srcEndpt,
+                      Ptr    data,
+                      UInt16 len);
+
+/*!
+ *  @brief      Delete a created MessageQ instance.
+ *
+ *  This function deletes a created message queue instance. If the
+ *  message queue is non-empty, any messages remaining in the queue
+ *  will be lost.
+ *
+ *  @param[in,out]  handlePtr   Pointer to handle to delete.
+ *
+ *  @return     MessageQ status:
+ *              - #MessageQCopy_E_FAIL: delete failed
+ *              - #MessageQCopy_S_SUCCESS: delete successful, *handlePtr = NULL.
+ */
+Int MessageQCopy_delete(MessageQCopy_Handle *handlePtr);
+
+/*!
+ *  @brief      Unblocks a MessageQ
+ *
+ *  Unblocks a reader thread that is blocked on a MessageQCopy_recv.  The
+ *  MessageQCopy_recv call will return with status #MessageQ_E_UNBLOCKED
+ *  indicating that it returned due to a MessageQCopy_unblock rather than by
+ *  a timeout or receiving a message.
+ *
+ *  Restrictions:
+ *  -  A queue may not be used after it has been unblocked.
+ *  -  MessageQ_unblock may only be called on a local queue.
+ *
+ *  @param[in]  handle      MessageQCopy handle
+ *
+ *  @sa         MessageQCopy_recv
+ */
+Void MessageQCopy_unblock(MessageQCopy_Handle handle);
+
+#if defined (__cplusplus)
+}
+#endif /* defined (__cplusplus) */
+#endif /* ti_ipc_MessageQCopy__include */
index 67959850b7c3eae4e75adc3906b7460d16f72366..79ad9d63b7f8f442f5327d961223c9e3a7a9acfa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Texas Instruments Incorporated
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  *  ======== package.bld ========
  */
 
+var Build = xdc.useModule('xdc.bld.BuildEnvironment');
 var Pkg = xdc.useModule('xdc.bld.PackageContents');
 
-/* This package doesn't build any libraries, just exports some headers */
-Pkg.otherFiles = ["package.bld", "Rpmsg.h", "virtio_ring.h"];
+Pkg.attrs.exportSrc = true;
+
+Pkg.otherFiles = ["package.bld", "Rpmsg.h", "virtio_ring.h", "MessageQCopy.h"];
+
+var SRCS = ["MessageQCopy.c"];
+
+/* remove this output directory during a clean */
+Pkg.generatedFiles.$add("lib/");
+
+for (var i = 0; i < Build.targets.length; i++) {
+    var targ = Build.targets[i];
+    var isaDefs = "";
+
+    /* Yuck, yuck, yuck! */
+    if (targ.isa == "674") {
+        isaDefs = "-DOMAPL138";
+// OMAP4/5 not yet supported
+//    } else if ((targ.isa == "v7M") || (targ.isa == "64T")) {
+//        isaDefs = "-DOMAP4430";
+    } else if (targ.isa == "66") {
+        /* TBD: Only one of Appleton or Kepler can build for now: */
+       isaDefs = "-DTCI6638";
+       //isaDefs = "-DTCI6614";
+    } else {
+        continue;
+    }
+
+    /* Build for all profiles */
+    for (var profile in targ.profiles) {
+
+       Pkg.addLibrary("lib/" + profile + "/" + Pkg.name, targ, {
+           profile: profile,
+           copts: "--gcc",   /* b/c Rpmsg.h requires gcc-isms */
+           defs: isaDefs
+       }).addObjects(SRCS);
+    }
+}
index 3f37323756af2ffc30f8654d389180013325fb73..cac6282b5546856393abe56d7c739d6087ee9171 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2011-2012, Texas Instruments Incorporated
+ * Copyright (c) 2011-2013, Texas Instruments Incorporated
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 
 /*!
  *  ======== ti.ipc.rpmsg ========
- *  Inter processor communication.
- *
- *  Contains modules are that OS independent and support
- *  streaming messaging between threads and/or processors.
- *
+ *  IPC over Virtio vrings (RPMSG).
  */
 
-package ti.ipc.rpmsg [1,0,0,0] {
+package ti.ipc.rpmsg [1,0,0] {
 }