Rename: git mv src packages to complete application of ipc-j patches to ipcdev.
[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 /* message sent to remote procId */
67 typedef struct NameServerMsg {
68     MessageQ_MsgHeader header;  /* message header                   */
69     Bits32  value;              /* holds value                      */
70     Bits32  request;            /* whether its a request/response   */
71     Bits32  requestStatus;      /* status of request                */
72     Bits32  reserved;           /* reserved field                   */
73                                 /* name of NameServer instance      */
74     Bits32  instanceName[NAMEARRAYSZIE];
75                                 /* name of NameServer entry         */
76     Bits32  name[NAMEARRAYSZIE];
77 } NameServerMsg;
79 /*
80  *************************************************************************
81  *                       Instance functions
82  *************************************************************************
83  */
84 Void NameServerMessageQ_Instance_init(NameServerMessageQ_Object *obj,
85         UInt16 remoteProcId,
86         const NameServerMessageQ_Params *params)
87 {
88     /* Assert that remoteProcId is valid */
89     Assert_isTrue(remoteProcId != MultiProc_self() &&
90                   remoteProcId != MultiProc_INVALIDID,
91                   Ipc_A_invParam);
93     obj->remoteProcId = remoteProcId;
95     /* register the remote driver with NameServer */
96     ti_sdo_utils_NameServer_registerRemoteDriver(
97             NameServerMessageQ_Handle_upCast(obj), remoteProcId);
98 }
100 /*
101  *  ======== NameServerMessageQ_Instance_finalize ========
102  */
103 Void NameServerMessageQ_Instance_finalize(NameServerMessageQ_Object *obj)
105     /* unregister remote driver from NameServer module */
106     ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
109 /*
110  *************************************************************************
111  *                       Module functions
112  *************************************************************************
113  */
115 /*
116  *  ======== NameServerMessageQ_Module_startup ========
117  */
118 Int NameServerMessageQ_Module_startup(Int phase)
120     MessageQ_Params  messageQParams;
122     /* Ensure MessageQ and SyncSwi Module_startup() have completed */
123     if ((ti_sdo_ipc_MessageQ_Module_startupDone() == FALSE) ||
124         (ti_sysbios_syncs_SyncSwi_Module_startupDone() == FALSE)) {
125         return (Startup_NOTDONE);
126     }
128     /* Create the message queue for NameServer using SyncSwi */
129     MessageQ_Params_init(&messageQParams);
130     messageQParams.synchronizer = NameServerMessageQ_module->syncSwiHandle;
131     NameServerMessageQ_module->msgHandle =
132         (ti_sdo_ipc_MessageQ_Handle)MessageQ_create(NULL, &messageQParams);
134     /* assert msgHandle is not null */
135     Assert_isTrue(NameServerMessageQ_module->msgHandle != NULL,
136         Ipc_A_nullPointer);
138     /* assert this is the first MessageQ created */
139     Assert_isTrue((MessageQ_getQueueId((MessageQ_Handle)
140         NameServerMessageQ_module->msgHandle) & 0xffff) == 0,
141         NameServerMessageQ_A_reservedMsgQueueId);
143     return (Startup_DONE);
146 /*
147  *  ======== NameServerMessageQ_attach ========
148  */
149 Int NameServerMessageQ_attach(UInt16 remoteProcId, Ptr sharedAddr)
151     NameServerMessageQ_Params params;
152     NameServerMessageQ_Handle handle;
153     Int status = NameServerMessageQ_E_FAIL;
154     Error_Block eb;
156     Error_init(&eb);
158     /* init params */
159     NameServerMessageQ_Params_init(&params);
161     /* create driver to remote proc */
162     handle = NameServerMessageQ_create(remoteProcId,
163                                        &params,
164                                        &eb);
166     if (handle != NULL) {
167         status = NameServerMessageQ_S_SUCCESS;
168     }
170     return (status);
173 /*
174  *  ======== NameServerMessageQ_detach ========
175  */
176 Int NameServerMessageQ_detach(UInt16 remoteProcId)
178     NameServerMessageQ_Handle handle;
179     Int status = NameServerMessageQ_S_SUCCESS;
181     /* return handle based upon procId */
182     for (handle = NameServerMessageQ_Object_first(); handle != NULL;
183         handle = NameServerMessageQ_Object_next(handle)) {
184         if (handle->remoteProcId == remoteProcId) {
185             break;
186         }
187     }
189     if (handle == NULL) {
190         status = NameServerMessageQ_E_FAIL;
191     }
192     else {
193         NameServerMessageQ_delete(&handle);
194     }
196     return (status);
199 /*
200  *  ======== NameServerMessageQ_get ========
201  */
202 Int NameServerMessageQ_get(NameServerMessageQ_Object *obj,
203                            String instanceName,
204                            String name,
205                            Ptr value,
206                            UInt32 *valueLen,
207                            ISync_Handle syncHandle,
208                            Error_Block *eb)
210     Int len;
211     Int status;
212     IArg key;
213     MessageQ_QueueId queueId;
214     NameServerMsg    *msg;
215     Semaphore_Handle semRemoteWait = NameServerMessageQ_module->semRemoteWait;
216     GateMutex_Handle gateMutex = NameServerMessageQ_module->gateMutex;
218     /* enter gate - prevent multiple threads from entering */
219     key = GateMutex_enter(gateMutex);
221     /* alloc a message from specified heap */
222     msg = (NameServerMsg *)MessageQ_alloc(NameServerMessageQ_heapId,
223                                           sizeof(NameServerMsg));
225     /* make sure message is not NULL */
226     if (msg == NULL) {
227         Error_raise(eb, NameServerMessageQ_E_outOfMemory,
228                     NameServerMessageQ_heapId, 0);
229         return (NameServer_E_OSFAILURE);
230     }
232     /* make sure this is a request message */
233     msg->request = NameServerMessageQ_REQUEST;
234     msg->requestStatus = 0;
236     /* get the length of instanceName */
237     len = strlen(instanceName);
239     /* assert length is smaller than max (must have room for null character) */
240     Assert_isTrue(len < MAXNAMEINCHAR, NameServerMessageQ_A_nameIsTooLong);
242     /* copy the name of instance into putMsg */
243     strncpy((Char *)msg->instanceName, instanceName, len);
245     /* get the length of name */
246     len = strlen(name);
248     /* assert length is smaller than max (must have room for null character) */
249     Assert_isTrue(len < MAXNAMEINCHAR, NameServerMessageQ_A_nameIsTooLong);
251     /* copy the name of nameserver entry into putMsg */
252     strncpy((Char *)msg->name, name, len);
254     /* determine the queueId based upon the processor */
255     queueId = (UInt32)obj->remoteProcId << 16;
257     /* set the reply procId */
258     MessageQ_setReplyQueue(
259         (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
260         (MessageQ_Msg)msg);
262     /* send message to remote processor. */
263     status = MessageQ_put(queueId, (MessageQ_Msg)msg);
265     /* make sure message sent successfully */
266     if (status < 0) {
267         /* free the message */
268         MessageQ_free((MessageQ_Msg)msg);
270         return (NameServer_E_FAIL);
271     }
273     /* pend here until we get a response back from remote processor */
274     status = Semaphore_pend(semRemoteWait, NameServerMessageQ_timeout);
276     if (status == FALSE) {
277         /* return timeout failure */
278         return (NameServer_E_OSFAILURE);
279     }
281     /* get the message */
282     msg = NameServerMessageQ_module->msg;
284     if (msg->requestStatus) {
285         /* name is found */
287         /* set length to amount of data that was copied */
288         *valueLen = sizeof(Bits32);
290         /* set the contents of value */
291         memcpy(value, &(msg->value), sizeof(Bits32));
293         /* set the status to success */
294         status = NameServer_S_SUCCESS;
295     }
296     else {
297         /* name is not found */
299         /* set status to not found */
300         status = NameServer_E_NOTFOUND;
301     }
303     /* free the message */
304     MessageQ_free((MessageQ_Msg)msg);
306     /* leave the gate */
307     GateMutex_leave(gateMutex, key);
309     /* return success status */
310     return (status);
313 /*
314  *  ======== NameServerMessageQ_sharedMemReq ========
315  */
316 SizeT NameServerMessageQ_sharedMemReq(Ptr sharedAddr)
318     return (0);
321 /*
322  *  ======== NameServerMessageQ_swiFxn ========
323  */
324 Void NameServerMessageQ_swiFxn(UArg arg0, UArg arg1)
326     NameServerMsg     *msg;
327     NameServer_Handle handle;
328     MessageQ_QueueId  queueId;
329     Int               status = NameServer_E_FAIL;
330     Semaphore_Handle  semRemoteWait = NameServerMessageQ_module->semRemoteWait;
332     /* drain all messages in the messageQ */
333     while (1) {
334         /* get a message, this never waits */
335         status = MessageQ_get(
336                     (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
337                     (MessageQ_Msg *)&msg, 0);
339         /* if no message then return */
340         if (status != MessageQ_S_SUCCESS) {
341             break;
342         }
344         if (msg->request == NameServerMessageQ_REQUEST) {
345             /* reset value of status */
346             status = NameServer_E_FAIL;
348             /*
349              *  Message is a request. Lookup name in NameServer table.
350              *  Send a response message back to source processor.
351              */
352             handle = NameServer_getHandle((String)msg->instanceName);
354             if (handle != NULL) {
355                 /* Search for the NameServer entry */
356                 status = NameServer_getLocalUInt32(handle,
357                          (String)msg->name, &msg->value);
358             }
360             /* set the request status */
361             if (status < 0) {
362                 msg->requestStatus = 0;
363             }
364             else {
365                 msg->requestStatus = 1;
366             }
368             /* specify message as a response */
369             msg->request = NameServerMessageQ_RESPONSE;
371             /* get the remote processor from the msg header */
372             queueId = (UInt32)(msg->header.replyProc) << 16;
374             /* send response message to remote processor */
375             MessageQ_put(queueId, (MessageQ_Msg)msg);
376         }
377         else {
378             /*
379              *  This is a response message. At any given time, there is
380              *  only one of these outstanding because of semMultiBlock.
381              *  This allows us to safely set the Module state's msg pointer
382              *  and post semaphore.
383              */
384             NameServerMessageQ_module->msg = msg;
385             Semaphore_post(semRemoteWait);
386         }
388     }