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;
123 MessageQ_QueueId queueId;
125 /* Ensure MessageQ and SyncSwi Module_startup() have completed */
126 if ((ti_sdo_ipc_MessageQ_Module_startupDone() == FALSE) ||
127 (ti_sysbios_syncs_SyncSwi_Module_startupDone() == FALSE)) {
128 return (Startup_NOTDONE);
129 }
131 /* Create the message queue for NameServer using SyncSwi */
132 MessageQ_Params2_init(&messageQParams);
133 messageQParams.synchronizer = NameServerMessageQ_module->syncSwiHandle;
134 messageQParams.queueIndex = MESSAGEQ_INDEX;
135 NameServerMessageQ_module->msgHandle =
136 (ti_sdo_ipc_MessageQ_Handle)MessageQ_create2(NULL, &messageQParams);
138 /* assert msgHandle is not null */
139 Assert_isTrue(NameServerMessageQ_module->msgHandle != NULL,
140 Ipc_A_nullPointer);
141 /* Additonal check for case with assert disabled */
142 if(NameServerMessageQ_module->msgHandle == NULL) {
143 return Startup_NOTDONE;
144 }
146 queueId = MessageQ_getQueueId((MessageQ_Handle)
147 NameServerMessageQ_module->msgHandle);
148 /* assert this is the first MessageQ created */
149 Assert_isTrue( (queueId & 0xffff) == MESSAGEQ_INDEX,
150 NameServerMessageQ_A_reservedMsgQueueId);
151 /* Additonal check for case with assert disabled */
152 if ((queueId & 0xffff) != MESSAGEQ_INDEX) {
153 return Startup_NOTDONE;
154 }
156 return (Startup_DONE);
157 }
159 /*
160 * ======== NameServerMessageQ_attach ========
161 */
162 Int NameServerMessageQ_attach(UInt16 remoteProcId, Ptr sharedAddr)
163 {
164 NameServerMessageQ_Params params;
165 NameServerMessageQ_Handle handle;
166 Int status = NameServerMessageQ_E_FAIL;
167 Error_Block eb;
169 Error_init(&eb);
171 /* init params */
172 NameServerMessageQ_Params_init(¶ms);
174 /* create driver to remote proc */
175 handle = NameServerMessageQ_create(remoteProcId,
176 ¶ms,
177 &eb);
179 if (handle != NULL) {
180 status = NameServerMessageQ_S_SUCCESS;
181 }
183 return (status);
184 }
186 /*
187 * ======== NameServerMessageQ_detach ========
188 */
189 Int NameServerMessageQ_detach(UInt16 remoteProcId)
190 {
191 NameServerMessageQ_Handle handle;
192 Int status = NameServerMessageQ_S_SUCCESS;
194 /* return handle based upon procId */
195 for (handle = NameServerMessageQ_Object_first(); handle != NULL;
196 handle = NameServerMessageQ_Object_next(handle)) {
197 if (handle->remoteProcId == remoteProcId) {
198 break;
199 }
200 }
202 if (handle == NULL) {
203 status = NameServerMessageQ_E_FAIL;
204 }
205 else {
206 NameServerMessageQ_delete(&handle);
207 }
209 return (status);
210 }
212 /*
213 * ======== NameServerMessageQ_get ========
214 */
215 Int NameServerMessageQ_get(NameServerMessageQ_Object *obj,
216 String instanceName,
217 String name,
218 Ptr value,
219 UInt32 *valueLen,
220 ISync_Handle syncHandle,
221 Error_Block *eb)
222 {
223 Int status;
224 IArg key;
225 MessageQ_QueueId queueId;
226 NameServerMsg *msg;
227 Semaphore_Handle semRemoteWait = NameServerMessageQ_module->semRemoteWait;
228 GateMutex_Handle gateMutex = NameServerMessageQ_module->gateMutex;
230 /* enter gate - prevent multiple threads from entering */
231 key = GateMutex_enter(gateMutex);
233 /* alloc a message from specified heap */
234 msg = (NameServerMsg *)MessageQ_alloc(NameServerMessageQ_heapId,
235 sizeof(NameServerMsg));
237 /* make sure message is not NULL */
238 if (msg == NULL) {
239 Error_raise(eb, NameServerMessageQ_E_outOfMemory,
240 NameServerMessageQ_heapId, 0);
241 return (NameServer_E_OSFAILURE);
242 }
244 /* make sure this is a request message */
245 msg->request = NameServerMessageQ_REQUEST;
246 msg->requestStatus = 0;
248 /* assert length is smaller than max (must have room for null character) */
249 Assert_isTrue(strlen(instanceName) < MAXNAMEINCHAR,
250 NameServerMessageQ_A_nameIsTooLong);
252 /* copy the name of instance into putMsg */
253 strncpy((Char *)msg->instanceName, instanceName, MAXNAMEINCHAR - 1);
254 ((Char *)msg->instanceName) [MAXNAMEINCHAR - 1] = '0';
256 /* assert length is smaller than max (must have room for null character) */
257 Assert_isTrue(strlen(name) < MAXNAMEINCHAR,
258 NameServerMessageQ_A_nameIsTooLong);
260 /* copy the name of nameserver entry into putMsg */
261 strncpy((Char *)msg->name, name, MAXNAMEINCHAR - 1);
262 ((Char *)msg->name) [MAXNAMEINCHAR - 1] = '0';
264 /* determine the queueId based upon the processor */
265 queueId = MessageQ_openQueueId(MESSAGEQ_INDEX, obj->remoteProcId);
267 /* set the reply procId */
268 MessageQ_setReplyQueue(
269 (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
270 (MessageQ_Msg)msg);
272 /* send message to remote processor. */
273 status = MessageQ_put(queueId, (MessageQ_Msg)msg);
275 /* make sure message sent successfully */
276 if (status < 0) {
277 /* free the message */
278 MessageQ_free((MessageQ_Msg)msg);
280 return (NameServer_E_FAIL);
281 }
283 /* pend here until we get a response back from remote processor */
284 status = Semaphore_pend(semRemoteWait, NameServerMessageQ_timeout);
286 if (status == FALSE) {
287 /* return timeout failure */
288 return (NameServer_E_OSFAILURE);
289 }
291 /* get the message */
292 msg = NameServerMessageQ_module->msg;
294 if (msg->requestStatus) {
295 /* name is found */
297 /* set length to amount of data that was copied */
298 *valueLen = sizeof(Bits32);
300 /* set the contents of value */
301 memcpy(value, &(msg->value), sizeof(Bits32));
303 /* set the status to success */
304 status = NameServer_S_SUCCESS;
305 }
306 else {
307 /* name is not found */
309 /* set status to not found */
310 status = NameServer_E_NOTFOUND;
311 }
313 /* free the message */
314 MessageQ_free((MessageQ_Msg)msg);
316 /* leave the gate */
317 GateMutex_leave(gateMutex, key);
319 /* return success status */
320 return (status);
321 }
323 /*
324 * ======== NameServerMessageQ_sharedMemReq ========
325 */
326 SizeT NameServerMessageQ_sharedMemReq(Ptr sharedAddr)
327 {
328 return (0);
329 }
331 /*
332 * ======== NameServerMessageQ_swiFxn ========
333 */
334 Void NameServerMessageQ_swiFxn(UArg arg0, UArg arg1)
335 {
336 NameServerMsg *msg;
337 NameServer_Handle handle;
338 MessageQ_QueueId queueId;
339 Int status = NameServer_E_FAIL;
340 Semaphore_Handle semRemoteWait = NameServerMessageQ_module->semRemoteWait;
342 /* drain all messages in the messageQ */
343 while (1) {
344 /* get a message, this never waits */
345 status = MessageQ_get(
346 (MessageQ_Handle)NameServerMessageQ_module->msgHandle,
347 (MessageQ_Msg *)&msg, 0);
349 /* if no message then return */
350 if (status != MessageQ_S_SUCCESS) {
351 break;
352 }
354 if (msg->request == NameServerMessageQ_REQUEST) {
355 /* reset value of status */
356 status = NameServer_E_FAIL;
358 /*
359 * Message is a request. Lookup name in NameServer table.
360 * Send a response message back to source processor.
361 */
362 handle = NameServer_getHandle((String)msg->instanceName);
364 if (handle != NULL) {
365 /* Search for the NameServer entry */
366 status = NameServer_getLocalUInt32(handle,
367 (String)msg->name, &msg->value);
368 }
370 /* set the request status */
371 if (status < 0) {
372 msg->requestStatus = 0;
373 }
374 else {
375 msg->requestStatus = 1;
376 }
378 /* specify message as a response */
379 msg->request = NameServerMessageQ_RESPONSE;
381 /* get the remote processor from the msg header */
382 queueId = (UInt32)(msg->header.replyProc) << 16;
384 /* send response message to remote processor */
385 MessageQ_put(queueId, (MessageQ_Msg)msg);
386 }
387 else {
388 /*
389 * This is a response message. At any given time, there is
390 * only one of these outstanding because of semMultiBlock.
391 * This allows us to safely set the Module state's msg pointer
392 * and post semaphore.
393 */
394 NameServerMessageQ_module->msg = msg;
395 Semaphore_post(semRemoteWait);
396 }
398 }
399 }