Merge recent 3.00 changes into 3.10
[ipc/ipcdev.git] / packages / ti / sdo / ipc / nsremote / NameServerMessageQ.c
1 /*
2  * Copyright (c) 2012-2013, Texas Instruments Incorporated
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * *  Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  *
12  * *  Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * *  Neither the name of Texas Instruments Incorporated nor the names of
17  *    its contributors may be used to endorse or promote products derived
18  *    from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  */
32 /*
33  *  ======== NameServerMessageQ.c ========
34  */
36 #include <xdc/std.h>
37 #include <string.h>
38 #include <stdlib.h>
40 #include <xdc/runtime/Assert.h>
41 #include <xdc/runtime/Error.h>
42 #include <xdc/runtime/Startup.h>
43 #include <xdc/runtime/knl/ISync.h>
45 #include <ti/sysbios/BIOS.h>
46 #include <ti/sysbios/knl/Swi.h>
47 #include <ti/sysbios/knl/Semaphore.h>
48 #include <ti/sysbios/syncs/SyncSwi.h>
49 #include <ti/sysbios/gates/GateMutex.h>
51 #include "package/internal/NameServerMessageQ.xdc.h"
53 #include <ti/sdo/ipc/Ipc.h>
54 #include <ti/sdo/ipc/_MessageQ.h>
55 #include <ti/sdo/utils/_MultiProc.h>
56 #include <ti/sdo/utils/_NameServer.h>
58 /*
59  *  Determine name array size:
60  *    maxNameLen / ((bits per char) / (bits per byte) * (sizeof(Bits32)))
61  */
62 #define MAXNAMEINCHAR   (NameServerMessageQ_maxNameLen / \
63                         (xdc_target__bitsPerChar / 8))
64 #define NAMEARRAYSZIE   (((MAXNAMEINCHAR - 1) / sizeof(Bits32)) + 1)
66 #define MESSAGEQ_INDEX 0
68 /* message sent to remote procId */
69 typedef struct NameServerMsg {
70     MessageQ_MsgHeader header;  /* message header                   */
71     Bits32  value;              /* holds value                      */
72     Bits32  request;            /* whether its a request/response   */
73     Bits32  requestStatus;      /* status of request                */
74     Bits32  reserved;           /* reserved field                   */
75                                 /* name of NameServer instance      */
76     Bits32  instanceName[NAMEARRAYSZIE];
77                                 /* name of NameServer entry         */
78     Bits32  name[NAMEARRAYSZIE];
79 } NameServerMsg;
81 /*
82  *************************************************************************
83  *                       Instance functions
84  *************************************************************************
85  */
86 Void NameServerMessageQ_Instance_init(NameServerMessageQ_Object *obj,
87         UInt16 remoteProcId,
88         const NameServerMessageQ_Params *params)
89 {
90     /* Assert that remoteProcId is valid */
91     Assert_isTrue(remoteProcId != MultiProc_self() &&
92                   remoteProcId != MultiProc_INVALIDID,
93                   Ipc_A_invParam);
95     obj->remoteProcId = remoteProcId;
97     /* register the remote driver with NameServer */
98     ti_sdo_utils_NameServer_registerRemoteDriver(
99             NameServerMessageQ_Handle_upCast(obj), remoteProcId);
102 /*
103  *  ======== NameServerMessageQ_Instance_finalize ========
104  */
105 Void NameServerMessageQ_Instance_finalize(NameServerMessageQ_Object *obj)
107     /* unregister remote driver from NameServer module */
108     ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
111 /*
112  *************************************************************************
113  *                       Module functions
114  *************************************************************************
115  */
117 /*
118  *  ======== NameServerMessageQ_Module_startup ========
119  */
120 Int NameServerMessageQ_Module_startup(Int phase)
122     MessageQ_Params2  messageQParams;
124     /* Ensure MessageQ and SyncSwi Module_startup() have completed */
125     if ((ti_sdo_ipc_MessageQ_Module_startupDone() == FALSE) ||
126         (ti_sysbios_syncs_SyncSwi_Module_startupDone() == FALSE)) {
127         return (Startup_NOTDONE);
128     }
130     /* Create the message queue for NameServer using SyncSwi */
131     MessageQ_Params2_init(&messageQParams);
132     messageQParams.synchronizer = NameServerMessageQ_module->syncSwiHandle;
133     messageQParams.queueIndex = MESSAGEQ_INDEX;
134     NameServerMessageQ_module->msgHandle =
135         (ti_sdo_ipc_MessageQ_Handle)MessageQ_create2(NULL, &messageQParams);
137     /* assert msgHandle is not null */
138     Assert_isTrue(NameServerMessageQ_module->msgHandle != NULL,
139         Ipc_A_nullPointer);
141     /* assert this is the first MessageQ created */
142     Assert_isTrue((MessageQ_getQueueId((MessageQ_Handle)
143         NameServerMessageQ_module->msgHandle) & 0xffff) == MESSAGEQ_INDEX,
144         NameServerMessageQ_A_reservedMsgQueueId);
146     return (Startup_DONE);
149 /*
150  *  ======== NameServerMessageQ_attach ========
151  */
152 Int NameServerMessageQ_attach(UInt16 remoteProcId, Ptr sharedAddr)
154     NameServerMessageQ_Params params;
155     NameServerMessageQ_Handle handle;
156     Int status = NameServerMessageQ_E_FAIL;
157     Error_Block eb;
159     Error_init(&eb);
161     /* init params */
162     NameServerMessageQ_Params_init(&params);
164     /* create driver to remote proc */
165     handle = NameServerMessageQ_create(remoteProcId,
166                                        &params,
167                                        &eb);
169     if (handle != NULL) {
170         status = NameServerMessageQ_S_SUCCESS;
171     }
173     return (status);
176 /*
177  *  ======== NameServerMessageQ_detach ========
178  */
179 Int NameServerMessageQ_detach(UInt16 remoteProcId)
181     NameServerMessageQ_Handle handle;
182     Int status = NameServerMessageQ_S_SUCCESS;
184     /* return handle based upon procId */
185     for (handle = NameServerMessageQ_Object_first(); handle != NULL;
186         handle = NameServerMessageQ_Object_next(handle)) {
187         if (handle->remoteProcId == remoteProcId) {
188             break;
189         }
190     }
192     if (handle == NULL) {
193         status = NameServerMessageQ_E_FAIL;
194     }
195     else {
196         NameServerMessageQ_delete(&handle);
197     }
199     return (status);
202 /*
203  *  ======== NameServerMessageQ_get ========
204  */
205 Int NameServerMessageQ_get(NameServerMessageQ_Object *obj,
206                            String instanceName,
207                            String name,
208                            Ptr value,
209                            UInt32 *valueLen,
210                            ISync_Handle syncHandle,
211                            Error_Block *eb)
213     Int len;
214     Int status;
215     IArg key;
216     MessageQ_QueueId queueId;
217     NameServerMsg    *msg;
218     Semaphore_Handle semRemoteWait = NameServerMessageQ_module->semRemoteWait;
219     GateMutex_Handle gateMutex = NameServerMessageQ_module->gateMutex;
221     /* enter gate - prevent multiple threads from entering */
222     key = GateMutex_enter(gateMutex);
224     /* alloc a message from specified heap */
225     msg = (NameServerMsg *)MessageQ_alloc(NameServerMessageQ_heapId,
226                                           sizeof(NameServerMsg));
228     /* make sure message is not NULL */
229     if (msg == NULL) {
230         Error_raise(eb, NameServerMessageQ_E_outOfMemory,
231                     NameServerMessageQ_heapId, 0);
232         return (NameServer_E_OSFAILURE);
233     }
235     /* make sure this is a request message */
236     msg->request = NameServerMessageQ_REQUEST;
237     msg->requestStatus = 0;
239     /* get the length of instanceName */
240     len = strlen(instanceName);
242     /* assert length is smaller than max (must have room for null character) */
243     Assert_isTrue(len < MAXNAMEINCHAR, NameServerMessageQ_A_nameIsTooLong);
245     /* copy the name of instance into putMsg */
246     strncpy((Char *)msg->instanceName, instanceName, len);
248     /* get the length of name */
249     len = strlen(name);
251     /* assert length is smaller than max (must have room for null character) */
252     Assert_isTrue(len < MAXNAMEINCHAR, NameServerMessageQ_A_nameIsTooLong);
254     /* copy the name of nameserver entry into putMsg */
255     strncpy((Char *)msg->name, name, len);
257     /* determine the queueId based upon the processor */
258     queueId = MessageQ_openQueueId(MESSAGEQ_INDEX, obj->remoteProcId);
260     /* set the reply procId */
261     MessageQ_setReplyQueue(
262         (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
263         (MessageQ_Msg)msg);
265     /* send message to remote processor. */
266     status = MessageQ_put(queueId, (MessageQ_Msg)msg);
268     /* make sure message sent successfully */
269     if (status < 0) {
270         /* free the message */
271         MessageQ_free((MessageQ_Msg)msg);
273         return (NameServer_E_FAIL);
274     }
276     /* pend here until we get a response back from remote processor */
277     status = Semaphore_pend(semRemoteWait, NameServerMessageQ_timeout);
279     if (status == FALSE) {
280         /* return timeout failure */
281         return (NameServer_E_OSFAILURE);
282     }
284     /* get the message */
285     msg = NameServerMessageQ_module->msg;
287     if (msg->requestStatus) {
288         /* name is found */
290         /* set length to amount of data that was copied */
291         *valueLen = sizeof(Bits32);
293         /* set the contents of value */
294         memcpy(value, &(msg->value), sizeof(Bits32));
296         /* set the status to success */
297         status = NameServer_S_SUCCESS;
298     }
299     else {
300         /* name is not found */
302         /* set status to not found */
303         status = NameServer_E_NOTFOUND;
304     }
306     /* free the message */
307     MessageQ_free((MessageQ_Msg)msg);
309     /* leave the gate */
310     GateMutex_leave(gateMutex, key);
312     /* return success status */
313     return (status);
316 /*
317  *  ======== NameServerMessageQ_sharedMemReq ========
318  */
319 SizeT NameServerMessageQ_sharedMemReq(Ptr sharedAddr)
321     return (0);
324 /*
325  *  ======== NameServerMessageQ_swiFxn ========
326  */
327 Void NameServerMessageQ_swiFxn(UArg arg0, UArg arg1)
329     NameServerMsg     *msg;
330     NameServer_Handle handle;
331     MessageQ_QueueId  queueId;
332     Int               status = NameServer_E_FAIL;
333     Semaphore_Handle  semRemoteWait = NameServerMessageQ_module->semRemoteWait;
335     /* drain all messages in the messageQ */
336     while (1) {
337         /* get a message, this never waits */
338         status = MessageQ_get(
339                     (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
340                     (MessageQ_Msg *)&msg, 0);
342         /* if no message then return */
343         if (status != MessageQ_S_SUCCESS) {
344             break;
345         }
347         if (msg->request == NameServerMessageQ_REQUEST) {
348             /* reset value of status */
349             status = NameServer_E_FAIL;
351             /*
352              *  Message is a request. Lookup name in NameServer table.
353              *  Send a response message back to source processor.
354              */
355             handle = NameServer_getHandle((String)msg->instanceName);
357             if (handle != NULL) {
358                 /* Search for the NameServer entry */
359                 status = NameServer_getLocalUInt32(handle,
360                          (String)msg->name, &msg->value);
361             }
363             /* set the request status */
364             if (status < 0) {
365                 msg->requestStatus = 0;
366             }
367             else {
368                 msg->requestStatus = 1;
369             }
371             /* specify message as a response */
372             msg->request = NameServerMessageQ_RESPONSE;
374             /* get the remote processor from the msg header */
375             queueId = (UInt32)(msg->header.replyProc) << 16;
377             /* send response message to remote processor */
378             MessageQ_put(queueId, (MessageQ_Msg)msg);
379         }
380         else {
381             /*
382              *  This is a response message. At any given time, there is
383              *  only one of these outstanding because of semMultiBlock.
384              *  This allows us to safely set the Module state's msg pointer
385              *  and post semaphore.
386              */
387             NameServerMessageQ_module->msg = msg;
388             Semaphore_post(semRemoteWait);
389         }
391     }