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 * ======== NameServerRemoteNotify.c ========
34 */
36 /* Remove Windows strncpy warning */
37 #define _CRT_SECURE_NO_DEPRECATE 1
39 #include <xdc/std.h>
40 #include <string.h>
41 #include <stdlib.h>
43 #include <xdc/runtime/Assert.h>
44 #include <xdc/runtime/Error.h>
45 #include <xdc/runtime/knl/ISync.h>
47 #include <ti/sysbios/BIOS.h>
48 #include <ti/sysbios/hal/Cache.h>
49 #include <ti/sysbios/knl/Swi.h>
50 #include <ti/sysbios/knl/Semaphore.h>
52 #include "package/internal/NameServerRemoteNotify.xdc.h"
54 #include <ti/sdo/ipc/Ipc.h>
55 #include <ti/sdo/ipc/_Notify.h>
56 #include <ti/sdo/ipc/_GateMP.h>
57 #include <ti/sdo/ipc/_SharedRegion.h>
58 #include <ti/sdo/utils/_MultiProc.h>
59 #include <ti/sdo/utils/_NameServer.h>
61 /* Need to use reserved notify events */
62 #undef NameServerRemoteNotify_notifyEventId
63 #define NameServerRemoteNotify_notifyEventId \
64 ti_sdo_ipc_nsremote_NameServerRemoteNotify_notifyEventId + \
65 (UInt32)((UInt32)Notify_SYSTEMKEY << 16)
67 /* private constant values */
68 #define NameServerRemoteNotify_RequestMsg 1
69 #define NameServerRemoteNotify_ResponseMsg 2
71 /*
72 *************************************************************************
73 * Instance functions
74 *************************************************************************
75 */
76 Int NameServerRemoteNotify_Instance_init(NameServerRemoteNotify_Object *obj,
77 UInt16 remoteProcId, const NameServerRemoteNotify_Params *params,
78 Error_Block *eb)
79 {
80 Int offset = 0;
81 Int status;
82 Semaphore_Params semParams;
83 Semaphore_Handle semHandle;
84 Swi_Params swiParams;
85 Swi_Handle swiHandle;
87 /* Assert that a NameServerRemoteNotify_Params has been supplied */
88 Assert_isTrue(params != NULL, Ipc_A_nullArgument);
90 /* Assert that remoteProcId is valid */
91 Assert_isTrue(remoteProcId != MultiProc_self() &&
92 remoteProcId != MultiProc_INVALIDID,
93 Ipc_A_invParam);
95 /* determine the offset based upon own id and remote's id */
96 if (MultiProc_self() > remoteProcId) {
97 offset = 1;
98 }
100 obj->regionId = SharedRegion_getId(params->sharedAddr);
101 obj->localState = NameServerRemoteNotify_IDLE;
102 obj->remoteState = NameServerRemoteNotify_IDLE;
104 /* assert that sharedAddr is cache aligned */
105 Assert_isTrue(SharedRegion_getCacheLineSize(obj->regionId) == 0 ||
106 ((UInt32)params->sharedAddr %
107 SharedRegion_getCacheLineSize(obj->regionId) == 0),
108 Ipc_A_addrNotCacheAligned);
110 /* asset message structure size is cache aligned */
111 Assert_isTrue(SharedRegion_getCacheLineSize(obj->regionId) == 0 ||
112 (sizeof(NameServerRemoteNotify_Message) %
113 SharedRegion_getCacheLineSize(obj->regionId)) == 0,
114 NameServerRemoteNotify_A_messageSize);
116 obj->msg[0] = (NameServerRemoteNotify_Message *)(params->sharedAddr);
117 obj->msg[1] = (NameServerRemoteNotify_Message *)((UInt32)obj->msg[0] +
118 sizeof(NameServerRemoteNotify_Message));
119 obj->gate = params->gate;
120 obj->remoteProcId = remoteProcId;
122 /* construct the remoteWait semaphore */
123 semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
124 Semaphore_Params_init(&semParams);
125 Semaphore_construct(Semaphore_struct(semHandle), 0, &semParams);
127 /* construct the multiBlock semaphore */
128 semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
129 Semaphore_Params_init(&semParams);
130 Semaphore_construct(Semaphore_struct(semHandle), 1, &semParams);
132 /* construct swi which handles the request message */
133 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
134 Swi_Params_init(&swiParams);
135 swiParams.arg0 = (UArg)obj;
136 swiParams.priority = 0; /* lowest priority */
137 Swi_construct(Swi_struct(swiHandle),
138 (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnRequest,
139 &swiParams, eb);
141 /* construct swi which handles the response message */
142 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
143 Swi_Params_init(&swiParams);
144 swiParams.arg0 = (UArg)obj;
145 swiParams.priority = 0; /* lowest priority */
146 Swi_construct(Swi_struct(swiHandle),
147 (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnResponse,
148 &swiParams, eb);
150 /* initialize own side of message struct only */
151 obj->msg[offset]->requestStatus = 0;
152 obj->msg[offset]->value = 0;
153 obj->msg[offset]->valueLen = 0;
155 memset(obj->msg[offset]->instanceName, 0,
156 sizeof(obj->msg[offset]->instanceName));
157 memset(obj->msg[offset]->name, 0,
158 sizeof(obj->msg[offset]->name));
160 /* determine cacheability of the object from the regionId */
161 obj->cacheEnable = SharedRegion_isCacheEnabled(obj->regionId);
162 if (obj->cacheEnable) {
163 /* write back shared memory that was modified */
164 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
165 Cache_Type_ALL, TRUE);
166 }
168 /* register notify callback function to handle message notifications */
169 status = Notify_registerEventSingle(remoteProcId, 0,
170 NameServerRemoteNotify_notifyEventId,
171 (Notify_FnNotifyCbck)NameServerRemoteNotify_cbFxn, (UArg)obj);
173 /* if not successful return */
174 if (status < 0) {
175 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
176 return (1);
177 }
179 /* register the remote driver with NameServer */
180 ti_sdo_utils_NameServer_registerRemoteDriver(
181 NameServerRemoteNotify_Handle_upCast(obj), remoteProcId);
183 return (0);
184 }
186 /*
187 * ======== NameServerRemoteNotify_Instance_finalize ========
188 */
189 Void NameServerRemoteNotify_Instance_finalize(
190 NameServerRemoteNotify_Object *obj, Int status)
191 {
192 Semaphore_Handle semHandle;
193 Swi_Handle swiHandle;
195 if (status == 0) {
196 /* unregister remote driver from NameServer module */
197 ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
199 /* unregister event from Notify module */
200 Notify_unregisterEventSingle(obj->remoteProcId, 0,
201 NameServerRemoteNotify_notifyEventId);
202 }
204 semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
205 if (semHandle != NULL) {
206 Semaphore_destruct(Semaphore_struct(semHandle));
207 }
209 semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
210 if (semHandle != NULL) {
211 Semaphore_destruct(Semaphore_struct(semHandle));
212 }
214 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
215 if (swiHandle != NULL) {
216 Swi_destruct(Swi_struct(swiHandle));
217 }
219 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
220 if (swiHandle != NULL) {
221 Swi_destruct(Swi_struct(swiHandle));
222 }
223 }
225 /*
226 *************************************************************************
227 * Module functions
228 *************************************************************************
229 */
231 /*
232 * ======== NameServerRemoteNotify_attach ========
233 */
234 Int NameServerRemoteNotify_attach(UInt16 remoteProcId, Ptr sharedAddr)
235 {
236 NameServerRemoteNotify_Params nsrParams;
237 NameServerRemoteNotify_Handle handle;
238 Int status = NameServerRemoteNotify_E_FAIL;
239 Error_Block eb;
241 /* Assert that the default GateMP is not NULL */
242 Assert_isTrue(GateMP_getDefaultRemote() != NULL, Ipc_A_internal);
244 Error_init(&eb);
246 /* Use default GateMP */
247 NameServerRemoteNotify_Params_init(&nsrParams);
248 nsrParams.gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
250 /* determine the address */
251 nsrParams.sharedAddr = sharedAddr;
253 /* create only if notify driver has been created to remote proc */
254 if (Notify_intLineRegistered(remoteProcId, 0)) {
255 handle = NameServerRemoteNotify_create(remoteProcId,
256 &nsrParams,
257 &eb);
258 if (handle != NULL) {
259 status = NameServerRemoteNotify_S_SUCCESS;
260 }
261 }
263 return (status);
264 }
266 /*
267 * ======== NameServerRemoteNotify_cbFxn ========
268 */
269 Void NameServerRemoteNotify_cbFxn(UInt16 procId, UInt16 lineId, UInt32 eventId,
270 UArg arg, UInt32 payload)
271 {
272 NameServerRemoteNotify_Object *obj;
273 Swi_Handle swiHandle = NULL;
275 obj = (NameServerRemoteNotify_Object *)arg;
278 switch (payload)
279 {
280 case NameServerRemoteNotify_RequestMsg:
281 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
283 /* set object state (used by ROV) */
284 obj->remoteState = NameServerRemoteNotify_RECEIVE_REQUEST;
285 break;
287 case NameServerRemoteNotify_ResponseMsg:
288 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
290 /* set object state (used by ROV) */
291 obj->localState = NameServerRemoteNotify_RECEIVE_RESPONSE;
292 break;
294 default:
295 /* We should never get here but assert if we do */
296 Assert_isTrue(swiHandle != NULL, Ipc_A_internal);
297 }
299 Swi_post(swiHandle);
300 }
302 /*
303 * ======== NameServerRemoteNotify_detach ========
304 */
305 Int NameServerRemoteNotify_detach(UInt16 remoteProcId)
306 {
307 NameServerRemoteNotify_Handle handle;
308 Int status = NameServerRemoteNotify_S_SUCCESS;
310 for (handle = NameServerRemoteNotify_Object_first(); handle != NULL;
311 handle = NameServerRemoteNotify_Object_next(handle)) {
312 if (handle->remoteProcId == remoteProcId) {
313 break;
314 }
315 }
317 if (handle == NULL) {
318 status = NameServerRemoteNotify_E_FAIL;
319 }
320 else {
321 NameServerRemoteNotify_delete(&handle);
322 }
324 return (status);
325 }
327 /*
328 * ======== NameServerRemoteNotify_get ========
329 */
330 Int NameServerRemoteNotify_get(NameServerRemoteNotify_Object *obj,
331 String instanceName, String name, Ptr value, UInt32 *valueLen,
332 ISync_Handle syncHandle, Error_Block *eb)
333 {
334 Int len;
335 Int retval = NameServer_E_NOTFOUND;
336 Int offset = 0;
337 Int status;
338 Int notifyStatus;
339 Semaphore_Handle semRemoteWait;
340 Semaphore_Handle semMultiBlock;
342 Assert_isTrue(*valueLen <= 300, NameServerRemoteNotify_A_invalidValueLen);
344 semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
345 semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
347 /* prevent multiple threads from entering */
348 Semaphore_pend(semMultiBlock, BIOS_WAIT_FOREVER);
350 if (MultiProc_self() > obj->remoteProcId) {
351 offset = 1;
352 }
354 if (obj->cacheEnable) {
355 /* Make sure there's no outstanding message */
356 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
357 Cache_Type_ALL, TRUE);
358 }
360 /* this is a request message */
361 obj->msg[offset]->requestStatus = 0;
362 obj->msg[offset]->valueLen = *valueLen;
364 /* copy the name of instance into shared memory */
365 len = strlen(instanceName);
366 strncpy((Char *)obj->msg[offset]->instanceName, instanceName, len + 1);
368 /* copy the name of nameserver entry into shared memory */
369 len = strlen(name);
370 strncpy((Char *)obj->msg[offset]->name, name, len + 1);
372 /* set object state (used by ROV) */
373 obj->localState = NameServerRemoteNotify_SEND_REQUEST;
375 if (obj->cacheEnable) {
376 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
377 Cache_Type_ALL, TRUE);
378 }
380 /*
381 * Send the notification to remote processor. Do not wait here since
382 * we hold the GateMP.
383 */
384 notifyStatus = Notify_sendEvent(obj->remoteProcId, 0,
385 NameServerRemoteNotify_notifyEventId,
386 NameServerRemoteNotify_RequestMsg, TRUE);
388 if (notifyStatus < 0) {
389 /* undo previous options */
390 obj->msg[offset]->valueLen = 0;
392 /* post the semaphore to make sure it doesn't block */
393 Semaphore_post(semMultiBlock);
395 return (retval);
396 }
398 /* pend here until we get a notification back from remote processor */
399 status = Semaphore_pend(semRemoteWait, NameServerRemoteNotify_timeout);
401 if (status == FALSE) {
402 retval = NameServer_E_TIMEOUT;
403 }
404 else {
405 /* getting here means we got the notification back */
407 if (obj->cacheEnable) {
408 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
409 Cache_Type_ALL, TRUE);
410 }
412 /* if successful request then copy to value */
413 if (obj->msg[offset]->requestStatus == TRUE) {
415 /* copy to value */
416 if (obj->msg[offset]->valueLen == sizeof(UInt32)) {
417 memcpy(value, &(obj->msg[offset]->value), sizeof(UInt32));
418 }
419 else {
420 memcpy(value, &(obj->msg[offset]->valueBuf),
421 obj->msg[offset]->valueLen);
422 }
424 /* set length to amount of data that was copied */
425 *valueLen = obj->msg[offset]->valueLen;
427 /* set the status */
428 retval = NameServer_S_SUCCESS;
429 }
431 /* set object state (used by ROV) */
432 obj->localState = NameServerRemoteNotify_IDLE;
433 }
435 Semaphore_post(semMultiBlock);
437 return (retval);
438 }
440 /*
441 * ======== NameServerRemoteNotify_sharedMemReq ========
442 */
443 SizeT NameServerRemoteNotify_sharedMemReq(Ptr sharedAddr)
444 {
445 /*
446 * Two Message structs are required.
447 * One for sending request and one for sending response.
448 */
449 if (ti_sdo_utils_MultiProc_numProcessors > 1) {
450 return (2 * sizeof(NameServerRemoteNotify_Message));
451 }
453 return (0);
454 }
456 /*
457 * ======== NameServerRemoteNotify_swiFxnRequest ========
458 */
459 Void NameServerRemoteNotify_swiFxnRequest(UArg arg)
460 {
461 Int count = NameServer_E_FAIL;
462 Int remoteId;
463 UInt32 valueLen;
464 NameServer_Handle handle;
465 NameServerRemoteNotify_Object *obj;
466 #ifndef xdc_runtime_Assert_DISABLE_ALL
467 Int status;
468 #endif
470 obj = (NameServerRemoteNotify_Object *)arg;
472 /* compute index to remote message */
473 remoteId = (MultiProc_self() > obj->remoteProcId) ? 0 : 1;
475 if (obj->cacheEnable) {
476 Cache_inv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
477 Cache_Type_ALL, TRUE);
478 }
480 /* get the NameServer handle */
481 handle = NameServer_getHandle((String)obj->msg[remoteId]->instanceName);
482 valueLen = obj->msg[remoteId]->valueLen;
484 if (handle != NULL) {
485 /* Search for the NameServer entry */
486 if (valueLen == sizeof(UInt32)) {
487 count = NameServer_getLocalUInt32(handle,
488 (String)obj->msg[remoteId]->name, &obj->msg[remoteId]->value);
489 }
490 else {
491 count = NameServer_getLocal(handle,
492 (String)obj->msg[remoteId]->name,
493 &obj->msg[remoteId]->valueBuf, &valueLen);
494 }
495 }
497 /*
498 * If an entry was found, set requestStatus to TRUE
499 * and valueLen to the size of data that was copied.
500 */
501 if (count == NameServer_S_SUCCESS) {
502 obj->msg[remoteId]->requestStatus = TRUE;
503 obj->msg[remoteId]->valueLen = valueLen;
504 }
506 /* set object state (used by ROV) */
507 obj->remoteState = NameServerRemoteNotify_SEND_RESPONSE;
509 if (obj->cacheEnable) {
510 Cache_wbInv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
511 Cache_Type_ALL, TRUE);
512 }
514 /* must wait to prevent dropped events, even though this is a swi */
515 #ifndef xdc_runtime_Assert_DISABLE_ALL
516 status =
517 #endif
518 Notify_sendEvent(obj->remoteProcId, 0,
519 NameServerRemoteNotify_notifyEventId,
520 NameServerRemoteNotify_ResponseMsg, TRUE);
522 /* The NS query could fail, but the reply should never fail */
523 Assert_isTrue(status >= 0, Ipc_A_internal);
525 /* set object state (used by ROV) */
526 obj->remoteState = NameServerRemoteNotify_IDLE;
527 }
529 /*
530 * ======== NameServerRemoteNotify_swiFxnResponse ========
531 */
532 Void NameServerRemoteNotify_swiFxnResponse(UArg arg)
533 {
534 NameServerRemoteNotify_Object *obj;
535 Semaphore_Handle sem;
537 obj = (NameServerRemoteNotify_Object *)arg;
539 /* post the semaphore to unblock waiting task */
540 sem = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
541 Semaphore_post(sem);
542 }
544 /*
545 * ======== NameServerRemoteNotify_getHandle ========
546 */
547 NameServerRemoteNotify_Handle NameServerRemoteNotify_getHandle(
548 UInt16 remoteProcId)
549 {
550 NameServerRemoteNotify_Handle obj;
552 for (obj = NameServerRemoteNotify_Object_first(); obj != NULL;
553 obj = NameServerRemoteNotify_Object_next(obj)) {
554 if (obj->remoteProcId == remoteProcId) {
555 break;
556 }
557 }
559 return (obj);
560 }