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)
104 {
105 /* unregister remote driver from NameServer module */
106 ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
107 }
109 /*
110 *************************************************************************
111 * Module functions
112 *************************************************************************
113 */
115 /*
116 * ======== NameServerMessageQ_Module_startup ========
117 */
118 Int NameServerMessageQ_Module_startup(Int phase)
119 {
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);
144 }
146 /*
147 * ======== NameServerMessageQ_attach ========
148 */
149 Int NameServerMessageQ_attach(UInt16 remoteProcId, Ptr sharedAddr)
150 {
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(¶ms);
161 /* create driver to remote proc */
162 handle = NameServerMessageQ_create(remoteProcId,
163 ¶ms,
164 &eb);
166 if (handle != NULL) {
167 status = NameServerMessageQ_S_SUCCESS;
168 }
170 return (status);
171 }
173 /*
174 * ======== NameServerMessageQ_detach ========
175 */
176 Int NameServerMessageQ_detach(UInt16 remoteProcId)
177 {
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);
197 }
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)
209 {
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);
311 }
313 /*
314 * ======== NameServerMessageQ_sharedMemReq ========
315 */
316 SizeT NameServerMessageQ_sharedMemReq(Ptr sharedAddr)
317 {
318 return (0);
319 }
321 /*
322 * ======== NameServerMessageQ_swiFxn ========
323 */
324 Void NameServerMessageQ_swiFxn(UArg arg0, UArg arg1)
325 {
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 }
389 }