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 UInt32 startCount; /* number of times GateMP is started */
95 pthread_mutex_t lock;
96 } GateMP_ModuleObject;
98 /* Internal functions */
99 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
100 UInt16 * creatorProcId);
101 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
103 /* =============================================================================
104 * Globals
105 * =============================================================================
106 */
107 /*
108 * GateMP_state
109 */
110 static GateMP_ModuleObject GateMP_state = {
111 .numRemoteSystem = 0,
112 .numRemoteCustom1 = 0,
113 .numRemoteCustom2 = 0,
114 .remoteSystemInUse = NULL,
115 .remoteCustom1InUse = NULL,
116 .remoteCustom2InUse = NULL,
117 .defaultGate = NULL,
118 .nameServer = NULL,
119 .isSetup = FALSE,
120 .startCount = 0,
121 .lock = PTHREAD_RMUTEX_INITIALIZER
122 };
124 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
126 /* =============================================================================
127 * APIS
128 * =============================================================================
129 */
131 /* Function to setup the gatemp module. */
132 Int GateMP_setup(Int32 * sr0ProcId)
133 {
134 Int status = GateMP_S_SUCCESS;
135 NameServer_Params params;
136 UInt32 nsValue[NUM_INFO_FIELDS];
137 UInt32 len;
138 UInt timeout = SETUP_TIMEOUT;
139 UInt16 procId;
141 NameServer_Params_init(¶ms);
142 params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
143 params.maxNameLen = MAX_NAME_LEN;
145 /* Assume info entry has more fields than other entries */
146 params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
148 pthread_mutex_lock(&GateMP_module->lock);
150 if (GateMP_module->isSetup) {
151 pthread_mutex_unlock(&GateMP_module->lock);
152 return (GateMP_S_ALREADYSETUP);
153 }
155 GateMP_module->nameServer =
156 NameServer_create(GateMP_NAMESERVER, ¶ms);
158 if (GateMP_module->nameServer == NULL) {
159 status = GateMP_E_FAIL;
160 LOG0("GateMP_setup: NameServer_create failed\n");
161 }
163 if (status == GateMP_S_SUCCESS) {
164 /* The default gate creator is the owner of SR0 */
165 while (((status = GateMP_openDefaultGate(&GateMP_module->defaultGate,
166 &procId)) == GateMP_E_NOTFOUND) && (timeout > 0)) {
167 sleep(1);
168 timeout--;
169 }
171 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
172 LOG0("GateMP_setup: failed to open default gate\n");
173 status = GateMP_E_FAIL;
174 }
175 else if (status == GateMP_S_SUCCESS) {
176 *sr0ProcId = procId;
177 }
178 else {
179 /* If default gate is not found, return GateMP_E_NOTFOUND */
180 }
181 }
183 if (status == GateMP_S_SUCCESS) {
184 /* Process global info NameServer entry */
185 len = sizeof(nsValue);
187 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
188 &nsValue, &len, NULL);
190 if (status < 0) {
191 LOG0("GateMP_setup: failed to find info entry\n");
192 status = GateMP_E_NOTFOUND;
193 }
194 else {
195 GateMP_module->numRemoteSystem = nsValue[3];
196 GateMP_module->numRemoteCustom1 = nsValue[4];
197 GateMP_module->numRemoteCustom2 = nsValue[5];
199 /* Map InUse arrays to daemon's address space */
200 GateMP_module->remoteSystemInUse = mmap(NULL,
201 GateMP_module->numRemoteSystem * sizeof (UInt8),
202 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
203 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
204 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
205 GateMP_module->remoteSystemInUse = NULL;
206 status = GateMP_E_MEMORY;
207 LOG0("Failed to map remoteSystemInUse to host address space!");
208 }
210 if (status == GateMP_S_SUCCESS) {
211 GateMP_module->remoteCustom1InUse = mmap(NULL,
212 GateMP_module->numRemoteCustom1 * sizeof (UInt8),
213 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
214 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
215 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
216 GateMP_module->remoteCustom1InUse = NULL;
217 status = GateMP_E_MEMORY;
218 LOG0("Failed to map remoteSystemInUse to host address" \
219 " space!");
220 }
221 }
223 if (status == GateMP_S_SUCCESS) {
224 GateMP_module->remoteCustom2InUse = mmap(NULL,
225 GateMP_module->numRemoteCustom2 * sizeof (UInt8),
226 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
227 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
228 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
229 GateMP_module->remoteCustom2InUse = NULL;
230 status = GateMP_E_MEMORY;
231 LOG0("Failed to map remoteSystemInUse to host address" \
232 " space!");
233 }
234 }
235 }
236 }
238 /* TODO: setup the proxy map */
240 /* clean up if error */
241 if (status < 0) {
242 GateMP_destroy(TRUE);
243 }
244 else {
245 GateMP_module->isSetup = TRUE;
246 }
248 pthread_mutex_unlock(&GateMP_module->lock);
250 return (status);
251 }
253 Int GateMP_destroy(Bool forced)
254 {
255 pthread_mutex_lock(&GateMP_module->lock);
257 if ((!forced) && (GateMP_module->startCount != 0)) {
258 /* Some process on the host is still using GateMP */
259 pthread_mutex_unlock(&GateMP_module->lock);
260 return (GateMP_E_FAIL);
261 }
263 if (GateMP_module->remoteSystemInUse) {
264 munmap((unsigned int *)GateMP_module->remoteSystemInUse,
265 GateMP_module->numRemoteSystem * sizeof (UInt8));
266 GateMP_module->remoteSystemInUse = NULL;
267 }
269 if (GateMP_module->remoteCustom1InUse) {
270 munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
271 GateMP_module->numRemoteCustom1 * sizeof (UInt8));
272 GateMP_module->remoteCustom1InUse = NULL;
273 }
275 if (GateMP_module->remoteCustom2InUse) {
276 munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
277 GateMP_module->numRemoteCustom2 * sizeof (UInt8));
278 GateMP_module->remoteCustom2InUse = NULL;
279 }
281 if (GateMP_module->defaultGate) {
282 GateMP_closeDefaultGate(&GateMP_module->defaultGate);
283 }
285 if (GateMP_module->nameServer) {
286 NameServer_delete(&GateMP_module->nameServer);
287 GateMP_module->nameServer = NULL;
288 }
290 GateMP_module->isSetup = FALSE;
292 pthread_mutex_unlock(&GateMP_module->lock);
294 return (GateMP_S_SUCCESS);
295 }
297 /* Open default gate during GateMP_setup. Should only be called once */
298 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr,
299 UInt16 * creatorProcId)
300 {
301 Int status = GateMP_S_SUCCESS;
302 UInt32 len;
303 UInt32 nsValue[4];
304 GateMP_Object * obj = NULL;
305 UInt32 arg;
306 UInt32 mask;
308 GateMP_RemoteSystemProxy_Params systemParams;
310 /* assert that a valid pointer has been supplied */
311 if (handlePtr == NULL) {
312 LOG0("GateMP_open: argument cannot be null\n");
313 status = GateMP_E_INVALIDARG;
314 }
316 if (status == GateMP_S_SUCCESS) {
317 len = sizeof(nsValue);
319 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
320 &nsValue, &len, NULL);
322 if (status < 0) {
323 *handlePtr = NULL;
324 status = GateMP_E_NOTFOUND;
325 }
326 else {
327 arg = nsValue[2];
328 mask = nsValue[3];
329 *creatorProcId = nsValue[1] >> 16;
330 }
331 }
333 if (status == GateMP_S_SUCCESS) {
334 /* allocate the instance object */
335 obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
336 if (obj != NULL) {
337 obj->localGate = NULL; /* TODO: create the local gate instance */
338 obj->localProtect = GETLOCAL(mask);
339 obj->remoteProtect = GETREMOTE(mask);
340 obj->nsKey = 0;
341 obj->numOpens = 1;
342 obj->objType = Ipc_ObjType_OPENDYNAMIC;
343 obj->resourceId = arg;
345 assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
347 /* create the proxy object */
348 GateMP_RemoteSystemProxy_Params_init(&systemParams);
349 systemParams.resourceId = obj->resourceId;
350 systemParams.openFlag = TRUE;
352 /*
353 * TODO: Currently passing in localProtect instead of localGate,
354 * since GateHWSpinlock owns the local gate
355 */
356 obj->gateHandle = (IGateProvider_Handle)
357 GateMP_RemoteSystemProxy_create(obj->localProtect,
358 &systemParams);
360 if (obj->gateHandle == NULL) {
361 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
362 free(obj);
363 obj = NULL;
364 }
365 }
366 else {
367 LOG0("GateMP_openDefaultGate: Memory allocation failed")
368 }
370 if (obj == NULL) {
371 status = GateMP_E_FAIL;
372 }
373 }
375 /* Return the "opened" GateMP instance */
376 *handlePtr = (GateMP_Handle)obj;
378 return status;
379 }
381 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
382 {
383 Int status = GateMP_S_SUCCESS;
384 GateMP_Object * obj = *(GateMP_Object **)handlePtr;
386 if (obj->gateHandle != NULL) {
387 /* Default gate is always of type System when more than 1 processor */
388 GateMP_RemoteSystemProxy_delete(
389 (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
390 }
392 free(*handlePtr);
393 *handlePtr = NULL;
395 return(status);
396 }
398 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
399 {
400 IArg key;
401 Bool flag = FALSE;
402 Int resourceId = -1;
403 UInt8* inUse = NULL;
404 Int num = 0;
406 /* Remote case */
407 switch (type) {
408 /* TODO: currently only support System proxy */
409 case GateMP_RemoteProtect_SYSTEM:
410 case GateMP_RemoteProtect_CUSTOM1:
411 case GateMP_RemoteProtect_CUSTOM2:
412 inUse = GateMP_module->remoteSystemInUse;
413 num = GateMP_module->numRemoteSystem;
414 break;
416 default:
417 LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
418 break;
419 }
421 if (inUse != NULL) {
422 assert(GateMP_module->defaultGate != NULL);
423 key = GateMP_enter(GateMP_module->defaultGate);
425 /*
426 * Find a free resource id. Note: zero is reserved on the
427 * system proxy for the default gate.
428 */
429 for (resourceId = 0; resourceId < num; resourceId++) {
430 /*
431 * If not in-use, set the inUse to TRUE to prevent other
432 * creates from getting this one.
433 */
434 if (inUse[resourceId] == UNUSED) {
435 flag = TRUE;
437 /* Denote in shared memory that the resource is used */
438 inUse[resourceId] = USED;
439 break;
440 }
441 }
443 GateMP_leave(GateMP_module->defaultGate, key);
444 }
446 if (flag == FALSE) {
447 resourceId = -1;
448 }
450 return (resourceId);
451 }
453 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
454 {
455 Int status = GateMP_S_SUCCESS;
456 IArg key;
457 UInt8* inUse = NULL;
458 Int num = 0;
460 /* Remote case */
461 switch (type) {
462 /* TODO: currently only support System proxy */
463 case GateMP_RemoteProtect_SYSTEM:
464 case GateMP_RemoteProtect_CUSTOM1:
465 case GateMP_RemoteProtect_CUSTOM2:
466 inUse = GateMP_module->remoteSystemInUse;
467 num = GateMP_module->numRemoteSystem;
468 break;
470 default:
471 LOG0("GateMP_releaseResource: Invalid remote protection type\n");
472 status = GateMP_E_FAIL;
473 break;
474 }
476 if ((inUse != NULL) && (id < num)) {
477 assert(GateMP_module->defaultGate != NULL);
478 key = GateMP_enter(GateMP_module->defaultGate);
479 inUse[id] = UNUSED;
480 GateMP_leave(GateMP_module->defaultGate, key);
481 }
482 else {
483 /* Should not happen if module is properly setup */
484 status = GateMP_E_FAIL;
485 }
487 return (status);
488 }
490 Int GateMP_getNumResources(GateMP_RemoteProtect type)
491 {
492 Int num = -1;
494 /* Remote case */
495 switch (type) {
496 /* TODO: currently only support System proxy */
497 case GateMP_RemoteProtect_SYSTEM:
498 case GateMP_RemoteProtect_CUSTOM1:
499 case GateMP_RemoteProtect_CUSTOM2:
500 num = GateMP_module->numRemoteSystem;
501 break;
503 default:
504 LOG0("GateMP_getNumResources: Invalid remote protection type\n");
505 break;
506 }
508 return (num);
509 }
511 NameServer_Handle GateMP_getNameServer(Void)
512 {
513 return (GateMP_module->nameServer);
514 }
516 Int GateMP_start(Void)
517 {
518 Int status = GateMP_S_SUCCESS;
520 pthread_mutex_lock(&GateMP_module->lock);
522 if (GateMP_isSetup()) {
523 GateMP_module->startCount++;
524 }
525 else {
526 /* Cannot start GateMP if it is not setup */
527 status = GateMP_E_FAIL;
528 }
530 pthread_mutex_unlock(&GateMP_module->lock);
532 return (status);
533 }
535 Int GateMP_stop(Void)
536 {
537 Int status = GateMP_S_SUCCESS;
539 pthread_mutex_lock(&GateMP_module->lock);
541 if (GateMP_isSetup()) {
542 GateMP_module->startCount--;
543 }
544 else {
545 /* Cannot stop GateMP if it is not setup */
546 status = GateMP_E_FAIL;
547 }
549 pthread_mutex_unlock(&GateMP_module->lock);
551 return (status);
552 }
554 Bool GateMP_isSetup(Void)
555 {
556 return (GateMP_module->isSetup);
557 }
559 IArg GateMP_enter(GateMP_Handle handle)
560 {
561 GateMP_Object * obj;
562 IArg key;
564 obj = (GateMP_Object *)handle;
565 key = IGateProvider_enter(obj->gateHandle);
567 return(key);
568 }
570 Void GateMP_leave(GateMP_Handle handle, IArg key)
571 {
572 GateMP_Object *obj;
574 obj = (GateMP_Object *)handle;
575 IGateProvider_leave(obj->gateHandle, key);
576 }