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 * ======== 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(((UInt32)params->sharedAddr %
106 SharedRegion_getCacheLineSize(obj->regionId) == 0),
107 Ipc_A_addrNotCacheAligned);
109 /* asset message structure size is cache aligned */
110 Assert_isTrue((sizeof(NameServerRemoteNotify_Message) %
111 SharedRegion_getCacheLineSize(obj->regionId)) == 0,
112 NameServerRemoteNotify_A_messageSize);
114 obj->msg[0] = (NameServerRemoteNotify_Message *)(params->sharedAddr);
115 obj->msg[1] = (NameServerRemoteNotify_Message *)((UInt32)obj->msg[0] +
116 sizeof(NameServerRemoteNotify_Message));
117 obj->gate = params->gate;
118 obj->remoteProcId = remoteProcId;
120 /* construct the remoteWait semaphore */
121 semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
122 Semaphore_Params_init(&semParams);
123 Semaphore_construct(Semaphore_struct(semHandle), 0, &semParams);
125 /* construct the multiBlock semaphore */
126 semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
127 Semaphore_Params_init(&semParams);
128 Semaphore_construct(Semaphore_struct(semHandle), 1, &semParams);
130 /* construct swi which handles the request message */
131 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
132 Swi_Params_init(&swiParams);
133 swiParams.arg0 = (UArg)obj;
134 swiParams.priority = 0; /* lowest priority */
135 Swi_construct(Swi_struct(swiHandle),
136 (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnRequest,
137 &swiParams, eb);
139 /* construct swi which handles the response message */
140 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
141 Swi_Params_init(&swiParams);
142 swiParams.arg0 = (UArg)obj;
143 swiParams.priority = 0; /* lowest priority */
144 Swi_construct(Swi_struct(swiHandle),
145 (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxnResponse,
146 &swiParams, eb);
148 /* initialize own side of message struct only */
149 obj->msg[offset]->requestStatus = 0;
150 obj->msg[offset]->value = 0;
151 obj->msg[offset]->valueLen = 0;
153 memset(obj->msg[offset]->instanceName, 0,
154 sizeof(obj->msg[offset]->instanceName));
155 memset(obj->msg[offset]->name, 0,
156 sizeof(obj->msg[offset]->name));
158 /* determine cacheability of the object from the regionId */
159 obj->cacheEnable = SharedRegion_isCacheEnabled(obj->regionId);
160 if (obj->cacheEnable) {
161 /* write back shared memory that was modified */
162 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
163 Cache_Type_ALL, TRUE);
164 }
166 /* register notify callback function to handle message notifications */
167 status = Notify_registerEventSingle(remoteProcId, 0,
168 NameServerRemoteNotify_notifyEventId,
169 (Notify_FnNotifyCbck)NameServerRemoteNotify_cbFxn, (UArg)obj);
171 /* if not successful return */
172 if (status < 0) {
173 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
174 return (1);
175 }
177 /* register the remote driver with NameServer */
178 ti_sdo_utils_NameServer_registerRemoteDriver(
179 NameServerRemoteNotify_Handle_upCast(obj), remoteProcId);
181 return (0);
182 }
184 /*
185 * ======== NameServerRemoteNotify_Instance_finalize ========
186 */
187 Void NameServerRemoteNotify_Instance_finalize(
188 NameServerRemoteNotify_Object *obj, Int status)
189 {
190 Semaphore_Handle semHandle;
191 Swi_Handle swiHandle;
193 if (status == 0) {
194 /* unregister remote driver from NameServer module */
195 ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
197 /* unregister event from Notify module */
198 Notify_unregisterEventSingle(obj->remoteProcId, 0,
199 NameServerRemoteNotify_notifyEventId);
200 }
202 semHandle = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
203 if (semHandle != NULL) {
204 Semaphore_destruct(Semaphore_struct(semHandle));
205 }
207 semHandle = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
208 if (semHandle != NULL) {
209 Semaphore_destruct(Semaphore_struct(semHandle));
210 }
212 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
213 if (swiHandle != NULL) {
214 Swi_destruct(Swi_struct(swiHandle));
215 }
217 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
218 if (swiHandle != NULL) {
219 Swi_destruct(Swi_struct(swiHandle));
220 }
221 }
223 /*
224 *************************************************************************
225 * Module functions
226 *************************************************************************
227 */
229 /*
230 * ======== NameServerRemoteNotify_attach ========
231 */
232 Int NameServerRemoteNotify_attach(UInt16 remoteProcId, Ptr sharedAddr)
233 {
234 NameServerRemoteNotify_Params nsrParams;
235 NameServerRemoteNotify_Handle handle;
236 Int status = NameServerRemoteNotify_E_FAIL;
237 Error_Block eb;
239 /* Assert that the default GateMP is not NULL */
240 Assert_isTrue(GateMP_getDefaultRemote() != NULL, Ipc_A_internal);
242 Error_init(&eb);
244 /* Use default GateMP */
245 NameServerRemoteNotify_Params_init(&nsrParams);
246 nsrParams.gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
248 /* determine the address */
249 nsrParams.sharedAddr = sharedAddr;
251 /* create only if notify driver has been created to remote proc */
252 if (Notify_intLineRegistered(remoteProcId, 0)) {
253 handle = NameServerRemoteNotify_create(remoteProcId,
254 &nsrParams,
255 &eb);
256 if (handle != NULL) {
257 status = NameServerRemoteNotify_S_SUCCESS;
258 }
259 }
261 return (status);
262 }
264 /*
265 * ======== NameServerRemoteNotify_cbFxn ========
266 */
267 Void NameServerRemoteNotify_cbFxn(UInt16 procId, UInt16 lineId, UInt32 eventId,
268 UArg arg, UInt32 payload)
269 {
270 NameServerRemoteNotify_Object *obj;
271 Swi_Handle swiHandle;
273 obj = (NameServerRemoteNotify_Object *)arg;
276 switch (payload)
277 {
278 case NameServerRemoteNotify_RequestMsg:
279 swiHandle = NameServerRemoteNotify_Instance_State_swiRequest(obj);
281 /* set object state (used by ROV) */
282 obj->remoteState = NameServerRemoteNotify_RECEIVE_REQUEST;
283 break;
285 case NameServerRemoteNotify_ResponseMsg:
286 swiHandle = NameServerRemoteNotify_Instance_State_swiResponse(obj);
288 /* set object state (used by ROV) */
289 obj->localState = NameServerRemoteNotify_RECEIVE_RESPONSE;
290 break;
291 }
293 Swi_post(swiHandle);
294 }
296 /*
297 * ======== NameServerRemoteNotify_detach ========
298 */
299 Int NameServerRemoteNotify_detach(UInt16 remoteProcId)
300 {
301 NameServerRemoteNotify_Handle handle;
302 Int status = NameServerRemoteNotify_S_SUCCESS;
304 for (handle = NameServerRemoteNotify_Object_first(); handle != NULL;
305 handle = NameServerRemoteNotify_Object_next(handle)) {
306 if (handle->remoteProcId == remoteProcId) {
307 break;
308 }
309 }
311 if (handle == NULL) {
312 status = NameServerRemoteNotify_E_FAIL;
313 }
314 else {
315 NameServerRemoteNotify_delete(&handle);
316 }
318 return (status);
319 }
321 /*
322 * ======== NameServerRemoteNotify_get ========
323 */
324 Int NameServerRemoteNotify_get(NameServerRemoteNotify_Object *obj,
325 String instanceName, String name, Ptr value, UInt32 *valueLen,
326 ISync_Handle syncHandle, Error_Block *eb)
327 {
328 Int len;
329 Int retval = NameServer_E_NOTFOUND;
330 Int offset = 0;
331 Int status;
332 Int notifyStatus;
333 Semaphore_Handle semRemoteWait;
334 Semaphore_Handle semMultiBlock;
336 Assert_isTrue(*valueLen <= 300, NameServerRemoteNotify_A_invalidValueLen);
338 semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
339 semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
341 /* prevent multiple threads from entering */
342 Semaphore_pend(semMultiBlock, BIOS_WAIT_FOREVER);
344 if (MultiProc_self() > obj->remoteProcId) {
345 offset = 1;
346 }
348 if (obj->cacheEnable) {
349 /* Make sure there's no outstanding message */
350 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
351 Cache_Type_ALL, TRUE);
352 }
354 /* this is a request message */
355 obj->msg[offset]->requestStatus = 0;
356 obj->msg[offset]->valueLen = *valueLen;
358 /* copy the name of instance into shared memory */
359 len = strlen(instanceName);
360 strncpy((Char *)obj->msg[offset]->instanceName, instanceName, len + 1);
362 /* copy the name of nameserver entry into shared memory */
363 len = strlen(name);
364 strncpy((Char *)obj->msg[offset]->name, name, len + 1);
366 /* set object state (used by ROV) */
367 obj->localState = NameServerRemoteNotify_SEND_REQUEST;
369 if (obj->cacheEnable) {
370 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
371 Cache_Type_ALL, TRUE);
372 }
374 /*
375 * Send the notification to remote processor. Do not wait here since
376 * we hold the GateMP.
377 */
378 notifyStatus = Notify_sendEvent(obj->remoteProcId, 0,
379 NameServerRemoteNotify_notifyEventId,
380 NameServerRemoteNotify_RequestMsg, TRUE);
382 if (notifyStatus < 0) {
383 /* undo previous options */
384 obj->msg[offset]->valueLen = 0;
386 /* post the semaphore to make sure it doesn't block */
387 Semaphore_post(semMultiBlock);
389 return (retval);
390 }
392 /* pend here until we get a notification back from remote processor */
393 status = Semaphore_pend(semRemoteWait, NameServerRemoteNotify_timeout);
395 if (status == FALSE) {
396 retval = NameServer_E_OSFAILURE;
397 }
398 else {
399 /* getting here means we got the notification back */
401 if (obj->cacheEnable) {
402 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
403 Cache_Type_ALL, TRUE);
404 }
406 /* if successful request then copy to value */
407 if (obj->msg[offset]->requestStatus == TRUE) {
409 /* copy to value */
410 if (obj->msg[offset]->valueLen == sizeof(UInt32)) {
411 memcpy(value, &(obj->msg[offset]->value), sizeof(UInt32));
412 }
413 else {
414 memcpy(value, &(obj->msg[offset]->valueBuf),
415 obj->msg[offset]->valueLen);
416 }
418 /* set length to amount of data that was copied */
419 *valueLen = obj->msg[offset]->valueLen;
421 /* set the status */
422 retval = NameServer_S_SUCCESS;
423 }
425 /* set object state (used by ROV) */
426 obj->localState = NameServerRemoteNotify_IDLE;
427 }
429 Semaphore_post(semMultiBlock);
431 return (retval);
432 }
434 /*
435 * ======== NameServerRemoteNotify_sharedMemReq ========
436 */
437 SizeT NameServerRemoteNotify_sharedMemReq(Ptr sharedAddr)
438 {
439 /*
440 * Two Message structs are required.
441 * One for sending request and one for sending response.
442 */
443 if (ti_sdo_utils_MultiProc_numProcessors > 1) {
444 return (2 * sizeof(NameServerRemoteNotify_Message));
445 }
447 return (0);
448 }
450 /*
451 * ======== NameServerRemoteNotify_swiFxnRequest ========
452 */
453 Void NameServerRemoteNotify_swiFxnRequest(UArg arg)
454 {
455 Int count = NameServer_E_FAIL;
456 Int remoteId;
457 UInt32 valueLen;
458 NameServer_Handle handle;
459 NameServerRemoteNotify_Object *obj;
460 #ifndef xdc_runtime_Assert_DISABLE_ALL
461 Int status;
462 #endif
464 obj = (NameServerRemoteNotify_Object *)arg;
466 /* compute index to remote message */
467 remoteId = (MultiProc_self() > obj->remoteProcId) ? 0 : 1;
469 if (obj->cacheEnable) {
470 Cache_inv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
471 Cache_Type_ALL, TRUE);
472 }
474 /* get the NameServer handle */
475 handle = NameServer_getHandle((String)obj->msg[remoteId]->instanceName);
476 valueLen = obj->msg[remoteId]->valueLen;
478 if (handle != NULL) {
479 /* Search for the NameServer entry */
480 if (valueLen == sizeof(UInt32)) {
481 count = NameServer_getLocalUInt32(handle,
482 (String)obj->msg[remoteId]->name, &obj->msg[remoteId]->value);
483 }
484 else {
485 count = NameServer_getLocal(handle,
486 (String)obj->msg[remoteId]->name,
487 &obj->msg[remoteId]->valueBuf, &valueLen);
488 }
489 }
491 /*
492 * If an entry was found, set requestStatus to TRUE
493 * and valueLen to the size of data that was copied.
494 */
495 if (count == NameServer_S_SUCCESS) {
496 obj->msg[remoteId]->requestStatus = TRUE;
497 obj->msg[remoteId]->valueLen = valueLen;
498 }
500 /* set object state (used by ROV) */
501 obj->remoteState = NameServerRemoteNotify_SEND_RESPONSE;
503 if (obj->cacheEnable) {
504 Cache_wbInv(obj->msg[remoteId], sizeof(NameServerRemoteNotify_Message),
505 Cache_Type_ALL, TRUE);
506 }
508 /* must wait to prevent dropped events, even though this is a swi */
509 #ifndef xdc_runtime_Assert_DISABLE_ALL
510 status =
511 #endif
512 Notify_sendEvent(obj->remoteProcId, 0,
513 NameServerRemoteNotify_notifyEventId,
514 NameServerRemoteNotify_ResponseMsg, TRUE);
516 /* The NS query could fail, but the reply should never fail */
517 Assert_isTrue(status >= 0, Ipc_A_internal);
519 /* set object state (used by ROV) */
520 obj->remoteState = NameServerRemoteNotify_IDLE;
521 }
523 /*
524 * ======== NameServerRemoteNotify_swiFxnResponse ========
525 */
526 Void NameServerRemoteNotify_swiFxnResponse(UArg arg)
527 {
528 NameServerRemoteNotify_Object *obj;
529 Semaphore_Handle sem;
531 obj = (NameServerRemoteNotify_Object *)arg;
533 /* post the semaphore to unblock waiting task */
534 sem = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
535 Semaphore_post(sem);
536 }
538 /*
539 * ======== NameServerRemoteNotify_getHandle ========
540 */
541 NameServerRemoteNotify_Handle NameServerRemoteNotify_getHandle(
542 UInt16 remoteProcId)
543 {
544 NameServerRemoteNotify_Handle obj;
546 for (obj = NameServerRemoteNotify_Object_first(); obj != NULL;
547 obj = NameServerRemoteNotify_Object_next(obj)) {
548 if (obj->remoteProcId == remoteProcId) {
549 break;
550 }
551 }
553 return (obj);
554 }