1 /*
2 * Copyright (c) 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 */
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 #define NUM_INFO_FIELDS 6 /* Number of fields in info entry */
67 /* Values used to populate the resource 'inUse' arrays */
68 #define UNUSED ((UInt8)0)
69 #define USED ((UInt8)1)
70 #define RESERVED ((UInt8)-1)
72 /* Name of GateMP's nameserver */
73 #define GateMP_NAMESERVER "GateMP"
75 /* =============================================================================
76 * Structures & Enums
77 * =============================================================================
78 */
80 /* structure for GateMP module state */
81 typedef struct {
82 Int numRemoteSystem;
83 Int numRemoteCustom1;
84 Int numRemoteCustom2;
85 UInt8 * remoteSystemInUse;
86 UInt8 * remoteCustom1InUse;
87 UInt8 * remoteCustom2InUse;
88 GateMP_Handle defaultGate;
89 NameServer_Handle nameServer;
90 Bool isSetup;
91 } GateMP_ModuleObject;
93 /* Internal functions */
94 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr);
95 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr);
97 /* =============================================================================
98 * Globals
99 * =============================================================================
100 */
101 /*
102 * GateMP_state
103 */
104 static GateMP_ModuleObject GateMP_state = {
105 .numRemoteSystem = 0,
106 .numRemoteCustom1 = 0,
107 .numRemoteCustom2 = 0,
108 .remoteSystemInUse = NULL,
109 .remoteCustom1InUse = NULL,
110 .remoteCustom2InUse = NULL,
111 .defaultGate = NULL,
112 .nameServer = NULL,
113 .isSetup = FALSE
114 };
116 static GateMP_ModuleObject * GateMP_module = &GateMP_state;
118 /* =============================================================================
119 * APIS
120 * =============================================================================
121 */
123 /* Function to setup the gatemp module. */
124 Int GateMP_setup(Void)
125 {
126 Int status = GateMP_S_SUCCESS;
127 NameServer_Params params;
128 UInt32 nsValue[NUM_INFO_FIELDS];
129 UInt32 len;
131 NameServer_Params_init(¶ms);
132 params.maxRuntimeEntries = MAX_RUNTIME_ENTRIES;
133 params.maxNameLen = MAX_NAME_LEN;
135 /* Assume info entry has more fields than other entries */
136 params.maxValueLen = NUM_INFO_FIELDS * sizeof(UInt32);
138 GateMP_module->nameServer =
139 NameServer_create(GateMP_NAMESERVER, ¶ms);
141 if (GateMP_module->nameServer == NULL) {
142 status = GateMP_E_FAIL;
143 LOG0("GateMP_setup: NameServer_create failed\n");
144 }
146 if (status == GateMP_S_SUCCESS) {
147 do {
148 sleep(1); /* Give the slaves some time to get NameServer ready */
149 status = GateMP_openDefaultGate(&GateMP_module->defaultGate);
150 } while (status == GateMP_E_NOTFOUND);
153 if (status < 0) {
154 LOG0("GateMP_setup: failed to open default gate\n");
155 status = GateMP_E_FAIL;
156 }
157 }
159 if (status == GateMP_S_SUCCESS) {
160 /* Process global info NameServer entry */
161 len = sizeof(nsValue);
163 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_info",
164 &nsValue, &len, NULL);
166 if (status < 0) {
167 LOG0("GateMP_setup: failed to find info entry\n");
168 status = GateMP_E_NOTFOUND;
169 }
170 else {
171 GateMP_module->numRemoteSystem = nsValue[3];
172 GateMP_module->numRemoteCustom1 = nsValue[4];
173 GateMP_module->numRemoteCustom2 = nsValue[5];
175 /* Map InUse arrays to daemon's address space */
176 GateMP_module->remoteSystemInUse = mmap(NULL,
177 GateMP_module->numRemoteSystem * sizeof (UInt8),
178 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
179 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[0]);
180 if (GateMP_module->remoteSystemInUse == MAP_FAILED) {
181 GateMP_module->remoteSystemInUse = NULL;
182 status = GateMP_E_MEMORY;
183 LOG0("Failed to map remoteSystemInUse to host address space!");
184 }
186 if (status == GateMP_S_SUCCESS) {
187 GateMP_module->remoteCustom1InUse = mmap(NULL,
188 GateMP_module->numRemoteCustom1 * sizeof (UInt8),
189 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
190 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[1]);
191 if (GateMP_module->remoteCustom1InUse == MAP_FAILED) {
192 GateMP_module->remoteCustom1InUse = NULL;
193 status = GateMP_E_MEMORY;
194 LOG0("Failed to map remoteSystemInUse to host address" \
195 " space!");
196 }
197 }
199 if (status == GateMP_S_SUCCESS) {
200 GateMP_module->remoteCustom2InUse = mmap(NULL,
201 GateMP_module->numRemoteCustom2 * sizeof (UInt8),
202 (PROT_READ|PROT_WRITE|PROT_NOCACHE),
203 (MAP_PHYS|MAP_SHARED), NOFD, (off_t)nsValue[2]);
204 if (GateMP_module->remoteCustom2InUse == MAP_FAILED) {
205 GateMP_module->remoteCustom2InUse = NULL;
206 status = GateMP_E_MEMORY;
207 LOG0("Failed to map remoteSystemInUse to host address" \
208 " space!");
209 }
210 }
211 }
212 }
214 /* TODO: setup the proxy map */
216 /* clean up if error */
217 if (status < 0) {
218 GateMP_destroy();
219 }
221 GateMP_module->isSetup = TRUE;
223 return (status);
224 }
226 Void GateMP_destroy(Void)
227 {
228 if (GateMP_module->remoteSystemInUse) {
229 munmap((unsigned int *)GateMP_module->remoteSystemInUse,
230 GateMP_module->numRemoteSystem * sizeof (UInt8));
231 GateMP_module->remoteSystemInUse = NULL;
232 }
234 if (GateMP_module->remoteCustom1InUse) {
235 munmap((unsigned int *)GateMP_module->remoteCustom1InUse,
236 GateMP_module->numRemoteCustom1 * sizeof (UInt8));
237 GateMP_module->remoteCustom1InUse = NULL;
238 }
240 if (GateMP_module->remoteCustom2InUse) {
241 munmap((unsigned int *)GateMP_module->remoteCustom2InUse,
242 GateMP_module->numRemoteCustom2 * sizeof (UInt8));
243 GateMP_module->remoteCustom2InUse = NULL;
244 }
246 if (GateMP_module->defaultGate) {
247 GateMP_closeDefaultGate(&GateMP_module->defaultGate);
248 }
250 if (GateMP_module->nameServer) {
251 NameServer_delete(&GateMP_module->nameServer);
252 GateMP_module->nameServer = NULL;
253 }
255 GateMP_module->isSetup = FALSE;
257 return;
258 }
260 /* Open default gate during GateMP_setup. Should only be called once */
261 static Int GateMP_openDefaultGate(GateMP_Handle *handlePtr)
262 {
263 Int status = GateMP_S_SUCCESS;
264 UInt32 len;
265 UInt32 nsValue[4];
266 GateMP_Object * obj = NULL;
267 UInt32 arg;
268 UInt32 mask;
269 UInt32 creatorProcId;
271 GateMP_RemoteSystemProxy_Params systemParams;
273 /* assert that a valid pointer has been supplied */
274 if (handlePtr == NULL) {
275 LOG0("GateMP_open: argument cannot be null\n");
276 status = GateMP_E_INVALIDARG;
277 }
279 if (status == GateMP_S_SUCCESS) {
280 len = sizeof(nsValue);
282 status = NameServer_get(GateMP_module->nameServer, "_GateMP_TI_dGate",
283 &nsValue, &len, NULL);
285 if (status < 0) {
286 *handlePtr = NULL;
287 status = GateMP_E_NOTFOUND;
288 }
289 else {
290 arg = nsValue[2];
291 mask = nsValue[3];
292 creatorProcId = nsValue[1] >> 16;
293 }
294 }
296 if (status == GateMP_S_SUCCESS) {
297 /* allocate the instance object */
298 obj = (GateMP_Object *)calloc(1, sizeof (GateMP_Object));
299 if (obj != NULL) {
300 obj->localGate = NULL; /* TODO: create the local gate instance */
301 obj->localProtect = GETLOCAL(mask);
302 obj->remoteProtect = GETREMOTE(mask);
303 obj->nsKey = 0;
304 obj->numOpens = 1;
305 obj->objType = Ipc_ObjType_OPENDYNAMIC;
306 obj->resourceId = arg;
308 assert(obj->remoteProtect == GateMP_RemoteProtect_SYSTEM);
310 /* create the proxy object */
311 GateMP_RemoteSystemProxy_Params_init(&systemParams);
312 systemParams.resourceId = obj->resourceId;
313 systemParams.openFlag = TRUE;
315 /*
316 * TODO: Currently passing in localProtect instead of localGate,
317 * since GateHWSpinlock owns the local gate
318 */
319 obj->gateHandle = (IGateProvider_Handle)
320 GateMP_RemoteSystemProxy_create(obj->localProtect,
321 &systemParams);
323 if (obj->gateHandle == NULL) {
324 LOG0("GateMP_openDefaultGate: failed to create proxy\n");
325 free(obj);
326 obj = NULL;
327 }
328 }
329 else {
330 LOG0("GateMP_openDefaultGate: Memory allocation failed")
331 }
333 if (obj == NULL) {
334 status = GateMP_E_FAIL;
335 }
336 }
338 /* Return the "opened" GateMP instance */
339 *handlePtr = (GateMP_Handle)obj;
341 return status;
342 }
344 static Int GateMP_closeDefaultGate(GateMP_Handle *handlePtr)
345 {
346 Int status = GateMP_S_SUCCESS;
347 GateMP_Object * obj = *(GateMP_Object **)handlePtr;
349 if (obj->gateHandle != NULL) {
350 /* Default gate is always of type System when more than 1 processor */
351 GateMP_RemoteSystemProxy_delete(
352 (GateMP_RemoteSystemProxy_Handle *)&obj->gateHandle);
353 }
355 free(*handlePtr);
356 *handlePtr = NULL;
358 return(status);
359 }
361 Int GateMP_getFreeResource(GateMP_RemoteProtect type)
362 {
363 IArg key;
364 Bool flag = FALSE;
365 Int resourceId = -1;
366 UInt8* inUse = NULL;
367 Int num = 0;
369 /* Remote case */
370 switch (type) {
371 /* TODO: currently only support System proxy */
372 case GateMP_RemoteProtect_SYSTEM:
373 case GateMP_RemoteProtect_CUSTOM1:
374 case GateMP_RemoteProtect_CUSTOM2:
375 inUse = GateMP_module->remoteSystemInUse;
376 num = GateMP_module->numRemoteSystem;
377 break;
379 default:
380 LOG0("GateMP_getFreeResource: Invalid remote protection type\n");
381 break;
382 }
384 if (inUse != NULL) {
385 assert(GateMP_module->defaultGate != NULL);
386 key = GateMP_enter(GateMP_module->defaultGate);
388 /*
389 * Find a free resource id. Note: zero is reserved on the
390 * system proxy for the default gate.
391 */
392 for (resourceId = 0; resourceId < num; resourceId++) {
393 /*
394 * If not in-use, set the inUse to TRUE to prevent other
395 * creates from getting this one.
396 */
397 if (inUse[resourceId] == UNUSED) {
398 flag = TRUE;
400 /* Denote in shared memory that the resource is used */
401 inUse[resourceId] = USED;
402 break;
403 }
404 }
406 GateMP_leave(GateMP_module->defaultGate, key);
407 }
409 if (flag == FALSE) {
410 resourceId = -1;
411 }
413 return (resourceId);
414 }
416 Int GateMP_releaseResource(UInt id, GateMP_RemoteProtect type)
417 {
418 Int status = GateMP_S_SUCCESS;
419 IArg key;
420 UInt8* inUse = NULL;
421 Int num = 0;
423 /* Remote case */
424 switch (type) {
425 /* TODO: currently only support System proxy */
426 case GateMP_RemoteProtect_SYSTEM:
427 case GateMP_RemoteProtect_CUSTOM1:
428 case GateMP_RemoteProtect_CUSTOM2:
429 inUse = GateMP_module->remoteSystemInUse;
430 num = GateMP_module->numRemoteSystem;
431 break;
433 default:
434 LOG0("GateMP_releaseResource: Invalid remote protection type\n");
435 status = GateMP_E_FAIL;
436 break;
437 }
439 if ((inUse != NULL) && (id < num)) {
440 assert(GateMP_module->defaultGate != NULL);
441 key = GateMP_enter(GateMP_module->defaultGate);
442 inUse[id] = UNUSED;
443 GateMP_leave(GateMP_module->defaultGate, key);
444 }
445 else {
446 /* Should not happen if module is properly setup */
447 status = GateMP_E_FAIL;
448 }
450 return (status);
451 }
453 Int GateMP_getNumResources(GateMP_RemoteProtect type)
454 {
455 Int num = -1;
457 /* Remote case */
458 switch (type) {
459 /* TODO: currently only support System proxy */
460 case GateMP_RemoteProtect_SYSTEM:
461 case GateMP_RemoteProtect_CUSTOM1:
462 case GateMP_RemoteProtect_CUSTOM2:
463 num = GateMP_module->numRemoteSystem;
464 break;
466 default:
467 LOG0("GateMP_getNumResources: Invalid remote protection type\n");
468 break;
469 }
471 return (num);
472 }
474 NameServer_Handle GateMP_getNameServer(Void)
475 {
476 return (GateMP_module->nameServer);
477 }
479 Bool GateMP_isSetup(Void)
480 {
481 return (GateMP_module->isSetup);
482 }
484 IArg GateMP_enter(GateMP_Handle handle)
485 {
486 GateMP_Object * obj;
487 IArg key;
489 obj = (GateMP_Object *)handle;
490 key = IGateProvider_enter(obj->gateHandle);
492 return(key);
493 }
495 Void GateMP_leave(GateMP_Handle handle, IArg key)
496 {
497 GateMP_Object *obj;
499 obj = (GateMP_Object *)handle;
500 IGateProvider_leave(obj->gateHandle, key);
501 }