48a1dd15d92df863b5990cb254c21a321b3e82b7
[ipc/ipcdev.git] / packages / ti / sdo / ipc / nsremote / NameServerMessageQ.c
1 /*
2  * Copyright (c) 2012-2015 Texas Instruments Incorporated - http://www.ti.com
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 NAMEARRAYSIZE   (((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[NAMEARRAYSIZE];
77                                 /* name of NameServer entry         */
78     Bits32  name[NAMEARRAYSIZE];
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 status;
214     IArg key;
215     MessageQ_QueueId queueId;
216     NameServerMsg    *msg;
217     Semaphore_Handle semRemoteWait = NameServerMessageQ_module->semRemoteWait;
218     GateMutex_Handle gateMutex = NameServerMessageQ_module->gateMutex;
220     /* enter gate - prevent multiple threads from entering */
221     key = GateMutex_enter(gateMutex);
223     /* alloc a message from specified heap */
224     msg = (NameServerMsg *)MessageQ_alloc(NameServerMessageQ_heapId,
225                                           sizeof(NameServerMsg));
227     /* make sure message is not NULL */
228     if (msg == NULL) {
229         Error_raise(eb, NameServerMessageQ_E_outOfMemory,
230                     NameServerMessageQ_heapId, 0);
231         return (NameServer_E_OSFAILURE);
232     }
234     /* make sure this is a request message */
235     msg->request = NameServerMessageQ_REQUEST;
236     msg->requestStatus = 0;
238     /* assert length is smaller than max (must have room for null character) */
239     Assert_isTrue(strlen(instanceName) < MAXNAMEINCHAR,
240             NameServerMessageQ_A_nameIsTooLong);
242     /* copy the name of instance into putMsg */
243     strncpy((Char *)msg->instanceName, instanceName, MAXNAMEINCHAR - 1);
244     ((Char *)msg->instanceName) [MAXNAMEINCHAR - 1] = '0';
246     /* assert length is smaller than max (must have room for null character) */
247     Assert_isTrue(strlen(name) < MAXNAMEINCHAR,
248             NameServerMessageQ_A_nameIsTooLong);
250     /* copy the name of nameserver entry into putMsg */
251     strncpy((Char *)msg->name, name, MAXNAMEINCHAR - 1);
252     ((Char *)msg->name) [MAXNAMEINCHAR - 1] = '0';
254     /* determine the queueId based upon the processor */
255     queueId = MessageQ_openQueueId(MESSAGEQ_INDEX, obj->remoteProcId);
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     }