1 /*
2 * Copyright (c) 2013-2015, 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 /* Linux specific header files */
42 #include <pthread.h>
44 /* System headers */
45 #include <sys/mman.h>
46 #include <sys/stat.h>
47 #include <fcntl.h>
48 #include <stdlib.h>
49 #include <assert.h>
51 /* Module level headers */
52 #include <ti/ipc/GateMP.h>
53 #include <ti/ipc/NameServer.h>
54 #include <ti/ipc/MultiProc.h>
55 #include <_MultiProc.h>
56 #include <GateMP_config.h>
57 #include <_GateMP.h>
59 #include <IGateProvider.h>
60 #include <_GateMP_daemon.h>
61 #include <_lad.h>
63 #if defined (__cplusplus)
64 extern "C" {
65 #endif
67 #define NUM_INFO_FIELDS 6 /* Number of fields in info entry */
69 /* Values used to populate the resource 'inUse' arrays */
70 #define UNUSED ((UInt8)0)
71 #define USED ((UInt8)1)
72 #define RESERVED ((UInt8)-1)
74 /* Name of GateMP's nameserver */
75 #define GateMP_NAMESERVER "GateMP"
77 #define PAGE_ALIGN(size, psz) (((size) + psz - 1) & ~(psz -1))
79 /* =============================================================================
80 * Structures & Enums
81 * =============================================================================
82 */
84 /* structure for GateMP module state */
85 typedef struct {
86 Int numRemoteSystem;
87 Int numRemoteCustom1;
88 Int numRemoteCustom2;
89 UInt8 * remoteSystemInUse;
90 UInt8 * remoteCustom1InUse;
91 UInt8 * remoteCustom2InUse;
92 GateMP_Handle defaultGate;
93 NameServer_Handle nameServer;
94 Bool isSetup;
95 } GateMP_ModuleObject;
97 /* Internal functions */
98 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr);
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(Void)
129 {
130 Int status = GateMP_S_SUCCESS;
131 NameServer_Params params;
132 UInt32 nsValue[NUM_INFO_FIELDS];
133 UInt32 len;
134 UInt32 size;
135 UInt32 alignDiff;
136 UInt32 offset;
137 Int32 fdMem;
139 NameServer_Params_init(¶ms);
140 params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
141 params.maxNameLen = MAX_NAME_LEN;
143 /* Assume info entry has more fields than other entries */
144 params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
146 GateMP_module->nameServer =
147 NameServer_create(GateMP_NAMESERVER, ¶ms);
149 if (GateMP_module->nameServer == NULL) {
150 status = GateMP_E_FAIL;
151 LOG0("GateMP_setup: NameServer_create failed\n");
152 }
154 if (status == GateMP_S_SUCCESS) {
155 do {
156 sleep(1); /* Give the slaves some time to get NameServer ready */
157 status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
158 } while (status == GateMP_E_NOTFOUND);
161 if (status < 0) {
162 LOG0("GateMP_setup: failed to open default gate\n");
163 status = GateMP_E_FAIL;
164 }
165 }
167 if (status == GateMP_S_SUCCESS) {
168 /* Process global info NameServer entry */
169 len = sizeof(nsValue);
171 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
172 &nsValue, &len, NULL);
174 if (status < 0) {
175 LOG0("GateMP_setup: failed to find info entry\n");
176 status = GateMP_E_NOTFOUND;
177 }
178 else {
179 fdMem = open ("/dev/mem", O_RDWR | O_SYNC);
181 if (fdMem < 0){
182 LOG0("GateMP_setup: failed to open the /dev/mem!\n");
183 status = GateMP_E_FAIL;
184 goto cleanup;
185 }
187 GateMP_module->numRemoteSystem = nsValue[3];
188 GateMP_module->numRemoteCustom1 = nsValue[4];
189 GateMP_module->numRemoteCustom2 = nsValue[5];
191 /* Map InUse arrays to daemon's address space */
192 size = GateMP_module->numRemoteSystem * sizeof (UInt8) +
193 (nsValue[0] & (sysconf(_SC_PAGE_SIZE) - 1));
194 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
195 offset = nsValue[0] & ~(sysconf(_SC_PAGE_SIZE) - 1);
196 #if defined(IPC_BUILDOS_ANDROID)
197 GateMP_module->remoteSystemInUse = mmap64(NULL, size,
198 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
199 (off64_t)offset);
200 #else
201 GateMP_module->remoteSystemInUse = mmap(NULL, size,
202 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
203 (off_t)offset);
204 #endif
205 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
206 LOG1("Failed to map remoteSystemInUse=0x%p to host address" \
207 " space!", GateMP_module->remoteSystemInUse);
208 GateMP_module->remoteSystemInUse = NULL;
209 status = GateMP_E_MEMORY;
210 }
211 else {
212 alignDiff = nsValue[0] - offset;
213 GateMP_module->remoteSystemInUse =
214 GateMP_module->remoteSystemInUse + alignDiff;
215 }
217 size = GateMP_module->numRemoteCustom1 * sizeof (UInt8) +
218 (nsValue[1] & (sysconf(_SC_PAGE_SIZE) - 1));
219 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
220 offset = nsValue[1] & ~(sysconf(_SC_PAGE_SIZE) - 1);
221 if (status == GateMP_S_SUCCESS) {
222 #if defined(IPC_BUILDOS_ANDROID)
223 GateMP_module->remoteCustom1InUse = mmap64(NULL, size,
224 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
225 (off64_t)offset);
226 #else
227 GateMP_module->remoteCustom1InUse = mmap(NULL, size,
228 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
229 (off_t)offset);
230 #endif
231 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
232 LOG1("Failed to map remoteCustom1InUse=%p to host address" \
233 " space!", GateMP_module->remoteCustom1InUse);
234 GateMP_module->remoteCustom1InUse = NULL;
235 status = GateMP_E_MEMORY;
236 }
237 else {
238 alignDiff = nsValue[1] - offset;
239 GateMP_module->remoteCustom1InUse =
240 GateMP_module->remoteCustom1InUse + alignDiff;
241 }
242 }
244 size = GateMP_module->numRemoteCustom2 * sizeof (UInt8) +
245 (nsValue[2] & (sysconf(_SC_PAGE_SIZE) - 1));
246 size = PAGE_ALIGN(size, sysconf(_SC_PAGE_SIZE));
247 offset = nsValue[2] & ~(sysconf(_SC_PAGE_SIZE) - 1);
248 if (status == GateMP_S_SUCCESS) {
249 #if defined(IPC_BUILDOS_ANDROID)
250 GateMP_module->remoteCustom2InUse = mmap64(NULL, size,
251 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
252 (off64_t)offset);
253 #else
254 GateMP_module->remoteCustom2InUse = mmap(NULL, size,
255 (PROT_READ|PROT_WRITE), (MAP_SHARED), fdMem,
256 (off_t)offset);
257 #endif
258 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
259 LOG1("Failed to map remoteCustom2InUse=%p to host address" \
260 " space!", GateMP_module->remoteCustom2InUse);
261 GateMP_module->remoteCustom2InUse = NULL;
262 status = GateMP_E_MEMORY;
263 }
264 else {
265 alignDiff = nsValue[2] - offset;
266 GateMP_module->remoteCustom2InUse =
267 GateMP_module->remoteCustom2InUse + alignDiff;
268 }
269 }
270 }
271 }
273 /* TODO: setup the proxy map */
275 cleanup:
276 /* clean up if error */
277 if (status < 0) {
278 GateMP_destroy();
279 }
281 GateMP_module->isSetup = TRUE;
283 return (status);
284 }
286 Void GateMP_destroy(Void)
287 {
288 if (GateMP_module->remoteSystemInUse) {
289 munmap((unsigned int *)GateMP_module->remoteSystemInUse,
290 GateMP_module->numRemoteSystem * sizeof (UInt8));
291 GateMP_module->remoteSystemInUse = NULL;
292 }
294 if (GateMP_module->remoteCustom1InUse) {
295 munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
296 GateMP_module->numRemoteCustom1 * sizeof (UInt8));
297 GateMP_module->remoteCustom1InUse = NULL;
298 }
300 if (GateMP_module->remoteCustom2InUse) {
301 munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
302 GateMP_module->numRemoteCustom2 * sizeof (UInt8));
303 GateMP_module->remoteCustom2InUse = NULL;
304 }
306 if (GateMP_module->defaultGate) {
307 GateMP_closeDefaultGate(&GateMP_module->defaultGate);
308 }
310 if (GateMP_module->nameServer) {
311 NameServer_delete(&GateMP_module->nameServer);
312 GateMP_module->nameServer = NULL;
313 }
315 GateMP_module->isSetup = FALSE;
317 return;
318 }
320 /* Open default gate during GateMP_setup. Should only be called once */
321 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
322 {
323 Int status = GateMP_S_SUCCESS;
324 UInt32 len;
325 UInt32 nsValue[4];
326 GateMP_Object * obj = NULL;
327 UInt32 arg;
328 UInt32 mask;
329 UInt32 creatorProcId;
331 GateMP_RemoteSystemProxy_Params systemParams;
333 /* assert that a valid pointer has been supplied */
334 if (handlePtr == NULL) {
335 LOG0("GateMP_open: argument cannot be null\n");
336 status = GateMP_E_INVALIDARG;
337 }
339 if (status == GateMP_S_SUCCESS) {
340 len = sizeof(nsValue);
342 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
343 &nsValue, &len, NULL);
345 if (status < 0) {
346 *handlePtr = NULL;
347 status = GateMP_E_NOTFOUND;
348 }
349 else {
350 arg = nsValue[2];
351 mask = nsValue[3];
352 creatorProcId = nsValue[1] >> 16;
353 }
354 }
356 if (status == GateMP_S_SUCCESS) {
357 /* allocate the instance object */
358 obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
359 if (obj != NULL) {
360 obj->localGate = NULL; /* TODO: create the local gate instance */
361 obj->localProtect = GETLOCAL(mask);
362 obj->remoteProtect = GETREMOTE(mask);
363 obj->nsKey = 0;
364 obj->numOpens = 1;
365 obj->objType = Ipc_ObjType_OPENDYNAMIC;
366 obj->resourceId = arg;
368 assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
370 /* create the proxy object */
371 GateMP_RemoteSystemProxy_Params_init(&systemParams);
372 systemParams.resourceId = obj->resourceId;
373 systemParams.openFlag = TRUE;
375 /*
376 * TODO: Currently passing in localProtect instead of localGate,
377 * since GateHWSpinlock owns the local gate
378 */
379 obj->gateHandle = (IGateProvider_Handle)
380 GateMP_RemoteSystemProxy_create(obj->localProtect,
381 &systemParams);
383 if (obj->gateHandle == NULL) {
384 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
385 free(obj);
386 obj = NULL;
387 }
388 }
389 else {
390 LOG0("GateMP_openDefaultGate: Memory allocation failed")
391 }
393 if (obj == NULL) {
394 status = GateMP_E_FAIL;
395 }
396 }
398 /* Return the "opened" GateMP instance */
399 *handlePtr = (GateMP_Handle)obj;
401 return status;
402 }
404 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
405 {
406 Int status = GateMP_S_SUCCESS;
407 GateMP_Object * obj = *(GateMP_Object **)handlePtr;
409 if (obj->gateHandle != NULL) {
410 /* Default gate is always of type System when more than 1 processor */
411 GateMP_RemoteSystemProxy_delete(
412 (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
413 }
415 free(*handlePtr);
416 *handlePtr = NULL;
418 return(status);
419 }
421 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
422 {
423 IArg key;
424 Bool flag = FALSE;
425 Int resourceId = -1;
426 UInt8* inUse = NULL;
427 Int num = 0;
429 /* Remote case */
430 switch (type) {
431 /* TODO: currently only support System proxy */
432 case GateMP_RemoteProtect_SYSTEM:
433 case GateMP_RemoteProtect_CUSTOM1:
434 case GateMP_RemoteProtect_CUSTOM2:
435 inUse = GateMP_module->remoteSystemInUse;
436 num = GateMP_module->numRemoteSystem;
437 break;
439 default:
440 LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
441 break;
442 }
444 if (inUse != NULL) {
445 assert(GateMP_module->defaultGate != NULL);
446 key = GateMP_enter(GateMP_module->defaultGate);
448 /*
449 * Find a free resource id. Note: zero is reserved on the
450 * system proxy for the default gate.
451 */
452 for (resourceId = 0; resourceId < num; resourceId++) {
453 /*
454 * If not in-use, set the inUse to TRUE to prevent other
455 * creates from getting this one.
456 */
457 if (inUse[resourceId] == UNUSED) {
458 flag = TRUE;
460 /* Denote in shared memory that the resource is used */
461 inUse[resourceId] = USED;
462 break;
463 }
464 }
466 GateMP_leave(GateMP_module->defaultGate, key);
467 }
469 if (flag == FALSE) {
470 resourceId = -1;
471 }
473 return (resourceId);
474 }
476 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
477 {
478 Int status = GateMP_S_SUCCESS;
479 IArg key;
480 UInt8* inUse = NULL;
481 Int num = 0;
483 /* Remote case */
484 switch (type) {
485 /* TODO: currently only support System proxy */
486 case GateMP_RemoteProtect_SYSTEM:
487 case GateMP_RemoteProtect_CUSTOM1:
488 case GateMP_RemoteProtect_CUSTOM2:
489 inUse = GateMP_module->remoteSystemInUse;
490 num = GateMP_module->numRemoteSystem;
491 break;
493 default:
494 LOG0("GateMP_releaseResource: Invalid remote protection type\n");
495 status = GateMP_E_FAIL;
496 break;
497 }
499 if ((inUse != NULL) && (id < num)) {
500 assert(GateMP_module->defaultGate != NULL);
501 key = GateMP_enter(GateMP_module->defaultGate);
502 inUse[id] = UNUSED;
503 GateMP_leave(GateMP_module->defaultGate, key);
504 }
505 else {
506 /* Should not happen if module is properly setup */
507 status = GateMP_E_FAIL;
508 }
510 return (status);
511 }
513 Int GateMP_getNumResources(GateMP_RemoteProtect type)
514 {
515 Int num = -1;
517 /* Remote case */
518 switch (type) {
519 /* TODO: currently only support System proxy */
520 case GateMP_RemoteProtect_SYSTEM:
521 case GateMP_RemoteProtect_CUSTOM1:
522 case GateMP_RemoteProtect_CUSTOM2:
523 num = GateMP_module->numRemoteSystem;
524 break;
526 default:
527 LOG0("GateMP_getNumResources: Invalid remote protection type\n");
528 break;
529 }
531 return (num);
532 }
534 NameServer_Handle GateMP_getNameServer(Void)
535 {
536 return (GateMP_module->nameServer);
537 }
539 Bool GateMP_isSetup(Void)
540 {
541 return (GateMP_module->isSetup);
542 }
544 IArg GateMP_enter(GateMP_Handle handle)
545 {
546 GateMP_Object * obj;
547 IArg key;
549 obj = (GateMP_Object *)handle;
550 key = IGateProvider_enter(obj->gateHandle);
552 return(key);
553 }
555 Void GateMP_leave(GateMP_Handle handle, IArg key)
556 {
557 GateMP_Object *obj;
559 obj = (GateMP_Object *)handle;
560 IGateProvider_leave(obj->gateHandle, key);
561 }