Rename: git mv src packages to complete application of ipc-j patches to ipcdev.
[ipc/ipcdev.git] / packages / ti / sdo / ipc / nsremote / NameServerRemoteNotify.c
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);
171 /*
172  *  ======== NameServerRemoteNotify_Instance_finalize ========
173  */
174 Void NameServerRemoteNotify_Instance_finalize(NameServerRemoteNotify_Object *obj,
175     Int status)
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     }
208 /*
209  *************************************************************************
210  *                       Module functions
211  *************************************************************************
212  */
214 /*
215  *  ======== NameServerRemoteNotify_attach ========
216  */
217 Int NameServerRemoteNotify_attach(UInt16 remoteProcId, Ptr sharedAddr)
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);
249 /*
250  *  ======== NameServerRemoteNotify_cbFxn ========
251  */
252 Void NameServerRemoteNotify_cbFxn(UInt16 procId,
253                                   UInt16 lineId,
254                                   UInt32 eventId,
255                                   UArg arg,
256                                   UInt32 payload)
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);
267 /*
268  *  ======== NameServerRemoteNotify_detach ========
269  */
270 Int NameServerRemoteNotify_detach(UInt16 remoteProcId)
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);
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)
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);
434 /*
435  *  ======== NameServerRemoteNotify_sharedMemReq ========
436  */
437 SizeT NameServerRemoteNotify_sharedMemReq(Ptr sharedAddr)
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);
450 /*
451  *  ======== NameServerRemoteNotify_swiFxn ========
452  */
453 Void NameServerRemoteNotify_swiFxn(UArg arg)
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     }
546 /*
547  *  ======== NameServerRemoteNotify_getHandle ========
548  */
549 NameServerRemoteNotify_Handle NameServerRemoteNotify_getHandle(
550     UInt16 remoteProcId)
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);