4aaf595bca427c714830407b93ee5cfa6872ec13
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
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)
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                             "init_ipc",
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                                 "init_ipc",
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                              "init_ipc",
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                                 "init_ipc",
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;
277 static int resetSlave(syslink_dev_t *dev, uint16_t procId)
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;
304 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
305     syslink_ocb_t *ocb)
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));
397 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
398     syslink_ocb_t *ocb)
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));
547 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
548     syslink_ocb_t *ocb)
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));
637 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
638     syslink_ocb_t *ocb)
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));
740 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
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));
813 extern OsalSemaphore_Handle mqcopy_test_sem;
815 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
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;
842 IOFUNC_OCB_T *
843 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
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);
859 void
860 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
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     }
872 int init_slave_devices(syslink_dev_t *dev)
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);
940 int deinit_slave_devices(syslink_dev_t *dev)
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);
961 int init_syslink_trace_device(syslink_dev_t *dev)
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);
1054 int deinit_syslink_trace_device(syslink_dev_t *dev)
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);
1081 /* Initialize the syslink device */
1082 int init_syslink_device(syslink_dev_t *dev)
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);
1139 /* De-initialize the syslink device */
1140 int deinit_syslink_device(syslink_dev_t *dev)
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);
1165 /* Initialize the devices */
1166 int init_devices(syslink_dev_t *dev)
1168     if (init_syslink_device(dev) < 0) {
1169         Osal_printf("IPC: device init failed");
1170         return(-1);
1171     }
1173     return(0);
1177 /* De-initialize the devices */
1178 int deinit_devices(syslink_dev_t *dev)
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);
1190 static void ipc_recover(Ptr args)
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     }
1209 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1210                       ProcMgr_State fromState, ProcMgr_State toState,
1211                       ProcMgr_EventStatus status, Ptr args)
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;
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)
1275     int status = 0;
1276     Ipc_Config iCfg;
1277     OsalThread_Params threadParams;
1278     ProcMgr_AttachParams attachParams;
1279     UInt16 procId;
1280     int i;
1282     if (status >= 0) {
1283         if (!recover) {
1284             /* Set up the MemoryOS module */
1285             status = MemoryOS_setup();
1286             if (status < 0)
1287                 goto memoryos_fail;
1288         }
1290         /* Setup IPC and platform-specific items */
1291         status = Ipc_setup (&iCfg);
1292         if (status < 0)
1293             goto ipcsetup_fail;
1295         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1296         if (!recover) {
1297             /* Setup Fault recovery items. */
1298             /* Create the thread object used for the interrupt handler. */
1299             threadParams.priority     = OsalThread_Priority_Medium;
1300             threadParams.priorityType = OsalThread_PriorityType_Generic;
1301             threadParams.once         = FALSE;
1302             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1303                                                         ipc_recover,
1304                                                         dev,
1305                                                         &threadParams);
1306             if (dev->ipc_recovery_work == NULL)
1307                 goto osalthreadcreate_fail;
1308         }
1309         else {
1310             pthread_mutex_lock(&dev->lock);
1311             dev->recover = FALSE;
1312             pthread_mutex_unlock(&dev->lock);
1313         }
1315         memset(procH_fileId, 0, sizeof(procH_fileId));
1317         for (i = 0; i < syslink_num_cores; i++) {
1318             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1319             if (procId >= MultiProc_MAXPROCESSORS) {
1320                 status = -1;
1321                 fprintf(stderr, "Invalid processor name specified\n");
1322                 break;
1323             }
1325             if (procH[procId]) {
1326                 GT_setFailureReason (curTrace,
1327                                      GT_4CLASS,
1328                                      "init_ipc",
1329                                      status,
1330                                      "invalid proc!");
1331                 break;
1332             }
1334             if (recover) {
1335                 /*
1336                  * if we are in recovery, we load the cores we previously
1337                  * attached to
1338                  */
1339                 firmware[i].attachOnly = false;
1340             }
1342             if ((!recover) || (firmware[i].reload)) {
1343                 status = runSlave(dev, procId, &firmware[i]);
1344                 if (status == 0) {
1345                     firmware[i].procState = RUNNING_STATE;
1346                     continue;
1347                 }
1348                 else {
1349                     break;
1350                 }
1351             }
1352             else {
1353                 /*
1354                  * During recovery, do not run cores unless they were previously
1355                  * running
1356                  */
1357                 continue;
1358             }
1359         }
1361         if (status < 0)
1362             goto tiipcsetup_fail;
1364         /* Set up rpmsg_mq */
1365         status = ti_ipc_setup();
1366         if (status < 0)
1367             goto tiipcsetup_fail;
1369         /* Set up rpmsg_rpc */
1370         status = rpmsg_rpc_setup();
1371         if (status < 0)
1372             goto rpcsetup_fail;
1374 #if defined(SYSLINK_PLATFORM_VAYU)
1375         if (gatempEnabled) {
1376             Int32 sr0ProcId;
1378             /* Set up NameServer for resource manager process */
1379             status = NameServer_setup();
1380             if (status < 0) {
1381                 goto nameserversetup_fail;
1382             }
1384             /* Set up GateMP */
1385             status = GateMP_setup(&sr0ProcId);
1386             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1387                 goto gatempsetup_fail;
1388             }
1389             else if (status == 0) {
1390                 sr0OwnerProcId = sr0ProcId;
1391             }
1392             else {
1393                 /*
1394                  * If we did not find the default gate, perhaps SR0 is
1395                  * not yet loaded. This is ok.
1396                  */
1397                 status = 0;
1398             }
1399         }
1400 #endif
1402         goto exit;
1403     }
1405 #if defined(SYSLINK_PLATFORM_VAYU)
1406 gatempsetup_fail:
1407     NameServer_destroy();
1408 nameserversetup_fail:
1409     rpmsg_rpc_destroy();
1410 #endif
1411 rpcsetup_fail:
1412     ti_ipc_destroy(recover);
1413 tiipcsetup_fail:
1414     for (i-=1; i >= 0; i--) {
1415         procId = firmware[i].proc_id;
1416         if (procId >= MultiProc_MAXPROCESSORS) {
1417             continue;
1418         }
1419         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1420                                 (Ptr)dev, errStates);
1421         if (!firmware[i].attachOnly) {
1422             ProcMgr_stop(procH[procId]);
1423             if (procH_fileId[procId]) {
1424                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1425                 procH_fileId[procId] = 0;
1426             }
1427         }
1428         ProcMgr_detach(procH[procId]);
1429         ProcMgr_close(&procH[procId]);
1430         procH[procId] = NULL;
1431         RscTable_free(&rscHandle[procId]);
1432         rscHandle[procId] = NULL;
1433     }
1434     OsalThread_delete(&dev->ipc_recovery_work);
1435 osalthreadcreate_fail:
1436     Ipc_destroy();
1437 ipcsetup_fail:
1438     MemoryOS_destroy();
1439 memoryos_fail:
1440 exit:
1441     return status;
1444 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1445     bool recover)
1447     int status = EOK;
1448     uint32_t i = 0, id = 0;
1450     if (logFilename) {
1451         /* wait a little bit for traces to finish dumping */
1452         sleep(1);
1453     }
1455     // Stop the remote cores right away
1456     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1457         if (procH[i]) {
1458             resetSlave(dev, i);
1459         }
1460     }
1462 #if defined(SYSLINK_PLATFORM_VAYU)
1463     if (gatempEnabled) {
1464         GateMP_destroy(TRUE);
1466         NameServer_destroy();
1467     }
1468 #endif
1470     rpmsg_rpc_destroy();
1472     ti_ipc_destroy(recover);
1474     if (!recover && dev->ipc_recovery_work != NULL) {
1475         OsalThread_delete (&dev->ipc_recovery_work);
1476         dev->ipc_recovery_work = NULL;
1477     }
1479     if (recover) {
1480         static FILE *log = NULL;
1481         if (logFilename) {
1482             /* Dump the trace information */
1483             Osal_printf("IPC: printing remote core trace dump");
1484             log = fopen(logFilename, "a+");
1485             if (log) {
1486                 for (id = 0; id < syslink_num_cores; id++) {
1487                     if (firmware[id].procState == RUNNING_STATE) {
1488                         if (proc_traces[id].va) {
1489                             /* print traces */
1490                             fprintf(log, "*************************************\n");
1491                             fprintf(log, "***       CORE%d TRACE DUMP        ***\n",
1492                                 firmware[i].proc_id);
1493                             fprintf(log, "*************************************\n");
1494                             for (i = (*proc_traces[id].widx + 1);
1495                                 i < (proc_traces[id].len - 8);
1496                                 i++) {
1497                                 fprintf(log, "%c",
1498                                     *(char *)((uint32_t)proc_traces[id].va + i));
1499                             }
1500                             for (i = 0; i < *proc_traces[id].widx; i++) {
1501                                 fprintf(log, "%c",
1502                                     *(char *)((uint32_t)proc_traces[id].va + i));
1503                             }
1504                         }
1505                     }
1506                 }
1507                 fflush(log);
1508                 fclose(log);
1509             }
1510             else {
1511                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1512                     logFilename);
1513                 exit(EXIT_FAILURE);
1514             }
1515         }
1516     }
1518     /* After printing trace, set all processor states to RESET */
1519     for (id = 0; id < syslink_num_cores; id++) {
1520         firmware[id].procState = RESET_STATE;
1521     }
1523     status = Ipc_destroy();
1524     if (status < 0) {
1525         printf("Ipc_destroy() failed 0x%x", status);
1526     }
1527     if (!recover) {
1528         status = MemoryOS_destroy();
1529         if (status < 0) {
1530             printf("MemoryOS_destroy() failed 0x%x", status);
1531         }
1532     }
1534     return status;
1538 /** print usage */
1539 static Void printUsage (Char * app)
1541     printf("\n\nUsage:\n");
1542 #if defined(SYSLINK_PLATFORM_OMAP5430)
1543     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1544         app);
1545     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1546     printf("      followed by the path to the executable to load on that core.\n");
1547     printf("Options:\n");
1548     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1549         " Default: 1)\n");
1550     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1551         " 5000 ms)\n");
1552 #else
1553     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1554         app);
1555     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1556     printf("      followed by the path to the executable to load on that core.\n");
1557     printf("Options:\n");
1558     printf("  -g   enable GateMP support on host\n");
1559 #endif
1560     printf("  -d   disable recovery\n");
1561     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1562     printf("              absolute path for filename)\n");
1563     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1564     printf("        and started. Perform late-attach to these cores.\n");
1566     exit (EXIT_SUCCESS);
1569 dispatch_t * syslink_dpp = NULL;
1571 int main(int argc, char *argv[])
1573     syslink_dev_t * dev = NULL;
1574     thread_pool_attr_t tattr;
1575     int status;
1576     int error = EOK;
1577     sigset_t set;
1578     int channelid = 0;
1579     int c;
1580     int hib_enable = 1;
1581     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1582     char *user_parm = NULL;
1583     struct stat          sbuf;
1584     int i = 0;
1585     char * abs_path = NULL;
1587     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1588         printf ("IPC Already Running...\n");
1589         return EXIT_FAILURE;
1590     }
1591     printf ("Starting IPC resource manager...\n");
1593     /* Parse the input args */
1594     while (1)
1595     {
1596         c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1597         if (c == -1)
1598             break;
1600         switch (c)
1601         {
1602 #if defined(SYSLINK_PLATFORM_OMAP5430)
1603         case 'H':
1604             hib_enable = atoi(optarg);
1605             if (hib_enable != 0 && hib_enable != 1) {
1606                 hib_enable = -1;
1607             }
1608             break;
1609         case 'T':
1610             hib_timeout = atoi(optarg);
1611             break;
1612 #endif
1613         case 'U':
1614             user_parm = optarg;
1615             break;
1616         case 'd':
1617             disableRecovery = true;
1618             break;
1619         case 'c':
1620             logFilename = optarg;
1621             break;
1622         case 'a':
1623             numAttach = atoi(optarg);
1624             printf("Late-attaching to %d core(s)\n", numAttach);
1625             break;
1626         case 'v':
1627             verbosity++;
1628             break;
1629 #if defined(SYSLINK_PLATFORM_VAYU)
1630         case 'g':
1631             printf("GateMP support enabled on host\n");
1632             gatempEnabled = true;
1633             break;
1634 #endif
1635         default:
1636             fprintf (stderr, "Unrecognized argument\n");
1637         }
1638     }
1640     /* Now parse the operands, which should be in the format:
1641      * "<multiproc_name> <firmware_file> ..*/
1642     for (; optind + 1 < argc; optind+=2) {
1643         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1644             printUsage(argv[0]);
1645             return (error);
1646         }
1647         if (strcmp(argv[optind], INVALID_PROC) == 0) {
1648             fprintf (stderr, "Unsupported core specified\n");
1649             return (error);
1650         }
1652         syslink_firmware[syslink_num_cores].proc = argv [optind];
1653         syslink_firmware[syslink_num_cores].attachOnly =
1654             ((numAttach-- > 0) ? true : false);
1655         syslink_firmware[syslink_num_cores].reload = true;
1656         syslink_firmware[syslink_num_cores].freeString = false;
1657         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1658     }
1660     /* Get the name of the binary from the input args */
1661     if (!syslink_num_cores) {
1662         fprintf(stderr, "At least one core_id and executable must be "\
1663             "specified");
1664         printUsage(argv[0]);
1665         return (error);
1666     }
1668     /* Validate hib_enable args */
1669     if (hib_enable == -1) {
1670         fprintf (stderr, "invalid hibernation enable value\n");
1671         printUsage(argv[0]);
1672         return (error);
1673     }
1675     syslink_hib_enable = (Bool)hib_enable;
1676     syslink_hib_timeout = hib_timeout;
1678     /* Init logging for syslink */
1679     if (Osal_initlogging(verbosity) != 0) {
1680         return -1;
1681     }
1683     /* Obtain I/O privity */
1684     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1685     if (error == -1) {
1686         Osal_printf("Unable to obtain I/O privity");
1687         return (error);
1688     }
1690     /* Get the abs path for all firmware files */
1691     for (i = 0; i < syslink_num_cores; i++) {
1692         abs_path = calloc(1, PATH_MAX + 1);
1693         if (abs_path == NULL) {
1694             return -1;
1695         }
1696         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1697             fprintf (stderr, "invalid path to executable\n");
1698             return -1;
1699         }
1700         syslink_firmware[i].firmware = abs_path;
1701     }
1703     /* allocate the device structure */
1704     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1705         Osal_printf("IPC: calloc() failed");
1706         return (-1);
1707     }
1709     /* create the channel */
1710     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1711                                     _NTO_CHF_DISCONNECT |
1712                                     _NTO_CHF_COID_DISCONNECT |
1713                                     _NTO_CHF_REPLY_LEN |
1714                                     _NTO_CHF_SENDER_LEN)) < 0) {
1715         Osal_printf("Unable to create channel %d", channelid);
1716         return (channelid);
1717     }
1719     /* create the dispatch structure */
1720     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1721         Osal_printf("IPC: dispatch_create() failed");
1722         return(-1);
1723     }
1725     /*
1726      * Mask out all signals before creating a thread pool.
1727      * This prevents other threads in the thread pool
1728      * from intercepting signals such as SIGTERM.
1729      */
1730     sigfillset(&set);
1731     pthread_sigmask(SIG_BLOCK, &set, NULL);
1733     /* Initialize the thread pool */
1734     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1735     tattr.handle = dev->dpp;
1736     tattr.context_alloc = dispatch_context_alloc;
1737     tattr.context_free = dispatch_context_free;
1738     tattr.block_func = dispatch_block;
1739     tattr.unblock_func = dispatch_unblock;
1740     tattr.handler_func = dispatch_handler;
1741     tattr.lo_water = 2;
1742     tattr.hi_water = 4;
1743     tattr.increment = 1;
1744     tattr.maximum = 10;
1746     /* Create the thread pool */
1747     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1748         Osal_printf("IPC: thread pool create failed");
1749         return(-1);
1750     }
1752     /* init syslink */
1753     status = init_ipc(dev, syslink_firmware, FALSE);
1754     if (status < 0) {
1755         Osal_printf("IPC: init failed");
1756         return(-1);
1757     }
1759     /* init the syslink device */
1760     status = init_devices(dev);
1761     if (status < 0) {
1762         Osal_printf("IPC: device init failed");
1763         return(-1);
1764     }
1766 #if (_NTO_VERSION >= 800)
1767     /* Relinquish privileges */
1768     status = procmgr_ability(  0,
1769                  DENY_ALL | PROCMGR_AID_SPAWN,
1770                  DENY_ALL | PROCMGR_AID_FORK,
1771                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1772                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1773                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1774                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1775                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1776                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1777                  (uint64_t)1, (uint64_t)~0,
1778                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1779                  (uint64_t)1, (uint64_t)~0,
1780                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1782     if (status != EOK) {
1783         Osal_printf("procmgr_ability failed! errno=%d", status);
1784         return EXIT_FAILURE;
1785     }
1787     /* Reduce priority to either what defined from command line or at least nobody */
1788     if (user_parm != NULL) {
1789         if (set_ids_from_arg(user_parm) < 0) {
1790             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1791             return EXIT_FAILURE;
1792         }
1793     } else {
1794         if (setuid(99) != 0) {
1795             Osal_printf("unable to set uid - %s", strerror(errno));
1796             return EXIT_FAILURE;
1797         }
1798     }
1799 #endif
1801     /* make this a daemon process */
1802     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1803         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1804         Osal_printf("IPC: procmgr_daemon() failed");
1805         return(-1);
1806     }
1808     /* start the thread pool */
1809     thread_pool_start(dev->tpool);
1811     /* Unmask signals to be caught */
1812     sigdelset (&set, SIGINT);
1813     sigdelset (&set, SIGTERM);
1814     pthread_sigmask (SIG_BLOCK, &set, NULL);
1816     /* Wait for one of these signals */
1817     sigemptyset (&set);
1818     sigaddset (&set, SIGINT);
1819     sigaddset (&set, SIGQUIT);
1820     sigaddset (&set, SIGTERM);
1822     Osal_printf("IPC resource manager started");
1824     /* Wait for a signal */
1825     while (1)
1826     {
1827         switch (SignalWaitinfo (&set, NULL))
1828         {
1829             case SIGTERM:
1830             case SIGQUIT:
1831             case SIGINT:
1832                 error = EOK;
1833                 goto done;
1835             default:
1836                 break;
1837         }
1838     }
1840     error = EOK;
1842 done:
1843     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1845     error = thread_pool_destroy(dev->tpool);
1846     if (error < 0) {
1847         Osal_printf("IPC: thread_pool_destroy returned an error");
1848     }
1849     deinit_ipc(dev, syslink_firmware, FALSE);
1850     deinit_devices(dev);
1851     free(dev);
1853     /* Free the abs path of firmware files if necessary */
1854     for (i = 0; i < syslink_num_cores; i++) {
1855         if ((syslink_firmware[i].freeString) &&
1856             (syslink_firmware[i].firmware)) {
1857             free(syslink_firmware[i].firmware);
1858         }
1859     }
1861     return (error);