Merge pull request #3 in PROCESSOR-SDK/pdk from PRSDK-7095 to master
[processor-sdk/pdk.git] / packages / ti / drv / ipc / src / ipc_api.c
1 /*
2  *  Copyright (c) Texas Instruments Incorporated 2018
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions
7  *  are met:
8  *
9  *    Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  *    Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the
15  *    distribution.
16  *
17  *    Neither the name of Texas Instruments Incorporated nor the names of
18  *    its contributors may be used to endorse or promote products derived
19  *    from this software without specific prior written permission.
20  *
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32  */
34 /**
35  *  \file ipc_api.c
36  *
37  *  \brief File containing the IPC driver APIs.
38  *
39  */
41 /* ========================================================================== */
42 /*                             Include Files                                  */
43 /* ========================================================================== */
44 #include <ti/drv/ipc/ipc.h>
45 #include <string.h>
47 #ifndef IPC_EXCLUDE_CTRL_TASKS
48 #include <ti/osal/osal.h>
49 #include <ti/osal/TaskP.h>
50 #endif
52 #include "ipc_priv.h"
53 #include "ipc_virtioPrivate.h"
54 #include "ipc_osal.h"
55 #include "ipc_utils.h"
56 #include "ipc_mailbox.h"
58 /* ========================================================================== */
59 /*                           Macros & Typedefs                                */
60 /* ========================================================================== */
61 #define MAXCALLBACKS           IPC_MAX_PROCS
63 #define MSGBUFFERSIZE          512U
64 #define SERVICENAMELEN         32U
65 #define HEAPALIGNMENT          8U
67 typedef struct RPMessage_Object*            RPMessage_EndptPool[MAXENDPOINTS];
69 /* ========================================================================== */
70 /*                         Structure Declarations                             */
71 /* ========================================================================== */
73 #define CNTRLMSG_ANNOUNCE (0x00000000U)
75 /* Message Header: Must match mp_msg_hdr in virtio_rp_msg.h on Linux side. */
76 typedef struct RPMessage_MsgHeader_s
77 {
78     uint32_t  srcAddr;             /* source endpoint addr       */
79     uint32_t  dstAddr;             /* destination endpoint addr  */
80     uint32_t  srcProcId;           /* reserved                   */
81     uint16_t  dataLen;             /* data length                */
82     uint16_t  flags;               /* bitmask of different flags */
83     uint8_t   payload[];           /* Data payload               */
84 }RPMessage_MsgHeader;
87 /* common fields of a control message */
88 typedef struct RPMessage_CntrlMsg_s
89 {
90     uint32_t  type;
91 }RPMessage_CntrlMsg;
93 /* announcement message */
94 typedef struct RPMessage_Announcement_s
95 {
96     char                 name[SERVICENAMELEN];
97     uint32_t             endPt;
98     RPMessage_CntrlMsg   ctrl;
99 } RPMessage_Announcement;
102 /* list element for the announcedEndpts list */
103 typedef struct RPMessage_NameEntry_s
105     IpcUtils_QElem   elem;
106     uint32_t         procId;
107     uint32_t         endPt;
108     char             name[SERVICENAMELEN];
109 } RPMessage_NameEntry;
112 /* list element for the waitingTasks list */
113 typedef struct RPMessage_Waiter_s
115     IpcUtils_QElem     elem;
116     void               *semHandle;
117     uint32_t           procId;
118     uint32_t           endPt;
119     char               name[SERVICENAMELEN];
120 } RPMessage_Waiter;
121 /**
122  *  \brief Element to hold payload copied onto receiver's queue.
123  */
124 typedef struct RPMessage_MsgElem_s
126     IpcUtils_QElem    elem;          /**< Allow list linking.          */
127     uint32_t          len;           /**< Length of data               */
128     uint32_t          src;           /**< Src address/endPt of the msg */
129     uint32_t          procId;        /**< Processor sending the msg    */
130     uint8_t           data[];        /**< payload begins here          */
131 } RPMessage_MsgElem;
133 /* The RPMessage Object */
134 typedef struct RPMessage_Object_s
136     uint32_t             endPt;        /**< Unique id (procId | queueIndex) */
137     void                 *semHandle;    /**< I/O Completion                 */
138     RPMessage_Callback   cb;           /**< RPMessage Callback */
139     void*                arg;          /**< Callback argument */
140     IpcUtils_QHandle     queue;       /**< Queue of pending messages             */
141     uint8_t                 unblocked;    /**< Use with signal to unblock _receive() */
142     IpcUtils_HeapParams  heapParams;   /* Save the heapBuf params to delete Heap   */
143     IpcUtils_HeapHandle  heap;         /* Heap from which to allocate free messages */
144     RPMessage_EndptPool  *pool;        /**< track associated pool for cleanup */
145     void*                recv_buffer;  /**< Application buffer from RPMessage_recv() */
146     RPMessage_MsgElem    payload;      /**< Message info for RPMessage_recv() */
147 } RPMessage_Object;
149 /**
150  *  \brief This struct is used as private data supplied to the VQ
151  *         callback function.  It is also passed to the SWI
152  *         functions through arg0. */
153 typedef struct RPMessage_CallbackData_s
155     Virtio_Handle        vq;
156     RPMessage_EndptPool  *pool;
157     Ipc_OsalHIsrHandle   swi;
158 } RPMessage_CallbackData;
160 /**
161  *  \brief Module_State
162  */
163 typedef struct RPMessage_Module_s
165     /* Instance gate: */
166     Ipc_OsalHIsrGateHandle gateSwi;
168     /* Lookup VQ handle from procId for sending messages. */
169     /* Array indexed by procId.                           */
170     Virtio_Handle tx_VQs[IPC_MAX_PROCS];
172     /* Array of callback structs. Used only for RX VirtQueues */
173     RPMessage_CallbackData VQ_callbacks[MAXCALLBACKS];
175     uint32_t numCallbacks;
177     /* Global endpoint pool */
178     RPMessage_EndptPool globalPool;
180     /* Lookup endpoint pool from procId.  Array indexed by procId. */
181     /* RPMessage_EndptPool pools[MAXREMOTEPROCS];            */
183     /* Queue to track announcements from other processors */
184     IpcUtils_QHandle announcedEndpts;
186     /* Queue to hold the semaphores of waiting tasks */
187     IpcUtils_QHandle waitingTasks;
189     /* Array of RPMessage Object, memory supplied by application */
190     RPMessage_Object*   objArry;
192     /* Current object Count */
193     uint16_t objCnt;
195     /* NameEntry count */
196     uint16_t  nameEntryCnt;
198     RPMessage_NameEntry  nameEntry[IPC_MAX_PROCS];
200 } RPMessage_Module;
202 /* ========================================================================== */
203 /*                          Function Declarations                             */
204 /* ========================================================================== */
206 static RPMessage_Object* RPMessage_rawCreate(RPMessage_Params *params,
207         RPMessage_EndptPool* pool, uint32_t *endPt);
210 /* ========================================================================== */
211 /*                            Global Variables                                */
212 /* ========================================================================== */
214 static RPMessage_Module module;
216 static Ipc_Object gIpcObject;
217 /**< IPC Object */
218 /* ========================================================================== */
219 /*                          Function Definitions                              */
220 /* ========================================================================== */
222 RPMessage_Object* RPMessage_lookupEndpt(void* p, uint32_t e);
223 void RPMessage_assignEndpt(void* p, uint32_t e, RPMessage_Object* obj);
224 void UNUSED(const uint32_t* x);
225 uint8_t is_aligned(const void* ptr, uint32_t byteCnt);
226 RPMessage_Object*  RPMessage_allocObject(void);
229 inline RPMessage_Object* RPMessage_lookupEndpt(void* p, uint32_t e)
231     return (((RPMessage_Object**)(p))[(e)]);
234 inline void RPMessage_assignEndpt(void* p, uint32_t e, RPMessage_Object* obj)
236     (((RPMessage_Object**)(p))[(e)] = (obj));
239 inline void UNUSED(const uint32_t* x)
241     (void)(x);
244 inline uint8_t is_aligned(const void* ptr, uint32_t byteCnt)
246     uint8_t retVal;
247     uint32_t bufAddr = (uint32_t)(uintptr_t)ptr;
248     retVal = (0 == (bufAddr%byteCnt)) ? TRUE : FALSE;
249     return retVal;
254 int32_t RPMessageParams_init(RPMessage_Params *params)
256     int32_t    retVal = IPC_SOK;
258     if(params == NULL)
259     {
260         retVal = IPC_EBADARGS;
261     }
262     else
263     {
264         params->requestedEndpt = RPMESSAGE_ANY;
265         params->numBufs        = RPMessage_Buffer_Count_Default;
266         params->stackBuffer    = NULL;
267         params->stackSize      = 0U;
268     }
270     return (retVal);
273 uint32_t RPMessage_getMessageBufferSize(void)
275     return MSGBUFFERSIZE;
278 uint32_t RPMessage_getObjMemRequired(void)
280     uint32_t objSize = sizeof(RPMessage_Object);
281     objSize = ((objSize + HEAPALIGNMENT-1) & ~(HEAPALIGNMENT-1));
282     return objSize;
286 RPMessage_Object*  RPMessage_allocObject(void)
288     RPMessage_Object* obj = NULL;
290     if(module.objArry != NULL)
291     {
292          obj = (RPMessage_Object*)&(module.objArry[module.objCnt]);
293          module.objCnt++;
294     }
296     return obj;
299 /*
300  *  ======== RPMessage_enqueMsg ========
301  */
302 /* Always assumed to be called in SWI context */
303 static int32_t RPMessage_enqueMsg(RPMessage_EndptPool *pool, RPMessage_MsgHeader *msg)
305     int32_t             status = IPC_SOK;
306     int32_t             key;
307     uint32_t            size;
308     RPMessage_MsgElem  *payload;
309     RPMessage_Object   *obj = NULL;
310     Ipc_OsalPrms        *pOsalPrms = &gIpcObject.initPrms.osalPrms;
312     /* Protect from RPMessage_delete */
313     if (NULL != pOsalPrms)
314     {
315         if ((NULL != pOsalPrms->lockHIsrGate) &&
316             (NULL != pOsalPrms->unLockHIsrGate))
317         {
318             key = pOsalPrms->lockHIsrGate(module.gateSwi);
319             obj = RPMessage_lookupEndpt(pool, msg->dstAddr);
320             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
321         }
322     }
324     if (NULL != obj)
325     {
326         if(NULL != obj->recv_buffer)
327         {
328             memcpy(obj->recv_buffer, msg->payload, msg->dataLen);
329             obj->recv_buffer = NULL;
330             obj->payload.len = msg->dataLen;
331             obj->payload.src = msg->srcAddr;
332             obj->payload.procId = msg->srcProcId;
334             if (NULL != gIpcObject.initPrms.newMsgFxn)
335             {
336                 gIpcObject.initPrms.newMsgFxn(msg->srcAddr, msg->srcProcId);
337             }
339             if (NULL != pOsalPrms->unlockMutex)
340             {
341                 pOsalPrms->unlockMutex(obj->semHandle);
342             }
343         }
344         else
345         {
346             /* Allocate a buffer to copy the payload: */
347             size = msg->dataLen + sizeof(RPMessage_MsgElem);
349             /* HeapBuf_alloc() is non-blocking, so needs protection: */
350             key = pOsalPrms->disableAllIntr();
351             payload = (RPMessage_MsgElem *)IpcUtils_HeapAlloc(&obj->heap, size, 0);
353             if (payload != NULL)
354             {
355                 memcpy(payload->data, msg->payload, msg->dataLen);
356                 payload->len = msg->dataLen;
357                 payload->src = msg->srcAddr;
358                 payload->procId = msg->srcProcId;
360                 IpcUtils_Qput(&obj->queue, &payload->elem, (void *)payload);
362                 pOsalPrms->restoreAllIntr(key);
364                 if (NULL != gIpcObject.initPrms.newMsgFxn)
365                 {
366                     gIpcObject.initPrms.newMsgFxn(msg->srcAddr, msg->srcProcId);
367                 }
369                 if (NULL != pOsalPrms->unlockMutex)
370                 {
371                     pOsalPrms->unlockMutex(obj->semHandle);
372                 }
373             }
374             else
375             {
376                 pOsalPrms->restoreAllIntr(key);
377                 status = IPC_EFAIL;
378             }
379         }
380     }
382     return status;
385 /**
386  * \brief RPMessage SWI function to talk to Linux
387  */
388 static void RPMessage_swiLinuxFxn(uintptr_t arg0, uintptr_t arg1)
390     RPMessage_CallbackData *cbdata = (RPMessage_CallbackData*)arg0;
391     RPMessage_MsgHeader    *msg;
392     Int16                  token;
393     int32_t                len;
394     uint8_t                usedBufAdded = FALSE;
396     /* Process all available buffers: */
397     while ((token = Virtio_getAvailBuf(cbdata->vq, (void **)&msg, &len)) >= 0)
398     {
399        /* Pass to desitination queue (which is on this proc): */
400         RPMessage_enqueMsg(cbdata->pool, msg);
402         Virtio_addUsedBuf(cbdata->vq, token, MSGBUFFERSIZE);
403         usedBufAdded = TRUE;
404     }
406     if (TRUE == usedBufAdded)
407     {
408        /* Tell host we've processed the buffers: */
409        Virtio_kick(cbdata->vq);
410     }
413 /**
414  * \brief RPMessage SWI function
415  */
416 static void RPMessage_swiFxn(uintptr_t arg0, uintptr_t arg1)
418     RPMessage_CallbackData *cbdata = (RPMessage_CallbackData*)arg0;
419     RPMessage_MsgHeader    *msg;
421     /* Process all available buffers: */
422     while ((msg = (RPMessage_MsgHeader *) Virtio_getUsedBuf(cbdata->vq)) != NULL)
423     {
424        /* Pass to desitination queue (which is on this proc): */
425         RPMessage_enqueMsg(cbdata->pool, msg);
427         Virtio_addAvailBuf(cbdata->vq, msg);
428     }
431 /**
432  *  \brief virtio_callback - This function executes in HWI context
433  */
434 static void virtio_callback(uint32_t* priv)
436     RPMessage_CallbackData *cbdata = (RPMessage_CallbackData*)priv;
438     if (NULL != cbdata)
439     {
440         gIpcObject.initPrms.osalPrms.postHIsr(&cbdata->swi);
441     }
444 /**
445  *  \brief RPMessage_announce : Announces the availabilty of an
446  *          endpoint to all processors or only one.
447  */
448 int32_t RPMessage_announce(uint32_t remoteProcId, uint32_t endPt, const char* name)
450     RPMessage_EndptPool     *pool = &module.globalPool;
451     RPMessage_Announcement  msg;
452     Virtio_Handle           vq;
453     uint32_t                c;
454     uint32_t                procId;
455     int32_t                 status = IPC_SOK;
456     uint32_t                namelen;
458 #if  DEBUG_PRINT
459     SystemP_printf("RPMessage_announce : remote %d, endpt %d, name %s\n",
460         remoteProcId, endPt, name);
461 #endif
463     namelen = strlen(name);
464     if(namelen >= SERVICENAMELEN || namelen == 0)
465     {
466         status = IPC_EFAIL;
467     }
469     if(IPC_EFAIL != status)
470     {
471         msg.ctrl.type = CNTRLMSG_ANNOUNCE;
472         msg.endPt = endPt;
473         strncpy(msg.name, name, SERVICENAMELEN-1);
474         msg.name[SERVICENAMELEN-1] = '\0';
476         if(remoteProcId == RPMESSAGE_ALL)
477         {
478             for(c = 0; c < module.numCallbacks; c++)
479             {
480                 /* Find callback for RX VQs that have matching pool. */
481                 if(module.VQ_callbacks[c].pool == pool)
482                 {
483                     vq = module.VQ_callbacks[c].vq;
484                     procId = Virtio_getProcId(vq);
485 #if DEBUG_PRINT
486                     SystemP_printf("RPMessage_announce.....c%d ProcId %d\n", c, procId);
487 #endif
488                     status = RPMessage_send(NULL, procId, IPC_CTRL_ENDPOINT_ID,
489                             IPC_CTRL_ENDPOINT_ID, &msg, sizeof(msg));
490                     if (status != IPC_SOK)
491                     {
492                         SystemP_printf("RPMessage_announce.....failed to send c %d (%s)\n", c, Ipc_mpGetName(procId));
493                         /* even if failed to annouce to one CPU continue to other CPUs */
494                         continue;
495                     }
496                 }
497             }
498         }
499         else
500         {
501             status = RPMessage_send(NULL, remoteProcId, IPC_CTRL_ENDPOINT_ID,
502                     IPC_CTRL_ENDPOINT_ID, &msg, sizeof(msg));
503             if (status != IPC_SOK)
504             {
505                 SystemP_printf("RPMessage_announce.....failed to send\n");
506             }
507         }
508     }
510     return status;
513 #ifndef IPC_EXCLUDE_CTRL_TASKS
514 /**
515  *  \brief RPMessage_processAnnounceMsg : Handle an endpoint annoucement
516  *         message from another processor
517  */
518 static void RPMessage_processAnnounceMsg(RPMessage_Announcement *amsg, uint32_t procId)
520     int32_t key;
521     RPMessage_NameEntry *p;
522     RPMessage_Waiter *w;
523     IpcUtils_QElem *elem, *head;
524     int32_t rtnVal = IPC_SOK;
525     Ipc_OsalPrms *pOsalPrms = &gIpcObject.initPrms.osalPrms;
527 #if DEBUG_PRINT
528     SystemP_printf("RPMessage_processAnnounceMsg : announcement from %d for endPt %d\n",
529              procId, amsg->endPt );
530 #endif
532     if (NULL != pOsalPrms)
533     {
534         if (((NULL == pOsalPrms->lockHIsrGate) ||
535              (NULL == pOsalPrms->unLockHIsrGate)) ||
536             (NULL == pOsalPrms->unlockMutex))
537         {
538             rtnVal = IPC_EFAIL;
539         }
540     }
542     if (IPC_SOK == rtnVal)
543     {
544         key = pOsalPrms->lockHIsrGate(module.gateSwi);
546         /* Save the annoucement for future calls to */
547         /* RPMessage_peerIsReady().                 */
548         if(module.nameEntryCnt == IPC_MAX_PROCS-1)
549         {
550             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
551             SystemP_printf("RPMessage_processAnnounceMsg : all remote core done\n");
552             rtnVal = IPC_EFAIL;
553         }
555         if(rtnVal != IPC_EFAIL)
556         {
557             p = &module.nameEntry[module.nameEntryCnt];
558             p->endPt = amsg->endPt;
559             p->procId = procId;
560             strncpy(p->name, amsg->name, SERVICENAMELEN-1);
561             p->name[SERVICENAMELEN-1] = '\0';
562             module.nameEntryCnt++;
564             /* No interrupt / SWI protection, required here again.
565                We are already in SWI protected region */
566             IpcUtils_Qput(&module.announcedEndpts, &p->elem, (void *)p);
568             /* Wakeup all the tasks that are waiting on the */
569             /* announced name.                              */
570             if (!IpcUtils_QisEmpty(&module.waitingTasks))
571             {
572                 /* No interrupt / SWI protection, required here again.
573                    We are already in SWI protected region */
574                 elem = head = (IpcUtils_QElem *) IpcUtils_QgetHeadNode(&module.waitingTasks);
575                 do
576                 {
577                     w = (RPMessage_Waiter*)elem;
578                     if( (NULL != w) && 
579                             (strncmp(w->name, amsg->name, SERVICENAMELEN-1) == 0) &&
580                             (w->procId == procId || w->procId == RPMESSAGE_ANY))
581                     {
582                         /* Update the waiter's entry with actual */
583                         /* announcement values.                   */
584                         w->procId = procId;
585                         w->endPt = amsg->endPt;
586 #if DEBUG_PRINT
587                         SystemP_printf("RPMessage_processAnnounceMsg :Semphore Handle 0x%x\n",
588                                 (uint32_t)w->semHandle);
589 #endif
591                         pOsalPrms->unlockMutex(w->semHandle);
592                     }
593                     elem = (IpcUtils_QElem *) IpcUtils_Qnext(elem);
594                 } while (elem != head);
595             }
596             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
597         }
598     }
601 #endif /* IPC_EXCLUDE_CTRL_TASKS */
603 /**
604  *  \brief RPMessage_lookupName : Checks if an announcement has already been
605  *           received.
606  *           non-blocking query - must be protected by caller
607  */
608 static uint8_t RPMessage_lookupName(uint32_t procId, const char* name, uint32_t *remoteProcId,
609                               uint32_t *remoteEndPt)
611     uint8_t               found = FALSE;
612     RPMessage_NameEntry  *p;
613     IpcUtils_QElem       *elem, *head;
615     if (FALSE == IpcUtils_QisEmpty(&module.announcedEndpts))
616     {
617         elem = head = (IpcUtils_QElem *) IpcUtils_QgetHeadNode(&module.announcedEndpts);
618         do
619         {
620             p = (RPMessage_NameEntry*)elem;
621             if( (NULL != p) &&
622                 (strncmp(p->name, name, SERVICENAMELEN) == 0) &&
623                 (p->procId == procId || procId == RPMESSAGE_ANY))
624             {
625                 found = TRUE;
626                 *remoteEndPt = p->endPt;
627                 *remoteProcId = p->procId;
628 #if DEBUG_PRINT
629                 SystemP_printf("RPMessage_lookupName found endpoint %d, remote %d\n",
630                     *remoteEndPt, *remoteProcId);
631 #endif
632                 break;
633             }
634             elem = (IpcUtils_QElem *) IpcUtils_Qnext(elem);
635         } while (elem != head);
636     }
637     return found;
640 /**
641  *  \brief RPMessage_waitForProc
642  */
643 int32_t RPMessage_getRemoteEndPt(uint32_t selfProcId, const char* name, uint32_t *remoteProcId,
644                              uint32_t *remoteEndPt, uint32_t timeout)
646     int32_t            key;
647     uint8_t            lookupStatus = FALSE;
648     int32_t            rtnVal = IPC_SOK;
649     void              *semHandle;
650     RPMessage_Waiter   taskWaiter;
651     uint32_t           namelen;
652     Ipc_OsalPrms      *pOsalPrms = &gIpcObject.initPrms.osalPrms;
654     namelen = strlen(name);
655     if ((namelen >= SERVICENAMELEN || namelen == 0))
656     {
657         rtnVal = IPC_EFAIL;
658     }
660     if (NULL != pOsalPrms)
661     {
662         if ((NULL == pOsalPrms->createMutex ||
663              NULL == pOsalPrms->lockMutex) ||
664              (NULL == pOsalPrms->deleteMutex))
665         {
666             rtnVal = IPC_EFAIL;
667         }
668         if ((NULL == pOsalPrms->lockHIsrGate) ||
669             (NULL == pOsalPrms->unLockHIsrGate))
670         {
671             rtnVal = IPC_EFAIL;
672         }
673     }
675     if (IPC_SOK == rtnVal)
676     {
677         semHandle   = pOsalPrms->createMutex();
678         taskWaiter.semHandle = semHandle;
679         strncpy(taskWaiter.name, name, SERVICENAMELEN-1);
680         taskWaiter.name[SERVICENAMELEN-1] = '\0';
681         taskWaiter.procId = selfProcId;
682         taskWaiter.endPt  = 0;
684         /* The order of steps is critical here.  There must
685          * not be an unprotected time between calling
686          * RPMessage_lookupName() and the IpcUtils_Qput().
687          */
688         key = pOsalPrms->disableAllIntr();
689         lookupStatus = RPMessage_lookupName(selfProcId, name,
690                                             remoteProcId, remoteEndPt);
691         if(FALSE == lookupStatus)
692         {
693             IpcUtils_Qput(&module.waitingTasks, &taskWaiter.elem,
694                             (void *)&taskWaiter);
695         }
696         pOsalPrms->restoreAllIntr(key);
698         if(FALSE == lookupStatus)
699         {
700             rtnVal = pOsalPrms->lockMutex(semHandle, timeout);
701             if(rtnVal == IPC_SOK)
702             {
703                 /* The endPt and procId in taskWaiter is assigned
704                  * by RPMessage_processAnnounceMsg() when it
705                  * wakes up this task.
706                  */
707                 *remoteEndPt = taskWaiter.endPt;
708                 *remoteProcId = taskWaiter.procId;
709             }
710             key = pOsalPrms->lockHIsrGate(module.gateSwi);
711             IpcUtils_Qremove((IpcUtils_QElem*)&taskWaiter.elem);
712             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
713         }
715         pOsalPrms->deleteMutex(semHandle);
716     }
718     return rtnVal;
721 #ifndef IPC_EXCLUDE_CTRL_TASKS
723 /**
724  *  \brief RPMessage_checkForMessages : This function checks for
725  *         messages in all virtio that are associated with a endpoint
726  *         pool.  This operation has the side effect that it may find
727  *         messages for end points that do not yet have an endpoint
728  *         created for them.  Those messages will be dropped.
729  */
730 static void RPMessage_checkForMessages(RPMessage_EndptPool *pool)
732     uint32_t   c;
733     int32_t   key;
735     for(c = 0; c < module.numCallbacks; c++)
736     {
737         /* Find callback for RX VQs that have matching pool. */
738         if(module.VQ_callbacks[c].pool == pool)
739         {
740             if(TRUE == Virtio_isReady(module.VQ_callbacks[c].vq))
741             {
742                 key = gIpcObject.initPrms.osalPrms.lockHIsrGate(module.gateSwi);
743                 RPMessage_swiFxn((uintptr_t)&module.VQ_callbacks[c], 0);
744                 gIpcObject.initPrms.osalPrms.unLockHIsrGate(module.gateSwi, key);
745             }
746         }
747     }
749 #endif /* IPC_EXCLUDE_CTRL_TASKS */
751 #ifndef IPC_EXCLUDE_CTRL_TASKS
753 /**
754  *  \brief RPMessage_ctrlMsgTask : Create an endpoint to receive
755  *         control messages and dispatch any control messages
756  *         received.
757  *         This function runs in its own task.
758  */
759 static void RPMessage_ctrlMsgTask(uint32_t* arg0, uint32_t* arg1)
761     RPMessage_Object *obj = (RPMessage_Object *)arg0;
762     uint32_t      remoteEndpoint;
763     uint32_t      remoteProcId;
764     int32_t       status;
765     uint16_t      len = MSGBUFFERSIZE;
766     uint32_t      buffer[MSGBUFFERSIZE/sizeof(uint32_t)]; /* alignment */
767     RPMessage_Announcement *amsg = (RPMessage_Announcement*)&buffer;
769     UNUSED(arg1);
771     while(1)
772     {
773         status = RPMessage_recv((RPMessage_Handle)obj, (void*)amsg, &len,
774                                       &remoteEndpoint, &remoteProcId,
775                                       IPC_RPMESSAGE_TIMEOUT_FOREVER);
776         if(status != IPC_SOK)
777         {
778             SystemP_printf("RPMessage_recv failed with code %d for endPt %d\n"
779                        "RPMessage_ctrlMsgTask terminating early",
780                        status, obj->endPt);
781             break;
782         }
784         if(amsg->ctrl.type == CNTRLMSG_ANNOUNCE)
785         {
786 #if DEBUG_PRINT
787             SystemP_printf("RPMessage_ctrlMsgTask ...CNTRLMSG_ANNOUNCE\n");
788 #endif
789             RPMessage_processAnnounceMsg((RPMessage_Announcement*)amsg,
790                                          remoteProcId);
791         }
792         else
793         {
794             SystemP_printf("Invalid cntrl msg type 0x%x from procId %d\n",
795                        amsg->ctrl.type, remoteProcId);
796         }
797     }
800 /**
801  * \brief Kick off the control message task.
802  * Typically this is called from Main context.
803  * It is best to call this before setting the
804  * VQ callbacks to avoid dropping cntrl messages.
805  */
806 static int32_t RPMessage_startCtrlMsgTask(RPMessage_Params *params)
808     TaskP_Params       tparams;
809     RPMessage_Object  *obj;
810     uint32_t           myEndpoint = 0;
811     int32_t            retVal     = IPC_SOK;
812     TaskP_Handle       tskHandle  = NULL;
814     /* Create the endpoint to receive control messages.
815      * This is done as early as possible to avoid missing
816      * any control messages.
817      */
818     params->requestedEndpt = IPC_CTRL_ENDPOINT_ID;
819     obj = RPMessage_rawCreate(params, &module.globalPool, &myEndpoint);
820     if(NULL != obj)
821     {
822         TaskP_Params_init(&tparams);
823         tparams.priority  = 10;
824         tparams.arg0      = (uint32_t*)obj;
825         tparams.stacksize = params->stackSize;
826         tparams.stack     = params->stackBuffer;
827         tskHandle = TaskP_create((void *) RPMessage_ctrlMsgTask, &tparams);
828         if(tskHandle == NULL)
829         {
830             retVal = IPC_EFAIL;
831         }
832     }
833     else
834     {
835         SystemP_printf("Failed to create control endpoint.\n");
836         retVal = IPC_EFAIL;
837     }
839     return retVal;
842 #endif /* IPC_EXCLUDE_CTRL_TASKS */
844 static RPMessage_Object* RPMessage_rawCreate(
845         RPMessage_Params *params,
846         RPMessage_EndptPool* pool,
847         uint32_t *endPt)
849     RPMessage_Object *obj   = NULL;
850     uint8_t           found = FALSE;
851     int32_t           i;
852     uint16_t          queueIndex = 0;
853     int32_t           key;
854     uint32_t          objSize = RPMessage_getObjMemRequired();
855     Ipc_OsalPrms     *pOsalPrms = &gIpcObject.initPrms.osalPrms;
856     int32_t           status = IPC_SOK;
858     /* Returning NULL, here Fix ME TBD
859         This function error checks would require an overhaul */
860     if ( (NULL == pOsalPrms) ||
861          (NULL == pOsalPrms->lockHIsrGate) ||
862          (NULL == pOsalPrms->unLockHIsrGate))
863     {
864         status = IPC_EFAIL;
865     }
867     if(IPC_SOK == status)
868     {
869         key = pOsalPrms->lockHIsrGate(module.gateSwi);
871         /* Allocate the endPt */
872         if (params->requestedEndpt == RPMESSAGE_ANY)
873         {
874             /* Search the array for a free slot above reserved: */
875             for (i = RPMessage_MAX_RESERVED_ENDPOINT + 1;
876                     (i < MAXENDPOINTS) && (found == 0U); i++)
877             {
878                 if (RPMessage_lookupEndpt(pool, i) == NULL)
879                 {
880                     queueIndex = i;
881                     found = TRUE;
882                     break;
883                 }
884             }
885         }
886         else if (params->requestedEndpt <= RPMessage_MAX_RESERVED_ENDPOINT)
887         {
888             if (RPMessage_lookupEndpt(pool, params->requestedEndpt) == NULL)
889             {
890                 queueIndex = params->requestedEndpt;
891                 found = TRUE;
892             }
893         }
894     }
896     if ((FALSE == found) || 
897         (params->numBufs < 1) ||
898         (params->bufSize < ((params->numBufs * MSGBUFFERSIZE) + objSize)))
899     {
900         status = IPC_EFAIL;
901     }
903     if(IPC_SOK == status)
904     {
905         obj = (RPMessage_Object *) params->buf;
906         if (NULL != obj)
907         {
908             obj->heapParams.blockSize    = MSGBUFFERSIZE;
909             obj->heapParams.numBlocks    = params->numBufs;
910             obj->heapParams.buf          = (void*)((uintptr_t)params->buf + objSize);
911             obj->heapParams.bufSize      = params->bufSize - objSize ;
912             obj->heapParams.align        = HEAPALIGNMENT;
913             status = IpcUtils_HeapCreate(&obj->heap, &obj->heapParams);
914             if (IPC_SOK == status)
915             {
916                 /* Allocate a semaphore to signal when messages received: */
917                 if (NULL != pOsalPrms->createMutex)
918                 {
919                     obj->semHandle = pOsalPrms->createMutex();
920                 }
922                 /* Create our queue of to be received messages: */
923                 IpcUtils_Qcreate(&obj->queue);
925                 /* Store our endPt, and object: */
926                 obj->endPt = queueIndex;
927                 RPMessage_assignEndpt(pool, queueIndex, obj);
929                 /* See RPMessage_unblock() */
930                 obj->unblocked   = FALSE;
931                 obj->pool        = pool;
932                 obj->recv_buffer = NULL;
933                 *endPt           = queueIndex;
934             }
935             else
936             {
937                 obj = NULL;
938             }
940             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
941         }
942     }
944     return (obj);
947 int32_t RPMessage_lateInit(uint32_t proc)
949     uint32_t         c;
950     uint32_t         tx_vqId, rx_vqId;
951     int32_t          retVal = IPC_SOK;
952     Ipc_OsalPrms     *pOsalPrms = &gIpcObject.initPrms.osalPrms;
954     if(TRUE == VirtioIPC_getVirtQueues(VIRTIOIPC_RPMSG, proc, 0, &tx_vqId, &rx_vqId))
955     {
956         uintptr_t arg0;
957         c = module.numCallbacks;
958         module.numCallbacks++;
960         /* setup the receiving path */
961         module.VQ_callbacks[c].pool = &module.globalPool;
962         module.VQ_callbacks[c].vq = Virtio_getHandle(proc, VIRTIO_RX);
964         arg0 = (uintptr_t)&module.VQ_callbacks[c];
965         if (TRUE == Virtio_isRemoteLinux(proc))
966         {
967             pOsalPrms->createHIsr(&module.VQ_callbacks[c].swi,
968                     &RPMessage_swiLinuxFxn, (void *)arg0);
969         }
970         else
971         {
972             pOsalPrms->createHIsr(&module.VQ_callbacks[c].swi,
973                     &RPMessage_swiFxn, (void *)arg0);
974         }
975         Virtio_setCallback(proc, virtio_callback, (uint32_t *)&module.VQ_callbacks[c]);
977         /* setup the sending path */
978         module.tx_VQs[proc] = Virtio_getHandle(proc, VIRTIO_TX);
979     }
980     else
981     {
982         retVal = IPC_EFAIL;
983     }
985 #ifndef IPC_EXCLUDE_CTRL_TASKS
986     if(retVal == IPC_SOK)
987         RPMessage_checkForMessages(&module.globalPool);
988 #endif /* IPC_EXCLUDE_CTRL_TASKS */
990     return retVal;
993 /**
994  *  \brief RPMessage_init : Initializing the framework
995  */
996 int32_t RPMessage_init(RPMessage_Params *params)
998     uint32_t         p;
999     uint32_t         c;
1000     uint32_t         tx_vqId, rx_vqId;
1001     int32_t          retVal = IPC_SOK;
1002     Ipc_OsalPrms     *pOsalPrms = &gIpcObject.initPrms.osalPrms;
1004     /* Clear module state */
1005     memset(&module, 0, sizeof(module));
1007     /* Gate to protect module object and lists: */
1008     if ((1U == is_aligned(params->buf,HEAPALIGNMENT)) &&
1009         (NULL != pOsalPrms->createHIsrGate) &&
1010         (NULL != pOsalPrms->createHIsr))
1011     {
1012         module.gateSwi = pOsalPrms->createHIsrGate();
1013     }
1014     else
1015     {
1016         retVal = IPC_EFAIL;
1017         SystemP_printf("RPMessage_init : Memory misalignment  or invalid HIstGate fxn\n");
1018     }
1020     if( retVal != IPC_EFAIL)
1021     {
1022         IpcUtils_Qcreate(&module.announcedEndpts);
1023         IpcUtils_Qcreate(&module.waitingTasks);
1025 #ifndef IPC_EXCLUDE_CTRL_TASKS
1026         /* Call startCtrlMsgTask() before setting the VQ
1027          * callbacks to avoid dropping control messages.
1028          */
1029         retVal = RPMessage_startCtrlMsgTask(params);
1030 #endif /* IPC_EXCLUDE_CTRL_TASKS */
1032         /* Connect to the VQs by setting the VQ callbacks and
1033          * creating the assocated SWIs.  Once the callbacks
1034          * are installed is it possilbe to drop messages if
1035          * the dest endpoint has not yet been created.
1036          */
1037         for(p = 0; ((p < IPC_MAX_PROCS) && (IPC_SOK == retVal)); p++)
1038         {
1039             if(TRUE == VirtioIPC_getVirtQueues(VIRTIOIPC_RPMSG, p, 0, &tx_vqId, &rx_vqId))
1040             {
1041                 uintptr_t arg0;
1042                 c = module.numCallbacks;
1043                 module.numCallbacks++;
1045                 /* setup the receiving path */
1046                 module.VQ_callbacks[c].pool = &module.globalPool;
1047                 module.VQ_callbacks[c].vq = Virtio_getHandle(p, VIRTIO_RX);
1049                 arg0 = (uintptr_t)&module.VQ_callbacks[c];
1050                 if (TRUE == Virtio_isRemoteLinux(p))
1051                 {
1052                     pOsalPrms->createHIsr(&module.VQ_callbacks[c].swi,
1053                             &RPMessage_swiLinuxFxn, (void *)arg0);
1054                 }
1055                 else
1056                 {
1057                     pOsalPrms->createHIsr(&module.VQ_callbacks[c].swi,
1058                             &RPMessage_swiFxn, (void *)arg0);
1059                 }
1060                 Virtio_setCallback(p, virtio_callback, (uint32_t *)&module.VQ_callbacks[c]);
1062                 /* setup the sending path */
1063                 module.tx_VQs[p] = Virtio_getHandle(p, VIRTIO_TX);
1064             }
1065             else
1066             {
1067                 module.tx_VQs[p] = NULL;
1068             }
1069         }
1071 #ifndef IPC_EXCLUDE_CTRL_TASKS
1072         /*
1073          * At this point, the control end point would not have been created.
1074          *  Let apps, decide when to process pending messages
1075          */
1076         RPMessage_checkForMessages(&module.globalPool);
1078 #endif /* IPC_EXCLUDE_CTRL_TASKS */
1079     }
1081     return retVal;
1085 /*
1086  *  ======== RPMessage_create ========
1087  */
1088 RPMessage_Handle RPMessage_create(RPMessage_Params *params, uint32_t *endPt)
1090     RPMessage_Object *obj = NULL;
1091     RPMessage_Params defaultParams;
1093     if(params == NULL)
1094     {
1095         params = &defaultParams;
1096         RPMessageParams_init(params);
1097     }
1099     if( 0U == is_aligned(params->buf,HEAPALIGNMENT))
1100     {
1101         SystemP_printf("RPMessage_create : Memory alignment failed\n");
1102     }
1103     else
1104     {
1105         obj = RPMessage_rawCreate(params, &module.globalPool, endPt);
1106     }
1108     return (RPMessage_Handle)obj;
1111 /**
1112  *  \brief RPMessage_deinit : Tear down the module
1113  */
1114 void RPMessage_deInit(void)
1116     uint32_t c;
1118     for(c = 0; c < module.numCallbacks; c++)
1119     {
1120         gIpcObject.initPrms.osalPrms.deleteHIsr(&(module.VQ_callbacks[c].swi));
1121     }
1123     if (NULL != gIpcObject.initPrms.osalPrms.deleteHIsrGate)
1124     {
1125         gIpcObject.initPrms.osalPrms.deleteHIsrGate(&module.gateSwi);
1126     }
1129 /*
1130  *  ======== RPMessage_delete ========
1131  */
1132 int32_t RPMessage_delete(RPMessage_Handle *handlePtr)
1134     int32_t                    status = IPC_EFAIL;
1135     RPMessage_Object          *obj;
1136     RPMessage_MsgElem         *payload;
1137     int32_t                    key;
1138     Ipc_OsalPrms              *pOsalPrms = &gIpcObject.initPrms.osalPrms;
1140     if (NULL != pOsalPrms)
1141     {
1142         if ((NULL != pOsalPrms->lockHIsrGate) &&
1143              (NULL != pOsalPrms->unLockHIsrGate))
1144         {
1145             status = IPC_SOK;
1146         }
1147     }
1148     if ((handlePtr && (obj = (RPMessage_Object *)(*handlePtr))) &&
1149         (IPC_SOK == status))
1150     {
1151        /* Null out our slot in the endpoint pool. */
1152        key = pOsalPrms->lockHIsrGate(module.gateSwi);
1153        RPMessage_assignEndpt(obj->pool, obj->endPt, NULL);
1154        obj->pool = NULL;
1155        pOsalPrms->unLockHIsrGate(module.gateSwi, key);
1157        if (NULL != pOsalPrms->deleteMutex)
1158        {
1159             pOsalPrms->deleteMutex(obj->semHandle);
1160        }
1162        key = gIpcObject.initPrms.osalPrms.disableAllIntr();
1164        /* Free/discard all queued message buffers: */
1165        while (0U == IpcUtils_QisEmpty(&obj->queue))
1166        {
1167             payload = (RPMessage_MsgElem *)IpcUtils_QgetHead(&obj->queue);
1168             if(NULL != payload)
1169             {
1170                 IpcUtils_HeapFree(&obj->heap, (void *)payload, MSGBUFFERSIZE);
1171             }
1172        }
1174        gIpcObject.initPrms.osalPrms.restoreAllIntr(key);
1176        IpcUtils_HeapDelete(&obj->heap);
1178        IpcUtils_Qdelete(&(obj->queue));
1180        *handlePtr = NULL;
1181     }
1183     return(status);
1186 /*
1187  *  ======== RPMessage_recv ========
1188  */
1189 int32_t RPMessage_recv(RPMessage_Handle handle, void* data, uint16_t *len,
1190                    uint32_t *rplyEndPt, uint32_t *rplyProcId, uint32_t timeout)
1192 #ifndef IPC_EXCLUDE_BLOCKING_RX
1193     int32_t             status = IPC_SOK;
1194     RPMessage_Object   *obj = (RPMessage_Object *)handle;
1195     int32_t             semStatus;
1196     uint8_t             skiplist = FALSE;
1197     RPMessage_MsgElem  *payload;
1198     uint32_t            key;
1199     /* Fix ME TBD, skipping the null tests, as this function check's/error
1200         handling would require an overhaul */
1201     Ipc_OsalPrms *pOsalPrms = &gIpcObject.initPrms.osalPrms;
1203     key = pOsalPrms->lockHIsrGate(module.gateSwi);
1204     if (TRUE == IpcUtils_QisEmpty(&obj->queue))
1205     {
1206         obj->recv_buffer = data;
1207         skiplist = TRUE;
1208     }
1209     pOsalPrms->unLockHIsrGate(module.gateSwi, key);
1211     /*  Block until notified. */
1212     semStatus = IPC_SOK;
1213     semStatus = pOsalPrms->lockMutex(obj->semHandle, timeout);
1215     if (semStatus == IPC_ETIMEOUT)
1216     {
1217         status = IPC_ETIMEOUT;
1218     }
1219     else if (TRUE == obj->unblocked)
1220     {
1221         status = IPC_E_UNBLOCKED;
1222     }
1223     else if(TRUE == skiplist)
1224     {
1225         *len = obj->payload.len;
1226         *rplyEndPt = obj->payload.src;
1227         *rplyProcId = obj->payload.procId;
1228     }
1229     else
1230     {
1231         key = gIpcObject.initPrms.osalPrms.disableAllIntr();
1233         payload = (RPMessage_MsgElem *)IpcUtils_QgetHead(&obj->queue);
1234         if ( (NULL == payload) ||
1235              (payload == (RPMessage_MsgElem *)&obj->queue))
1236         {
1237             status = IPC_EFAIL;
1238         }
1240         if(status != IPC_EFAIL)
1241         {
1242             /* Now, copy payload to client and free our internal msg */
1243             memcpy(data, payload->data, payload->len);
1244             *len        = payload->len;
1245             *rplyEndPt  = payload->src;
1246             *rplyProcId = payload->procId;
1247             IpcUtils_HeapFree(&obj->heap, (void *)payload,
1248                     (payload->len + sizeof(RPMessage_MsgElem)));
1249             gIpcObject.initPrms.osalPrms.restoreAllIntr(key);
1250         }
1251     }
1253     return (status);
1254 #else
1256     return (IPC_EUNSUPPORTED);
1258 #endif /* IPC_EXCLUDE_BLOCKING_RX */
1261 /*
1262  *  ======== RPMessage_recvNb ========
1263  */
1264 int32_t RPMessage_recvNb(RPMessage_Handle handle, void* data, uint16_t *len,
1265                    uint32_t *rplyEndPt, uint32_t *rplyProcId)
1267     RPMessage_Object    *obj;
1268     RPMessage_MsgElem   *payload;
1269     uint32_t            key;
1270     int32_t             status = IPC_EBADARGS;
1272     if (((NULL != data) && (NULL != len)) &&
1273         ((NULL != rplyEndPt) && (NULL != rplyProcId)))
1274     {
1275         obj = (RPMessage_Object *)handle;
1276         status = IPC_ETIMEOUT;
1277         if (FALSE == IpcUtils_QisEmpty(&obj->queue))
1278         {
1279             key = gIpcObject.initPrms.osalPrms.disableAllIntr();
1281             payload = (RPMessage_MsgElem *)IpcUtils_QgetHead(&obj->queue);
1282             if (payload != (RPMessage_MsgElem *)&obj->queue)
1283             {
1284                 /* Now, copy payload to client and free our internal msg */
1285                 memcpy(data, payload->data, payload->len);
1286                 *len = payload->len;
1287                 *rplyEndPt = payload->src;
1288                 *rplyProcId = payload->procId;
1290                 IpcUtils_HeapFree(&obj->heap, (void *)payload,
1291                     (payload->len + sizeof(RPMessage_MsgElem)));
1293                 status = IPC_SOK;
1294             }
1295             else
1296             {
1297                 /* No elements in the queue, but why? */
1298                 status = IPC_EFAIL;
1299             }
1300             gIpcObject.initPrms.osalPrms.restoreAllIntr(key);
1301         }
1302     }
1304     return (status);
1308 /*
1309  *  ======== RPMessage_rawSend ========
1310  */
1311 static int32_t RPMessage_rawSend(Virtio_Handle vq,
1312                       uint32_t dstEndPt,
1313                       uint32_t srcEndPt,
1314                       void*    data,
1315                       uint16_t len)
1317     int32_t               status = IPC_SOK;
1318     int32_t               token = 0;
1319     int32_t               key;
1320     int32_t               length = 0;
1321     uint32_t              bufSize;
1322     RPMessage_MsgHeader*  msg = NULL;
1323     Ipc_OsalPrms          *pOsalPrms = &gIpcObject.initPrms.osalPrms;
1325     bufSize = sizeof(RPMessage_MsgHeader) + len;
1327     if (NULL != pOsalPrms)
1328     {
1329         if ((NULL != pOsalPrms->lockHIsrGate) &&
1330             (NULL != pOsalPrms->unLockHIsrGate))
1331         {
1332             /* Send to remote processor: */
1333             key = pOsalPrms->lockHIsrGate(module.gateSwi);
1334             token = Virtio_getAvailBuf(vq, (void **)&msg, &length);
1335             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
1336         }
1337     }
1338     if(!msg)
1339     {
1340         SystemP_printf("RPMessage_rawSend ...NULL MsgHdr\n");
1341         status = IPC_EFAIL;
1342     }
1343     if(length < bufSize)
1344     {
1345         SystemP_printf("RPMessage_rawSend ...length %d, reqrd %d\n", length, bufSize);
1346         status = IPC_EFAIL;
1347     }
1348     if(status != IPC_EFAIL)
1349     {
1350         if (token >= 0)
1351         {
1352             /* Copy the payload and set message header: */
1353             memcpy(msg->payload, data, len);
1354             msg->dataLen = len;
1355             msg->dstAddr = dstEndPt;
1356             msg->srcAddr = srcEndPt;
1357             msg->flags = 0;
1358             msg->srcProcId = Ipc_mpGetSelfId();
1360             key = pOsalPrms->lockHIsrGate(module.gateSwi);
1361             Virtio_addUsedBuf(vq, token, bufSize);
1362             Virtio_kick(vq);
1363             pOsalPrms->unLockHIsrGate(module.gateSwi, key);
1364         }
1365         else
1366         {
1367             SystemP_printf("RPMessage_rawSend ...Invalid token %d\n", token);
1368             status = IPC_EFAIL;
1369         }
1370     }
1372     return (status);
1375 /*
1376  *  ======== RPMessage_send ========
1377  */
1378 int32_t RPMessage_send(RPMessage_Handle handle, uint32_t procId, uint32_t dstEndPt,
1379      uint32_t srcEndPt, void* data, uint16_t len)
1381     Virtio_Handle       vq;
1382     uint32_t            endPt;
1383     int32_t             status = IPC_SOK;
1385     if(procId >= IPC_MAX_PROCS)
1386     {
1387         status = IPC_EFAIL;
1388     }
1390     if(procId == Ipc_mpGetSelfId())
1391     {
1392         status = IPC_EFAIL;
1393     }
1395     if(status != IPC_EFAIL)
1396     {
1397         vq = module.tx_VQs[procId];
1398         if(NULL == vq)
1399         {
1400             SystemP_printf("RPMessage_send ...NULL vq\n");
1401             status = IPC_EFAIL;
1402         }
1403         else
1404         {
1405             endPt = (handle == NULL) ? srcEndPt : handle->endPt;
1406             status = RPMessage_rawSend(vq, dstEndPt, endPt, data, len);
1407         }
1408     }
1410     return status;
1414 /*
1415  *  ======== RPMessage_unblock ========
1416  */
1417 void RPMessage_unblock(RPMessage_Handle handle)
1419     RPMessage_Object *obj = (RPMessage_Object *)handle;
1421     /* Set instance to 'unblocked' state, and post */
1422     obj->unblocked = TRUE;
1424     if (NULL != gIpcObject.initPrms.osalPrms.unlockMutex)
1425     {
1426         gIpcObject.initPrms.osalPrms.unlockMutex(obj->semHandle);
1427     }
1430 #ifndef IPC_EXCLUDE_INIT_PARAMS_INIT
1431 void IpcInitPrms_init(uint32_t instId, Ipc_InitPrms *initPrms)
1433     if(NULL != initPrms)
1434     {
1435         memset(initPrms, 0, sizeof(*initPrms));
1436         initPrms->instId                = instId;
1438         initPrms->virtToPhyFxn          = NULL;
1439         initPrms->phyToVirtFxn          = NULL;
1441         IpcOsalPrms_init(&initPrms->osalPrms);
1442     }
1444     return;
1446 #endif /* IPC_EXCLUDE_INIT_PARAMS_INIT */
1448 Ipc_Object *getIpcObjInst(uint32_t instId)
1450     return &gIpcObject;
1453 int32_t Ipc_init(Ipc_InitPrms *cfg)
1455     int32_t retVal = IPC_EINVALID_PARAMS;
1457     memset(&gIpcObject, 0, sizeof(gIpcObject));
1459 #ifndef IPC_EXCLUDE_INIT_PARAMS_INIT
1460     if (NULL == cfg)
1461     {
1462         IpcInitPrms_init(0U, &gIpcObject.initPrms);
1464         Ipc_mailboxModuleStartup();
1466         retVal = IPC_SOK;
1467     }
1468     else
1469 #endif /* IPC_EXCLUDE_INIT_PARAMS_INIT */
1470     {
1471         if (0U == cfg->instId)
1472         {
1473             if ((NULL == cfg->osalPrms.disableAllIntr) ||
1474                 (NULL == cfg->osalPrms.restoreAllIntr))
1475             {
1476                 retVal = IPC_EINVALID_PARAMS;
1477             }
1478             else
1479             {
1480                 memcpy(&gIpcObject.initPrms, cfg, sizeof(gIpcObject.initPrms));
1481                 retVal = IPC_SOK;
1482             }
1483         }
1484     }
1485     if (IPC_SOK == retVal)
1486     {
1487         IpcUtils_Init(&gIpcObject.initPrms.osalPrms);
1488     }
1489     gIpcObject.instId = 0U;
1491     return (retVal);
1494 int32_t Ipc_deinit(void)
1496     int32_t  retVal = IPC_SOK;
1498     return (retVal);
1501 void Ipc_newMessageIsr(uint32_t srcProcId)
1503 #ifdef IPC_EXCLUDE_INTERRUPT_REG
1504     Ipc_mailboxIsr(srcProcId);
1505 #endif /* IPC_EXCLUDE_INTERRUPT_REG */
1507     return;