609c824737296ba8e765a5721b09a6fbc7b7a8db
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 /*
68 *************************************************************************
69 * Instance functions
70 *************************************************************************
71 */
72 Int NameServerRemoteNotify_Instance_init(NameServerRemoteNotify_Object *obj,
73 UInt16 remoteProcId,
74 const NameServerRemoteNotify_Params *params,
75 Error_Block *eb)
76 {
77 Int offset = 0;
78 Int status;
79 Semaphore_Params semParams;
80 Semaphore_Handle semRemoteWait;
81 Semaphore_Handle semMultiBlock;
82 Swi_Handle swiHandle;
83 Swi_Params swiParams;
85 /* Assert that a NameServerRemoteNotify_Params has been supplied */
86 Assert_isTrue(params != NULL, Ipc_A_nullArgument);
88 /* Assert that remoteProcId is valid */
89 Assert_isTrue(remoteProcId != MultiProc_self() &&
90 remoteProcId != MultiProc_INVALIDID,
91 Ipc_A_invParam);
93 /* determine the offset based upon own id and remote's id */
94 if (MultiProc_self() > remoteProcId) {
95 offset = 1;
96 }
98 obj->regionId = SharedRegion_getId(params->sharedAddr);
100 /* Assert that sharedAddr is cache aligned */
101 Assert_isTrue(((UInt32)params->sharedAddr %
102 SharedRegion_getCacheLineSize(obj->regionId) == 0),
103 Ipc_A_addrNotCacheAligned);
105 semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
106 semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
107 swiHandle = NameServerRemoteNotify_Instance_State_swiObj(obj);
109 obj->msg[0] = (NameServerRemoteNotify_Message *)(params->sharedAddr);
110 obj->msg[1] = (NameServerRemoteNotify_Message *)((UInt32)obj->msg[0] +
111 sizeof(NameServerRemoteNotify_Message));
112 obj->gate = params->gate;
113 obj->remoteProcId = remoteProcId;
115 /* construct the semaphore */
116 Semaphore_Params_init(&semParams);
117 Semaphore_construct(Semaphore_struct(semRemoteWait), 0, &semParams);
119 /* construct the semaphore */
120 Semaphore_construct(Semaphore_struct(semMultiBlock), 1, &semParams);
122 /* swi created with lowest priority and fxn = swiFxn */
123 Swi_Params_init(&swiParams);
124 swiParams.arg0 = (UArg)obj;
125 swiParams.priority = 0;
126 Swi_construct(Swi_struct(swiHandle),
127 (ti_sysbios_knl_Swi_FuncPtr)NameServerRemoteNotify_swiFxn,
128 &swiParams, eb);
130 /* initialize own side of message struct only */
131 obj->msg[offset]->request = 0;
132 obj->msg[offset]->response = 0;
133 obj->msg[offset]->requestStatus = 0;
134 obj->msg[offset]->value = 0;
135 obj->msg[offset]->valueLen = 0;
137 memset(obj->msg[offset]->instanceName, 0,
138 sizeof(obj->msg[offset]->instanceName));
139 memset(obj->msg[offset]->name, 0,
140 sizeof(obj->msg[offset]->name));
142 /* determine cacheability of the object from the regionId */
143 obj->cacheEnable = SharedRegion_isCacheEnabled(obj->regionId);
144 if (obj->cacheEnable) {
145 /* write back shared memory that was modified */
146 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
147 Cache_Type_ALL, TRUE);
148 }
150 /* register the call back function and event Id with notify */
151 status = Notify_registerEventSingle(
152 remoteProcId,
153 0,
154 NameServerRemoteNotify_notifyEventId,
155 (Notify_FnNotifyCbck)NameServerRemoteNotify_cbFxn,
156 (UArg)swiHandle);
158 /* if not successful return */
159 if (status < 0) {
160 Error_raise(eb, ti_sdo_ipc_Ipc_E_internal, 0, 0);
161 return (1);
162 }
164 /* register the remote driver with NameServer */
165 ti_sdo_utils_NameServer_registerRemoteDriver(
166 NameServerRemoteNotify_Handle_upCast(obj), remoteProcId);
168 return (0);
169 }
171 /*
172 * ======== NameServerRemoteNotify_Instance_finalize ========
173 */
174 Void NameServerRemoteNotify_Instance_finalize(NameServerRemoteNotify_Object *obj,
175 Int status)
176 {
177 Semaphore_Handle semRemoteWait;
178 Semaphore_Handle semMultiBlock;
179 Swi_Handle swiHandle;
181 if (status == 0) {
182 /* unregister remote driver from NameServer module */
183 ti_sdo_utils_NameServer_unregisterRemoteDriver(obj->remoteProcId);
185 /* unregister event from Notify module */
186 Notify_unregisterEventSingle(
187 obj->remoteProcId,
188 0,
189 NameServerRemoteNotify_notifyEventId);
190 }
192 semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
193 if (semRemoteWait != NULL) {
194 Semaphore_destruct(Semaphore_struct(semRemoteWait));
195 }
197 semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
198 if (semMultiBlock != NULL) {
199 Semaphore_destruct(Semaphore_struct(semMultiBlock));
200 }
202 swiHandle = NameServerRemoteNotify_Instance_State_swiObj(obj);
203 if (swiHandle != NULL) {
204 Swi_destruct(Swi_struct(swiHandle));
205 }
206 }
208 /*
209 *************************************************************************
210 * Module functions
211 *************************************************************************
212 */
214 /*
215 * ======== NameServerRemoteNotify_attach ========
216 */
217 Int NameServerRemoteNotify_attach(UInt16 remoteProcId, Ptr sharedAddr)
218 {
219 NameServerRemoteNotify_Params nsrParams;
220 NameServerRemoteNotify_Handle handle;
221 Int status = NameServerRemoteNotify_E_FAIL;
222 Error_Block eb;
224 /* Assert that the default GateMP is not NULL */
225 Assert_isTrue(GateMP_getDefaultRemote() != NULL, Ipc_A_internal);
227 Error_init(&eb);
229 /* Use default GateMP */
230 NameServerRemoteNotify_Params_init(&nsrParams);
231 nsrParams.gate = (ti_sdo_ipc_GateMP_Handle)GateMP_getDefaultRemote();
233 /* determine the address */
234 nsrParams.sharedAddr = sharedAddr;
236 /* create only if notify driver has been created to remote proc */
237 if (Notify_intLineRegistered(remoteProcId, 0)) {
238 handle = NameServerRemoteNotify_create(remoteProcId,
239 &nsrParams,
240 &eb);
241 if (handle != NULL) {
242 status = NameServerRemoteNotify_S_SUCCESS;
243 }
244 }
246 return (status);
247 }
249 /*
250 * ======== NameServerRemoteNotify_cbFxn ========
251 */
252 Void NameServerRemoteNotify_cbFxn(UInt16 procId,
253 UInt16 lineId,
254 UInt32 eventId,
255 UArg arg,
256 UInt32 payload)
257 {
258 Swi_Handle swiHandle;
260 /* Swi_Handle was passed as arg in register */
261 swiHandle = (Swi_Handle)arg;
263 /* post the Swi */
264 Swi_post(swiHandle);
265 }
267 /*
268 * ======== NameServerRemoteNotify_detach ========
269 */
270 Int NameServerRemoteNotify_detach(UInt16 remoteProcId)
271 {
272 NameServerRemoteNotify_Handle handle;
273 Int status = NameServerRemoteNotify_S_SUCCESS;
275 for (handle = NameServerRemoteNotify_Object_first(); handle != NULL;
276 handle = NameServerRemoteNotify_Object_next(handle)) {
277 if (handle->remoteProcId == remoteProcId) {
278 break;
279 }
280 }
282 if (handle == NULL) {
283 status = NameServerRemoteNotify_E_FAIL;
284 }
285 else {
286 NameServerRemoteNotify_delete(&handle);
287 }
289 return (status);
290 }
292 /*
293 * ======== NameServerRemoteNotify_get ========
294 */
295 Int NameServerRemoteNotify_get(NameServerRemoteNotify_Object *obj,
296 String instanceName,
297 String name,
298 Ptr value,
299 UInt32 *valueLen,
300 ISync_Handle syncHandle,
301 Error_Block *eb)
302 {
303 Int len;
304 Int retval = NameServer_E_NOTFOUND;
305 Int offset = 0;
306 Int status;
307 Int notifyStatus;
308 IArg key;
309 Semaphore_Handle semRemoteWait;
310 Semaphore_Handle semMultiBlock;
312 Assert_isTrue(*valueLen <= 300,
313 NameServerRemoteNotify_A_invalidValueLen);
315 semRemoteWait = NameServerRemoteNotify_Instance_State_semRemoteWait(obj);
316 semMultiBlock = NameServerRemoteNotify_Instance_State_semMultiBlock(obj);
318 /* prevent multiple threads from entering */
319 Semaphore_pend(semMultiBlock, BIOS_WAIT_FOREVER);
321 if (MultiProc_self() > obj->remoteProcId) {
322 offset = 1;
323 }
325 if (obj->cacheEnable) {
326 /* Make sure there's no outstanding message */
327 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
328 Cache_Type_ALL, TRUE);
329 }
331 /* enter gate so nobody can be modifying message in shared memory */
332 key = GateMP_enter((GateMP_Handle)obj->gate);
334 /* this is a request message */
335 obj->msg[offset]->request = 1;
336 obj->msg[offset]->response = 0;
337 obj->msg[offset]->requestStatus = 0;
338 obj->msg[offset]->valueLen = *valueLen;
340 /* copy the name of instance into shared memory */
341 len = strlen(instanceName);
342 strncpy((Char *)obj->msg[offset]->instanceName, instanceName, len + 1);
344 /* copy the name of nameserver entry into shared memory */
345 len = strlen(name);
346 strncpy((Char *)obj->msg[offset]->name, name, len + 1);
348 if (obj->cacheEnable) {
349 Cache_wbInv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
350 Cache_Type_ALL, TRUE);
351 }
353 /*
354 * Send the notification to remote processor. Do not wait here since
355 * we hold the GateMP.
356 */
357 notifyStatus = Notify_sendEvent(
358 obj->remoteProcId,
359 0,
360 NameServerRemoteNotify_notifyEventId,
361 0,
362 FALSE);
364 /* now we can leave the gate after we send the notification */
365 GateMP_leave((GateMP_Handle)obj->gate, key);
367 if (notifyStatus < 0) {
368 /* undo previous options */
369 obj->msg[offset]->request = 0;
370 obj->msg[offset]->valueLen = 0;
372 /* post the semaphore to make sure it doesn't block */
373 Semaphore_post(semMultiBlock);
375 return (retval);
376 }
378 /* pend here until we get a notification back from remote processor */
379 status = Semaphore_pend(semRemoteWait, NameServerRemoteNotify_timeout);
381 if (status == FALSE) {
382 retval = NameServer_E_OSFAILURE;
383 }
384 else {
385 /* getting here means we got the notification back */
386 /* enter gate so nobody can be modifying message in shared memory */
387 key = GateMP_enter((GateMP_Handle)obj->gate);
389 if (obj->cacheEnable) {
390 Cache_inv(obj->msg[offset], sizeof(NameServerRemoteNotify_Message),
391 Cache_Type_ALL, TRUE);
392 }
394 /* if successful request then copy to value */
395 if (obj->msg[offset]->requestStatus == TRUE) {
396 /* clear out requestStatus */
397 obj->msg[offset]->requestStatus = FALSE;
399 /* copy to value */
400 if (obj->msg[offset]->valueLen == sizeof(UInt32)) {
401 memcpy(value, &(obj->msg[offset]->value), sizeof(UInt32));
402 }
403 else {
404 memcpy(value, &(obj->msg[offset]->valueBuf),
405 obj->msg[offset]->valueLen);
406 }
408 /* set length to amount of data that was copied */
409 *valueLen = obj->msg[offset]->valueLen;
411 /* set the status */
412 retval = NameServer_S_SUCCESS;
413 }
415 /* clear out the request and response flags */
416 obj->msg[offset]->request = 0;
417 obj->msg[offset]->response = 0;
419 if (obj->cacheEnable) {
420 Cache_wbInv(obj->msg[offset],
421 sizeof(NameServerRemoteNotify_Message),
422 Cache_Type_ALL, TRUE);
423 }
425 /* Now we can leave the gate after we send the notification */
426 GateMP_leave((GateMP_Handle)obj->gate, key);
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_swiFxn ========
452 */
453 Void NameServerRemoteNotify_swiFxn(UArg arg)
454 {
455 Int count = NameServer_E_FAIL;
456 Int offset = 0;
457 UInt32 valueLen;
458 IArg key;
459 NameServer_Handle handle;
460 NameServerRemoteNotify_Object *obj;
461 #ifndef xdc_runtime_Assert_DISABLE_ALL
462 Int status;
463 #endif
465 obj = (NameServerRemoteNotify_Object *)arg;
467 if (MultiProc_self() > obj->remoteProcId) {
468 offset = 1;
469 }
471 if (obj->cacheEnable) {
472 /* invalidate both request and response messages */
473 Cache_inv(obj->msg[0],
474 sizeof(NameServerRemoteNotify_Message) << 1,
475 Cache_Type_ALL, TRUE);
476 }
478 /* in case of request */
479 if (obj->msg[1 - offset]->request == TRUE) {
480 /* get the NameServer handle */
481 handle = NameServer_getHandle(
482 (String)obj->msg[1 - offset]->instanceName);
483 valueLen = obj->msg[1 - offset]->valueLen;
485 if (handle != NULL) {
486 /* Search for the NameServer entry */
487 if (valueLen == sizeof(UInt32)) {
488 count = NameServer_getLocalUInt32(handle,
489 (String)obj->msg[1 - offset]->name,
490 &obj->msg[1 - offset]->value);
491 }
492 else {
493 count = NameServer_getLocal(handle,
494 (String)obj->msg[1 - offset]->name,
495 &obj->msg[1 - offset]->valueBuf, &valueLen);
496 }
497 }
499 /* enter gate so nobody can be modifying message in shared memory */
500 key = GateMP_enter((GateMP_Handle)obj->gate);
502 /*
503 * If an entry was found, set requestStatus to TRUE
504 * and valueLen to the size of data that was copied.
505 */
506 if (count == NameServer_S_SUCCESS) {
507 obj->msg[1 - offset]->requestStatus = TRUE;
508 obj->msg[1 - offset]->valueLen = valueLen;
509 }
511 /* Send a response back */
512 obj->msg[1 - offset]->response = TRUE;
513 obj->msg[1 - offset]->request = FALSE;
515 if (obj->cacheEnable) {
516 Cache_wbInv(obj->msg[1 - offset],
517 sizeof(NameServerRemoteNotify_Message),
518 Cache_Type_ALL, TRUE);
519 }
521 /* now we can leave the gate */
522 GateMP_leave((GateMP_Handle)obj->gate, key);
524 /*
525 * The Notify line must be active at this point for this processor to
526 * have received a request. Do not wait here since we are in a Swi.
527 */
528 #ifndef xdc_runtime_Assert_DISABLE_ALL
529 status =
530 #endif
531 Notify_sendEvent(obj->remoteProcId,
532 0, NameServerRemoteNotify_notifyEventId, 0, FALSE);
533 /* The NS query could fail, but the reply should never fail */
534 Assert_isTrue(status >= 0, Ipc_A_internal);
536 }
538 /* in case of response */
539 if (obj->msg[offset]->response == TRUE) {
540 /* post the Semaphore */
541 Semaphore_post(
542 NameServerRemoteNotify_Instance_State_semRemoteWait(obj));
543 }
544 }
546 /*
547 * ======== NameServerRemoteNotify_getHandle ========
548 */
549 NameServerRemoteNotify_Handle NameServerRemoteNotify_getHandle(
550 UInt16 remoteProcId)
551 {
552 NameServerRemoteNotify_Handle obj;
554 for (obj = NameServerRemoteNotify_Object_first(); obj != NULL;
555 obj = NameServerRemoteNotify_Object_next(obj)) {
556 if (obj->remoteProcId == remoteProcId) {
557 break;
558 }
559 }
561 return (obj);
562 }