1 /*
2 * @file syslink_main.c
3 *
4 * @brief syslink main
5 *
6 *
7 * @ver 02.00.00.46_alpha1
8 *
9 * ============================================================================
10 *
11 * Copyright (c) 2011-2014, Texas Instruments Incorporated
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * * Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * * Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in the
22 * documentation and/or other materials provided with the distribution.
23 *
24 * * Neither the name of Texas Instruments Incorporated nor the names of
25 * its contributors may be used to endorse or promote products derived
26 * from this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
30 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
31 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
32 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
33 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
34 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
35 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
36 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
37 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
38 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 * Contact information for paper mail:
40 * Texas Instruments
41 * Post Office Box 655303
42 * Dallas, Texas 75265
43 * Contact information:
44 * http://www-k.ext.ti.com/sc/technical-support/product-information-centers.htm?
45 * DCMP=TIHomeTracking&HQS=Other+OT+home_d_contact
46 * ============================================================================
47 *
48 */
50 #include "proto.h"
52 #include <pthread.h>
53 #include <fcntl.h>
54 #include <stdint.h>
55 #include <sys/procmgr.h>
56 #include <sys/neutrino.h>
57 #include <sys/siginfo.h>
58 #include <signal.h>
59 #include <stdbool.h>
61 #include <IpcKnl.h>
63 /* OSAL & Utils headers */
64 #include <ti/syslink/utils/List.h>
65 #include <ti/syslink/utils/MemoryOS.h>
66 #include <ti/ipc/MultiProc.h>
67 #include <ti/ipc/NameServer.h>
68 #include <_MultiProc.h>
69 #include <_NameServer.h>
70 #include <_GateMP_daemon.h>
71 #include <OsalSemaphore.h>
72 #include <ti/syslink/utils/OsalPrint.h>
73 #if defined(SYSLINK_PLATFORM_OMAP5430)
74 #include <_ipu_pm.h>
75 #endif
76 #include <ti/syslink/utils/Trace.h>
77 #include <ti/syslink/ProcMgr.h>
78 #include <Bitops.h>
79 #include <RscTable.h>
81 #include <ti-ipc.h>
83 #define DENY_ALL \
84 PROCMGR_ADN_ROOT \
85 | PROCMGR_ADN_NONROOT \
86 | PROCMGR_AOP_DENY \
87 | PROCMGR_AOP_LOCK
90 static int verbosity = 2;
92 /* Disable recovery mechanism if true */
93 static int disableRecovery = false;
94 static char * logFilename = NULL;
96 /* Number of cores to attach to */
97 static int numAttach = 0;
99 #if defined(SYSLINK_PLATFORM_VAYU)
100 /* DSP2 is invalid on Vayu */
101 #define INVALID_PROC "DSP2"
103 static bool gatempEnabled = false;
104 static Int32 sr0OwnerProcId = -1;
105 #else
106 #define INVALID_PROC ""
107 #endif
109 // Syslink hibernation global variables
110 Bool syslink_hib_enable = TRUE;
111 #if !defined(SYSLINK_PLATFORM_OMAP5430)
112 #define PM_HIB_DEFAULT_TIME 5000
113 #endif
114 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
115 Bool syslink_hib_hibernating = FALSE;
116 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
117 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
119 extern Int rpmsg_rpc_setup (Void);
120 extern Void rpmsg_rpc_destroy (Void);
121 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
123 typedef struct syslink_firmware_info_t {
124 uint16_t proc_id;
125 char * proc;
126 char * firmware;
127 bool attachOnly;
128 int procState; /* state of processor - index into procStateNames array */
129 int readProcState; /* state that is currently being printed */
130 bool reload; /* reload core during recovery */
131 bool freeString; /* Need to free previously allocated firmware string */
132 } syslink_firmware_info;
133 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
135 /* Number of valid entries in syslink_firmware array */
136 static unsigned int syslink_num_cores = 0;
138 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
139 bool recover);
140 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
141 bool recover);
142 int init_syslink_trace_device(syslink_dev_t *dev);
143 int deinit_syslink_trace_device(syslink_dev_t *dev);
145 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
146 ProcMgr_State fromState, ProcMgr_State toState,
147 ProcMgr_EventStatus status, Ptr args);
149 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
151 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
152 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
153 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
154 ProcMgr_State_Error,
155 ProcMgr_State_Watchdog,
156 ProcMgr_State_EndValue};
158 /* Processor states */
159 #define RESET_STATE 0
160 #define RUNNING_STATE 1
162 static String procStateNames[] = { "In reset",
163 "Running" };
165 typedef struct syslink_trace_info_t {
166 uintptr_t va;
167 uint32_t len;
168 uint32_t * widx;
169 uint32_t * ridx;
170 Bool firstRead;
171 } syslink_trace_info;
173 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
175 static int runSlave(syslink_dev_t *dev, uint16_t procId,
176 syslink_firmware_info * firmware_info)
177 {
178 int status = 0;
179 ProcMgr_AttachParams attachParams;
181 if (firmware_info->firmware) {
182 rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
183 if (rscHandle[procId] == NULL) {
184 status = -1;
185 return status;
186 }
187 }
189 status = ProcMgr_open(&procH[procId], procId);
190 if (status < 0 || procH[procId] == NULL) {
191 goto procmgropen_fail;
192 }
194 /* Load and start the remote processor. */
195 ProcMgr_getAttachParams(procH[procId], &attachParams);
196 if (firmware_info->attachOnly) {
197 attachParams.bootMode = ProcMgr_BootMode_NoBoot;
198 }
199 status = ProcMgr_attach(procH[procId], &attachParams);
200 if (status < 0) {
201 GT_setFailureReason(curTrace,
202 GT_4CLASS,
203 "runSlave",
204 status,
205 "ProcMgr_attach failed!");
206 goto procmgrattach_fail;
207 }
209 if ((firmware_info->firmware) &&
210 (!firmware_info->attachOnly)) {
211 status = ProcMgr_load(procH[procId],
212 (String)firmware_info->firmware, 0, NULL,
213 NULL, &procH_fileId[procId]);
214 if (status < 0) {
215 GT_setFailureReason(curTrace,
216 GT_4CLASS,
217 "runSlave",
218 status,
219 "ProcMgr_load failed!");
220 goto procmgrload_fail;
221 }
222 }
224 status = Ipc_attach(procId);
225 if (status < 0) {
226 GT_setFailureReason(curTrace,
227 GT_4CLASS,
228 "runSlave",
229 status,
230 "Ipc_attach failed!");
231 goto ipcattach_fail;
232 }
234 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
235 -1, errStates);
236 if (status < 0) {
237 goto procmgrreg_fail;
238 }
240 if (!firmware_info->attachOnly) {
241 status = ProcMgr_start(procH[procId], NULL);
242 if (status < 0) {
243 GT_setFailureReason(curTrace,
244 GT_4CLASS,
245 "runSlave",
246 status,
247 "ProcMgr_start failed!");
248 goto procmgrstart_fail;
249 }
250 }
252 Osal_printf("runSlave successful for core %d\n", procId);
254 return 0;
256 procmgrstart_fail:
257 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
258 (Ptr)dev, errStates);
259 procmgrreg_fail:
260 Ipc_detach(procId);
261 ipcattach_fail:
262 if ((firmware_info->firmware) &&
263 (!firmware_info->attachOnly)) {
264 ProcMgr_unload(procH[procId], procH_fileId[procId]);
265 }
266 procmgrload_fail:
267 ProcMgr_detach(procH[procId]);
268 procmgrattach_fail:
269 ProcMgr_close(&procH[procId]);
270 procH[procId] = NULL;
271 procmgropen_fail:
272 RscTable_free(&rscHandle[procId]);
274 return -1;
275 }
277 static int resetSlave(syslink_dev_t *dev, uint16_t procId)
278 {
279 if ((procH[procId]) && (procH_fileId[procId])) {
280 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
281 ProcMgr_stop(procH[procId]);
282 }
284 if (procH[procId]) {
285 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb, (Ptr)dev,
286 errStates);
287 Ipc_detach(procId);
288 if (procH_fileId[procId]) {
289 ProcMgr_unload(procH[procId], procH_fileId[procId]);
290 procH_fileId[procId] = 0;
291 }
292 ProcMgr_detach(procH[procId]);
293 ProcMgr_close(&procH[procId]);
294 procH[procId] = NULL;
295 RscTable_free(&rscHandle[procId]);
296 rscHandle[procId] = NULL;
297 }
299 Osal_printf("resetSlave successful for core %d\n", procId);
301 return 0;
302 }
304 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
305 syslink_ocb_t *ocb)
306 {
307 int nbytes;
308 int nparts;
309 int status;
310 int nleft;
311 int i;
312 uint16_t procid = ocb->ocb.attr->procid;
313 syslink_dev_t * dev = ocb->ocb.attr->dev;
315 if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
316 return (status);
317 }
319 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
320 return (ENOSYS);
321 }
323 if (strcmp(MultiProc_getName(procid), INVALID_PROC) == 0) {
324 fprintf(stderr, "Unsupported core\n");
325 return (EPERM);
326 }
328 pthread_mutex_lock(&dev->firmwareLock);
330 for (i = 0; i < syslink_num_cores; i++) {
331 if (syslink_firmware[i].proc_id == procid) {
332 break;
333 }
334 }
335 if (i == syslink_num_cores) {
336 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
337 syslink_firmware[syslink_num_cores].proc =
338 MultiProc_getName(procid);
339 syslink_firmware[syslink_num_cores].proc_id = procid;
340 syslink_firmware[syslink_num_cores].attachOnly = false;
341 syslink_firmware[syslink_num_cores].reload = false;
342 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
343 syslink_firmware[syslink_num_cores].freeString = false;
344 syslink_firmware[syslink_num_cores++].firmware = NULL;
345 }
346 else {
347 pthread_mutex_unlock(&dev->firmwareLock);
348 return (EBADSLT);
349 }
350 }
352 if (ocb->ocb.offset == 0) {
353 /* latch onto new state, so that we print out complete strings */
354 syslink_firmware[i].readProcState = syslink_firmware[i].procState;
355 }
357 nleft = strlen(procStateNames[syslink_firmware[i].readProcState])
358 - ocb->ocb.offset; /* the state is expressed in one byte */
359 nbytes = min(msg->i.nbytes, nleft);
361 /* Make sure the user has supplied a big enough buffer */
362 if (nbytes > 0) {
363 /* set up the return data IOV */
364 SETIOV(ctp->iov,
365 (char *)procStateNames[syslink_firmware[i].readProcState]
366 + ocb->ocb.offset, nbytes);
368 pthread_mutex_unlock(&dev->firmwareLock);
370 /* set up the number of bytes (returned by client's read()) */
371 _IO_SET_READ_NBYTES(ctp, nbytes);
373 ocb->ocb.offset += nbytes;
375 nparts = 1;
376 }
377 else {
378 pthread_mutex_unlock(&dev->firmwareLock);
380 _IO_SET_READ_NBYTES (ctp, 0);
382 /* reset offset */
383 ocb->ocb.offset = 0;
385 nparts = 0;
386 }
388 /* mark the access time as invalid (we just accessed it) */
390 if (msg->i.nbytes > 0) {
391 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
392 }
394 return (_RESMGR_NPARTS(nparts));
395 }
397 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
398 syslink_ocb_t *ocb)
399 {
400 int status;
401 char * buf;
402 uint16_t procid = ocb->ocb.attr->procid;
403 int i;
404 char * ptr;
405 syslink_dev_t * dev = ocb->ocb.attr->dev;
406 Int32 sr0ProcId;
408 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
409 return (status);
410 }
412 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
413 return (ENOSYS);
414 }
416 if (strcmp(MultiProc_getName(procid), INVALID_PROC) == 0) {
417 fprintf(stderr, "Unsupported core\n");
418 return (EPERM);
419 }
421 /* set up the number of bytes (returned by client's write()) */
422 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
424 buf = (char *) malloc(msg->i.nbytes + 1);
425 if (buf == NULL) {
426 return (ENOMEM);
427 }
429 /*
430 * Read the data from the sender's message buffer.
431 */
432 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
433 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
434 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
435 *ptr = '\0';
436 }
438 pthread_mutex_lock(&dev->firmwareLock);
439 for (i = 0; i < syslink_num_cores; i++) {
440 if (syslink_firmware[i].proc_id == procid) {
441 break;
442 }
443 }
444 if (i == syslink_num_cores) {
445 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
446 syslink_firmware[syslink_num_cores].proc =
447 MultiProc_getName(procid);
448 syslink_firmware[syslink_num_cores].proc_id = procid;
449 syslink_firmware[syslink_num_cores].attachOnly = false;
450 syslink_firmware[syslink_num_cores].reload = false;
451 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
452 syslink_firmware[syslink_num_cores].freeString = false;
453 syslink_firmware[syslink_num_cores++].firmware = NULL;
454 }
455 else {
456 pthread_mutex_unlock(&dev->firmwareLock);
457 return (EBADSLT);
458 }
459 }
461 if (strcmp("1", buf) == 0) {
462 if ((syslink_firmware[i].procState == RESET_STATE) &&
463 (syslink_firmware[i].firmware != NULL)) {
464 runSlave(ocb->ocb.attr->dev, procid, &syslink_firmware[i]);
465 #if defined(SYSLINK_PLATFORM_VAYU)
466 if (gatempEnabled) {
467 if (sr0OwnerProcId == -1) {
468 /* Set up GateMP */
469 status = GateMP_setup(&sr0ProcId);
470 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
471 resetSlave(ocb->ocb.attr->dev, procid);
472 pthread_mutex_unlock(&dev->firmwareLock);
473 free(buf);
474 return (EIO);
475 }
476 else if (status == 0) {
477 /* We have discovered an owner for SR0 */
478 sr0OwnerProcId = sr0ProcId;
479 }
480 }
481 else {
482 /*
483 * We have already identified SR0 owner and setup GateMP.
484 * Do nothing.
485 */
486 }
487 }
488 #endif
489 printf("Core is now running with image '%s'\n",
490 syslink_firmware[i].firmware);
491 syslink_firmware[i].procState = RUNNING_STATE;
492 syslink_firmware[i].reload = true;
493 status = init_syslink_trace_device(dev);
494 if (status < 0) {
495 pthread_mutex_unlock(&dev->firmwareLock);
496 free(buf);
497 return (EIO);
498 }
499 printf("Core %s has been started.\n", MultiProc_getName(procid));
500 }
501 }
502 else if (strcmp("0", buf) == 0) {
503 if (syslink_firmware[i].procState == RUNNING_STATE) {
504 #if defined(SYSLINK_PLATFORM_VAYU)
505 if ((gatempEnabled) && (procid == sr0OwnerProcId)) {
506 sr0OwnerProcId = -1;
507 status = GateMP_destroy(FALSE);
508 if (status < 0) {
509 pthread_mutex_unlock(&dev->firmwareLock);
510 free(buf);
511 fprintf(stderr, "Core %s cannot be reset. GateMP may still"
512 " be in use by host\n", MultiProc_getName(procid));
513 return (EIO);
514 }
515 }
516 #endif
517 resetSlave(ocb->ocb.attr->dev, procid);
518 syslink_firmware[i].procState = RESET_STATE;
519 syslink_firmware[i].reload = false;
520 status = deinit_syslink_trace_device(dev);
521 if (status < 0) {
522 pthread_mutex_unlock(&dev->firmwareLock);
523 free(buf);
524 Osal_printf("IPC: deinit_syslink_trace_device failed %d",
525 status);
526 return (EIO);
527 }
528 printf("Core %s has been reset.\n", MultiProc_getName(procid));
529 }
530 }
531 else {
532 /* ignore the input as it is not recognized */
533 fprintf(stderr, "Unrecognized input\n");
534 }
536 pthread_mutex_unlock(&dev->firmwareLock);
538 free(buf);
540 if (msg->i.nbytes > 0) {
541 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
542 }
544 return (_RESMGR_NPARTS(0));
545 }
547 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
548 syslink_ocb_t *ocb)
549 {
550 int nbytes;
551 int nparts;
552 int status;
553 int nleft;
554 int i;
555 uint16_t procid = ocb->ocb.attr->procid;
556 syslink_dev_t * dev = ocb->ocb.attr->dev;
558 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
559 return (status);
560 }
562 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
563 return (ENOSYS);
564 }
566 if (strcmp(MultiProc_getName(procid), INVALID_PROC) == 0) {
567 fprintf(stderr, "Unsupported core\n");
568 return (EPERM);
569 }
571 pthread_mutex_lock(&dev->firmwareLock);
572 for (i = 0; i < syslink_num_cores; i++) {
573 if (syslink_firmware[i].proc_id == procid) {
574 break;
575 }
576 }
578 if (i == syslink_num_cores) {
579 if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
580 syslink_firmware[syslink_num_cores].proc =
581 MultiProc_getName(procid);
582 syslink_firmware[syslink_num_cores].proc_id = procid;
583 syslink_firmware[syslink_num_cores].attachOnly = false;
584 syslink_firmware[syslink_num_cores].reload = false;
585 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
586 syslink_firmware[syslink_num_cores].freeString = false;
587 syslink_firmware[syslink_num_cores++].firmware = NULL;
588 }
589 else {
590 pthread_mutex_unlock(&dev->firmwareLock);
591 return (EBADSLT);
592 }
593 }
595 if (syslink_firmware[i].firmware == NULL) {
596 nbytes = 0;
597 }
598 else {
599 nleft = strlen(syslink_firmware[i].firmware)
600 - ocb->ocb.offset; /* the state is expressed in one byte */
601 nbytes = min(msg->i.nbytes, nleft);
602 }
604 /* Make sure the user has supplied a big enough buffer */
605 if (nbytes > 0) {
606 /* set up the return data IOV */
607 SETIOV(ctp->iov, (char *)syslink_firmware[i].firmware
608 + ocb->ocb.offset, nbytes);
610 /* set up the number of bytes (returned by client's read()) */
611 _IO_SET_READ_NBYTES(ctp, nbytes);
613 ocb->ocb.offset += nbytes;
615 nparts = 1;
616 }
617 else {
618 _IO_SET_READ_NBYTES (ctp, 0);
620 /* reset offset */
621 ocb->ocb.offset = 0;
623 nparts = 0;
624 }
626 pthread_mutex_unlock(&dev->firmwareLock);
628 /* mark the access time as invalid (we just accessed it) */
630 if (msg->i.nbytes > 0) {
631 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
632 }
634 return (_RESMGR_NPARTS(nparts));
635 }
637 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
638 syslink_ocb_t *ocb)
639 {
640 int status;
641 char * buf;
642 uint16_t procid = ocb->ocb.attr->procid;
643 int i;
644 char * absPath;
645 char * ptr;
646 syslink_dev_t * dev = ocb->ocb.attr->dev;
648 if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
649 return (status);
650 }
652 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
653 return (ENOSYS);
654 }
656 if (strcmp(MultiProc_getName(procid), INVALID_PROC) == 0) {
657 fprintf(stderr, "Unsupported core\n");
658 return (EPERM);
659 }
661 /* set up the number of bytes (returned by client's write()) */
662 _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
664 buf = (char *) malloc(msg->i.nbytes + 1);
665 if (buf == NULL) {
666 return (ENOMEM);
667 }
669 /*
670 * Read the data from the sender's message buffer.
671 */
672 resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
673 buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
674 if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
675 *ptr = '\0';
676 }
678 /* Get the abs path for all firmware files */
679 absPath = calloc(1, PATH_MAX + 1);
680 if (absPath == NULL) {
681 free(buf);
682 return (ENOMEM);
683 }
684 if (NULL == realpath(buf, absPath)) {
685 fprintf(stderr, "invalid path to executable: %d\n", errno);
686 fprintf(stderr, "make sure you are specifying the full path to the "
687 "file.\n");
688 free(absPath);
689 free(buf);
690 return (ENOENT);
691 }
692 free(buf);
694 pthread_mutex_lock(&dev->firmwareLock);
696 /*
697 * Check if an entry in syslink_firmware already exists for this core.
698 * If not, create one. Otherwise just update the firmware path.
699 */
700 for (i = 0; i < syslink_num_cores; i++) {
701 if (syslink_firmware[i].proc_id == procid) {
702 break;
703 }
704 }
705 if (i == syslink_num_cores) {
706 if (syslink_num_cores < MultiProc_MAXPROCESSORS) {
707 syslink_firmware[syslink_num_cores].proc =
708 MultiProc_getName(procid);
709 syslink_firmware[syslink_num_cores].proc_id = procid;
710 syslink_firmware[syslink_num_cores].attachOnly = false;
711 syslink_firmware[syslink_num_cores].reload = false;
712 syslink_firmware[syslink_num_cores].procState = RESET_STATE;
713 syslink_firmware[syslink_num_cores].freeString = true;
714 syslink_firmware[syslink_num_cores++].firmware = absPath;
715 }
716 else {
717 pthread_mutex_unlock(&dev->firmwareLock);
718 free(absPath);
719 return (EBADSLT);
720 }
721 }
722 else {
723 /* Free previously allocated string */
724 if ((syslink_firmware[syslink_num_cores].freeString) &&
725 (syslink_firmware[syslink_num_cores].firmware)) {
726 free(syslink_firmware[i].firmware);
727 }
728 syslink_firmware[i].firmware = absPath;
729 }
731 pthread_mutex_unlock(&dev->firmwareLock);
733 if (msg->i.nbytes > 0) {
734 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
735 }
737 return (_RESMGR_NPARTS(0));
738 }
740 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
741 {
742 int nbytes;
743 int nparts;
744 int status;
745 int nleft;
746 uint32_t len;
747 uint16_t procid = ocb->ocb.attr->procid;
749 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
750 return (status);
752 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
753 return (ENOSYS);
755 /* check to see where the trace buffer is */
756 if (proc_traces[procid].va == NULL) {
757 return (ENOSYS);
758 }
759 if (ocb->ocb.offset == 0) {
760 ocb->widx = *(proc_traces[procid].widx);
761 ocb->ridx = *(proc_traces[procid].ridx);
762 *(proc_traces[procid].ridx) = ocb->widx;
763 }
765 /* Check for wrap-around */
766 if (ocb->widx < ocb->ridx)
767 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
768 else
769 len = ocb->widx - ocb->ridx;
771 /* Determine the amount left to print */
772 if (ocb->widx >= ocb->ridx)
773 nleft = len - ocb->ocb.offset;
774 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
775 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
776 else
777 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
779 nbytes = min (msg->i.nbytes, nleft);
781 /* Make sure the user has supplied a big enough buffer */
782 if (nbytes > 0) {
783 /* set up the return data IOV */
784 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
785 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
786 else
787 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
789 /* set up the number of bytes (returned by client's read()) */
790 _IO_SET_READ_NBYTES (ctp, nbytes);
792 ocb->ocb.offset += nbytes;
794 nparts = 1;
795 }
796 else {
797 _IO_SET_READ_NBYTES (ctp, 0);
799 /* reset offset */
800 ocb->ocb.offset = 0;
802 nparts = 0;
803 }
805 /* mark the access time as invalid (we just accessed it) */
807 if (msg->i.nbytes > 0)
808 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
810 return (_RESMGR_NPARTS (nparts));
811 }
813 extern OsalSemaphore_Handle mqcopy_test_sem;
815 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
816 {
817 int status = _RESMGR_NOREPLY;
818 struct _msg_info info;
820 /*
821 * Try to run the default unblock for this message.
822 */
823 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
824 return status;
825 }
827 /*
828 * Check if rcvid is still valid and still has an unblock
829 * request pending.
830 */
831 if (MsgInfo(ctp->rcvid, &info) == -1 ||
832 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
833 return _RESMGR_NOREPLY;
834 }
836 if (mqcopy_test_sem)
837 OsalSemaphore_post(mqcopy_test_sem);
839 return _RESMGR_NOREPLY;
840 }
842 IOFUNC_OCB_T *
843 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
844 {
845 syslink_ocb_t *ocb = NULL;
847 /* Allocate the OCB */
848 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
849 if (ocb == NULL){
850 errno = ENOMEM;
851 return (NULL);
852 }
854 ocb->pid = ctp->info.pid;
856 return (IOFUNC_OCB_T *)(ocb);
857 }
859 void
860 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
861 {
862 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
864 if (ocb) {
865 #ifndef SYSLINK_PLATFORM_VAYU
866 GateHWSpinlock_LeaveLockForPID(ocb->pid);
867 #endif
868 free (ocb);
869 }
870 }
872 int init_slave_devices(syslink_dev_t *dev)
873 {
874 resmgr_attr_t resmgr_attr;
875 int i;
876 syslink_attr_t * slave_attr;
877 int status = 0;
879 memset(&resmgr_attr, 0, sizeof resmgr_attr);
880 resmgr_attr.nparts_max = 1;
881 resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
883 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
884 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_state[i],
885 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_state[i]);
886 slave_attr = &dev->syslink.cattr_slave[i];
887 iofunc_attr_init(&slave_attr->attr,
888 S_IFCHR | 0777, NULL, NULL);
889 slave_attr->attr.mount = &dev->syslink.mattr;
890 slave_attr->procid = i;
891 slave_attr->dev = (Ptr)dev;
892 iofunc_time_update(&slave_attr->attr);
893 snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
894 "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
895 dev->syslink.iofuncs_state[i].read = slave_state_read;
896 dev->syslink.iofuncs_state[i].write = slave_state_write;
898 if (-1 == (dev->syslink.resmgr_id_state[i] =
899 resmgr_attach(dev->dpp, &resmgr_attr,
900 dev->syslink.device_name, _FTYPE_ANY, 0,
901 &dev->syslink.cfuncs_state[i],
902 &dev->syslink.iofuncs_state[i],
903 &slave_attr->attr))) {
904 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
905 status, "resmgr_attach failed");
906 return (-1);
907 }
908 }
910 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
911 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_file[i],
912 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_file[i]);
913 slave_attr = &dev->syslink.cattr_slave[i];
914 iofunc_attr_init(&slave_attr->attr,
915 S_IFCHR | 0777, NULL, NULL);
916 slave_attr->attr.mount = &dev->syslink.mattr;
917 slave_attr->procid = i;
918 slave_attr->dev = (Ptr)dev;
919 iofunc_time_update(&slave_attr->attr);
920 snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
921 "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
922 dev->syslink.iofuncs_file[i].read = slave_file_read;
923 dev->syslink.iofuncs_file[i].write = slave_file_write;
925 if (-1 == (dev->syslink.resmgr_id_file[i] =
926 resmgr_attach(dev->dpp, &resmgr_attr,
927 dev->syslink.device_name, _FTYPE_ANY, 0,
928 &dev->syslink.cfuncs_file[i],
929 &dev->syslink.iofuncs_file[i],
930 &slave_attr->attr))) {
931 GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
932 status, "resmgr_attach failed");
933 return (-1);
934 }
935 }
937 return (status);
938 }
940 int deinit_slave_devices(syslink_dev_t *dev)
941 {
942 int status = EOK;
943 int i = 0;
945 for (i = 1; i < MultiProc_getNumProcessors(); i++) {
946 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_state[i], 0);
947 if (status < 0) {
948 Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
949 i, errno);
950 }
951 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_file[i], 0);
952 if (status < 0) {
953 Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
954 i, errno);
955 }
956 }
958 return (status);
959 }
961 int init_syslink_trace_device(syslink_dev_t *dev)
962 {
963 resmgr_attr_t resmgr_attr;
964 int i;
965 syslink_attr_t * trace_attr;
966 char trace_name[_POSIX_PATH_MAX];
967 int status = 0;
968 unsigned int da = 0, pa = 0;
969 unsigned int len;
971 memset(&resmgr_attr, 0, sizeof resmgr_attr);
972 resmgr_attr.nparts_max = 10;
973 resmgr_attr.msg_max_size = 2048;
975 for (i = 0; i < syslink_num_cores; i++) {
976 /*
977 * Initialize trace device only for cores that are running and their
978 * device is not yet setup.
979 */
980 if ((syslink_firmware[i].procState == RUNNING_STATE) &&
981 (proc_traces[i].va == NULL)) {
982 iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
983 &dev->syslink.cfuncs_trace[i],
984 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
985 trace_attr = &dev->syslink.cattr_trace[i];
986 iofunc_attr_init(&trace_attr->attr,
987 S_IFCHR | 0777, NULL, NULL);
988 trace_attr->attr.mount = &dev->syslink.mattr;
989 trace_attr->procid = i;
990 iofunc_time_update(&trace_attr->attr);
991 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
992 "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
993 dev->syslink.iofuncs_trace[i].read = syslink_read;
994 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
995 pa = 0;
996 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE,
997 0, &da, &pa, &len);
998 if (status == 0) {
999 /* last 8 bytes are for writeIdx/readIdx */
1000 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1001 if (da && !pa) {
1002 /* need to translate da->pa */
1003 status = ProcMgr_translateAddr(
1004 procH[syslink_firmware[i].proc_id],
1005 (Ptr *) &pa,
1006 ProcMgr_AddrType_MasterPhys,
1007 (Ptr) da,
1008 ProcMgr_AddrType_SlaveVirt);
1009 }
1010 else {
1011 GT_setFailureReason(curTrace, GT_4CLASS,
1012 "init_syslink_trace_device",
1013 status, "not performing ProcMgr_translate");
1014 }
1015 /* map length aligned to page size */
1016 proc_traces[i].va =
1017 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1018 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1019 proc_traces[i].len);
1020 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1021 + sizeof(uint32_t));
1022 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1023 GT_setFailureReason(curTrace, GT_4CLASS,
1024 "init_syslink_trace_device",
1025 status, "mmap_device_io failed");
1026 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1027 proc_traces[i].va = NULL;
1028 }
1029 proc_traces[i].firstRead = TRUE;
1030 }
1031 else {
1032 GT_setFailureReason(curTrace, GT_4CLASS,
1033 "init_syslink_trace_device",
1034 status, "RscTable_getInfo failed");
1035 proc_traces[i].va = NULL;
1036 }
1037 if (-1 == (dev->syslink.resmgr_id_trace[i] =
1038 resmgr_attach(dev->dpp, &resmgr_attr,
1039 dev->syslink.device_name, _FTYPE_ANY, 0,
1040 &dev->syslink.cfuncs_trace[i],
1041 &dev->syslink.iofuncs_trace[i],
1042 &trace_attr->attr))) {
1043 GT_setFailureReason(curTrace, GT_4CLASS,
1044 "init_syslink_trace_device",
1045 status, "resmgr_attach failed");
1046 return(-1);
1047 }
1048 }
1049 }
1051 return (status);
1052 }
1054 int deinit_syslink_trace_device(syslink_dev_t *dev)
1055 {
1056 int status = EOK;
1057 int i = 0;
1059 for (i = 0; i < syslink_num_cores; i++) {
1060 /* Only disable trace device on cores in RESET state */
1061 if ((syslink_firmware[i].procState == RESET_STATE) &&
1062 (proc_traces[i].va != NULL)) {
1063 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i],
1064 0);
1065 if (status < 0) {
1066 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1067 i, errno);
1068 status = errno;
1069 }
1070 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1071 munmap((void *)proc_traces[i].va,
1072 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1073 }
1074 proc_traces[i].va = NULL;
1075 }
1076 }
1078 return (status);
1079 }
1081 /* Initialize the syslink device */
1082 int init_syslink_device(syslink_dev_t *dev)
1083 {
1084 iofunc_attr_t * attr;
1085 resmgr_attr_t resmgr_attr;
1086 int status = 0;
1088 pthread_mutex_init(&dev->lock, NULL);
1089 pthread_mutex_init(&dev->firmwareLock, NULL);
1091 memset(&resmgr_attr, 0, sizeof resmgr_attr);
1092 resmgr_attr.nparts_max = 10;
1093 resmgr_attr.msg_max_size = 2048;
1095 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
1096 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
1097 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1098 IOFUNC_PC_NO_TRUNC |
1099 IOFUNC_PC_SYNC_IO;
1100 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
1102 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
1103 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1105 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
1106 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
1108 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
1110 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
1111 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
1112 dev->syslink.iofuncs.devctl = syslink_devctl;
1113 dev->syslink.iofuncs.unblock = syslink_unblock;
1115 attr->mount = &dev->syslink.mattr;
1116 iofunc_time_update(attr);
1118 if (-1 == (dev->syslink.resmgr_id =
1119 resmgr_attach(dev->dpp, &resmgr_attr,
1120 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1121 &dev->syslink.cfuncs,
1122 &dev->syslink.iofuncs, attr))) {
1123 return(-1);
1124 }
1126 status = init_slave_devices(dev);
1127 if (status < 0) {
1128 return status;
1129 }
1131 status = init_syslink_trace_device(dev);
1132 if (status < 0) {
1133 return status;
1134 }
1136 return(0);
1137 }
1139 /* De-initialize the syslink device */
1140 int deinit_syslink_device(syslink_dev_t *dev)
1141 {
1142 int status = EOK;
1144 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
1145 if (status < 0) {
1146 Osal_printf("IPC: resmgr_detach of %s failed: %d",
1147 IPC_DEVICE_PATH, errno);
1148 status = errno;
1149 }
1151 status = deinit_syslink_trace_device(dev);
1152 if (status < 0) {
1153 Osal_printf("IPC: deinit_syslink_trace_device failed %d", status);
1154 }
1156 status = deinit_slave_devices(dev);
1157 if (status < 0) {
1158 Osal_printf("IPC: deinit_slave_devices failed %d", status);
1159 }
1161 return(status);
1162 }
1165 /* Initialize the devices */
1166 int init_devices(syslink_dev_t *dev)
1167 {
1168 if (init_syslink_device(dev) < 0) {
1169 Osal_printf("IPC: device init failed");
1170 return(-1);
1171 }
1173 return(0);
1174 }
1177 /* De-initialize the devices */
1178 int deinit_devices(syslink_dev_t *dev)
1179 {
1180 int status = EOK;
1182 if ((status = deinit_syslink_device(dev)) < 0) {
1183 fprintf( stderr, "IPC: device de-init failed %d\n", status);
1184 status = errno;
1185 }
1187 return(status);
1188 }
1190 static void ipc_recover(Ptr args)
1191 {
1192 syslink_dev_t * dev = (syslink_dev_t *)args;
1194 if (!disableRecovery) {
1195 /* Protect the syslink_firmware array as we recover */
1196 pthread_mutex_lock(&dev->firmwareLock);
1197 deinit_ipc(dev, syslink_firmware, TRUE);
1198 deinit_syslink_trace_device(dev);
1199 init_ipc(dev, syslink_firmware, TRUE);
1200 init_syslink_trace_device(dev);
1201 pthread_mutex_unlock(&dev->firmwareLock);
1202 }
1203 else {
1204 GT_0trace(curTrace, GT_4CLASS,
1205 "ipc_recover: Recovery disabled.\n");
1206 }
1207 }
1209 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1210 ProcMgr_State fromState, ProcMgr_State toState,
1211 ProcMgr_EventStatus status, Ptr args)
1212 {
1213 Int ret = 0;
1214 String errString = NULL;
1215 syslink_dev_t * dev = (syslink_dev_t *)args;
1217 if (status == ProcMgr_EventStatus_Event) {
1218 switch (toState) {
1219 case ProcMgr_State_Mmu_Fault:
1220 errString = "MMU Fault";
1221 break;
1222 case ProcMgr_State_Error:
1223 errString = "Exception";
1224 break;
1225 case ProcMgr_State_Watchdog:
1226 errString = "Watchdog";
1227 break;
1228 default:
1229 errString = "Unexpected State";
1230 ret = -1;
1231 break;
1232 }
1233 GT_2trace (curTrace, GT_4CLASS,
1234 "syslink_error_cb: Received Error Callback for %s : %s\n",
1235 MultiProc_getName(procId), errString);
1236 /* Don't allow re-schedule of recovery until complete */
1237 pthread_mutex_lock(&dev->lock);
1238 if (ret != -1 && dev->recover == FALSE) {
1239 /* Schedule recovery. */
1240 dev->recover = TRUE;
1241 /* Activate a thread to handle the recovery. */
1242 GT_0trace (curTrace, GT_4CLASS,
1243 "syslink_error_cb: Scheduling recovery...");
1244 OsalThread_activate(dev->ipc_recovery_work);
1245 }
1246 else {
1247 GT_0trace (curTrace, GT_4CLASS,
1248 "syslink_error_cb: Recovery already scheduled.");
1249 }
1250 pthread_mutex_unlock(&dev->lock);
1251 }
1252 else if (status == ProcMgr_EventStatus_Canceled) {
1253 GT_1trace (curTrace, GT_3CLASS,
1254 "SysLink Error Callback Cancelled for %s",
1255 MultiProc_getName(procId));
1256 }
1257 else {
1258 GT_1trace (curTrace, GT_4CLASS,
1259 "SysLink Error Callback Unexpected Event for %s",
1260 MultiProc_getName(procId));
1261 }
1263 return ret;
1264 }
1266 /*
1267 * Initialize the syslink ipc
1268 *
1269 * This function sets up the "kernel"-side IPC modules, and does any special
1270 * initialization required for QNX and the platform being used. This function
1271 * also registers for error notifications and initializes the recovery thread.
1272 */
1273 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
1274 {
1275 int status = 0;
1276 Ipc_Config iCfg;
1277 OsalThread_Params threadParams;
1278 UInt16 procId;
1279 int i;
1281 if (status >= 0) {
1282 if (!recover) {
1283 /* Set up the MemoryOS module */
1284 status = MemoryOS_setup();
1285 if (status < 0)
1286 goto memoryos_fail;
1287 }
1289 /* Setup IPC and platform-specific items */
1290 status = Ipc_setup (&iCfg);
1291 if (status < 0)
1292 goto ipcsetup_fail;
1294 /* NOTE: this is for handling the procmgr event notifications to userspace list */
1295 if (!recover) {
1296 /* Setup Fault recovery items. */
1297 /* Create the thread object used for the interrupt handler. */
1298 threadParams.priority = OsalThread_Priority_Medium;
1299 threadParams.priorityType = OsalThread_PriorityType_Generic;
1300 threadParams.once = FALSE;
1301 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1302 ipc_recover,
1303 dev,
1304 &threadParams);
1305 if (dev->ipc_recovery_work == NULL)
1306 goto osalthreadcreate_fail;
1307 }
1308 else {
1309 pthread_mutex_lock(&dev->lock);
1310 dev->recover = FALSE;
1311 pthread_mutex_unlock(&dev->lock);
1312 }
1314 memset(procH_fileId, 0, sizeof(procH_fileId));
1316 for (i = 0; i < syslink_num_cores; i++) {
1317 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1318 if (procId >= MultiProc_MAXPROCESSORS) {
1319 status = -1;
1320 fprintf(stderr, "Invalid processor name specified\n");
1321 break;
1322 }
1324 if (procH[procId]) {
1325 GT_setFailureReason (curTrace,
1326 GT_4CLASS,
1327 "init_ipc",
1328 status,
1329 "invalid proc!");
1330 break;
1331 }
1333 if (recover) {
1334 /*
1335 * if we are in recovery, we load the cores we previously
1336 * attached to
1337 */
1338 firmware[i].attachOnly = false;
1339 }
1341 if ((!recover) || (firmware[i].reload)) {
1342 status = runSlave(dev, procId, &firmware[i]);
1343 if (status == 0) {
1344 firmware[i].procState = RUNNING_STATE;
1345 continue;
1346 }
1347 else {
1348 break;
1349 }
1350 }
1351 else {
1352 /*
1353 * During recovery, do not run cores unless they were previously
1354 * running
1355 */
1356 continue;
1357 }
1358 }
1360 if (status < 0)
1361 goto tiipcsetup_fail;
1363 /* Set up rpmsg_mq */
1364 status = ti_ipc_setup();
1365 if (status < 0)
1366 goto tiipcsetup_fail;
1368 /* Set up rpmsg_rpc */
1369 status = rpmsg_rpc_setup();
1370 if (status < 0)
1371 goto rpcsetup_fail;
1373 #if defined(SYSLINK_PLATFORM_VAYU)
1374 if (gatempEnabled) {
1375 Int32 sr0ProcId;
1377 /* Set up NameServer for resource manager process */
1378 status = NameServer_setup();
1379 if (status < 0) {
1380 goto nameserversetup_fail;
1381 }
1383 /* Set up GateMP */
1384 status = GateMP_setup(&sr0ProcId);
1385 if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1386 goto gatempsetup_fail;
1387 }
1388 else if (status == 0) {
1389 sr0OwnerProcId = sr0ProcId;
1390 }
1391 else {
1392 /*
1393 * If we did not find the default gate, perhaps SR0 is
1394 * not yet loaded. This is ok.
1395 */
1396 status = 0;
1397 }
1398 }
1399 #endif
1401 goto exit;
1402 }
1404 #if defined(SYSLINK_PLATFORM_VAYU)
1405 gatempsetup_fail:
1406 NameServer_destroy();
1407 nameserversetup_fail:
1408 rpmsg_rpc_destroy();
1409 #endif
1410 rpcsetup_fail:
1411 ti_ipc_destroy(recover);
1412 tiipcsetup_fail:
1413 for (i-=1; i >= 0; i--) {
1414 procId = firmware[i].proc_id;
1415 if (procId >= MultiProc_MAXPROCESSORS) {
1416 continue;
1417 }
1418 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1419 (Ptr)dev, errStates);
1420 if (!firmware[i].attachOnly) {
1421 ProcMgr_stop(procH[procId]);
1422 if (procH_fileId[procId]) {
1423 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1424 procH_fileId[procId] = 0;
1425 }
1426 }
1427 ProcMgr_detach(procH[procId]);
1428 ProcMgr_close(&procH[procId]);
1429 procH[procId] = NULL;
1430 RscTable_free(&rscHandle[procId]);
1431 rscHandle[procId] = NULL;
1432 }
1433 OsalThread_delete(&dev->ipc_recovery_work);
1434 osalthreadcreate_fail:
1435 Ipc_destroy();
1436 ipcsetup_fail:
1437 MemoryOS_destroy();
1438 memoryos_fail:
1439 exit:
1440 return status;
1441 }
1443 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1444 bool recover)
1445 {
1446 int status = EOK;
1447 uint32_t i = 0, id = 0;
1449 if (logFilename) {
1450 /* wait a little bit for traces to finish dumping */
1451 sleep(1);
1452 }
1454 // Stop the remote cores right away
1455 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1456 if (procH[i]) {
1457 resetSlave(dev, i);
1458 }
1459 }
1461 #if defined(SYSLINK_PLATFORM_VAYU)
1462 if (gatempEnabled) {
1463 GateMP_destroy(TRUE);
1465 NameServer_destroy();
1466 }
1467 #endif
1469 rpmsg_rpc_destroy();
1471 ti_ipc_destroy(recover);
1473 if (!recover && dev->ipc_recovery_work != NULL) {
1474 OsalThread_delete (&dev->ipc_recovery_work);
1475 dev->ipc_recovery_work = NULL;
1476 }
1478 if (recover) {
1479 static FILE *log = NULL;
1480 if (logFilename) {
1481 /* Dump the trace information */
1482 Osal_printf("IPC: printing remote core trace dump");
1483 log = fopen(logFilename, "a+");
1484 if (log) {
1485 for (id = 0; id < syslink_num_cores; id++) {
1486 if (firmware[id].procState == RUNNING_STATE) {
1487 if (proc_traces[id].va) {
1488 /* print traces */
1489 fprintf(log, "*************************************\n");
1490 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
1491 firmware[i].proc_id);
1492 fprintf(log, "*************************************\n");
1493 for (i = (*proc_traces[id].widx + 1);
1494 i < (proc_traces[id].len - 8);
1495 i++) {
1496 fprintf(log, "%c",
1497 *(char *)((uint32_t)proc_traces[id].va + i));
1498 }
1499 for (i = 0; i < *proc_traces[id].widx; i++) {
1500 fprintf(log, "%c",
1501 *(char *)((uint32_t)proc_traces[id].va + i));
1502 }
1503 }
1504 }
1505 }
1506 fflush(log);
1507 fclose(log);
1508 }
1509 else {
1510 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1511 logFilename);
1512 exit(EXIT_FAILURE);
1513 }
1514 }
1515 }
1517 /* After printing trace, set all processor states to RESET */
1518 for (id = 0; id < syslink_num_cores; id++) {
1519 firmware[id].procState = RESET_STATE;
1520 }
1522 status = Ipc_destroy();
1523 if (status < 0) {
1524 printf("Ipc_destroy() failed 0x%x", status);
1525 }
1526 if (!recover) {
1527 status = MemoryOS_destroy();
1528 if (status < 0) {
1529 printf("MemoryOS_destroy() failed 0x%x", status);
1530 }
1531 }
1533 return status;
1534 }
1537 /** print usage */
1538 static Void printUsage (Char * app)
1539 {
1540 printf("\n\nUsage:\n");
1541 #if defined(SYSLINK_PLATFORM_OMAP5430)
1542 printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1543 app);
1544 printf(" <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1545 printf(" followed by the path to the executable to load on that core.\n");
1546 printf("Options:\n");
1547 printf(" -H <arg> enable/disable hibernation, 1: ON, 0: OFF,"
1548 " Default: 1)\n");
1549 printf(" -T <arg> specify the hibernation timeout in ms, Default:"
1550 " 5000 ms)\n");
1551 #else
1552 printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1553 app);
1554 printf(" <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1555 printf(" followed by the path to the executable to load on that core.\n");
1556 printf("Options:\n");
1557 printf(" -g enable GateMP support on host\n");
1558 #endif
1559 printf(" -d disable recovery\n");
1560 printf(" -c <file> generate dump of slave trace during crashes (use\n");
1561 printf(" absolute path for filename)\n");
1562 printf(" -a<n> specify that the first n cores have been pre-loaded\n");
1563 printf(" and started. Perform late-attach to these cores.\n");
1565 exit (EXIT_SUCCESS);
1566 }
1568 dispatch_t * syslink_dpp = NULL;
1570 int main(int argc, char *argv[])
1571 {
1572 syslink_dev_t * dev = NULL;
1573 thread_pool_attr_t tattr;
1574 int status;
1575 int error = EOK;
1576 sigset_t set;
1577 int channelid = 0;
1578 int c;
1579 int hib_enable = 1;
1580 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1581 char *user_parm = NULL;
1582 struct stat sbuf;
1583 int i = 0;
1584 char * abs_path = NULL;
1586 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1587 printf ("IPC Already Running...\n");
1588 return EXIT_FAILURE;
1589 }
1590 printf ("Starting IPC resource manager...\n");
1592 /* Parse the input args */
1593 while (1)
1594 {
1595 c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1596 if (c == -1)
1597 break;
1599 switch (c)
1600 {
1601 #if defined(SYSLINK_PLATFORM_OMAP5430)
1602 case 'H':
1603 hib_enable = atoi(optarg);
1604 if (hib_enable != 0 && hib_enable != 1) {
1605 hib_enable = -1;
1606 }
1607 break;
1608 case 'T':
1609 hib_timeout = atoi(optarg);
1610 break;
1611 #endif
1612 case 'U':
1613 user_parm = optarg;
1614 break;
1615 case 'd':
1616 disableRecovery = true;
1617 break;
1618 case 'c':
1619 logFilename = optarg;
1620 break;
1621 case 'a':
1622 numAttach = atoi(optarg);
1623 printf("Late-attaching to %d core(s)\n", numAttach);
1624 break;
1625 case 'v':
1626 verbosity++;
1627 break;
1628 #if defined(SYSLINK_PLATFORM_VAYU)
1629 case 'g':
1630 printf("GateMP support enabled on host\n");
1631 gatempEnabled = true;
1632 break;
1633 #endif
1634 default:
1635 fprintf (stderr, "Unrecognized argument\n");
1636 }
1637 }
1639 /* Now parse the operands, which should be in the format:
1640 * "<multiproc_name> <firmware_file> ..*/
1641 for (; optind + 1 < argc; optind+=2) {
1642 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1643 printUsage(argv[0]);
1644 return (error);
1645 }
1646 if (strcmp(argv[optind], INVALID_PROC) == 0) {
1647 fprintf (stderr, "Unsupported core specified\n");
1648 return (error);
1649 }
1651 syslink_firmware[syslink_num_cores].proc = argv [optind];
1652 syslink_firmware[syslink_num_cores].attachOnly =
1653 ((numAttach-- > 0) ? true : false);
1654 syslink_firmware[syslink_num_cores].reload = true;
1655 syslink_firmware[syslink_num_cores].freeString = false;
1656 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1657 }
1659 /* Validate hib_enable args */
1660 if (hib_enable == -1) {
1661 fprintf (stderr, "invalid hibernation enable value\n");
1662 printUsage(argv[0]);
1663 return (error);
1664 }
1666 syslink_hib_enable = (Bool)hib_enable;
1667 syslink_hib_timeout = hib_timeout;
1669 /* Init logging for syslink */
1670 if (Osal_initlogging(verbosity) != 0) {
1671 return -1;
1672 }
1674 /* Obtain I/O privity */
1675 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1676 if (error == -1) {
1677 Osal_printf("Unable to obtain I/O privity");
1678 return (error);
1679 }
1681 /* Get the abs path for all firmware files */
1682 for (i = 0; i < syslink_num_cores; i++) {
1683 abs_path = calloc(1, PATH_MAX + 1);
1684 if (abs_path == NULL) {
1685 return -1;
1686 }
1687 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1688 fprintf (stderr, "invalid path to executable\n");
1689 return -1;
1690 }
1691 syslink_firmware[i].firmware = abs_path;
1692 }
1694 /* allocate the device structure */
1695 if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1696 Osal_printf("IPC: calloc() failed");
1697 return (-1);
1698 }
1700 /* create the channel */
1701 if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1702 _NTO_CHF_DISCONNECT |
1703 _NTO_CHF_COID_DISCONNECT |
1704 _NTO_CHF_REPLY_LEN |
1705 _NTO_CHF_SENDER_LEN)) < 0) {
1706 Osal_printf("Unable to create channel %d", channelid);
1707 return (channelid);
1708 }
1710 /* create the dispatch structure */
1711 if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1712 Osal_printf("IPC: dispatch_create() failed");
1713 return(-1);
1714 }
1716 /*
1717 * Mask out all signals before creating a thread pool.
1718 * This prevents other threads in the thread pool
1719 * from intercepting signals such as SIGTERM.
1720 */
1721 sigfillset(&set);
1722 pthread_sigmask(SIG_BLOCK, &set, NULL);
1724 /* Initialize the thread pool */
1725 memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1726 tattr.handle = dev->dpp;
1727 tattr.context_alloc = dispatch_context_alloc;
1728 tattr.context_free = dispatch_context_free;
1729 tattr.block_func = dispatch_block;
1730 tattr.unblock_func = dispatch_unblock;
1731 tattr.handler_func = dispatch_handler;
1732 tattr.lo_water = 2;
1733 tattr.hi_water = 4;
1734 tattr.increment = 1;
1735 tattr.maximum = 10;
1737 /* Create the thread pool */
1738 if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1739 Osal_printf("IPC: thread pool create failed");
1740 return(-1);
1741 }
1743 /* init syslink */
1744 status = init_ipc(dev, syslink_firmware, FALSE);
1745 if (status < 0) {
1746 Osal_printf("IPC: init failed");
1747 return(-1);
1748 }
1750 /* init the syslink device */
1751 status = init_devices(dev);
1752 if (status < 0) {
1753 Osal_printf("IPC: device init failed");
1754 return(-1);
1755 }
1757 #if (_NTO_VERSION >= 800)
1758 /* Relinquish privileges */
1759 status = procmgr_ability( 0,
1760 DENY_ALL | PROCMGR_AID_SPAWN,
1761 DENY_ALL | PROCMGR_AID_FORK,
1762 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1763 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1764 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1765 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1766 PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1767 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1768 (uint64_t)1, (uint64_t)~0,
1769 PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1770 (uint64_t)1, (uint64_t)~0,
1771 PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1773 if (status != EOK) {
1774 Osal_printf("procmgr_ability failed! errno=%d", status);
1775 return EXIT_FAILURE;
1776 }
1778 /* Reduce priority to either what defined from command line or at least nobody */
1779 if (user_parm != NULL) {
1780 if (set_ids_from_arg(user_parm) < 0) {
1781 Osal_printf("unable to set uid/gid - %s", strerror(errno));
1782 return EXIT_FAILURE;
1783 }
1784 } else {
1785 if (setuid(99) != 0) {
1786 Osal_printf("unable to set uid - %s", strerror(errno));
1787 return EXIT_FAILURE;
1788 }
1789 }
1790 #endif
1792 /* make this a daemon process */
1793 if (-1 == procmgr_daemon(EXIT_SUCCESS,
1794 PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1795 Osal_printf("IPC: procmgr_daemon() failed");
1796 return(-1);
1797 }
1799 /* start the thread pool */
1800 thread_pool_start(dev->tpool);
1802 /* Unmask signals to be caught */
1803 sigdelset (&set, SIGINT);
1804 sigdelset (&set, SIGTERM);
1805 pthread_sigmask (SIG_BLOCK, &set, NULL);
1807 /* Wait for one of these signals */
1808 sigemptyset (&set);
1809 sigaddset (&set, SIGINT);
1810 sigaddset (&set, SIGQUIT);
1811 sigaddset (&set, SIGTERM);
1813 Osal_printf("IPC resource manager started");
1815 /* Wait for a signal */
1816 while (1)
1817 {
1818 switch (SignalWaitinfo (&set, NULL))
1819 {
1820 case SIGTERM:
1821 case SIGQUIT:
1822 case SIGINT:
1823 error = EOK;
1824 goto done;
1826 default:
1827 break;
1828 }
1829 }
1831 error = EOK;
1833 done:
1834 GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1836 error = thread_pool_destroy(dev->tpool);
1837 if (error < 0) {
1838 Osal_printf("IPC: thread_pool_destroy returned an error");
1839 }
1840 deinit_ipc(dev, syslink_firmware, FALSE);
1841 deinit_devices(dev);
1842 free(dev);
1844 /* Free the abs path of firmware files if necessary */
1845 for (i = 0; i < syslink_num_cores; i++) {
1846 if ((syslink_firmware[i].freeString) &&
1847 (syslink_firmware[i].firmware)) {
1848 free(syslink_firmware[i].firmware);
1849 }
1850 }
1852 return (error);
1853 }