Add initial support to start/stop cores after launching QNX IPC resource manager
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / MessageQCopy.c
1 /*
2  *  Copyright (c) 2011-2014, Texas Instruments Incorporated
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *
8  *  *  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  *
11  *  *  Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *
15  *  *  Neither the name of Texas Instruments Incorporated nor the names of
16  *     its contributors may be used to endorse or promote products derived
17  *     from this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21  *  THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22  *  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23  *  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24  *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25  *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
26  *  OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *  WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28  *  OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29  *  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
33 /* Standard headers */
34 #include <ti/syslink/Std.h>
36 /* Osal & utils headers */
37 #include <ti/syslink/utils/Trace.h>
38 #include <ti/syslink/utils/String.h>
39 #include <ti/syslink/utils/Gate.h>
40 #include <ti/syslink/utils/IGateProvider.h>
41 #include <ti/syslink/utils/GateSpinlock.h>
42 #include <ti/syslink/utils/Memory.h>
43 #include <ti/syslink/utils/List.h>
44 #include <ti/syslink/inc/Bitops.h>
45 #include <ti/ipc/MultiProc.h>
46 #include <OsalSemaphore.h>
47 #include <atomic_qnx.h>
49 /* Module headers */
50 #include <ti/syslink/ProcMgr.h>
51 #include <ti/ipc/MessageQCopy.h>
52 #include <_MessageQCopyDefs.h>
53 #include <_MessageQCopy.h>
54 #include <VirtQueue.h>
55 //#include "virtio_ring.h"
56 #include <rpmsg.h>
58 #if defined (__cplusplus)
59 extern "C" {
60 #endif /* defined (__cplusplus) */
63 /* =============================================================================
64  *  Macros, types, and constants
65  *  For additional, see _MessageQCopyDefs.h
66  * =============================================================================
67  */
68 /*!
69  *  @brief Macro to make a correct module magic number with refCount
70  */
71 #define MessageQCopy_MAKE_MAGICSTAMP(x) ((MessageQCopy_MODULEID << 12u) | (x))
73 /*!
74  *  @brief   Defines the Notify instance object.
75  */
76 typedef struct MessageQCopyTransport_Object_tag {
77     UInt16                  procId;
78     /*!< Remote MultiProc id        */
79     ProcMgr_Handle          procHandle;
80     /*!< Remote Proc handle         */
81     UInt32                  vqAddr;
82     /*!< Virtial address of VQ, needed for un-mapping */
83     UInt32                  vqPAddr;
84     /*!< Physical address of VQ, needed for un-mapping */
85     MessageQCopy_Handle     mq [MessageQCopy_MAXMQS];
86     /*!< List of MessgeQCopy_Handles associated with this transport */
87     VirtQueue_Handle        vq [MessageQCopy_NUMVIRTQS];
88     /*!< VirtQueues associated with this transport */
89 } MessageQCopyTransport_Object;
91 /*!
92  *  @brief  Defines the type for the handle to the Notify driver.
93  */
94 typedef MessageQCopyTransport_Object * MessageQCopyTransport_Handle;
96 /*!
97  *  @brief   Defines the Notify state object, which contains all the module
98  *           specific information.
99  */
100 typedef struct MessageQCopy_ModuleObject_tag {
101     Atomic                          refCount;
102     /*!< Reference count */
103     MessageQCopy_Config             cfg;
104     /*!< Notify configuration structure */
105     MessageQCopy_Config             defCfg;
106     /*!< Default module configuration */
107     IGateProvider_Handle            gateHandle;
108     /*!< Handle of gate to be used for local thread safety */
109     Bool                            isSetup;
110     /*!< Indicates whether the MessageQCopy module is setup. */
111     MessageQCopyTransport_Handle    transport [MultiProc_MAXPROCESSORS];
112     /*!< Array of configured transports. */
113     MessageQCopy_Handle             mq [MessageQCopy_MAXMQS];
114     /*!< Array of endpoints that exist on this processor */
115 }MessageQCopy_ModuleObject;
117 /*!
118  *  @brief   Defines the MessageQCopy instance object.
119  */
120 typedef struct MessageQCopy_Object_tag {
121     UInt16              procId;
122     /*!< Remote MultiProc id */
123     UInt32              addr;
124     /*!< Address (endpoint) of this MessageQCopy instance */
125     Char                name [RPMSG_NAME_SIZE];
126     /*!< Name of this MessageQCopy instance (may not be set) */
127     Char                desc [RPMSG_NAME_SIZE];
128     /*!< Desc of this MessageQCopy instance (may not be set) */
129     Bool                announce;
130     /*!< Flag to indicate if creation/deletion of this instance should be
131          announced to the remote cores. */
132     Void (*cb)(MessageQCopy_Handle, Void *, Int, Void *, UInt32, UInt16);
133     /*!< Callback to invoke when a message is received for this addr.  */
134     Void              * priv;
135     /*!< Private data that is passed to the callback */
136     Void (*notifyCb)(MessageQCopy_Handle, UInt16, UInt32, Char *, Bool);
137     /*!< Optional callback that can be registered to request notification when
138          MQCopy objects of the same name are created */
139 } MessageQCopy_Object;
142 /* =============================================================================
143  *  Forward declarations of internal functions.
144  * =============================================================================
145  */
146 static
147  Void
148  _MessageQCopy_callback_NS (MessageQCopy_Handle handle, Void *data, Int len,
149                             Void *priv, UInt32 src, UInt16 srcProc);
151 static
152 Void
153 _MessageQCopy_callback_bufReady (VirtQueue_Handle vq, void *arg);
155 static
156 MessageQCopy_Handle
157 _MessageQCopy_create (MessageQCopyTransport_Handle handle, UInt32 reserved,
158                       String name, String desc,
159                       Void (*cb)(MessageQCopy_Handle,
160                                  Void *, Int, Void *, UInt32, UInt16),
161                       Void *priv, UInt32 * endpoint);
164 /* =============================================================================
165  *  Globals
166  * =============================================================================
167  */
168 /*!
169  *  @var    MessageQCopy_state
170  *
171  *  @brief  MessageQCopy state object variable
172  */
173 static
174 MessageQCopy_ModuleObject MessageQCopy_state =
176     .gateHandle = NULL,
177     .isSetup = FALSE,
178 };
180 /*!
181  *  @var    MessageQCopy_module
182  *
183  *  @brief  Pointer to the MessageQCopy module state.
184  */
185 static
186 MessageQCopy_ModuleObject * MessageQCopy_module = &MessageQCopy_state;
189 /* =============================================================================
190  *  APIs called by applications.
191  * =============================================================================
192  */
193 /*!
194  *  @brief      Setup the MessageQCopy module.
195  *
196  *              This function sets up the MessageQCopy module. This function
197  *              must be called before any other instance-level APIs can be
198  *              invoked.
199  *              Module-level configuration needs to be provided to this
200  *              function.
201  *              This function call the VirtQueue startup function for each
202  *              processor in the configuration and creates the transports
203  *              (VirtQueues) per each processor mentioned in the configuration.
204  *
205  *  @param      cfg   MessageQCopy module configuration.
206  *
207  *  @sa         MessageQCopy_destroy
208  *              GateSpinlock_create
209  *              VirtQueue_startup
210  *              VirtQueue_create
211  *              VirtQueue_addAvailBuf
212  *              VirtQueue_addUsedBufAddr
213  *              VirtQueue_kick
214  *              MessageQCopy_create
215  */
216 Int
217 MessageQCopy_setup (const MessageQCopy_Config * cfg)
219     Int                                 status      = MessageQCopy_S_SUCCESS;
220     UInt32                              endpoint    = 0;
221     Error_Block                         eb;
223     GT_0trace (curTrace, GT_ENTER, "MessageQCopy_setup");
225     GT_assert (curTrace, (cfg != NULL));
227     Error_init(&eb);
229     /* This sets the refCount variable if not initialized, upper 16 bits is
230      * written with module Id to ensure correctness of refCount variable.
231      */
232     Atomic_cmpmask_and_set (&MessageQCopy_module->refCount,
233                             MessageQCopy_MAKE_MAGICSTAMP(0),
234                             MessageQCopy_MAKE_MAGICSTAMP(0));
236     if (Atomic_inc_return (&MessageQCopy_module->refCount)
237                            != MessageQCopy_MAKE_MAGICSTAMP(1u)) {
238         status = MessageQCopy_S_ALREADYSETUP;
239         GT_0trace (curTrace,
240                    GT_2CLASS,
241                    "MessageQCopy module already initialized!");
242     }
243     else if (cfg == NULL) {
244         /*! @retval  MessageQCopy_E_INVALIDARG Invalid cfg argument
245                                          provided. */
246         status = MessageQCopy_E_INVALIDARG;
247         GT_setFailureReason (curTrace,
248                              GT_4CLASS,
249                              "MessageQCopy_setup",
250                              status,
251                              "Invalid cfg argument provided.");
252     }
253     else {
254         /* Create a default gate handle for local module protection. */
255         MessageQCopy_module->gateHandle = (IGateProvider_Handle)
256                         GateSpinlock_create ((GateSpinlock_Params *) NULL, &eb);
257 #if !defined(SYSLINK_BUILD_OPTIMIZE)
258         if (MessageQCopy_module->gateHandle == NULL) {
259             /*! @retval MessageQCopy_E_FAIL Failed to create GateSpinlock! */
260             status = MessageQCopy_E_FAIL;
261             GT_setFailureReason (curTrace,
262                                  GT_4CLASS,
263                                  "MessageQCopy_setup",
264                                  status,
265                                  "Failed to create GateSpinlock!");
266         }
267         else {
268 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
269             /* Initialize the driver mapping array. */
270             Memory_set (MessageQCopy_module->transport,
271                         0,
272                         (sizeof (MessageQCopyTransport_Handle)
273                          * MultiProc_MAXPROCESSORS));
275             /* Initialize all the local endpoints. */
276             Memory_set (&MessageQCopy_module->mq,
277                         0,
278                         (sizeof (MessageQCopy_Handle) * MessageQCopy_MAXMQS));
279 #if !defined(SYSLINK_BUILD_OPTIMIZE)
280         }
281 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
283         MessageQCopy_module->mq[MessageQCopy_NS_PORT] =
284                                      MessageQCopy_create (MessageQCopy_NS_PORT,
285                                                       NULL,
286                                                       _MessageQCopy_callback_NS,
287                                                       NULL,
288                                                       &endpoint);
289         if (MessageQCopy_module->mq[MessageQCopy_NS_PORT] == NULL) {
290             /*! @retval MessageQCopy_E_MEMORY Failed to create virtqueue! */
291             status = MessageQCopy_E_MEMORY;
292             GT_setFailureReason (curTrace,
293                                  GT_4CLASS,
294                                  "MessageQCopy_setup",
295                                  status,
296                                  "Failed to create name service MessageQ!");
297         }
298         else {
299             Memory_copy (&MessageQCopy_module->cfg, (Ptr)cfg,
300                          sizeof (MessageQCopy_Config));
301         }
303         if (status < 0) {
304             MessageQCopy_destroy();
305         }
306 #if !defined(SYSLINK_BUILD_OPTIMIZE)
307     }
308 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
310     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_setup", status);
312     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
313     return (status);
317 /*!
318  *  @brief      Destroy the MessageQCopy module.
319  *
320  *              Once this function is called, other MessageQCopy module APIs
321  *              cannot be called anymore.
322  *
323  *  @sa         MessageQCopy_setup
324  *              GateSpinlock_delete
325  *              MessageQCopy_delete
326  */
327 Int
328 MessageQCopy_destroy (Void)
330     Int                                 status      = MessageQCopy_S_SUCCESS;
331     Int16                               i           = 0;
333     GT_0trace (curTrace, GT_ENTER, "MessageQCopy_destroy");
335 #if !defined(SYSLINK_BUILD_OPTIMIZE)
336     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
337                                MessageQCopy_MAKE_MAGICSTAMP(0),
338                                MessageQCopy_MAKE_MAGICSTAMP(1))
339         == TRUE) {
340         /*! @retval Notify_E_INVALIDSTATE Module was not initialized */
341         status = MessageQCopy_E_INVALIDSTATE;
342         GT_setFailureReason (curTrace,
343                              GT_4CLASS,
344                              "MessageQCopy_destroy",
345                              status,
346                              "Module was not initialized!");
347     }
348     else {
349 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
350         if (Atomic_dec_return (&MessageQCopy_module->refCount)
351             == MessageQCopy_MAKE_MAGICSTAMP(0)) {
352             /* Temporarily increment refCount here. */
353             Atomic_set (&MessageQCopy_module->refCount,
354                         MessageQCopy_MAKE_MAGICSTAMP(1));
356             if (MessageQCopy_module->mq[MessageQCopy_NS_PORT] != NULL) {
357                 MessageQCopy_delete (
358                                &MessageQCopy_module->mq[MessageQCopy_NS_PORT]);
359                 MessageQCopy_module->mq[MessageQCopy_NS_PORT] = NULL;
360             }
362             /* Check if any MessageQ instances have not been deleted so far.
363              * If not, assert.
364              */
365             for (i = 0 ; i < MessageQCopy_MAXMQS; i++) {
366                 GT_assert (curTrace,
367                            (MessageQCopy_module->mq [i] == NULL));
368                 if (MessageQCopy_module->mq [i] != NULL) {
369                     MessageQCopy_delete(&MessageQCopy_module->mq [i]);
370                     MessageQCopy_module->mq [i] = NULL;
371                 }
372             }
374             /* Decrease the refCount */
375             Atomic_set (&MessageQCopy_module->refCount,
376                         MessageQCopy_MAKE_MAGICSTAMP(0));
378             if (MessageQCopy_module->gateHandle != NULL) {
379                 GateSpinlock_delete ((GateSpinlock_Handle *)
380                                      &(MessageQCopy_module->gateHandle));
381             }
382         }
383 #if !defined(SYSLINK_BUILD_OPTIMIZE)
384     }
385 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
387     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_destroy", status);
389     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
390     return (status);
393 /* Calls the SetupProxy to setup the MessageQ transports. */
394 Int
395 MessageQCopy_attach (UInt16 remoteProcId, Ptr sharedAddr, UInt16 startId)
397     Int                                 status      = MessageQCopy_S_SUCCESS;
398     MessageQCopyTransport_Object *      obj         = NULL;
399     UInt                                i           = 0;
400     Void *                              buf         = NULL;
401     Int32                               vqVAddr     = 0;
402     Int32                               vqPAddr     = 0;
403     UInt32                              recvBufsAddr;
404     UInt32                              sendBufsAddr;
405     ProcMgr_AddrInfo                    addrInfo;
407     GT_2trace (curTrace, GT_ENTER, "MessageQCopy_attach", remoteProcId,
408                sharedAddr);
410     if (EXPECT_TRUE (MultiProc_getNumProcessors () > 1)) {
411 #if !defined(SYSLINK_BUILD_OPTIMIZE)
412         if (remoteProcId >= MultiProc_getNumProcessors()) {
413             /*! @retval MessageQCopy_E_INVALIDPROCID ProcId is invalid! */
414             status = MessageQCopy_E_INVALIDPROCID;
415             GT_setFailureReason (curTrace,
416                                  GT_4CLASS,
417                                  "MessageQCopy_attach",
418                                  status,
419                                  "ProcId is invalid!");
420         }
421         else if (MessageQCopy_module->transport[remoteProcId]) {
422             /*! @retval MessageQCopy_E_ALREADYEXISTS Transport already
423                                         exists! */
424             status = MessageQCopy_E_ALREADYEXISTS;
425             GT_setFailureReason (curTrace,
426                                  GT_4CLASS,
427                                  "MessageQCopy_attach",
428                                  status,
429                                  "Transport is already attached!");
430         }
431         else {
432 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
434             /* Allocate memory for the MessageQCopyTransport object. */
435             obj = Memory_calloc (NULL,
436                                  sizeof (MessageQCopyTransport_Object), 0u,
437                                  NULL);
438 #if !defined(SYSLINK_BUILD_OPTIMIZE)
439             if (obj == NULL) {
440                 /*! @retval MessageQCopy_E_MEMORY Failed to allocate memory
441                                         for MessageQCopyTransport_Object! */
442                 status = MessageQCopy_E_MEMORY;
443                 GT_setFailureReason (curTrace,
444                                      GT_4CLASS,
445                                      "MessageQCopy_attach",
446                                      status,
447                                      "Failed to allocate memory for "
448                                      "MessageQCopyTransport_Object!");
449             }
450             else {
451 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
452                 obj->procId = remoteProcId;
454                 status = ProcMgr_open(&obj->procHandle, obj->procId);
455 #if !defined(SYSLINK_BUILD_OPTIMIZE)
456                 if (status < 0) {
457                         Memory_free(NULL, obj,
458                                     sizeof (MessageQCopyTransport_Object));
459                         /*! @retval MessageQCopy_E_MEMORY Unable to open Proc
460                                                           handle for specified
461                                                           remoteProcId! */
462                         status = MessageQCopy_E_RESOURCE;
463                         GT_setFailureReason (curTrace,
464                                              GT_4CLASS,
465                                              "MessageQCopy_attach",
466                                              status,
467                                              "Unable to open Proc handle for "
468                                              "specified remoteProcId!");
469                 }
470                 else {
471 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
472                     status = ProcMgr_translateAddr(obj->procHandle,
473                                                    (Ptr *)&vqPAddr,
474                                                    ProcMgr_AddrType_MasterPhys,
475                                                    sharedAddr,
476                                                    ProcMgr_AddrType_SlaveVirt);
477                     if (status < 0) {
478                         ProcMgr_close(&obj->procHandle);
479                         Memory_free(NULL, obj,
480                                     sizeof (MessageQCopyTransport_Object));
481                         /*! @retval MessageQCopy_E_MEMORY Unable translate
482                                                           addr! */
483                         status = MessageQCopy_E_MEMORY;
484                         GT_setFailureReason (curTrace,
485                                              GT_4CLASS,
486                                              "MessageQCopy_attach",
487                                              status,
488                                              "Unable to translate addr!");
489                     }
490                     else {
491                         obj->vqPAddr = vqPAddr;
492                         addrInfo.addr[ProcMgr_AddrType_MasterPhys] = vqPAddr;
493                         addrInfo.size = (MessageQCopy_NUMVIRTQS *\
494                                          ROUND_UP(MessageQCopy_RINGSIZE,
495                                                   0x4000)) +
496                                          (MessageQCopy_NUMBUFS * \
497                                               MessageQCopy_BUFSIZE * 2);
498                         addrInfo.isCached = FALSE;
499                         addrInfo.isMapped = TRUE;
500                         status = ProcMgr_map(obj->procHandle,
501                                              ProcMgr_MASTERKNLVIRT, &addrInfo,
502                                              ProcMgr_AddrType_MasterPhys);
503                         if (status < 0) {
504                             ProcMgr_close(&obj->procHandle);
505                             Memory_free(NULL, obj,
506                                         sizeof (MessageQCopyTransport_Object));
507                             /*! @retval MessageQCopy_E_MEMORY Unable translate
508                                                               addr! */
509                             status = MessageQCopy_E_MEMORY;
510                             GT_setFailureReason (curTrace,
511                                                  GT_4CLASS,
512                                                  "MessageQCopy_attach",
513                                                  status,
514                                                  "Unable to translate addr!");
515                         }
516                         obj->vqAddr = vqVAddr =
517                                   addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt];
518                     }
520                     if (status >= 0) {
521                         /* Startup the VirtQueue module for this procId. */
522                         VirtQueue_startup(obj->procId,
523                                     MessageQCopy_module->cfg.intId[obj->procId],
524                                     vqPAddr);
526                         /*
527                          * The buffer area is divided into two parts, one
528                          * for receiving messages from the remote processor
529                          * and one for sending messages.  Here, we calculate
530                          * the address of the start of each buffer section.
531                          */
532                         recvBufsAddr = vqVAddr + (MessageQCopy_NUMVIRTQS *\
533                                        ROUND_UP(MessageQCopy_RINGSIZE, 0x4000));
534                         sendBufsAddr = recvBufsAddr +
535                                              (MessageQCopy_NUMBUFS * \
536                                               MessageQCopy_BUFSIZE);
538                         /* Create the virtqueues */
539                         for (i = 0; i < MessageQCopy_NUMVIRTQS; i++) {
540                             obj->vq[i] = VirtQueue_create (
541                                                 _MessageQCopy_callback_bufReady,
542                                                 obj->procId,
543                                                 startId + i,
544                                                 vqVAddr,
545                                                 vqPAddr,
546                                                 MessageQCopy_NUMBUFS,
547                                                 MessageQCopy_VRINGALIGN,
548                                                 (void *)obj);
550 #if !defined(SYSLINK_BUILD_OPTIMIZE)
551                             if (obj->vq[i] == NULL) {
552                                 for (; i >= 0; --i) {
553                                     VirtQueue_delete (&obj->vq[i]);
554                                 }
555                                 VirtQueue_destroy(obj->procId);
556                                 addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt] = obj->vqAddr;
557                                 ProcMgr_unmap(obj->procHandle,
558                                               ProcMgr_MASTERKNLVIRT, &addrInfo,
559                                               ProcMgr_AddrType_MasterPhys);
560                                 ProcMgr_close(&obj->procHandle);
561                                 Memory_free(NULL, obj,
562                                             sizeof (MessageQCopyTransport_Object));
563                                 /*! @retval MessageQCopy_E_MEMORY Failed to
564                                                                   create
565                                                                   virtqueue! */
566                                 status = MessageQCopy_E_MEMORY;
567                                 GT_setFailureReason (curTrace,
568                                                      GT_4CLASS,
569                                                      "MessageQCopy_attach",
570                                                      status,
571                                                      "Failed to create "
572                                                      "virtqueue!");
573                                 break;
574                             }
575 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
576                             vqVAddr += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
577                             vqPAddr += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
578                         }
579                     }
581                     if (status >= 0) {
582                         /* Register for interrupts */
583                         for (i = 0; i < MessageQCopy_NUMBUFS; i++) {
584                             buf = (Void *)((UInt32)recvBufsAddr +\
585                                            (i * MessageQCopy_BUFSIZE));
586                             VirtQueue_addAvailBuf (obj->vq[0], buf, 0, i);
587                         }
588                         /* Add all the bufs for A9->remote proc communication */
589                         for (i = 0; i < MessageQCopy_NUMBUFS; i++) {
590                             buf = (Void *)((UInt32)sendBufsAddr +\
591                                            (i * MessageQCopy_BUFSIZE));
592                             VirtQueue_addUsedBufAddr (obj->vq[1], buf,
593                                                       MessageQCopy_BUFSIZE);
594                         }
595                         /* Notify the remote proc about the buffers */
596                         VirtQueue_kick(obj->vq[0]);
598                         /* Save the transport object */
599                         MessageQCopy_module->transport [obj->procId] = obj;
600                     }
601                 }
602 #if !defined(SYSLINK_BUILD_OPTIMIZE)
603             }
604         }
605         if (status < 0) {
606             GT_setFailureReason (curTrace,
607                                  GT_4CLASS,
608                                  "MessageQCopy_attach",
609                                  status,
610                                  "Failed in transport setup!");
611         }
612 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
613     }
614     else {
615         status = MessageQCopy_E_FAIL;
616         GT_setFailureReason (curTrace,
617                              GT_4CLASS,
618                              "MessageQCopy_attach",
619                              status,
620                              "Function called incorrectly!");
621     }
623     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_attach", status);
625     /*! @retval MessageQCopy_S_SUCCESS Operation successfully completed! */
626     return status;
629 /* Calls the SetupProxy to detach the MessageQ transports. */
630 Int
631 MessageQCopy_detach (UInt16 remoteProcId)
633     Int status = MessageQCopy_S_SUCCESS;
634     MessageQCopyTransport_Object *      obj         = NULL;
635     Int16                               i           = 0;
636     ProcMgr_AddrInfo                    addrInfo;
638     GT_1trace (curTrace, GT_ENTER, "MessageQCopy_detach", remoteProcId);
640     if (EXPECT_TRUE (MultiProc_getNumProcessors () > 1)) {
641 #if !defined(SYSLINK_BUILD_OPTIMIZE)
642         if (remoteProcId >= MultiProc_getNumProcessors()) {
643             /*! @retval MessageQCopy_E_INVALIDPROCID ProcId is invalid! */
644             status = MessageQCopy_E_INVALIDPROCID;
645             GT_setFailureReason (curTrace,
646                                  GT_4CLASS,
647                                  "MessageQCopy_detach",
648                                  status,
649                                  "ProcId is invalid!");
650         }
651         else if (MessageQCopy_module->transport[remoteProcId] == NULL) {
652             /*! @retval MessageQCopy_E_NOTFOUND Transport is not
653                                         setup! */
654             status = MessageQCopy_E_NOTFOUND;
655             GT_setFailureReason (curTrace,
656                                  GT_4CLASS,
657                                  "MessageQCopy_detach",
658                                  status,
659                                  "Transport is not setup!");
660         }
661         else {
662 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
663             obj = MessageQCopy_module->transport[remoteProcId];
665             /* Check if any MessageQ instances have not been deleted so far.
666              * Delete them, but don't assert since these are remote-proc
667              * allocated MessageQ's.
668              */
669             for (i = 0 ; i < MessageQCopy_MAXMQS; i++) {
670                 if (obj->mq [i] != NULL) {
671                     MessageQCopy_delete(&obj->mq [i]);
672                     obj->mq [i] = NULL;
673                 }
674             }
676             MessageQCopy_module->transport[remoteProcId] = NULL;
678             /* Delete the virtqueues */
679             for (i = 0; i < MessageQCopy_NUMVIRTQS; i++) {
680                 VirtQueue_delete (&obj->vq[i]);
681                 obj->vq[i] = NULL;
682             }
684             VirtQueue_destroy(remoteProcId);
685             addrInfo.addr[ProcMgr_AddrType_MasterPhys] = obj->vqPAddr;
686             addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt] = obj->vqAddr;
687             addrInfo.size = (MessageQCopy_NUMVIRTQS *\
688                              ROUND_UP(MessageQCopy_RINGSIZE, 0x4000)) +
689                              (MessageQCopy_NUMBUFS * MessageQCopy_BUFSIZE * 2);
690             addrInfo.isCached = FALSE;
691             addrInfo.isMapped = TRUE;
692             ProcMgr_unmap(obj->procHandle,
693                           ProcMgr_MASTERKNLVIRT, &addrInfo,
694                           ProcMgr_AddrType_MasterPhys);
695             ProcMgr_close(&obj->procHandle);
696             /* Allocate memory for the MessageQCopyTransport object. */
697             Memory_free (NULL, obj, sizeof (MessageQCopyTransport_Object));
698 #if !defined(SYSLINK_BUILD_OPTIMIZE)
699         }
700 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
701     }
702     else {
703         status = MessageQCopy_E_FAIL;
704         GT_setFailureReason (curTrace,
705                              GT_4CLASS,
706                              "MessageQCopy_detach",
707                              status,
708                              "Function called incorrectly!");
709     }
711     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_detach", status);
713     /*! @retval MessageQCopy_S_SUCCESS Operation successfully completed! */
714     return status;
718 /* Internal create function. */
719 static
720 MessageQCopy_Handle
721 _MessageQCopy_create (MessageQCopyTransport_Handle handle, UInt32 reserved,
722            String name, String desc,
723            void (*cb)(MessageQCopy_Handle, void *, int, void *, UInt32, UInt16),
724            Void *priv, UInt32 * endpoint)
726     Int32                       status          = MessageQCopy_S_SUCCESS;
727     MessageQCopy_Object *       obj             = NULL;
728     IArg                        key             = NULL;
729     Bool                        found           = FALSE;
730     Int                         i               = 0;
731     UInt16                      queueIndex      = 0;
732     MessageQCopy_Handle *       mq              = NULL;
733     Bool                        announce        = FALSE;
735     GT_5trace (curTrace, GT_ENTER, "_MessageQCopy_create",
736                handle, reserved, name, desc, endpoint);
738     GT_assert (curTrace, (endpoint != NULL));
739     /* name is optional and may be NULL. */
740     /* desc is optional and may be NULL. */
741     /* handle is optional and may be NULL. */
743 #if !defined(SYSLINK_BUILD_OPTIMIZE)
744     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
745                                MessageQCopy_MAKE_MAGICSTAMP(0),
746                                MessageQCopy_MAKE_MAGICSTAMP(1))
747         == TRUE) {
748        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
749         status = MessageQCopy_E_INVALIDSTATE;
750         GT_setFailureReason (curTrace,
751                              GT_4CLASS,
752                              "_MessageQCopy_create",
753                              status,
754                              "MessageQCopy module not setup");
755     }
756     else if (endpoint == NULL) {
757         /*! @retval  MessageQCopy_E_INVALIDARG Invalid endpoint argument
758                                          provided. */
759         status = MessageQCopy_E_INVALIDARG;
760         GT_setFailureReason (curTrace,
761                              GT_4CLASS,
762                              "_MessageQCopy_create",
763                              status,
764                              "Invalid endpoint argument provided");
765     }
766     else if (name && String_nlen(name, RPMSG_NAME_SIZE - 1) == -1) {
767         /*! @retval  MessageQCopy_E_INVALIDARG Invalid name argument
768                                          provided. */
769         status = MessageQCopy_E_INVALIDARG;
770         GT_setFailureReason (curTrace,
771                              GT_4CLASS,
772                              "_MessageQCopy_create",
773                              status,
774                              "Invalid name argument provided");
775     }
776     else if (desc && String_nlen(desc, RPMSG_NAME_SIZE - 1) == -1) {
777         /*! @retval  MessageQCopy_E_INVALIDARG Invalid name argument
778                                          provided. */
779         status = MessageQCopy_E_INVALIDARG;
780         GT_setFailureReason (curTrace,
781                              GT_4CLASS,
782                              "_MessageQCopy_create",
783                              status,
784                              "Invalid desc argument provided");
785     }
786     else {
787 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
788         if (handle == NULL) {
789             mq = MessageQCopy_module->mq;
790             if (reserved != MessageQCopy_ADDRANY && name != NULL)
791                 announce = TRUE;
792         }
793         else {
794             mq = handle->mq;
795         }
797         /* Enter critical section protection. */
798         key = IGateProvider_enter (MessageQCopy_module->gateHandle);
800         if (reserved == MessageQCopy_ADDRANY)  {
801             /* Search the array for a free slot above reserved: */
802             for (i = MessageQCopy_MAXRESERVEDEPT + 1;
803                  (i < MessageQCopy_MAXMQS) && (found == FALSE) ; i++) {
804                 if (mq[i] == NULL) {
805                     queueIndex = i;
806                     found = TRUE;
807                     break;
808                 }
809             }
810         }
811         else if ((queueIndex = reserved) < MessageQCopy_MAXMQS) {
812             if (mq[queueIndex] == NULL)
813                 found = TRUE;
814         }
816         if (found) {
817             obj = Memory_calloc(NULL, sizeof(MessageQCopy_Object), 0, NULL);
818             if (obj != NULL) {
819                 /* Store our endpoint, and object: */
820                 obj->addr = queueIndex;
821                 obj->cb = cb;
822                 obj->priv = priv;
823                 if (handle)
824                     obj->procId = handle->procId;
825                 else
826                     obj->procId = MultiProc_self();
827                 if (name) {
828                     String_cpy (obj->name, name);
829                 }
830                 else
831                     obj->name[0] = '\0';
832                 if (desc) {
833                     String_cpy (obj->desc, desc);
834                 }
835                 else
836                     obj->desc[0] = '\0';
838                 mq[queueIndex] = obj;
840                 *endpoint = queueIndex;
842                 obj->announce = announce;
843                 if (obj->announce) {
844                     struct rpmsg_ns_msg msg;
846                     msg.addr = obj->addr;
847                     msg.flags = RPMSG_NS_CREATE;
848                     String_ncpy (msg.name, obj->name, RPMSG_NAME_SIZE);
849                     if (obj->desc)
850                         String_ncpy (msg.desc, obj->desc, RPMSG_NAME_SIZE);
851                     else
852                         msg.desc[0] = '\0';
854                     /* Send to all procs */
855                     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
856                         if (MessageQCopy_module->transport[i]) {
857                             UInt16 remoteProcId =
858                                       MessageQCopy_module->transport[i]->procId;
859                             UInt16 localProcId = MultiProc_self();
861                             IGateProvider_leave (
862                                                 MessageQCopy_module->gateHandle,
863                                                 key);
865                             status = MessageQCopy_send (
866                                   remoteProcId,
867                                   localProcId,
868                                   MessageQCopy_NS_PORT, obj->addr, &msg,
869                                   sizeof (struct rpmsg_ns_msg), TRUE);
871                             key = IGateProvider_enter (
872                                                MessageQCopy_module->gateHandle);
873                         }
874                     }
875                 }
877                 /* notify anyone registered of this channel */
878                 if (name) {
879                     for (i = 0; i < MessageQCopy_MAXMQS; i++) {
880                         if (MessageQCopy_module->mq[i] &&
881                             MessageQCopy_module->mq[i]->name) {
882                             if (!String_ncmp(name,
883                                              MessageQCopy_module->mq[i]->name,
884                                              RPMSG_NAME_SIZE)) {
885                                 if (MessageQCopy_module->mq[i]->notifyCb)
886                                     MessageQCopy_module->mq[i]->notifyCb(
887                                                      MessageQCopy_module->mq[i],
888                                                      obj->procId,
889                                                      obj->addr,
890                                                      obj->desc,
891                                                      TRUE);
892                             }
893                         }
894                     }
895                 }
896             }
897         }
899         /* Leave critical section protection. */
900         IGateProvider_leave (MessageQCopy_module->gateHandle, key);
901 #if !defined(SYSLINK_BUILD_OPTIMIZE)
902     }
903 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
905     GT_1trace (curTrace, GT_LEAVE, "_MessageQCopy_create", status);
907     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
908     return (MessageQCopy_Handle)(obj);
912 /* Create an endpoint and handle.  Return a handle. */
913 MessageQCopy_Handle
914 MessageQCopy_create (UInt32 reserved, String name,
915            void (*cb)(MessageQCopy_Handle, void *, int, void *, UInt32, UInt16),
916            Void *priv, UInt32 * endpoint)
918     Int32                       status      = MessageQCopy_S_SUCCESS;
919     MessageQCopy_Object *       obj         = NULL;
921     GT_3trace (curTrace, GT_ENTER, "MessageQCopy_create",
922                reserved, name, endpoint);
924     GT_assert (curTrace, (endpoint != NULL));
925     /* name is optional and may be NULL. */
927 #if !defined(SYSLINK_BUILD_OPTIMIZE)
928     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
929                                MessageQCopy_MAKE_MAGICSTAMP(0),
930                                MessageQCopy_MAKE_MAGICSTAMP(1))
931         == TRUE) {
932        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
933         status = MessageQCopy_E_INVALIDSTATE;
934         GT_setFailureReason (curTrace,
935                              GT_4CLASS,
936                              "MessageQCopy_create",
937                              status,
938                              "MessageQCopy module not setup");
939     }
940     else if (cb == NULL) {
941         /*! @retval  MessageQCopy_E_INVALIDARG Invalid cb argument
942                                          provided. */
943         status = MessageQCopy_E_INVALIDARG;
944         GT_setFailureReason (curTrace,
945                              GT_4CLASS,
946                              "MessageQCopy_create",
947                              status,
948                              "Invalid cb argument provided");
949     }
950     else {
951 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
953         obj = _MessageQCopy_create (NULL, reserved, name, NULL, cb, priv,
954                                     endpoint);
956 #if !defined(SYSLINK_BUILD_OPTIMIZE)
957         if (obj == NULL) {
958             /*! @retval  MessageQCopy_E_FAIL Failed to create handle. */
959             status = MessageQCopy_E_FAIL;
960             GT_setFailureReason (curTrace,
961                                  GT_4CLASS,
962                                  "MessageQCopy_create",
963                                  status,
964                                  "Failed to create handle");
965         }
966     }
967 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
969     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_create", status);
971     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
972     return (MessageQCopy_Handle)obj;
976 /* Internal delete function. */
977 Int
978 MessageQCopy_delete (      MessageQCopy_Handle * handlePtr)
980     Int32                           status          = MessageQCopy_S_SUCCESS;
981     MessageQCopy_Object *           obj             = NULL;
982     IArg                            key             = NULL;
983     UInt32                          i               = 0;
984     UInt32                          j               = 0;
985     MessageQCopy_Handle *           mq              = NULL;
986     Bool                            found           = FALSE;
988     GT_1trace (curTrace, GT_ENTER, "MessageQCopy_delete", handlePtr);
990     GT_assert (curTrace, (handlePtr != NULL));
992 #if !defined(SYSLINK_BUILD_OPTIMIZE)
993     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
994                                MessageQCopy_MAKE_MAGICSTAMP(0),
995                                MessageQCopy_MAKE_MAGICSTAMP(1))
996         == TRUE) {
997        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
998         status = MessageQCopy_E_INVALIDSTATE;
999         GT_setFailureReason (curTrace,
1000                              GT_4CLASS,
1001                              "MessageQCopy_delete",
1002                              status,
1003                              "MessageQCopy module not setup");
1004     }
1005     else if (handlePtr == NULL) {
1006         /*! @retval  MessageQCopy_E_INVALIDARG Invalid handlePtr argument
1007                                          provided. */
1008         status = MessageQCopy_E_INVALIDARG;
1009         GT_setFailureReason (curTrace,
1010                              GT_4CLASS,
1011                              "MessageQCopy_delete",
1012                              status,
1013                              "Invalid handlePtr argument provided");
1014     }
1015     else if (*handlePtr == NULL) {
1016         /*! @retval  MessageQCopy_E_INVALIDARG Invalid *handlePtr argument
1017                                          provided. */
1018         status = MessageQCopy_E_INVALIDARG;
1019         GT_setFailureReason (curTrace,
1020                              GT_4CLASS,
1021                              "MessageQCopy_delete",
1022                              status,
1023                              "Invalid *handlePtr argument provided");
1024     }
1025     else {
1026 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1027         obj = (MessageQCopy_Object *)(*handlePtr);
1028         /* Search through all transports for this handle to validate that it is real */
1029         mq = MessageQCopy_module->mq;
1030         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1031             if (mq[i] == obj) {
1032                 found = TRUE;
1033                 break;
1034             }
1035         }
1036         if (!found) {
1037             for (j = 0; j < MultiProc_MAXPROCESSORS; j++) {
1038                 if (MessageQCopy_module->transport[j]) {
1039                     mq = MessageQCopy_module->transport[j]->mq;
1040                     for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1041                         if (mq[i] == obj) {
1042                             found = TRUE;
1043                             break;
1044                         }
1045                     }
1046                     if (found == TRUE)
1047                         break;
1048                 }
1049             }
1050         }
1051         if (found) {
1052             /* Enter critical section protection. */
1053             key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1055             if (obj->announce) {
1056                 struct rpmsg_ns_msg msg;
1058                 msg.addr = obj->addr;
1059                 msg.flags = RPMSG_NS_DESTROY;
1060                 String_ncpy(msg.name, obj->name, RPMSG_NAME_SIZE);
1061                 if (obj->desc)
1062                     String_ncpy(msg.desc, obj->desc, RPMSG_NAME_SIZE);
1063                 else
1064                     msg.desc[0] = '\0';
1066                 /* Send to all procs */
1067                 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1068                     if (MessageQCopy_module->transport[i]) {
1069                         UInt16 remoteProcId =
1070                                       MessageQCopy_module->transport[i]->procId;
1071                         UInt16 localProcId = MultiProc_self();
1073                         IGateProvider_leave (MessageQCopy_module->gateHandle,
1074                                              key);
1075                         status = MessageQCopy_send (remoteProcId, localProcId,
1076                                                    MessageQCopy_NS_PORT,
1077                                                    obj->addr, &msg,
1078                                                    sizeof (struct rpmsg_ns_msg),
1079                                                    TRUE);
1080                         key = IGateProvider_enter (
1081                                                MessageQCopy_module->gateHandle);
1082                     }
1083                 }
1084             }
1085             /* notify anyone registered of this channel */
1086             if (obj->name) {
1087                 for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1088                     if (MessageQCopy_module->mq[i] &&
1089                         MessageQCopy_module->mq[i]->name &&
1090                         obj->procId != MessageQCopy_module->mq[i]->procId) {
1091                         if (!String_ncmp(obj->name,
1092                                          MessageQCopy_module->mq[i]->name,
1093                                          RPMSG_NAME_SIZE)) {
1094                             if (MessageQCopy_module->mq[i]->notifyCb)
1095                                 MessageQCopy_module->mq[i]->notifyCb(
1096                                                      MessageQCopy_module->mq[i],
1097                                                      obj->procId,
1098                                                      obj->addr,
1099                                                      obj->desc,
1100                                                      FALSE);
1101                         }
1102                     }
1103                 }
1104             }
1106             mq[obj->addr] = NULL;
1108             /* Leave critical section protection. */
1109             IGateProvider_leave (MessageQCopy_module->gateHandle, key);
1111             Memory_free (NULL, obj, sizeof (MessageQCopy_Object));
1113             *handlePtr = NULL;
1114         }
1115         else {
1116             /*! @retval  MessageQCopy_E_INVALIDARG Invalid *handlePtr argument
1117                                              provided. */
1118             status = MessageQCopy_E_INVALIDARG;
1119             GT_setFailureReason (curTrace,
1120                                  GT_4CLASS,
1121                                  "MessageQCopy_delete",
1122                                  status,
1123                                  "Invalid *handlePtr argument provided");
1124         }
1125 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1126     }
1127 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1129     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_delete", status);
1131     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1132     return (status);
1136 /* Register to be notified of a MQ created on the remote core. */
1137 Int
1138 MessageQCopy_registerNotify (MessageQCopy_Handle handle,
1139                   Void (*cb)(MessageQCopy_Handle, UInt16, UInt32, Char *, Bool))
1141     Int32                               status      = MessageQCopy_S_SUCCESS;
1142     MessageQCopyTransport_Object *      obj         = NULL;
1143     IArg                                key         = NULL;
1144     Int                                 i           = 0;
1145     Int                                 j           = 0;
1146     Bool                                found       = FALSE;
1148     GT_2trace (curTrace, GT_ENTER, "MessageQCopy_registerNotify", handle, cb);
1150     GT_assert (curTrace, (handle != NULL));
1151     GT_assert (curTrace, (cb != NULL));
1153 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1154     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1155                                MessageQCopy_MAKE_MAGICSTAMP(0),
1156                                MessageQCopy_MAKE_MAGICSTAMP(1))
1157         == TRUE) {
1158        /*! @retval  MessageQCopy_E_INVALIDSTATE MessageQCopy module not setup */
1159         status = MessageQCopy_E_INVALIDSTATE;
1160         GT_setFailureReason (curTrace,
1161                              GT_4CLASS,
1162                              "MessageQCopy_registerNotify",
1163                              status,
1164                              "MessageQCopy module not setup");
1165     }
1166     else if (handle == NULL) {
1167         /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1168                                          provided. */
1169         status = MessageQCopy_E_INVALIDARG;
1170         GT_setFailureReason (curTrace,
1171                              GT_4CLASS,
1172                              "MessageQCopy_registerNotify",
1173                              status,
1174                              "Invalid handle argument provided");
1175     }
1176     else if (cb == NULL) {
1177         /*! @retval  MessageQCopy_E_INVALIDARG Invalid callback argument
1178                                          provided. */
1179         status = MessageQCopy_E_INVALIDARG;
1180         GT_setFailureReason (curTrace,
1181                              GT_4CLASS,
1182                              "MessageQCopy_registerNotify",
1183                              status,
1184                              "Invalid callback argument provided.");
1185     }
1186     else {
1187 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1188         /* Enter critical section protection. */
1189         key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1191         /*
1192          * Search through the local transport for this handle to validate that
1193          * it is real. The handle must be a local handle.
1194          */
1195         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1196             if (MessageQCopy_module->mq[i] == handle) {
1197                 found = TRUE;
1198                 break;
1199             }
1200         }
1202         if (found) {
1203             if (String_nlen(handle->name, RPMSG_NAME_SIZE - 1) == 0) {
1204                 /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1205                                                  provided. */
1206                 status = MessageQCopy_E_INVALIDARG;
1207                 GT_setFailureReason (curTrace,
1208                                      GT_4CLASS,
1209                                      "MessageQCopy_registerNotify",
1210                                      status,
1211                                      "Invalid handle argument provided");
1212             }
1213             else {
1214                 /* save the callback for future use */
1215                 handle->notifyCb = cb;
1217                 /* using the id_table, try to find a registered channel */
1218                 for (j = 0; j < MultiProc_MAXPROCESSORS; j++) {
1219                     obj = MessageQCopy_module->transport[j];
1221                     if (obj) {
1222                         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1223                             if (obj->mq[i] && obj->mq[i]->name) {
1224                                 if (!String_ncmp (handle->name,
1225                                                   obj->mq[i]->name,
1226                                                   RPMSG_NAME_SIZE) ) {
1227                                     /* call the callback */
1228                                     cb(handle, j, obj->mq[i]->addr,
1229                                        obj->mq[i]->desc, TRUE);
1230                                 }
1231                             }
1232                         }
1233                     }
1234                 }
1235             }
1236         }
1237         else {
1238             /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1239                                              provided. */
1240             status = MessageQCopy_E_INVALIDARG;
1241             GT_setFailureReason (curTrace,
1242                                  GT_4CLASS,
1243                                  "MessageQCopy_registerNotify",
1244                                  status,
1245                                  "Invalid handle argument provided");
1246         }
1248         /* Leave critical section protection. */
1249         IGateProvider_leave (MessageQCopy_module->gateHandle, key);
1250 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1251     }
1252 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1254     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_registerNotify", status);
1256     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1257     return status;
1261 /*
1262  * Send the specified message to the specified proc using the specified src and
1263  * dst endpoints.
1264  */
1265 Int
1266 MessageQCopy_send (UInt16 dstProc, UInt16 srcProc, UInt32 dstEndpt,
1267                    UInt32 srcEndpt, Ptr data, UInt16 len, Bool wait)
1270     Int32                               status      = MessageQCopy_S_SUCCESS;
1271     MessageQCopyTransport_Object *      obj         = NULL;
1272     IArg                                key         = NULL;
1273     struct rpmsg_hdr *                  msg         = NULL;
1274     Int16                               token       = 0;
1276     GT_5trace (curTrace, GT_ENTER, "MessageQCopy_send",
1277                dstProc, dstEndpt, srcEndpt, data, len);
1279     GT_assert (curTrace, (dstProc < MultiProc_getNumProcessors()));
1280     GT_assert (curTrace, (data != NULL));
1281     GT_assert (curTrace, (len > 0));
1282     GT_assert (curTrace, (len <= (MessageQCopy_BUFSIZE -\
1283                                   sizeof(struct rpmsg_hdr))));
1285 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1286     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1287                                MessageQCopy_MAKE_MAGICSTAMP(0),
1288                                MessageQCopy_MAKE_MAGICSTAMP(1))
1289         == TRUE) {
1290        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
1291         status = MessageQCopy_E_INVALIDSTATE;
1292         GT_setFailureReason (curTrace,
1293                              GT_4CLASS,
1294                              "MessageQCopy_send",
1295                              status,
1296                              "MessageQCopy module not setup");
1297     }
1298     else if (dstProc >= MultiProc_getNumProcessors()) {
1299         /*! @retval  MessageQCopy_E_INVALIDARG Invalid procId argument
1300                                          provided. */
1301         status = MessageQCopy_E_INVALIDARG;
1302         GT_setFailureReason (curTrace,
1303                              GT_4CLASS,
1304                              "MessageQCopy_send",
1305                              status,
1306                              "Invalid dstProc argument provided");
1307     }
1308     else if (srcProc != MultiProc_self()) {
1309         /*! @retval  MessageQCopy_E_INVALIDARG Invalid procId argument
1310                                          provided. */
1311         status = MessageQCopy_E_INVALIDARG;
1312         GT_setFailureReason (curTrace,
1313                              GT_4CLASS,
1314                              "MessageQCopy_send",
1315                              status,
1316                              "Invalid srcProc argument provided");
1317     }
1318     else if (data == NULL) {
1319         /*! @retval  MessageQCopy_E_INVALIDARG Invalid data argument
1320                                          provided. */
1321         status = MessageQCopy_E_INVALIDARG;
1322         GT_setFailureReason (curTrace,
1323                              GT_4CLASS,
1324                              "MessageQCopy_send",
1325                              status,
1326                              "Invalid data argument provided");
1327     }
1328     else if (len <= 0) {
1329         /*! @retval  MessageQCopy_E_INVALIDARG Invalid len specified. */
1330         status = MessageQCopy_E_INVALIDARG;
1331         GT_setFailureReason (curTrace,
1332                              GT_4CLASS,
1333                              "MessageQCopy_send",
1334                              status,
1335                              "Invalid len specified.");
1336     }
1337     else if (len > (MessageQCopy_BUFSIZE - sizeof(struct rpmsg_hdr))) {
1338         /*! @retval  MessageQCopy_E_INVALIDARG Invalid len specified. */
1339         status = MessageQCopy_E_INVALIDARG;
1340         GT_setFailureReason (curTrace,
1341                              GT_4CLASS,
1342                              "MessageQCopy_send",
1343                              status,
1344                              "Invalid len specified");
1345     }
1346     else if (dstEndpt == MessageQCopy_ADDRANY) {
1347         /*! @retval  MessageQCopy_E_INVALIDARG Invalid dstEndpt. */
1348         status = MessageQCopy_E_INVALIDARG;
1349         GT_setFailureReason (curTrace,
1350                              GT_4CLASS,
1351                              "MessageQCopy_send",
1352                              status,
1353                              "Invalid dstEndpt.");
1354     }
1355     else if (srcEndpt == MessageQCopy_ADDRANY) {
1356         /*! @retval  MessageQCopy_E_INVALIDARG Invalid srcEndpt. */
1357         status = MessageQCopy_E_INVALIDARG;
1358         GT_setFailureReason (curTrace,
1359                              GT_4CLASS,
1360                              "MessageQCopy_send",
1361                              status,
1362                              "Invalid srcEndpt.");
1363     }
1364     else {
1365 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1367         if (dstProc != MultiProc_self()) {
1368             /* Enter critical section protection. */
1369             key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1371             obj = (MessageQCopyTransport_Object *)
1372                       MessageQCopy_module->transport[dstProc];
1374             if (obj == NULL) {
1375                 status = MessageQCopy_E_INVALIDARG;
1376                 GT_setFailureReason (curTrace,
1377                                      GT_4CLASS,
1378                                      "MessageQCopy_send",
1379                                      status,
1380                                      "obj is NULL.");
1381             }
1382             else if (obj->vq[1] == NULL) {
1383                 status = MessageQCopy_E_INVALIDSTATE;
1384                 GT_setFailureReason (curTrace,
1385                                      GT_4CLASS,
1386                                      "MessageQCopy is not attached",
1387                                      status,
1388                                      "obj->vq[1] is NULL.");
1389             }
1390             else {
1391                 /* Get a buf from the UsedBuf list */
1392                 token = VirtQueue_getUsedBuf (obj->vq[1], (Void **)&msg);
1394                 if (token != -1 && msg != NULL) {
1395                     /* Copy the payload and set message header: */
1396                     Memory_copy(msg->data, data, len);
1397                     msg->len = len;
1398                     msg->dst = dstEndpt;
1399                     msg->src = srcEndpt;
1400                     msg->flags = 0;
1401                     msg->unused = 0;
1403                     VirtQueue_addAvailBuf(obj->vq[1], msg, sizeof(*msg) + len, token);
1404                     VirtQueue_kick(obj->vq[1]);
1405                 }
1406                 else {
1407                     status = MessageQCopy_E_FAIL;
1408                     GT_setFailureReason (curTrace,
1409                                          GT_4CLASS,
1410                                          "MessageQCopy_send",
1411                                          status,
1412                                          "getAvailBuf failed.");
1413                 }
1414             }
1415             IGateProvider_leave(MessageQCopy_module->gateHandle, key);
1416         }
1417         else {
1418             status = MessageQCopy_E_INVALIDARG;
1419             GT_setFailureReason (curTrace,
1420                                  GT_4CLASS,
1421                                  "MessageQCopy_send",
1422                                  status,
1423                                  "sending to local proc not supported.");
1424         }
1425 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1426     }
1427 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1429     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_send", status);
1431     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1432     return (status);
1436 /* =============================================================================
1437  *  Internal functions
1438  * =============================================================================
1439  */
1440  static
1441  Void
1442  _MessageQCopy_callback_NS(MessageQCopy_Handle handle, void *data,
1443                             int len, void *priv, UInt32 src, UInt16 srcProc)
1445     struct rpmsg_ns_msg *           msg         = data;
1446     UInt32                          endpoint    = MessageQCopy_ADDRANY;
1447     MessageQCopyTransport_Object *  transport   = NULL;
1449     GT_6trace (curTrace, GT_ENTER, "_MessageQCopy_callback_NS",
1450                handle, data, len, priv, src, srcProc);
1452     /* handle will be NULL */
1453     GT_assert (curTrace, (data != NULL));
1454     GT_assert (curTrace, (len >= sizeof(struct rpmsg_ns_msg)));
1455     GT_assert (curTrace, (srcProc < MultiProc_MAXPROCESSORS));
1457 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1458     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1459                                MessageQCopy_MAKE_MAGICSTAMP(0),
1460                                MessageQCopy_MAKE_MAGICSTAMP(1))
1461         == TRUE) {
1462         GT_setFailureReason (curTrace,
1463                              GT_4CLASS,
1464                              "_MessageQCopy_callback_NS",
1465                              MessageQCopy_E_INVALIDSTATE,
1466                              "rpmsg module not setup");
1467     }
1468     else if (data == NULL) {
1469         GT_setFailureReason (curTrace,
1470                              GT_4CLASS,
1471                              "_MessageQCopy_callback_NS",
1472                              MessageQCopy_E_INVALIDARG,
1473                              "Invalid data argument provided");
1474     }
1475     else if (len < sizeof(struct rpmsg_ns_msg)) {
1476         GT_setFailureReason (curTrace,
1477                              GT_4CLASS,
1478                              "_MessageQCopy_callback_NS",
1479                              MessageQCopy_E_INVALIDARG,
1480                              "Invalid len argument provided");
1481     }
1482     else if (srcProc >= MultiProc_MAXPROCESSORS) {
1483         GT_setFailureReason (curTrace,
1484                              GT_4CLASS,
1485                              "_MessageQCopy_callback_NS",
1486                              MessageQCopy_E_INVALIDARG,
1487                              "Invalid srcProc argument provided");
1488     }
1489     else {
1490 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1491         transport = MessageQCopy_module->transport[srcProc];
1493         if (transport) {
1494             /* Check flag to see if this is a create or destroy call */
1495             if (msg->flags & RPMSG_NS_DESTROY) {
1496                 MessageQCopy_delete (&transport->mq[msg->addr]);
1497             }
1498             else {
1499                 if (!_MessageQCopy_create (transport, msg->addr, msg->name,
1500                                            msg->desc, NULL, NULL, &endpoint)) {
1501                     GT_0trace (curTrace, GT_4CLASS,
1502                                "creating of MQ in NS Callback failed!");
1503                 }
1504             }
1505         }
1506 #if !defined(SYSLINK_BUILD_OPTIMIZE)
1507     }
1508 #endif /* if !defined(SYSLINK_BUILD_OPTIMIZE) */
1512 static
1513 Void
1514 _MessageQCopy_callback_bufReady (VirtQueue_Handle vq, void *arg)
1516     struct rpmsg_hdr *                  msg                 = NULL;
1517     Bool                                availBufAdded       = FALSE;
1518     MessageQCopyTransport_Object *      obj                 = NULL;
1519     MessageQCopy_Object *               mq                  = NULL;
1520     Int16                               token               = 0;
1522     if (vq) {
1523         obj = (MessageQCopyTransport_Object *)arg;
1524     }
1526     if (obj && obj->vq[0] == vq) {
1527         /* this is a notification of a ready message on the remote proc */
1528         /* Process all available buffers: */
1529         while ((token = VirtQueue_getUsedBuf(vq, (Void **)&msg)) != -1) {
1531             /* Put on a Message queue on this processor: */
1532             mq = MessageQCopy_module->mq[msg->dst];
1533             if (mq == NULL) {
1534                 Osal_printf ("_MessageQCopy_callback_bufReady: "
1535                              "no object for endpoint: %d", msg->dst);
1536             }
1537             else {
1538                 if (mq->cb) {
1539                     mq->cb(mq, msg->data, msg->len, mq->priv, msg->src,
1540                            obj->procId);
1541                 }
1542                 else {
1543                     Osal_printf ("_MessageQCopy_callback_bufReady: "
1544                                  "no callback for endpoint: %d", msg->dst);
1545                 }
1546                 VirtQueue_addAvailBuf(vq, msg, sizeof(*msg) + msg->len, token);
1547                 availBufAdded = TRUE;
1548             }
1549         }
1550         if (availBufAdded)  {
1551            /* Tell host we've processed the buffers: */
1552            VirtQueue_kick(vq);
1553         }
1554     }
1555     else if (obj && obj->vq[1] == vq) {
1556         /* this is a notification that the remote proc has processed a buffer */
1557     }
1558     else {
1559         /* something has gone wrong! */
1560     }
1564 #if defined (__cplusplus)
1566 #endif /* defined (__cplusplus) */