Improve MessageQ recovery on DRA7xx QNX
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / MessageQCopy.c
1 /*
2  *  Copyright (c) 2011-2015, 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(IPC_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(IPC_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(IPC_BUILD_OPTIMIZE)
280         }
281 #endif /* if !defined(IPC_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(IPC_BUILD_OPTIMIZE)
307     }
308 #endif /* if !defined(IPC_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(IPC_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(IPC_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             for (i = 0 ; i < MessageQCopy_MAXMQS; i++) {
364                 /*
365                  * This is possible if recovery is performed and the app does
366                  * not yet know about it, hence has not yet had a chance to
367                  * clean up.
368                  */
369                 if (MessageQCopy_module->mq [i] != NULL) {
370                     MessageQCopy_delete(&MessageQCopy_module->mq [i]);
371                     MessageQCopy_module->mq [i] = NULL;
372                 }
373             }
375             /* Decrease the refCount */
376             Atomic_set (&MessageQCopy_module->refCount,
377                         MessageQCopy_MAKE_MAGICSTAMP(0));
379             if (MessageQCopy_module->gateHandle != NULL) {
380                 GateSpinlock_delete ((GateSpinlock_Handle *)
381                                      &(MessageQCopy_module->gateHandle));
382             }
383         }
384 #if !defined(IPC_BUILD_OPTIMIZE)
385     }
386 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
388     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_destroy", status);
390     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
391     return (status);
394 /* Calls the SetupProxy to setup the MessageQ transports. */
395 Int
396 MessageQCopy_attach (UInt16 remoteProcId, Ptr sharedAddr, UInt16 startId)
398     Int                                 status      = MessageQCopy_S_SUCCESS;
399     MessageQCopyTransport_Object *      obj         = NULL;
400     UInt                                i           = 0;
401     Void *                              buf         = NULL;
402     Int32                               vqVAddr     = 0;
403     Int32                               vqPAddr     = 0;
404     UInt32                              recvBufsAddr;
405     UInt32                              sendBufsAddr;
406     ProcMgr_AddrInfo                    addrInfo;
408     GT_2trace (curTrace, GT_ENTER, "MessageQCopy_attach", remoteProcId,
409                sharedAddr);
411     if (EXPECT_TRUE (MultiProc_getNumProcessors () > 1)) {
412 #if !defined(IPC_BUILD_OPTIMIZE)
413         if (remoteProcId >= MultiProc_getNumProcessors()) {
414             /*! @retval MessageQCopy_E_INVALIDPROCID ProcId is invalid! */
415             status = MessageQCopy_E_INVALIDPROCID;
416             GT_setFailureReason (curTrace,
417                                  GT_4CLASS,
418                                  "MessageQCopy_attach",
419                                  status,
420                                  "ProcId is invalid!");
421         }
422         else if (MessageQCopy_module->transport[remoteProcId]) {
423             /*! @retval MessageQCopy_E_ALREADYEXISTS Transport already
424                                         exists! */
425             status = MessageQCopy_E_ALREADYEXISTS;
426             GT_setFailureReason (curTrace,
427                                  GT_4CLASS,
428                                  "MessageQCopy_attach",
429                                  status,
430                                  "Transport is already attached!");
431         }
432         else {
433 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
435             /* Allocate memory for the MessageQCopyTransport object. */
436             obj = Memory_calloc (NULL,
437                                  sizeof (MessageQCopyTransport_Object), 0u,
438                                  NULL);
439 #if !defined(IPC_BUILD_OPTIMIZE)
440             if (obj == NULL) {
441                 /*! @retval MessageQCopy_E_MEMORY Failed to allocate memory
442                                         for MessageQCopyTransport_Object! */
443                 status = MessageQCopy_E_MEMORY;
444                 GT_setFailureReason (curTrace,
445                                      GT_4CLASS,
446                                      "MessageQCopy_attach",
447                                      status,
448                                      "Failed to allocate memory for "
449                                      "MessageQCopyTransport_Object!");
450             }
451             else {
452 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
453                 obj->procId = remoteProcId;
455                 status = ProcMgr_open(&obj->procHandle, obj->procId);
456 #if !defined(IPC_BUILD_OPTIMIZE)
457                 if (status < 0) {
458                         Memory_free(NULL, obj,
459                                     sizeof (MessageQCopyTransport_Object));
460                         /*! @retval MessageQCopy_E_MEMORY Unable to open Proc
461                                                           handle for specified
462                                                           remoteProcId! */
463                         status = MessageQCopy_E_RESOURCE;
464                         GT_setFailureReason (curTrace,
465                                              GT_4CLASS,
466                                              "MessageQCopy_attach",
467                                              status,
468                                              "Unable to open Proc handle for "
469                                              "specified remoteProcId!");
470                 }
471                 else {
472 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
473                     status = ProcMgr_translateAddr(obj->procHandle,
474                                                    (Ptr *)&vqPAddr,
475                                                    ProcMgr_AddrType_MasterPhys,
476                                                    sharedAddr,
477                                                    ProcMgr_AddrType_SlaveVirt);
478                     if (status < 0) {
479                         ProcMgr_close(&obj->procHandle);
480                         Memory_free(NULL, obj,
481                                     sizeof (MessageQCopyTransport_Object));
482                         /*! @retval MessageQCopy_E_MEMORY Unable translate
483                                                           addr! */
484                         status = MessageQCopy_E_MEMORY;
485                         GT_setFailureReason (curTrace,
486                                              GT_4CLASS,
487                                              "MessageQCopy_attach",
488                                              status,
489                                              "Unable to translate addr!");
490                     }
491                     else {
492                         obj->vqPAddr = vqPAddr;
493                         addrInfo.addr[ProcMgr_AddrType_MasterPhys] = vqPAddr;
494                         addrInfo.size = (MessageQCopy_NUMVIRTQS *\
495                                          ROUND_UP(MessageQCopy_RINGSIZE,
496                                                   0x4000)) +
497                                          (MessageQCopy_NUMBUFS * \
498                                               MessageQCopy_BUFSIZE * 2);
499                         addrInfo.isCached = FALSE;
500                         addrInfo.isMapped = TRUE;
501                         status = ProcMgr_map(obj->procHandle,
502                                              ProcMgr_MASTERKNLVIRT, &addrInfo,
503                                              ProcMgr_AddrType_MasterPhys);
504                         if (status < 0) {
505                             ProcMgr_close(&obj->procHandle);
506                             Memory_free(NULL, obj,
507                                         sizeof (MessageQCopyTransport_Object));
508                             /*! @retval MessageQCopy_E_MEMORY Unable translate
509                                                               addr! */
510                             status = MessageQCopy_E_MEMORY;
511                             GT_setFailureReason (curTrace,
512                                                  GT_4CLASS,
513                                                  "MessageQCopy_attach",
514                                                  status,
515                                                  "Unable to translate addr!");
516                         }
517                         obj->vqAddr = vqVAddr =
518                                   addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt];
519                     }
521                     if (status >= 0) {
522                         /* Startup the VirtQueue module for this procId. */
523                         VirtQueue_startup(obj->procId,
524                                     MessageQCopy_module->cfg.intId[obj->procId],
525                                     vqPAddr);
527                         /*
528                          * The buffer area is divided into two parts, one
529                          * for receiving messages from the remote processor
530                          * and one for sending messages.  Here, we calculate
531                          * the address of the start of each buffer section.
532                          */
533                         recvBufsAddr = vqVAddr + (MessageQCopy_NUMVIRTQS *\
534                                        ROUND_UP(MessageQCopy_RINGSIZE, 0x4000));
535                         sendBufsAddr = recvBufsAddr +
536                                              (MessageQCopy_NUMBUFS * \
537                                               MessageQCopy_BUFSIZE);
539                         /* Create the virtqueues */
540                         for (i = 0; i < MessageQCopy_NUMVIRTQS; i++) {
541                             obj->vq[i] = VirtQueue_create (
542                                                 _MessageQCopy_callback_bufReady,
543                                                 obj->procId,
544                                                 startId + i,
545                                                 vqVAddr,
546                                                 vqPAddr,
547                                                 MessageQCopy_NUMBUFS,
548                                                 MessageQCopy_VRINGALIGN,
549                                                 (void *)obj);
551 #if !defined(IPC_BUILD_OPTIMIZE)
552                             if (obj->vq[i] == NULL) {
553                                 for (; i >= 0; --i) {
554                                     VirtQueue_delete (&obj->vq[i]);
555                                 }
556                                 VirtQueue_destroy(obj->procId);
557                                 addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt] = obj->vqAddr;
558                                 ProcMgr_unmap(obj->procHandle,
559                                               ProcMgr_MASTERKNLVIRT, &addrInfo,
560                                               ProcMgr_AddrType_MasterPhys);
561                                 ProcMgr_close(&obj->procHandle);
562                                 Memory_free(NULL, obj,
563                                             sizeof (MessageQCopyTransport_Object));
564                                 /*! @retval MessageQCopy_E_MEMORY Failed to
565                                                                   create
566                                                                   virtqueue! */
567                                 status = MessageQCopy_E_MEMORY;
568                                 GT_setFailureReason (curTrace,
569                                                      GT_4CLASS,
570                                                      "MessageQCopy_attach",
571                                                      status,
572                                                      "Failed to create "
573                                                      "virtqueue!");
574                                 break;
575                             }
576 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
577                             vqVAddr += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
578                             vqPAddr += ROUND_UP(MessageQCopy_RINGSIZE, 0x4000);
579                         }
580                     }
582                     if (status >= 0) {
583                         /* Register for interrupts */
584                         for (i = 0; i < MessageQCopy_NUMBUFS; i++) {
585                             buf = (Void *)((UInt32)recvBufsAddr +\
586                                            (i * MessageQCopy_BUFSIZE));
587                             VirtQueue_addAvailBuf (obj->vq[0], buf, 0, i);
588                         }
589                         /* Add all the bufs for A9->remote proc communication */
590                         for (i = 0; i < MessageQCopy_NUMBUFS; i++) {
591                             buf = (Void *)((UInt32)sendBufsAddr +\
592                                            (i * MessageQCopy_BUFSIZE));
593                             VirtQueue_addUsedBufAddr (obj->vq[1], buf,
594                                                       MessageQCopy_BUFSIZE);
595                         }
596                         /* Notify the remote proc about the buffers */
597                         VirtQueue_kick(obj->vq[0]);
599                         /* Save the transport object */
600                         MessageQCopy_module->transport [obj->procId] = obj;
601                     }
602                 }
603 #if !defined(IPC_BUILD_OPTIMIZE)
604             }
605         }
606         if (status < 0) {
607             GT_setFailureReason (curTrace,
608                                  GT_4CLASS,
609                                  "MessageQCopy_attach",
610                                  status,
611                                  "Failed in transport setup!");
612         }
613 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
614     }
615     else {
616         status = MessageQCopy_E_FAIL;
617         GT_setFailureReason (curTrace,
618                              GT_4CLASS,
619                              "MessageQCopy_attach",
620                              status,
621                              "Function called incorrectly!");
622     }
624     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_attach", status);
626     /*! @retval MessageQCopy_S_SUCCESS Operation successfully completed! */
627     return status;
630 /* Calls the SetupProxy to detach the MessageQ transports. */
631 Int
632 MessageQCopy_detach (UInt16 remoteProcId)
634     Int status = MessageQCopy_S_SUCCESS;
635     MessageQCopyTransport_Object *      obj         = NULL;
636     Int16                               i           = 0;
637     ProcMgr_AddrInfo                    addrInfo;
639     GT_1trace (curTrace, GT_ENTER, "MessageQCopy_detach", remoteProcId);
641     if (EXPECT_TRUE (MultiProc_getNumProcessors () > 1)) {
642 #if !defined(IPC_BUILD_OPTIMIZE)
643         if (remoteProcId >= MultiProc_getNumProcessors()) {
644             /*! @retval MessageQCopy_E_INVALIDPROCID ProcId is invalid! */
645             status = MessageQCopy_E_INVALIDPROCID;
646             GT_setFailureReason (curTrace,
647                                  GT_4CLASS,
648                                  "MessageQCopy_detach",
649                                  status,
650                                  "ProcId is invalid!");
651         }
652         else if (MessageQCopy_module->transport[remoteProcId] == NULL) {
653             /*! @retval MessageQCopy_E_NOTFOUND Transport is not
654                                         setup! */
655             status = MessageQCopy_E_NOTFOUND;
656             GT_setFailureReason (curTrace,
657                                  GT_4CLASS,
658                                  "MessageQCopy_detach",
659                                  status,
660                                  "Transport is not setup!");
661         }
662         else {
663 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
664             obj = MessageQCopy_module->transport[remoteProcId];
666             /* Check if any MessageQ instances have not been deleted so far.
667              * Delete them, but don't assert since these are remote-proc
668              * allocated MessageQ's.
669              */
670             for (i = 0 ; i < MessageQCopy_MAXMQS; i++) {
671                 if (obj->mq [i] != NULL) {
672                     MessageQCopy_delete(&obj->mq [i]);
673                     obj->mq [i] = NULL;
674                 }
675             }
677             MessageQCopy_module->transport[remoteProcId] = NULL;
679             /* Delete the virtqueues */
680             for (i = 0; i < MessageQCopy_NUMVIRTQS; i++) {
681                 VirtQueue_delete (&obj->vq[i]);
682                 obj->vq[i] = NULL;
683             }
685             VirtQueue_destroy(remoteProcId);
686             addrInfo.addr[ProcMgr_AddrType_MasterPhys] = obj->vqPAddr;
687             addrInfo.addr[ProcMgr_AddrType_MasterKnlVirt] = obj->vqAddr;
688             addrInfo.size = (MessageQCopy_NUMVIRTQS *\
689                              ROUND_UP(MessageQCopy_RINGSIZE, 0x4000)) +
690                              (MessageQCopy_NUMBUFS * MessageQCopy_BUFSIZE * 2);
691             addrInfo.isCached = FALSE;
692             addrInfo.isMapped = TRUE;
693             ProcMgr_unmap(obj->procHandle,
694                           ProcMgr_MASTERKNLVIRT, &addrInfo,
695                           ProcMgr_AddrType_MasterPhys);
696             ProcMgr_close(&obj->procHandle);
697             /* Allocate memory for the MessageQCopyTransport object. */
698             Memory_free (NULL, obj, sizeof (MessageQCopyTransport_Object));
699 #if !defined(IPC_BUILD_OPTIMIZE)
700         }
701 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
702     }
703     else {
704         status = MessageQCopy_E_FAIL;
705         GT_setFailureReason (curTrace,
706                              GT_4CLASS,
707                              "MessageQCopy_detach",
708                              status,
709                              "Function called incorrectly!");
710     }
712     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_detach", status);
714     /*! @retval MessageQCopy_S_SUCCESS Operation successfully completed! */
715     return status;
719 /* Internal create function. */
720 static
721 MessageQCopy_Handle
722 _MessageQCopy_create (MessageQCopyTransport_Handle handle, UInt32 reserved,
723            String name, String desc,
724            void (*cb)(MessageQCopy_Handle, void *, int, void *, UInt32, UInt16),
725            Void *priv, UInt32 * endpoint)
727     Int32                       status          = MessageQCopy_S_SUCCESS;
728     MessageQCopy_Object *       obj             = NULL;
729     IArg                        key             = NULL;
730     Bool                        found           = FALSE;
731     Int                         i               = 0;
732     UInt16                      queueIndex      = 0;
733     MessageQCopy_Handle *       mq              = NULL;
734     Bool                        announce        = FALSE;
736     GT_5trace (curTrace, GT_ENTER, "_MessageQCopy_create",
737                handle, reserved, name, desc, endpoint);
739     GT_assert (curTrace, (endpoint != NULL));
740     /* name is optional and may be NULL. */
741     /* desc is optional and may be NULL. */
742     /* handle is optional and may be NULL. */
744 #if !defined(IPC_BUILD_OPTIMIZE)
745     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
746                                MessageQCopy_MAKE_MAGICSTAMP(0),
747                                MessageQCopy_MAKE_MAGICSTAMP(1))
748         == TRUE) {
749        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
750         status = MessageQCopy_E_INVALIDSTATE;
751         GT_setFailureReason (curTrace,
752                              GT_4CLASS,
753                              "_MessageQCopy_create",
754                              status,
755                              "MessageQCopy module not setup");
756     }
757     else if (endpoint == NULL) {
758         /*! @retval  MessageQCopy_E_INVALIDARG Invalid endpoint argument
759                                          provided. */
760         status = MessageQCopy_E_INVALIDARG;
761         GT_setFailureReason (curTrace,
762                              GT_4CLASS,
763                              "_MessageQCopy_create",
764                              status,
765                              "Invalid endpoint argument provided");
766     }
767     else if (name && String_nlen(name, RPMSG_NAME_SIZE - 1) == -1) {
768         /*! @retval  MessageQCopy_E_INVALIDARG Invalid name argument
769                                          provided. */
770         status = MessageQCopy_E_INVALIDARG;
771         GT_setFailureReason (curTrace,
772                              GT_4CLASS,
773                              "_MessageQCopy_create",
774                              status,
775                              "Invalid name argument provided");
776     }
777     else if (desc && String_nlen(desc, RPMSG_NAME_SIZE - 1) == -1) {
778         /*! @retval  MessageQCopy_E_INVALIDARG Invalid name argument
779                                          provided. */
780         status = MessageQCopy_E_INVALIDARG;
781         GT_setFailureReason (curTrace,
782                              GT_4CLASS,
783                              "_MessageQCopy_create",
784                              status,
785                              "Invalid desc argument provided");
786     }
787     else {
788 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
789         if (handle == NULL) {
790             mq = MessageQCopy_module->mq;
791             if (reserved != MessageQCopy_ADDRANY && name != NULL)
792                 announce = TRUE;
793         }
794         else {
795             mq = handle->mq;
796         }
798         /* Enter critical section protection. */
799         key = IGateProvider_enter (MessageQCopy_module->gateHandle);
801         if (reserved == MessageQCopy_ADDRANY)  {
802             /* Search the array for a free slot above reserved: */
803             for (i = MessageQCopy_MAXRESERVEDEPT + 1;
804                  (i < MessageQCopy_MAXMQS) && (found == FALSE) ; i++) {
805                 if (mq[i] == NULL) {
806                     queueIndex = i;
807                     found = TRUE;
808                     break;
809                 }
810             }
811         }
812         else if ((queueIndex = reserved) < MessageQCopy_MAXMQS) {
813             if (mq[queueIndex] == NULL)
814                 found = TRUE;
815         }
817         if (found) {
818             obj = Memory_calloc(NULL, sizeof(MessageQCopy_Object), 0, NULL);
819             if (obj != NULL) {
820                 /* Store our endpoint, and object: */
821                 obj->addr = queueIndex;
822                 obj->cb = cb;
823                 obj->priv = priv;
824                 if (handle)
825                     obj->procId = handle->procId;
826                 else
827                     obj->procId = MultiProc_self();
828                 if (name) {
829                     String_cpy (obj->name, name);
830                 }
831                 else
832                     obj->name[0] = '\0';
833                 if (desc) {
834                     String_cpy (obj->desc, desc);
835                 }
836                 else
837                     obj->desc[0] = '\0';
839                 mq[queueIndex] = obj;
841                 *endpoint = queueIndex;
843                 obj->announce = announce;
844                 if (obj->announce) {
845                     struct rpmsg_ns_msg msg;
847                     msg.addr = obj->addr;
848                     msg.flags = RPMSG_NS_CREATE;
849                     String_ncpy (msg.name, obj->name, RPMSG_NAME_SIZE);
850                     if (obj->desc)
851                         String_ncpy (msg.desc, obj->desc, RPMSG_NAME_SIZE);
852                     else
853                         msg.desc[0] = '\0';
855                     /* Send to all procs */
856                     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
857                         if (MessageQCopy_module->transport[i]) {
858                             UInt16 remoteProcId =
859                                       MessageQCopy_module->transport[i]->procId;
860                             UInt16 localProcId = MultiProc_self();
862                             IGateProvider_leave (
863                                                 MessageQCopy_module->gateHandle,
864                                                 key);
866                             status = MessageQCopy_send (
867                                   remoteProcId,
868                                   localProcId,
869                                   MessageQCopy_NS_PORT, obj->addr, &msg,
870                                   sizeof (struct rpmsg_ns_msg), TRUE);
872                             key = IGateProvider_enter (
873                                                MessageQCopy_module->gateHandle);
874                         }
875                     }
876                 }
878                 /* notify anyone registered of this channel */
879                 if (name) {
880                     for (i = 0; i < MessageQCopy_MAXMQS; i++) {
881                         if (MessageQCopy_module->mq[i] &&
882                             MessageQCopy_module->mq[i]->name) {
883                             if (!String_ncmp(name,
884                                              MessageQCopy_module->mq[i]->name,
885                                              RPMSG_NAME_SIZE)) {
886                                 if (MessageQCopy_module->mq[i]->notifyCb)
887                                     MessageQCopy_module->mq[i]->notifyCb(
888                                                      MessageQCopy_module->mq[i],
889                                                      obj->procId,
890                                                      obj->addr,
891                                                      obj->desc,
892                                                      TRUE);
893                             }
894                         }
895                     }
896                 }
897             }
898         }
900         /* Leave critical section protection. */
901         IGateProvider_leave (MessageQCopy_module->gateHandle, key);
902 #if !defined(IPC_BUILD_OPTIMIZE)
903     }
904 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
906     GT_1trace (curTrace, GT_LEAVE, "_MessageQCopy_create", status);
908     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
909     return (MessageQCopy_Handle)(obj);
913 /* Create an endpoint and handle.  Return a handle. */
914 MessageQCopy_Handle
915 MessageQCopy_create (UInt32 reserved, String name,
916            void (*cb)(MessageQCopy_Handle, void *, int, void *, UInt32, UInt16),
917            Void *priv, UInt32 * endpoint)
919     Int32                       status      = MessageQCopy_S_SUCCESS;
920     MessageQCopy_Object *       obj         = NULL;
922     GT_3trace (curTrace, GT_ENTER, "MessageQCopy_create",
923                reserved, name, endpoint);
925     GT_assert (curTrace, (endpoint != NULL));
926     /* name is optional and may be NULL. */
928 #if !defined(IPC_BUILD_OPTIMIZE)
929     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
930                                MessageQCopy_MAKE_MAGICSTAMP(0),
931                                MessageQCopy_MAKE_MAGICSTAMP(1))
932         == TRUE) {
933        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
934         status = MessageQCopy_E_INVALIDSTATE;
935         GT_setFailureReason (curTrace,
936                              GT_4CLASS,
937                              "MessageQCopy_create",
938                              status,
939                              "MessageQCopy module not setup");
940     }
941     else if (cb == NULL) {
942         /*! @retval  MessageQCopy_E_INVALIDARG Invalid cb argument
943                                          provided. */
944         status = MessageQCopy_E_INVALIDARG;
945         GT_setFailureReason (curTrace,
946                              GT_4CLASS,
947                              "MessageQCopy_create",
948                              status,
949                              "Invalid cb argument provided");
950     }
951     else {
952 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
954         obj = _MessageQCopy_create (NULL, reserved, name, NULL, cb, priv,
955                                     endpoint);
957 #if !defined(IPC_BUILD_OPTIMIZE)
958         if (obj == NULL) {
959             /*! @retval  MessageQCopy_E_FAIL Failed to create handle. */
960             status = MessageQCopy_E_FAIL;
961             GT_setFailureReason (curTrace,
962                                  GT_4CLASS,
963                                  "MessageQCopy_create",
964                                  status,
965                                  "Failed to create handle");
966         }
967     }
968 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
970     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_create", status);
972     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
973     return (MessageQCopy_Handle)obj;
977 /* Internal delete function. */
978 Int
979 MessageQCopy_delete (      MessageQCopy_Handle * handlePtr)
981     Int32                           status          = MessageQCopy_S_SUCCESS;
982     MessageQCopy_Object *           obj             = NULL;
983     IArg                            key             = NULL;
984     UInt32                          i               = 0;
985     UInt32                          j               = 0;
986     MessageQCopy_Handle *           mq              = NULL;
987     Bool                            found           = FALSE;
989     GT_1trace (curTrace, GT_ENTER, "MessageQCopy_delete", handlePtr);
991     GT_assert (curTrace, (handlePtr != NULL));
993 #if !defined(IPC_BUILD_OPTIMIZE)
994     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
995                                MessageQCopy_MAKE_MAGICSTAMP(0),
996                                MessageQCopy_MAKE_MAGICSTAMP(1))
997         == TRUE) {
998        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
999         status = MessageQCopy_E_INVALIDSTATE;
1000         GT_setFailureReason (curTrace,
1001                              GT_4CLASS,
1002                              "MessageQCopy_delete",
1003                              status,
1004                              "MessageQCopy module not setup");
1005     }
1006     else if (handlePtr == NULL) {
1007         /*! @retval  MessageQCopy_E_INVALIDARG Invalid handlePtr argument
1008                                          provided. */
1009         status = MessageQCopy_E_INVALIDARG;
1010         GT_setFailureReason (curTrace,
1011                              GT_4CLASS,
1012                              "MessageQCopy_delete",
1013                              status,
1014                              "Invalid handlePtr argument provided");
1015     }
1016     else if (*handlePtr == NULL) {
1017         /*! @retval  MessageQCopy_E_INVALIDARG Invalid *handlePtr argument
1018                                          provided. */
1019         status = MessageQCopy_E_INVALIDARG;
1020         GT_setFailureReason (curTrace,
1021                              GT_4CLASS,
1022                              "MessageQCopy_delete",
1023                              status,
1024                              "Invalid *handlePtr argument provided");
1025     }
1026     else {
1027 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1028         obj = (MessageQCopy_Object *)(*handlePtr);
1029         /* Search through all transports for this handle to validate that it is real */
1030         mq = MessageQCopy_module->mq;
1031         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1032             if (mq[i] == obj) {
1033                 found = TRUE;
1034                 break;
1035             }
1036         }
1037         if (!found) {
1038             for (j = 0; j < MultiProc_MAXPROCESSORS; j++) {
1039                 if (MessageQCopy_module->transport[j]) {
1040                     mq = MessageQCopy_module->transport[j]->mq;
1041                     for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1042                         if (mq[i] == obj) {
1043                             found = TRUE;
1044                             break;
1045                         }
1046                     }
1047                     if (found == TRUE)
1048                         break;
1049                 }
1050             }
1051         }
1052         if (found) {
1053             /* Enter critical section protection. */
1054             key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1056             if (obj->announce) {
1057                 struct rpmsg_ns_msg msg;
1059                 msg.addr = obj->addr;
1060                 msg.flags = RPMSG_NS_DESTROY;
1061                 String_ncpy(msg.name, obj->name, RPMSG_NAME_SIZE);
1062                 if (obj->desc)
1063                     String_ncpy(msg.desc, obj->desc, RPMSG_NAME_SIZE);
1064                 else
1065                     msg.desc[0] = '\0';
1067                 /* Send to all procs */
1068                 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1069                     if (MessageQCopy_module->transport[i]) {
1070                         UInt16 remoteProcId =
1071                                       MessageQCopy_module->transport[i]->procId;
1072                         UInt16 localProcId = MultiProc_self();
1074                         IGateProvider_leave (MessageQCopy_module->gateHandle,
1075                                              key);
1076                         status = MessageQCopy_send (remoteProcId, localProcId,
1077                                                    MessageQCopy_NS_PORT,
1078                                                    obj->addr, &msg,
1079                                                    sizeof (struct rpmsg_ns_msg),
1080                                                    TRUE);
1081                         key = IGateProvider_enter (
1082                                                MessageQCopy_module->gateHandle);
1083                     }
1084                 }
1085             }
1086             /* notify anyone registered of this channel */
1087             if (obj->name) {
1088                 for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1089                     if (MessageQCopy_module->mq[i] &&
1090                         MessageQCopy_module->mq[i]->name &&
1091                         obj->procId != MessageQCopy_module->mq[i]->procId) {
1092                         if (!String_ncmp(obj->name,
1093                                          MessageQCopy_module->mq[i]->name,
1094                                          RPMSG_NAME_SIZE)) {
1095                             if (MessageQCopy_module->mq[i]->notifyCb)
1096                                 MessageQCopy_module->mq[i]->notifyCb(
1097                                                      MessageQCopy_module->mq[i],
1098                                                      obj->procId,
1099                                                      obj->addr,
1100                                                      obj->desc,
1101                                                      FALSE);
1102                         }
1103                     }
1104                 }
1105             }
1107             mq[obj->addr] = NULL;
1109             /* Leave critical section protection. */
1110             IGateProvider_leave (MessageQCopy_module->gateHandle, key);
1112             Memory_free (NULL, obj, sizeof (MessageQCopy_Object));
1114             *handlePtr = NULL;
1115         }
1116         else {
1117             /*! @retval  MessageQCopy_E_INVALIDARG Invalid *handlePtr argument
1118                                              provided. */
1119             status = MessageQCopy_E_INVALIDARG;
1120             GT_setFailureReason (curTrace,
1121                                  GT_4CLASS,
1122                                  "MessageQCopy_delete",
1123                                  status,
1124                                  "Invalid *handlePtr argument provided");
1125         }
1126 #if !defined(IPC_BUILD_OPTIMIZE)
1127     }
1128 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1130     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_delete", status);
1132     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1133     return (status);
1137 /* Register to be notified of a MQ created on the remote core. */
1138 Int
1139 MessageQCopy_registerNotify (MessageQCopy_Handle handle,
1140                   Void (*cb)(MessageQCopy_Handle, UInt16, UInt32, Char *, Bool))
1142     Int32                               status      = MessageQCopy_S_SUCCESS;
1143     MessageQCopyTransport_Object *      obj         = NULL;
1144     IArg                                key         = NULL;
1145     Int                                 i           = 0;
1146     Int                                 j           = 0;
1147     Bool                                found       = FALSE;
1149     GT_2trace (curTrace, GT_ENTER, "MessageQCopy_registerNotify", handle, cb);
1151     GT_assert (curTrace, (handle != NULL));
1152     GT_assert (curTrace, (cb != NULL));
1154 #if !defined(IPC_BUILD_OPTIMIZE)
1155     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1156                                MessageQCopy_MAKE_MAGICSTAMP(0),
1157                                MessageQCopy_MAKE_MAGICSTAMP(1))
1158         == TRUE) {
1159        /*! @retval  MessageQCopy_E_INVALIDSTATE MessageQCopy module not setup */
1160         status = MessageQCopy_E_INVALIDSTATE;
1161         GT_setFailureReason (curTrace,
1162                              GT_4CLASS,
1163                              "MessageQCopy_registerNotify",
1164                              status,
1165                              "MessageQCopy module not setup");
1166     }
1167     else if (handle == NULL) {
1168         /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1169                                          provided. */
1170         status = MessageQCopy_E_INVALIDARG;
1171         GT_setFailureReason (curTrace,
1172                              GT_4CLASS,
1173                              "MessageQCopy_registerNotify",
1174                              status,
1175                              "Invalid handle argument provided");
1176     }
1177     else if (cb == NULL) {
1178         /*! @retval  MessageQCopy_E_INVALIDARG Invalid callback argument
1179                                          provided. */
1180         status = MessageQCopy_E_INVALIDARG;
1181         GT_setFailureReason (curTrace,
1182                              GT_4CLASS,
1183                              "MessageQCopy_registerNotify",
1184                              status,
1185                              "Invalid callback argument provided.");
1186     }
1187     else {
1188 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1189         /* Enter critical section protection. */
1190         key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1192         /*
1193          * Search through the local transport for this handle to validate that
1194          * it is real. The handle must be a local handle.
1195          */
1196         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1197             if (MessageQCopy_module->mq[i] == handle) {
1198                 found = TRUE;
1199                 break;
1200             }
1201         }
1203         if (found) {
1204             if (String_nlen(handle->name, RPMSG_NAME_SIZE - 1) == 0) {
1205                 /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1206                                                  provided. */
1207                 status = MessageQCopy_E_INVALIDARG;
1208                 GT_setFailureReason (curTrace,
1209                                      GT_4CLASS,
1210                                      "MessageQCopy_registerNotify",
1211                                      status,
1212                                      "Invalid handle argument provided");
1213             }
1214             else {
1215                 /* save the callback for future use */
1216                 handle->notifyCb = cb;
1218                 /* using the id_table, try to find a registered channel */
1219                 for (j = 0; j < MultiProc_MAXPROCESSORS; j++) {
1220                     obj = MessageQCopy_module->transport[j];
1222                     if (obj) {
1223                         for (i = 0; i < MessageQCopy_MAXMQS; i++) {
1224                             if (obj->mq[i] && obj->mq[i]->name) {
1225                                 if (!String_ncmp (handle->name,
1226                                                   obj->mq[i]->name,
1227                                                   RPMSG_NAME_SIZE) ) {
1228                                     /* call the callback */
1229                                     cb(handle, j, obj->mq[i]->addr,
1230                                        obj->mq[i]->desc, TRUE);
1231                                 }
1232                             }
1233                         }
1234                     }
1235                 }
1236             }
1237         }
1238         else {
1239             /*! @retval  MessageQCopy_E_INVALIDARG Invalid handle argument
1240                                              provided. */
1241             status = MessageQCopy_E_INVALIDARG;
1242             GT_setFailureReason (curTrace,
1243                                  GT_4CLASS,
1244                                  "MessageQCopy_registerNotify",
1245                                  status,
1246                                  "Invalid handle argument provided");
1247         }
1249         /* Leave critical section protection. */
1250         IGateProvider_leave (MessageQCopy_module->gateHandle, key);
1251 #if !defined(IPC_BUILD_OPTIMIZE)
1252     }
1253 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1255     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_registerNotify", status);
1257     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1258     return status;
1262 /*
1263  * Send the specified message to the specified proc using the specified src and
1264  * dst endpoints.
1265  */
1266 Int
1267 MessageQCopy_send (UInt16 dstProc, UInt16 srcProc, UInt32 dstEndpt,
1268                    UInt32 srcEndpt, Ptr data, UInt16 len, Bool wait)
1271     Int32                               status      = MessageQCopy_S_SUCCESS;
1272     MessageQCopyTransport_Object *      obj         = NULL;
1273     IArg                                key         = NULL;
1274     struct rpmsg_hdr *                  msg         = NULL;
1275     Int16                               token       = 0;
1277     GT_5trace (curTrace, GT_ENTER, "MessageQCopy_send",
1278                dstProc, dstEndpt, srcEndpt, data, len);
1280     GT_assert (curTrace, (dstProc < MultiProc_getNumProcessors()));
1281     GT_assert (curTrace, (data != NULL));
1282     GT_assert (curTrace, (len > 0));
1283     GT_assert (curTrace, (len <= (MessageQCopy_BUFSIZE -\
1284                                   sizeof(struct rpmsg_hdr))));
1286 #if !defined(IPC_BUILD_OPTIMIZE)
1287     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1288                                MessageQCopy_MAKE_MAGICSTAMP(0),
1289                                MessageQCopy_MAKE_MAGICSTAMP(1))
1290         == TRUE) {
1291        /*! @retval  MessageQCopy_E_INVALIDSTATE Notify module not setup */
1292         status = MessageQCopy_E_INVALIDSTATE;
1293         GT_setFailureReason (curTrace,
1294                              GT_4CLASS,
1295                              "MessageQCopy_send",
1296                              status,
1297                              "MessageQCopy module not setup");
1298     }
1299     else if (dstProc >= MultiProc_getNumProcessors()) {
1300         /*! @retval  MessageQCopy_E_INVALIDARG Invalid procId argument
1301                                          provided. */
1302         status = MessageQCopy_E_INVALIDARG;
1303         GT_setFailureReason (curTrace,
1304                              GT_4CLASS,
1305                              "MessageQCopy_send",
1306                              status,
1307                              "Invalid dstProc argument provided");
1308     }
1309     else if (srcProc != MultiProc_self()) {
1310         /*! @retval  MessageQCopy_E_INVALIDARG Invalid procId argument
1311                                          provided. */
1312         status = MessageQCopy_E_INVALIDARG;
1313         GT_setFailureReason (curTrace,
1314                              GT_4CLASS,
1315                              "MessageQCopy_send",
1316                              status,
1317                              "Invalid srcProc argument provided");
1318     }
1319     else if (data == NULL) {
1320         /*! @retval  MessageQCopy_E_INVALIDARG Invalid data argument
1321                                          provided. */
1322         status = MessageQCopy_E_INVALIDARG;
1323         GT_setFailureReason (curTrace,
1324                              GT_4CLASS,
1325                              "MessageQCopy_send",
1326                              status,
1327                              "Invalid data argument provided");
1328     }
1329     else if (len <= 0) {
1330         /*! @retval  MessageQCopy_E_INVALIDARG Invalid len specified. */
1331         status = MessageQCopy_E_INVALIDARG;
1332         GT_setFailureReason (curTrace,
1333                              GT_4CLASS,
1334                              "MessageQCopy_send",
1335                              status,
1336                              "Invalid len specified.");
1337     }
1338     else if (len > (MessageQCopy_BUFSIZE - sizeof(struct rpmsg_hdr))) {
1339         /*! @retval  MessageQCopy_E_INVALIDARG Invalid len specified. */
1340         status = MessageQCopy_E_INVALIDARG;
1341         GT_setFailureReason (curTrace,
1342                              GT_4CLASS,
1343                              "MessageQCopy_send",
1344                              status,
1345                              "Invalid len specified");
1346     }
1347     else if (dstEndpt == MessageQCopy_ADDRANY) {
1348         /*! @retval  MessageQCopy_E_INVALIDARG Invalid dstEndpt. */
1349         status = MessageQCopy_E_INVALIDARG;
1350         GT_setFailureReason (curTrace,
1351                              GT_4CLASS,
1352                              "MessageQCopy_send",
1353                              status,
1354                              "Invalid dstEndpt.");
1355     }
1356     else if (srcEndpt == MessageQCopy_ADDRANY) {
1357         /*! @retval  MessageQCopy_E_INVALIDARG Invalid srcEndpt. */
1358         status = MessageQCopy_E_INVALIDARG;
1359         GT_setFailureReason (curTrace,
1360                              GT_4CLASS,
1361                              "MessageQCopy_send",
1362                              status,
1363                              "Invalid srcEndpt.");
1364     }
1365     else {
1366 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1368         if (dstProc != MultiProc_self()) {
1369             /* Enter critical section protection. */
1370             key = IGateProvider_enter (MessageQCopy_module->gateHandle);
1372             obj = (MessageQCopyTransport_Object *)
1373                       MessageQCopy_module->transport[dstProc];
1375             if (obj == NULL) {
1376                 status = MessageQCopy_E_INVALIDARG;
1377                 GT_1trace(curTrace, GT_2CLASS,
1378                     "MessageQCopy_send: obj is NULL. Core %d is not attached",
1379                     dstProc);
1380             }
1381             else if (obj->vq[1] == NULL) {
1382                 status = MessageQCopy_E_INVALIDSTATE;
1383                 GT_setFailureReason (curTrace,
1384                                      GT_4CLASS,
1385                                      "MessageQCopy is not attached",
1386                                      status,
1387                                      "obj->vq[1] is NULL.");
1388             }
1389             else {
1390                 /* Get a buf from the UsedBuf list */
1391                 token = VirtQueue_getUsedBuf (obj->vq[1], (Void **)&msg);
1393                 if (token != -1 && msg != NULL) {
1394                     /* Copy the payload and set message header: */
1395                     Memory_copy(msg->data, data, len);
1396                     msg->len = len;
1397                     msg->dst = dstEndpt;
1398                     msg->src = srcEndpt;
1399                     msg->flags = 0;
1400                     msg->unused = 0;
1402                     VirtQueue_addAvailBuf(obj->vq[1], msg, sizeof(*msg) + len, token);
1403                     VirtQueue_kick(obj->vq[1]);
1404                 }
1405                 else {
1406                     status = MessageQCopy_E_FAIL;
1407                     GT_setFailureReason (curTrace,
1408                                          GT_4CLASS,
1409                                          "MessageQCopy_send",
1410                                          status,
1411                                          "getAvailBuf failed.");
1412                 }
1413             }
1414             IGateProvider_leave(MessageQCopy_module->gateHandle, key);
1415         }
1416         else {
1417             status = MessageQCopy_E_INVALIDARG;
1418             GT_setFailureReason (curTrace,
1419                                  GT_4CLASS,
1420                                  "MessageQCopy_send",
1421                                  status,
1422                                  "sending to local proc not supported.");
1423         }
1424 #if !defined(IPC_BUILD_OPTIMIZE)
1425     }
1426 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1428     GT_1trace (curTrace, GT_LEAVE, "MessageQCopy_send", status);
1430     /*! @retval MessageQCopy_S_SUCCESS Operation successful */
1431     return (status);
1435 /* =============================================================================
1436  *  Internal functions
1437  * =============================================================================
1438  */
1439  static
1440  Void
1441  _MessageQCopy_callback_NS(MessageQCopy_Handle handle, void *data,
1442                             int len, void *priv, UInt32 src, UInt16 srcProc)
1444     struct rpmsg_ns_msg *           msg         = data;
1445     UInt32                          endpoint    = MessageQCopy_ADDRANY;
1446     MessageQCopyTransport_Object *  transport   = NULL;
1448     GT_6trace (curTrace, GT_ENTER, "_MessageQCopy_callback_NS",
1449                handle, data, len, priv, src, srcProc);
1451     /* handle will be NULL */
1452     GT_assert (curTrace, (data != NULL));
1453     GT_assert (curTrace, (len >= sizeof(struct rpmsg_ns_msg)));
1454     GT_assert (curTrace, (srcProc < MultiProc_MAXPROCESSORS));
1456 #if !defined(IPC_BUILD_OPTIMIZE)
1457     if (Atomic_cmpmask_and_lt (&(MessageQCopy_module->refCount),
1458                                MessageQCopy_MAKE_MAGICSTAMP(0),
1459                                MessageQCopy_MAKE_MAGICSTAMP(1))
1460         == TRUE) {
1461         GT_setFailureReason (curTrace,
1462                              GT_4CLASS,
1463                              "_MessageQCopy_callback_NS",
1464                              MessageQCopy_E_INVALIDSTATE,
1465                              "rpmsg module not setup");
1466     }
1467     else if (data == NULL) {
1468         GT_setFailureReason (curTrace,
1469                              GT_4CLASS,
1470                              "_MessageQCopy_callback_NS",
1471                              MessageQCopy_E_INVALIDARG,
1472                              "Invalid data argument provided");
1473     }
1474     else if (len < sizeof(struct rpmsg_ns_msg)) {
1475         GT_setFailureReason (curTrace,
1476                              GT_4CLASS,
1477                              "_MessageQCopy_callback_NS",
1478                              MessageQCopy_E_INVALIDARG,
1479                              "Invalid len argument provided");
1480     }
1481     else if (srcProc >= MultiProc_MAXPROCESSORS) {
1482         GT_setFailureReason (curTrace,
1483                              GT_4CLASS,
1484                              "_MessageQCopy_callback_NS",
1485                              MessageQCopy_E_INVALIDARG,
1486                              "Invalid srcProc argument provided");
1487     }
1488     else {
1489 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1490         transport = MessageQCopy_module->transport[srcProc];
1492         if (transport) {
1493             /* Check flag to see if this is a create or destroy call */
1494             if (msg->flags & RPMSG_NS_DESTROY) {
1495                 MessageQCopy_delete (&transport->mq[msg->addr]);
1496             }
1497             else {
1498                 if (!_MessageQCopy_create (transport, msg->addr, msg->name,
1499                                            msg->desc, NULL, NULL, &endpoint)) {
1500                     GT_0trace (curTrace, GT_4CLASS,
1501                                "creating of MQ in NS Callback failed!");
1502                 }
1503             }
1504         }
1505 #if !defined(IPC_BUILD_OPTIMIZE)
1506     }
1507 #endif /* if !defined(IPC_BUILD_OPTIMIZE) */
1511 static
1512 Void
1513 _MessageQCopy_callback_bufReady (VirtQueue_Handle vq, void *arg)
1515     struct rpmsg_hdr *                  msg                 = NULL;
1516     Bool                                availBufAdded       = FALSE;
1517     MessageQCopyTransport_Object *      obj                 = NULL;
1518     MessageQCopy_Object *               mq                  = NULL;
1519     Int16                               token               = 0;
1521     if (vq) {
1522         obj = (MessageQCopyTransport_Object *)arg;
1523     }
1525     if (obj && obj->vq[0] == vq) {
1526         /* this is a notification of a ready message on the remote proc */
1527         /* Process all available buffers: */
1528         while ((token = VirtQueue_getUsedBuf(vq, (Void **)&msg)) != -1) {
1530             /* Put on a Message queue on this processor: */
1531             mq = MessageQCopy_module->mq[msg->dst];
1532             if (mq == NULL) {
1533                 Osal_printf ("_MessageQCopy_callback_bufReady: "
1534                              "no object for endpoint: %d", msg->dst);
1535             }
1536             else {
1537                 if (mq->cb) {
1538                     mq->cb(mq, msg->data, msg->len, mq->priv, msg->src,
1539                            obj->procId);
1540                 }
1541                 else {
1542                     Osal_printf ("_MessageQCopy_callback_bufReady: "
1543                                  "no callback for endpoint: %d", msg->dst);
1544                 }
1545                 VirtQueue_addAvailBuf(vq, msg, sizeof(*msg) + msg->len, token);
1546                 availBufAdded = TRUE;
1547             }
1548         }
1549         if (availBufAdded)  {
1550            /* Tell host we've processed the buffers: */
1551            VirtQueue_kick(vq);
1552         }
1553     }
1554     else if (obj && obj->vq[1] == vq) {
1555         /* this is a notification that the remote proc has processed a buffer */
1556     }
1557     else {
1558         /* something has gone wrong! */
1559     }
1563 #if defined (__cplusplus)
1565 #endif /* defined (__cplusplus) */