Add initial support to start/stop cores after launching QNX IPC resource manager
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / ipc / hlos / knl / GateMP_daemon.c
1 /*
2  * Copyright (c) 2013-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  */
33 /*
34  *  ======== GateMP_daemon.c ========
35  */
38 /* Standard headers */
39 #include <ti/ipc/Std.h>
41 /* Qnx specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <stdlib.h>
47 #include <assert.h>
49 /* Module level headers */
50 #include <ti/ipc/GateMP.h>
51 #include <ti/ipc/NameServer.h>
52 #include <ti/ipc/MultiProc.h>
53 #include <_MultiProc.h>
54 #include <GateMP_config.h>
55 #include <_GateMP.h>
57 #include <ti/syslink/utils/IGateProvider.h>
58 #include <ti/syslink/inc/_GateMP_daemon.h>
59 #include <_IpcLog.h>
61 #if defined (__cplusplus)
62 extern "C" {
63 #endif
65 /* Timeout of GateMP_setup in seconds */
66 #define SETUP_TIMEOUT         2
68 #define NUM_INFO_FIELDS       6    /* Number of fields in info entry */
70 /* Values used to populate the resource 'inUse' arrays */
71 #define UNUSED          ((UInt8)0)
72 #define USED            ((UInt8)1)
73 #define RESERVED        ((UInt8)-1)
75 /* Name of GateMP's nameserver */
76 #define GateMP_NAMESERVER  "GateMP"
78 /* =============================================================================
79  * Structures & Enums
80  * =============================================================================
81  */
83 /* structure for GateMP module state */
84 typedef struct {
85     Int               numRemoteSystem;
86     Int               numRemoteCustom1;
87     Int               numRemoteCustom2;
88     UInt8 *           remoteSystemInUse;
89     UInt8 *           remoteCustom1InUse;
90     UInt8 *           remoteCustom2InUse;
91     GateMP_Handle     defaultGate;
92     NameServer_Handle nameServer;
93     Bool              isSetup;
94 } GateMP_ModuleObject;
96 /* Internal functions */
97 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
98     UInt16 * creatorProcId);
99 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
101 /* =============================================================================
102  *  Globals
103  * =============================================================================
104  */
105 /*
106  * GateMP_state
107  */
108 static GateMP_ModuleObject GateMP_state = {
109     .numRemoteSystem                 = 0,
110     .numRemoteCustom1                = 0,
111     .numRemoteCustom2                = 0,
112     .remoteSystemInUse               = NULL,
113     .remoteCustom1InUse              = NULL,
114     .remoteCustom2InUse              = NULL,
115     .defaultGate                     = NULL,
116     .nameServer                      = NULL,
117     .isSetup                         = FALSE
118 };
120 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
122 /* =============================================================================
123  * APIS
124  * =============================================================================
125  */
127 /* Function to setup the gatemp module. */
128 Int GateMP_setup(Int32 * sr0ProcId)
130     Int               status = GateMP_S_SUCCESS;
131     NameServer_Params params;
132     UInt32            nsValue[NUM_INFO_FIELDS];
133     UInt32            len;
134     UInt              timeout = SETUP_TIMEOUT;
135     UInt16            procId;
137     NameServer_Params_init(&params);
138     params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
139     params.maxNameLen = MAX_NAME_LEN;
141     /* Assume info entry has more fields than other entries */
142     params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
144     GateMP_module->nameServer =
145                 NameServer_create(GateMP_NAMESERVER, &params);
147     if (GateMP_module->nameServer == NULL) {
148         status = GateMP_E_FAIL;
149         LOG0("GateMP_setup: NameServer_create failed\n");
150     }
152     if (status == GateMP_S_SUCCESS) {
153         /* The default gate creator is the owner of SR0 */
154         while (((status = GateMP_openDefaultGate(&GateMP_module->defaultGate,
155             &procId)) == GateMP_E_NOTFOUND) && (timeout > 0)) {
156             sleep(1);
157             timeout--;
158         }
160         if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
161             LOG0("GateMP_setup: failed to open default gate\n");
162             status = GateMP_E_FAIL;
163         }
164         else if (status == GateMP_S_SUCCESS) {
165             *sr0ProcId = procId;
166         }
167         else {
168             /* If default gate is not found, return GateMP_E_NOTFOUND */
169         }
170     }
172     if (status == GateMP_S_SUCCESS) {
173         /* Process global info NameServer entry */
174         len = sizeof(nsValue);
176         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
177             &nsValue, &len, NULL);
179         if (status < 0) {
180             LOG0("GateMP_setup: failed to find info entry\n");
181             status = GateMP_E_NOTFOUND;
182         }
183         else {
184             GateMP_module->numRemoteSystem = nsValue[3];
185             GateMP_module->numRemoteCustom1 = nsValue[4];
186             GateMP_module->numRemoteCustom2 = nsValue[5];
188             /* Map InUse arrays to daemon's address space */
189             GateMP_module->remoteSystemInUse = mmap(NULL,
190                 GateMP_module->numRemoteSystem * sizeof (UInt8),
191                 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
192                 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
193             if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
194                  GateMP_module->remoteSystemInUse = NULL;
195                  status = GateMP_E_MEMORY;
196                  LOG0("Failed to map remoteSystemInUse to host address space!");
197             }
199             if (status == GateMP_S_SUCCESS) {
200                 GateMP_module->remoteCustom1InUse = mmap(NULL,
201                     GateMP_module->numRemoteCustom1 * sizeof (UInt8),
202                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
203                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
204                 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
205                     GateMP_module->remoteCustom1InUse = NULL;
206                     status = GateMP_E_MEMORY;
207                     LOG0("Failed to map remoteSystemInUse to host address" \
208                         " space!");
209                 }
210             }
212             if (status == GateMP_S_SUCCESS) {
213                 GateMP_module->remoteCustom2InUse = mmap(NULL,
214                     GateMP_module->numRemoteCustom2 * sizeof (UInt8),
215                     (PROT_READ|PROT_WRITE|PROT_NOCACHE),
216                     (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
217                 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
218                     GateMP_module->remoteCustom2InUse = NULL;
219                     status = GateMP_E_MEMORY;
220                     LOG0("Failed to map remoteSystemInUse to host address" \
221                         " space!");
222                 }
223             }
224         }
225     }
227     /* TODO: setup the proxy map */
229     /* clean up if error */
230     if (status < 0) {
231         GateMP_destroy();
232     }
233     else {
234         GateMP_module->isSetup = TRUE;
235     }
237     return (status);
240 Void GateMP_destroy(Void)
242     if (GateMP_module->remoteSystemInUse) {
243         munmap((unsigned int *)GateMP_module->remoteSystemInUse,
244             GateMP_module->numRemoteSystem * sizeof (UInt8));
245         GateMP_module->remoteSystemInUse = NULL;
246     }
248     if (GateMP_module->remoteCustom1InUse) {
249         munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
250             GateMP_module->numRemoteCustom1 * sizeof (UInt8));
251         GateMP_module->remoteCustom1InUse = NULL;
252     }
254     if (GateMP_module->remoteCustom2InUse) {
255         munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
256             GateMP_module->numRemoteCustom2 * sizeof (UInt8));
257         GateMP_module->remoteCustom2InUse = NULL;
258     }
260     if (GateMP_module->defaultGate) {
261         GateMP_closeDefaultGate(&GateMP_module->defaultGate);
262     }
264     if (GateMP_module->nameServer) {
265         NameServer_delete(&GateMP_module->nameServer);
266         GateMP_module->nameServer = NULL;
267     }
269     GateMP_module->isSetup = FALSE;
271     return;
274 /* Open default gate during GateMP_setup. Should only be called once */
275 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
276     UInt16 * creatorProcId)
278     Int             status = GateMP_S_SUCCESS;
279     UInt32          len;
280     UInt32          nsValue[4];
281     GateMP_Object * obj = NULL;
282     UInt32          arg;
283     UInt32          mask;
285     GateMP_RemoteSystemProxy_Params     systemParams;
287     /* assert that a valid pointer has been supplied */
288     if (handlePtr == NULL) {
289         LOG0("GateMP_open: argument cannot be null\n");
290         status = GateMP_E_INVALIDARG;
291     }
293     if (status == GateMP_S_SUCCESS) {
294         len = sizeof(nsValue);
296         status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
297             &nsValue, &len, NULL);
299         if (status < 0) {
300             *handlePtr = NULL;
301             status = GateMP_E_NOTFOUND;
302         }
303         else {
304             arg = nsValue[2];
305             mask = nsValue[3];
306             *creatorProcId = nsValue[1] >> 16;
307         }
308     }
310     if (status == GateMP_S_SUCCESS) {
311         /* allocate the instance object */
312         obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
313         if (obj != NULL) {
314             obj->localGate  = NULL;  /* TODO: create the local gate instance */
315             obj->localProtect  = GETLOCAL(mask);
316             obj->remoteProtect = GETREMOTE(mask);
317             obj->nsKey         = 0;
318             obj->numOpens      = 1;
319             obj->objType       = Ipc_ObjType_OPENDYNAMIC;
320             obj->resourceId    = arg;
322             assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
324             /* create the proxy object */
325             GateMP_RemoteSystemProxy_Params_init(&systemParams);
326             systemParams.resourceId = obj->resourceId;
327             systemParams.openFlag = TRUE;
329             /*
330              * TODO: Currently passing in localProtect instead of localGate,
331              * since GateHWSpinlock owns the local gate
332              */
333             obj->gateHandle = (IGateProvider_Handle)
334                 GateMP_RemoteSystemProxy_create(obj->localProtect,
335                     &systemParams);
337             if (obj->gateHandle == NULL) {
338                 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
339                 free(obj);
340                 obj = NULL;
341             }
342         }
343         else {
344             LOG0("GateMP_openDefaultGate: Memory allocation failed")
345         }
347         if (obj == NULL) {
348             status = GateMP_E_FAIL;
349         }
350     }
352     /* Return the "opened" GateMP instance  */
353     *handlePtr = (GateMP_Handle)obj;
355     return status;
358 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
360     Int status = GateMP_S_SUCCESS;
361     GateMP_Object * obj = *(GateMP_Object **)handlePtr;
363     if (obj->gateHandle != NULL) {
364         /* Default gate is always of type System when more than 1 processor */
365         GateMP_RemoteSystemProxy_delete(
366             (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
367     }
369     free(*handlePtr);
370     *handlePtr = NULL;
372     return(status);
375 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
377     IArg   key;
378     Bool   flag = FALSE;
379     Int    resourceId = -1;
380     UInt8* inUse = NULL;
381     Int    num = 0;
383     /* Remote case */
384     switch (type) {
385         /* TODO: currently only support System proxy */
386         case GateMP_RemoteProtect_SYSTEM:
387         case GateMP_RemoteProtect_CUSTOM1:
388         case GateMP_RemoteProtect_CUSTOM2:
389             inUse = GateMP_module->remoteSystemInUse;
390             num = GateMP_module->numRemoteSystem;
391             break;
393         default:
394             LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
395             break;
396     }
398     if (inUse != NULL) {
399         assert(GateMP_module->defaultGate != NULL);
400         key = GateMP_enter(GateMP_module->defaultGate);
402         /*
403          *  Find a free resource id. Note: zero is reserved on the
404          *  system proxy for the default gate.
405          */
406         for (resourceId = 0; resourceId < num; resourceId++) {
407             /*
408              *  If not in-use, set the inUse to TRUE to prevent other
409              *  creates from getting this one.
410              */
411             if (inUse[resourceId] == UNUSED) {
412                 flag = TRUE;
414                 /* Denote in shared memory that the resource is used */
415                 inUse[resourceId] = USED;
416                 break;
417             }
418         }
420         GateMP_leave(GateMP_module->defaultGate, key);
421     }
423     if (flag == FALSE) {
424         resourceId = -1;
425     }
427     return (resourceId);
430 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
432     Int    status = GateMP_S_SUCCESS;
433     IArg   key;
434     UInt8* inUse = NULL;
435     Int    num = 0;
437     /* Remote case */
438     switch (type) {
439         /* TODO: currently only support System proxy */
440         case GateMP_RemoteProtect_SYSTEM:
441         case GateMP_RemoteProtect_CUSTOM1:
442         case GateMP_RemoteProtect_CUSTOM2:
443             inUse = GateMP_module->remoteSystemInUse;
444             num = GateMP_module->numRemoteSystem;
445             break;
447         default:
448             LOG0("GateMP_releaseResource: Invalid remote protection type\n");
449             status = GateMP_E_FAIL;
450             break;
451     }
453     if ((inUse != NULL) && (id < num)) {
454         assert(GateMP_module->defaultGate != NULL);
455         key = GateMP_enter(GateMP_module->defaultGate);
456         inUse[id] = UNUSED;
457         GateMP_leave(GateMP_module->defaultGate, key);
458     }
459     else {
460         /* Should not happen if module is properly setup */
461         status = GateMP_E_FAIL;
462     }
464     return (status);
467 Int GateMP_getNumResources(GateMP_RemoteProtect type)
469     Int   num = -1;
471     /* Remote case */
472     switch (type) {
473         /* TODO: currently only support System proxy */
474         case GateMP_RemoteProtect_SYSTEM:
475         case GateMP_RemoteProtect_CUSTOM1:
476         case GateMP_RemoteProtect_CUSTOM2:
477             num = GateMP_module->numRemoteSystem;
478             break;
480         default:
481             LOG0("GateMP_getNumResources: Invalid remote protection type\n");
482             break;
483     }
485     return (num);
488 NameServer_Handle GateMP_getNameServer(Void)
490     return (GateMP_module->nameServer);
493 Bool GateMP_isSetup(Void)
495     return (GateMP_module->isSetup);
498 IArg GateMP_enter(GateMP_Handle handle)
500     GateMP_Object * obj;
501     IArg            key;
503     obj = (GateMP_Object *)handle;
504     key = IGateProvider_enter(obj->gateHandle);
506     return(key);
509 Void GateMP_leave(GateMP_Handle handle, IArg key)
511     GateMP_Object *obj;
513     obj = (GateMP_Object *)handle;
514     IGateProvider_leave(obj->gateHandle, key);