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);
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 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);
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 }