1 /*
2 * Copyright (c) 2012-2014, 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 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);
100 }
102 /*
103 * ======== NameServerMessageQ_Instance_finalize ========
104 */
105 Void NameServerMessageQ_Instance_finalize(NameServerMessageQ_Object *obj)
106 {
107 /* unregister remote driver from NameServer module */
108 ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
109 }
111 /*
112 *************************************************************************
113 * Module functions
114 *************************************************************************
115 */
117 /*
118 * ======== NameServerMessageQ_Module_startup ========
119 */
120 Int NameServerMessageQ_Module_startup(Int phase)
121 {
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);
147 }
149 /*
150 * ======== NameServerMessageQ_attach ========
151 */
152 Int NameServerMessageQ_attach(UInt16 remoteProcId, Ptr sharedAddr)
153 {
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(¶ms);
164 /* create driver to remote proc */
165 handle = NameServerMessageQ_create(remoteProcId,
166 ¶ms,
167 &eb);
169 if (handle != NULL) {
170 status = NameServerMessageQ_S_SUCCESS;
171 }
173 return (status);
174 }
176 /*
177 * ======== NameServerMessageQ_detach ========
178 */
179 Int NameServerMessageQ_detach(UInt16 remoteProcId)
180 {
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);
200 }
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)
212 {
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);
314 }
316 /*
317 * ======== NameServerMessageQ_sharedMemReq ========
318 */
319 SizeT NameServerMessageQ_sharedMemReq(Ptr sharedAddr)
320 {
321 return (0);
322 }
324 /*
325 * ======== NameServerMessageQ_swiFxn ========
326 */
327 Void NameServerMessageQ_swiFxn(UArg arg0, UArg arg1)
328 {
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 }
392 }