52f536657a676952bb6ee1d73086c853b3628413
[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 static bool gatempEnabled = false;
101 static Int32 sr0OwnerProcId = -1;
102 #endif
104 // Syslink hibernation global variables
105 Bool syslink_hib_enable = TRUE;
106 #if !defined(SYSLINK_PLATFORM_OMAP5430)
107 #define PM_HIB_DEFAULT_TIME 5000
108 #endif
109 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
110 Bool syslink_hib_hibernating = FALSE;
111 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
112 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
114 extern Int rpmsg_rpc_setup (Void);
115 extern Void rpmsg_rpc_destroy (Void);
116 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
118 typedef struct syslink_firmware_info_t {
119     uint16_t proc_id;
120     char * proc;
121     char * firmware;
122     bool attachOnly;
123     int  procState;  /* state of processor - index into procStateNames array */
124     int  readProcState; /* state that is currently being printed */
125     bool reload;     /* reload core during recovery */
126     bool freeString; /* Need to free previously allocated firmware string */
127 } syslink_firmware_info;
128 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
130 /* Number of valid entries in syslink_firmware array */
131 static unsigned int syslink_num_cores = 0;
133 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
134     bool recover);
135 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
136     bool recover);
137 int init_syslink_trace_device(syslink_dev_t *dev);
138 int deinit_syslink_trace_device(syslink_dev_t *dev);
140 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
141                       ProcMgr_State fromState, ProcMgr_State toState,
142                       ProcMgr_EventStatus status, Ptr args);
144 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
146 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
147 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
148 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
149                                     ProcMgr_State_Error,
150                                     ProcMgr_State_Watchdog,
151                                     ProcMgr_State_EndValue};
153 /* Processor states */
154 #define RESET_STATE  0
155 #define RUNNING_STATE 1
157 static String procStateNames[] = { "In reset",
158                                    "Running" };
160 typedef struct syslink_trace_info_t {
161     uintptr_t   va;
162     uint32_t    len;
163     uint32_t *  widx;
164     uint32_t *  ridx;
165     Bool        firstRead;
166 } syslink_trace_info;
168 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
170 static int runSlave(syslink_dev_t *dev, uint16_t procId,
171     syslink_firmware_info * firmware_info)
173     int status = 0;
174     ProcMgr_AttachParams attachParams;
176     if (firmware_info->firmware) {
177         rscHandle[procId] = RscTable_alloc(firmware_info->firmware, procId);
178         if (rscHandle[procId] == NULL) {
179             status = -1;
180             return status;
181         }
182     }
184     status = ProcMgr_open(&procH[procId], procId);
185     if (status < 0 || procH[procId] == NULL) {
186         goto procmgropen_fail;
187     }
189     /* Load and start the remote processor. */
190     ProcMgr_getAttachParams(procH[procId], &attachParams);
191     if (firmware_info->attachOnly) {
192         attachParams.bootMode = ProcMgr_BootMode_NoBoot;
193     }
194     status = ProcMgr_attach(procH[procId], &attachParams);
195     if (status < 0) {
196         GT_setFailureReason(curTrace,
197                             GT_4CLASS,
198                             "init_ipc",
199                             status,
200                             "ProcMgr_attach failed!");
201         goto procmgrattach_fail;
202     }
204     if ((firmware_info->firmware) &&
205         (!firmware_info->attachOnly)) {
206         status = ProcMgr_load(procH[procId],
207             (String)firmware_info->firmware, 0, NULL,
208              NULL, &procH_fileId[procId]);
209         if (status < 0) {
210             GT_setFailureReason(curTrace,
211                                 GT_4CLASS,
212                                 "init_ipc",
213                                 status,
214                                 "ProcMgr_load failed!");
215             goto procmgrload_fail;
216         }
217     }
219     status = Ipc_attach(procId);
220     if (status < 0) {
221         GT_setFailureReason(curTrace,
222                              GT_4CLASS,
223                              "init_ipc",
224                              status,
225                              "Ipc_attach failed!");
226         goto ipcattach_fail;
227     }
229     status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
230         -1, errStates);
231     if (status < 0) {
232         goto procmgrreg_fail;
233     }
235     if (!firmware_info->attachOnly) {
236         status = ProcMgr_start(procH[procId], NULL);
237         if (status < 0) {
238             GT_setFailureReason(curTrace,
239                                 GT_4CLASS,
240                                 "init_ipc",
241                                 status,
242                                 "ProcMgr_start failed!");
243             goto procmgrstart_fail;
244         }
245     }
247     Osal_printf("runSlave successful for core %d\n", procId);
249     return 0;
251 procmgrstart_fail:
252     ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
253         (Ptr)dev, errStates);
254 procmgrreg_fail:
255     Ipc_detach(procId);
256 ipcattach_fail:
257     if ((firmware_info->firmware) &&
258         (!firmware_info->attachOnly)) {
259         ProcMgr_unload(procH[procId], procH_fileId[procId]);
260     }
261 procmgrload_fail:
262     ProcMgr_detach(procH[procId]);
263 procmgrattach_fail:
264     ProcMgr_close(&procH[procId]);
265     procH[procId] = NULL;
266 procmgropen_fail:
267     RscTable_free(&rscHandle[procId]);
269     return -1;
272 static int resetSlave(syslink_dev_t *dev, uint16_t procId)
274     if ((procH[procId]) && (procH_fileId[procId])) {
275         GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(procId));
276         ProcMgr_stop(procH[procId]);
277     }
279     if (procH[procId]) {
280         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb, (Ptr)dev,
281             errStates);
282         Ipc_detach(procId);
283         if (procH_fileId[procId]) {
284             ProcMgr_unload(procH[procId], procH_fileId[procId]);
285             procH_fileId[procId] = 0;
286         }
287         ProcMgr_detach(procH[procId]);
288         ProcMgr_close(&procH[procId]);
289         procH[procId] = NULL;
290         RscTable_free(&rscHandle[procId]);
291         rscHandle[procId] = NULL;
292     }
294     Osal_printf("resetSlave successful for core %d\n", procId);
296     return 0;
299 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
300     syslink_ocb_t *ocb)
302     int             nbytes;
303     int             nparts;
304     int             status;
305     int             nleft;
306     int             i;
307     uint16_t        procid = ocb->ocb.attr->procid;
308     syslink_dev_t * dev = ocb->ocb.attr->dev;
310     if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
311         return (status);
312     }
314     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
315         return (ENOSYS);
316     }
318     pthread_mutex_lock(&dev->firmwareLock);
320     for (i = 0; i < syslink_num_cores; i++) {
321         if (syslink_firmware[i].proc_id == procid) {
322             break;
323         }
324     }
325     if (i == syslink_num_cores) {
326         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
327             syslink_firmware[syslink_num_cores].proc =
328                 MultiProc_getName(procid);
329             syslink_firmware[syslink_num_cores].proc_id = procid;
330             syslink_firmware[syslink_num_cores].attachOnly = false;
331             syslink_firmware[syslink_num_cores].reload = false;
332             syslink_firmware[syslink_num_cores].procState = RESET_STATE;
333             syslink_firmware[syslink_num_cores].freeString = false;
334             syslink_firmware[syslink_num_cores++].firmware = NULL;
335         }
336         else {
337             pthread_mutex_unlock(&dev->firmwareLock);
338             return (EBADSLT);
339         }
340     }
342     if (ocb->ocb.offset == 0) {
343         /* latch onto new state, so that we print out complete strings */
344         syslink_firmware[i].readProcState = syslink_firmware[i].procState;
345     }
347     nleft = strlen(procStateNames[syslink_firmware[i].readProcState])
348         - ocb->ocb.offset; /* the state is expressed in one byte */
349     nbytes = min(msg->i.nbytes, nleft);
351     /* Make sure the user has supplied a big enough buffer */
352     if (nbytes > 0) {
353         /* set up the return data IOV */
354         SETIOV(ctp->iov,
355             (char *)procStateNames[syslink_firmware[i].readProcState]
356             + ocb->ocb.offset, nbytes);
358         pthread_mutex_unlock(&dev->firmwareLock);
360         /* set up the number of bytes (returned by client's read()) */
361         _IO_SET_READ_NBYTES(ctp, nbytes);
363         ocb->ocb.offset += nbytes;
365         nparts = 1;
366     }
367     else {
368         pthread_mutex_unlock(&dev->firmwareLock);
370         _IO_SET_READ_NBYTES (ctp, 0);
372         /* reset offset */
373         ocb->ocb.offset = 0;
375         nparts = 0;
376     }
378     /* mark the access time as invalid (we just accessed it) */
380     if (msg->i.nbytes > 0) {
381         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
382     }
384     return (_RESMGR_NPARTS(nparts));
387 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
388     syslink_ocb_t *ocb)
390     int             status;
391     char *          buf;
392     uint16_t        procid = ocb->ocb.attr->procid;
393     int             i;
394     char *          ptr;
395     syslink_dev_t * dev = ocb->ocb.attr->dev;
396     Int32           sr0ProcId;
398     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
399         return (status);
400     }
402     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
403         return (ENOSYS);
404     }
406     /* set up the number of bytes (returned by client's write()) */
407     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
409     buf = (char *) malloc(msg->i.nbytes + 1);
410     if (buf == NULL) {
411         return (ENOMEM);
412     }
414     /*
415      *  Read the data from the sender's message buffer.
416      */
417     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
418     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
419     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
420         *ptr = '\0';
421     }
423     pthread_mutex_lock(&dev->firmwareLock);
424     for (i = 0; i < syslink_num_cores; i++) {
425         if (syslink_firmware[i].proc_id == procid) {
426             break;
427         }
428     }
429     if (i == syslink_num_cores) {
430         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
431             syslink_firmware[syslink_num_cores].proc =
432                 MultiProc_getName(procid);
433             syslink_firmware[syslink_num_cores].proc_id = procid;
434             syslink_firmware[syslink_num_cores].attachOnly = false;
435             syslink_firmware[syslink_num_cores].reload = false;
436             syslink_firmware[syslink_num_cores].procState = RESET_STATE;
437             syslink_firmware[syslink_num_cores].freeString = false;
438             syslink_firmware[syslink_num_cores++].firmware = NULL;
439         }
440         else {
441             pthread_mutex_unlock(&dev->firmwareLock);
442             return (EBADSLT);
443         }
444     }
446     if (strcmp("1", buf) == 0) {
447         if ((syslink_firmware[i].procState == RESET_STATE) &&
448            (syslink_firmware[i].firmware != NULL)) {
449             runSlave(ocb->ocb.attr->dev, procid, &syslink_firmware[i]);
450 #if defined(SYSLINK_PLATFORM_VAYU)
451             if (gatempEnabled) {
452                 if (sr0OwnerProcId == -1) {
453                     /* Set up GateMP */
454                     status = GateMP_setup(&sr0ProcId);
455                     if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
456                         resetSlave(ocb->ocb.attr->dev, procid);
457                         pthread_mutex_unlock(&dev->firmwareLock);
458                         free(buf);
459                         return (EIO);
460                     }
461                     else if (status == 0) {
462                         /* We have discovered an owner for SR0 */
463                         sr0OwnerProcId = sr0ProcId;
464                     }
465                 }
466                 else {
467                     /*
468                      * We have already identified SR0 owner and setup GateMP.
469                      * Do nothing.
470                      */
471                 }
472             }
473 #endif
474             printf("Core is now running with image '%s'\n",
475                 syslink_firmware[i].firmware);
476             syslink_firmware[i].procState = RUNNING_STATE;
477             syslink_firmware[i].reload = true;
478             status = init_syslink_trace_device(dev);
479             if (status < 0) {
480                 pthread_mutex_unlock(&dev->firmwareLock);
481                 free(buf);
482                 return (EIO);
483             }
484             printf("Core %s has been started.\n", MultiProc_getName(procid));
485         }
486     }
487     else if (strcmp("0", buf) == 0) {
488         if (syslink_firmware[i].procState == RUNNING_STATE) {
489 #if defined(SYSLINK_PLATFORM_VAYU)
490             if ((gatempEnabled) && (procid == sr0OwnerProcId)) {
491                 sr0OwnerProcId = -1;
492                 status = GateMP_destroy(FALSE);
493                 if (status < 0) {
494                     pthread_mutex_unlock(&dev->firmwareLock);
495                     free(buf);
496                     fprintf(stderr, "Core %s cannot be reset. GateMP may still"
497                         " be in use by host\n", MultiProc_getName(procid));
498                     return (EIO);
499                 }
500             }
501 #endif
502             resetSlave(ocb->ocb.attr->dev, procid);
503             syslink_firmware[i].procState = RESET_STATE;
504             syslink_firmware[i].reload = false;
505             status = deinit_syslink_trace_device(dev);
506             if (status < 0) {
507                 pthread_mutex_unlock(&dev->firmwareLock);
508                 free(buf);
509                 Osal_printf("IPC: deinit_syslink_trace_device failed %d",
510                     status);
511                 return (EIO);
512             }
513             printf("Core %s has been reset.\n", MultiProc_getName(procid));
514         }
515     }
516     else {
517         /* ignore the input as it is not recognized */
518         fprintf(stderr, "Unrecognized input\n");
519     }
521     pthread_mutex_unlock(&dev->firmwareLock);
523     free(buf);
525     if (msg->i.nbytes > 0) {
526         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
527     }
529     return (_RESMGR_NPARTS(0));
532 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
533     syslink_ocb_t *ocb)
535     int             nbytes;
536     int             nparts;
537     int             status;
538     int             nleft;
539     int             i;
540     uint16_t        procid = ocb->ocb.attr->procid;
541     syslink_dev_t * dev = ocb->ocb.attr->dev;
543     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
544         return (status);
545     }
547     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
548         return (ENOSYS);
549     }
551     pthread_mutex_lock(&dev->firmwareLock);
552     for (i = 0; i < syslink_num_cores; i++) {
553         if (syslink_firmware[i].proc_id == procid) {
554             break;
555         }
556     }
558     if (i == syslink_num_cores) {
559         if ((syslink_num_cores < MultiProc_MAXPROCESSORS)) {
560             syslink_firmware[syslink_num_cores].proc =
561                 MultiProc_getName(procid);
562             syslink_firmware[syslink_num_cores].proc_id = procid;
563             syslink_firmware[syslink_num_cores].attachOnly = false;
564             syslink_firmware[syslink_num_cores].reload = false;
565             syslink_firmware[syslink_num_cores].procState = RESET_STATE;
566             syslink_firmware[syslink_num_cores].freeString = false;
567             syslink_firmware[syslink_num_cores++].firmware = NULL;
568         }
569         else {
570             pthread_mutex_unlock(&dev->firmwareLock);
571             return (EBADSLT);
572         }
573     }
575     if (syslink_firmware[i].firmware == NULL) {
576         nbytes = 0;
577     }
578     else {
579         nleft = strlen(syslink_firmware[i].firmware)
580             - ocb->ocb.offset; /* the state is expressed in one byte */
581         nbytes = min(msg->i.nbytes, nleft);
582     }
584     /* Make sure the user has supplied a big enough buffer */
585     if (nbytes > 0) {
586         /* set up the return data IOV */
587         SETIOV(ctp->iov, (char *)syslink_firmware[i].firmware
588             + ocb->ocb.offset, nbytes);
590         /* set up the number of bytes (returned by client's read()) */
591         _IO_SET_READ_NBYTES(ctp, nbytes);
593         ocb->ocb.offset += nbytes;
595         nparts = 1;
596     }
597     else {
598         _IO_SET_READ_NBYTES (ctp, 0);
600         /* reset offset */
601         ocb->ocb.offset = 0;
603         nparts = 0;
604     }
606     pthread_mutex_unlock(&dev->firmwareLock);
608     /* mark the access time as invalid (we just accessed it) */
610     if (msg->i.nbytes > 0) {
611         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
612     }
614     return (_RESMGR_NPARTS(nparts));
617 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
618     syslink_ocb_t *ocb)
620     int             status;
621     char *          buf;
622     uint16_t        procid = ocb->ocb.attr->procid;
623     int             i;
624     char *          absPath;
625     char *          ptr;
626     syslink_dev_t * dev = ocb->ocb.attr->dev;
628     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
629         return (status);
630     }
632     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
633         return (ENOSYS);
634     }
636     /* set up the number of bytes (returned by client's write()) */
637     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
639     buf = (char *) malloc(msg->i.nbytes + 1);
640     if (buf == NULL) {
641         return (ENOMEM);
642     }
644     /*
645      *  Read the data from the sender's message buffer.
646      */
647     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
648     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
649     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
650         *ptr = '\0';
651     }
653     /* Get the abs path for all firmware files */
654     absPath = calloc(1, PATH_MAX + 1);
655     if (absPath == NULL) {
656         free(buf);
657         return (ENOMEM);
658     }
659     if (NULL == realpath(buf, absPath)) {
660         fprintf(stderr, "invalid path to executable: %d\n", errno);
661         fprintf(stderr, "make sure you are specifying the full path to the "
662             "file.\n");
663         free(absPath);
664         free(buf);
665         return (ENOENT);
666     }
667     free(buf);
669     pthread_mutex_lock(&dev->firmwareLock);
671     /*
672      * Check if an entry in syslink_firmware already exists for this core.
673      * If not, create one. Otherwise just update the firmware path.
674      */
675     for (i = 0; i < syslink_num_cores; i++) {
676         if (syslink_firmware[i].proc_id == procid) {
677             break;
678         }
679     }
680     if (i == syslink_num_cores) {
681         if (syslink_num_cores < MultiProc_MAXPROCESSORS) {
682             syslink_firmware[syslink_num_cores].proc =
683                 MultiProc_getName(procid);
684             syslink_firmware[syslink_num_cores].proc_id = procid;
685             syslink_firmware[syslink_num_cores].attachOnly = false;
686             syslink_firmware[syslink_num_cores].reload = false;
687             syslink_firmware[syslink_num_cores].procState = RESET_STATE;
688             syslink_firmware[syslink_num_cores].freeString = true;
689             syslink_firmware[syslink_num_cores++].firmware = absPath;
690         }
691         else {
692             pthread_mutex_unlock(&dev->firmwareLock);
693             free(absPath);
694             return (EBADSLT);
695         }
696     }
697     else {
698         /* Free previously allocated string */
699         if ((syslink_firmware[syslink_num_cores].freeString) &&
700            (syslink_firmware[syslink_num_cores].firmware)) {
701             free(syslink_firmware[i].firmware);
702         }
703         syslink_firmware[i].firmware = absPath;
704     }
706     pthread_mutex_unlock(&dev->firmwareLock);
708     if (msg->i.nbytes > 0) {
709         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
710     }
712     return (_RESMGR_NPARTS(0));
715 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
717     int         nbytes;
718     int         nparts;
719     int         status;
720     int         nleft;
721     uint32_t    len;
722     uint16_t    procid = ocb->ocb.attr->procid;
724     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
725         return (status);
727     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
728         return (ENOSYS);
730     /* check to see where the trace buffer is */
731     if (proc_traces[procid].va == NULL) {
732         return (ENOSYS);
733     }
734     if (ocb->ocb.offset == 0) {
735         ocb->widx = *(proc_traces[procid].widx);
736         ocb->ridx = *(proc_traces[procid].ridx);
737         *(proc_traces[procid].ridx) = ocb->widx;
738     }
740     /* Check for wrap-around */
741     if (ocb->widx < ocb->ridx)
742         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
743     else
744         len = ocb->widx - ocb->ridx;
746     /* Determine the amount left to print */
747     if (ocb->widx >= ocb->ridx)
748         nleft = len - ocb->ocb.offset;
749     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
750         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
751     else
752         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
754     nbytes = min (msg->i.nbytes, nleft);
756     /* Make sure the user has supplied a big enough buffer */
757     if (nbytes > 0) {
758         /* set up the return data IOV */
759         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
760             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
761         else
762             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
764         /* set up the number of bytes (returned by client's read()) */
765         _IO_SET_READ_NBYTES (ctp, nbytes);
767         ocb->ocb.offset += nbytes;
769         nparts = 1;
770     }
771     else {
772         _IO_SET_READ_NBYTES (ctp, 0);
774         /* reset offset */
775         ocb->ocb.offset = 0;
777         nparts = 0;
778     }
780     /* mark the access time as invalid (we just accessed it) */
782     if (msg->i.nbytes > 0)
783         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
785     return (_RESMGR_NPARTS (nparts));
788 extern OsalSemaphore_Handle mqcopy_test_sem;
790 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
792     int status = _RESMGR_NOREPLY;
793     struct _msg_info info;
795     /*
796      * Try to run the default unblock for this message.
797      */
798     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
799         return status;
800     }
802     /*
803      * Check if rcvid is still valid and still has an unblock
804      * request pending.
805      */
806     if (MsgInfo(ctp->rcvid, &info) == -1 ||
807         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
808         return _RESMGR_NOREPLY;
809     }
811     if (mqcopy_test_sem)
812         OsalSemaphore_post(mqcopy_test_sem);
814     return _RESMGR_NOREPLY;
817 IOFUNC_OCB_T *
818 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
820     syslink_ocb_t *ocb = NULL;
822     /* Allocate the OCB */
823     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
824     if (ocb == NULL){
825         errno = ENOMEM;
826         return (NULL);
827     }
829     ocb->pid = ctp->info.pid;
831     return (IOFUNC_OCB_T *)(ocb);
834 void
835 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
837     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
839     if (ocb) {
840 #ifndef SYSLINK_PLATFORM_VAYU
841         GateHWSpinlock_LeaveLockForPID(ocb->pid);
842 #endif
843         free (ocb);
844     }
847 int init_slave_devices(syslink_dev_t *dev)
849     resmgr_attr_t    resmgr_attr;
850     int              i;
851     syslink_attr_t * slave_attr;
852     int              status = 0;
854     memset(&resmgr_attr, 0, sizeof resmgr_attr);
855     resmgr_attr.nparts_max = 1;
856     resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
858     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
859         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_state[i],
860                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_state[i]);
861         slave_attr = &dev->syslink.cattr_slave[i];
862         iofunc_attr_init(&slave_attr->attr,
863                          S_IFCHR | 0777, NULL, NULL);
864         slave_attr->attr.mount = &dev->syslink.mattr;
865         slave_attr->procid = i;
866         slave_attr->dev = (Ptr)dev;
867         iofunc_time_update(&slave_attr->attr);
868         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
869                   "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
870         dev->syslink.iofuncs_state[i].read = slave_state_read;
871         dev->syslink.iofuncs_state[i].write = slave_state_write;
873         if (-1 == (dev->syslink.resmgr_id_state[i] =
874             resmgr_attach(dev->dpp, &resmgr_attr,
875                 dev->syslink.device_name, _FTYPE_ANY, 0,
876                 &dev->syslink.cfuncs_state[i],
877                 &dev->syslink.iofuncs_state[i],
878                 &slave_attr->attr))) {
879             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
880                 status, "resmgr_attach failed");
881             return (-1);
882         }
883     }
885     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
886         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_file[i],
887                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_file[i]);
888         slave_attr = &dev->syslink.cattr_slave[i];
889         iofunc_attr_init(&slave_attr->attr,
890                          S_IFCHR | 0777, NULL, NULL);
891         slave_attr->attr.mount = &dev->syslink.mattr;
892         slave_attr->procid = i;
893         slave_attr->dev = (Ptr)dev;
894         iofunc_time_update(&slave_attr->attr);
895         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
896                   "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
897         dev->syslink.iofuncs_file[i].read = slave_file_read;
898         dev->syslink.iofuncs_file[i].write = slave_file_write;
900         if (-1 == (dev->syslink.resmgr_id_file[i] =
901             resmgr_attach(dev->dpp, &resmgr_attr,
902                 dev->syslink.device_name, _FTYPE_ANY, 0,
903                 &dev->syslink.cfuncs_file[i],
904                 &dev->syslink.iofuncs_file[i],
905                 &slave_attr->attr))) {
906             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
907                 status, "resmgr_attach failed");
908             return (-1);
909         }
910     }
912     return (status);
915 int deinit_slave_devices(syslink_dev_t *dev)
917     int status = EOK;
918     int i = 0;
920     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
921         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_state[i], 0);
922         if (status < 0) {
923             Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
924                 i, errno);
925         }
926         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_file[i], 0);
927         if (status < 0) {
928             Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
929                 i, errno);
930         }
931     }
933     return (status);
936 int init_syslink_trace_device(syslink_dev_t *dev)
938     resmgr_attr_t    resmgr_attr;
939     int              i;
940     syslink_attr_t * trace_attr;
941     char             trace_name[_POSIX_PATH_MAX];
942     int              status = 0;
943     unsigned int     da = 0, pa = 0;
944     unsigned int     len;
946     memset(&resmgr_attr, 0, sizeof resmgr_attr);
947     resmgr_attr.nparts_max = 10;
948     resmgr_attr.msg_max_size = 2048;
950     for (i = 0; i < syslink_num_cores; i++) {
951         /*
952          * Initialize trace device only for cores that are running and their
953          * device is not yet setup.
954          */
955         if ((syslink_firmware[i].procState == RUNNING_STATE) &&
956             (proc_traces[i].va == NULL)) {
957             iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
958                 &dev->syslink.cfuncs_trace[i],
959                 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
960             trace_attr = &dev->syslink.cattr_trace[i];
961             iofunc_attr_init(&trace_attr->attr,
962                          S_IFCHR | 0777, NULL, NULL);
963             trace_attr->attr.mount = &dev->syslink.mattr;
964             trace_attr->procid = i;
965             iofunc_time_update(&trace_attr->attr);
966             snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
967                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
968             dev->syslink.iofuncs_trace[i].read = syslink_read;
969             snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
970             pa = 0;
971             status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE,
972                 0, &da, &pa, &len);
973             if (status == 0) {
974                 /* last 8 bytes are for writeIdx/readIdx */
975                 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
976                 if (da && !pa) {
977                     /* need to translate da->pa */
978                     status = ProcMgr_translateAddr(
979                         procH[syslink_firmware[i].proc_id],
980                         (Ptr *) &pa,
981                         ProcMgr_AddrType_MasterPhys,
982                         (Ptr) da,
983                         ProcMgr_AddrType_SlaveVirt);
984                 }
985                 else {
986                     GT_setFailureReason(curTrace, GT_4CLASS,
987                         "init_syslink_trace_device",
988                         status, "not performing ProcMgr_translate");
989                 }
990                 /* map length aligned to page size */
991                 proc_traces[i].va =
992                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
993                 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
994                                                proc_traces[i].len);
995                 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
996                     + sizeof(uint32_t));
997                 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
998                     GT_setFailureReason(curTrace, GT_4CLASS,
999                         "init_syslink_trace_device",
1000                         status, "mmap_device_io failed");
1001                     GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1002                     proc_traces[i].va = NULL;
1003                 }
1004                 proc_traces[i].firstRead = TRUE;
1005             }
1006             else {
1007                 GT_setFailureReason(curTrace, GT_4CLASS,
1008                     "init_syslink_trace_device",
1009                     status, "RscTable_getInfo failed");
1010                 proc_traces[i].va = NULL;
1011             }
1012             if (-1 == (dev->syslink.resmgr_id_trace[i] =
1013                        resmgr_attach(dev->dpp, &resmgr_attr,
1014                                      dev->syslink.device_name, _FTYPE_ANY, 0,
1015                                      &dev->syslink.cfuncs_trace[i],
1016                                      &dev->syslink.iofuncs_trace[i],
1017                                      &trace_attr->attr))) {
1018                 GT_setFailureReason(curTrace, GT_4CLASS,
1019                     "init_syslink_trace_device",
1020                     status, "resmgr_attach failed");
1021                 return(-1);
1022             }
1023         }
1024     }
1026     return (status);
1029 int deinit_syslink_trace_device(syslink_dev_t *dev)
1031     int status = EOK;
1032     int i = 0;
1034     for (i = 0; i < syslink_num_cores; i++) {
1035         /* Only disable trace device on cores in RESET state */
1036         if ((syslink_firmware[i].procState == RESET_STATE) &&
1037             (proc_traces[i].va != NULL)) {
1038             status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i],
1039                 0);
1040             if (status < 0) {
1041                 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1042                     i, errno);
1043                 status = errno;
1044             }
1045             if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1046                 munmap((void *)proc_traces[i].va,
1047                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1048             }
1049             proc_traces[i].va = NULL;
1050         }
1051     }
1053     return (status);
1056 /* Initialize the syslink device */
1057 int init_syslink_device(syslink_dev_t *dev)
1059     iofunc_attr_t *  attr;
1060     resmgr_attr_t    resmgr_attr;
1061     int              status = 0;
1063     pthread_mutex_init(&dev->lock, NULL);
1064     pthread_mutex_init(&dev->firmwareLock, NULL);
1066     memset(&resmgr_attr, 0, sizeof resmgr_attr);
1067     resmgr_attr.nparts_max = 10;
1068     resmgr_attr.msg_max_size = 2048;
1070     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
1071     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
1072     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1073                               IOFUNC_PC_NO_TRUNC |
1074                               IOFUNC_PC_SYNC_IO;
1075     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
1077     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
1078     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1080     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
1081                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
1083     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
1085     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
1086     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
1087     dev->syslink.iofuncs.devctl = syslink_devctl;
1088     dev->syslink.iofuncs.unblock = syslink_unblock;
1090     attr->mount = &dev->syslink.mattr;
1091     iofunc_time_update(attr);
1093     if (-1 == (dev->syslink.resmgr_id =
1094         resmgr_attach(dev->dpp, &resmgr_attr,
1095                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1096                       &dev->syslink.cfuncs,
1097                       &dev->syslink.iofuncs, attr))) {
1098         return(-1);
1099     }
1101     status = init_slave_devices(dev);
1102     if (status < 0) {
1103         return status;
1104     }
1106     status = init_syslink_trace_device(dev);
1107     if (status < 0) {
1108         return status;
1109     }
1111     return(0);
1114 /* De-initialize the syslink device */
1115 int deinit_syslink_device(syslink_dev_t *dev)
1117     int status = EOK;
1119     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
1120     if (status < 0) {
1121         Osal_printf("IPC: resmgr_detach of %s failed: %d",
1122             IPC_DEVICE_PATH, errno);
1123         status = errno;
1124     }
1126     status = deinit_syslink_trace_device(dev);
1127     if (status < 0) {
1128         Osal_printf("IPC: deinit_syslink_trace_device failed %d", status);
1129     }
1131     status = deinit_slave_devices(dev);
1132     if (status < 0) {
1133         Osal_printf("IPC: deinit_slave_devices failed %d", status);
1134     }
1136     return(status);
1140 /* Initialize the devices */
1141 int init_devices(syslink_dev_t *dev)
1143     if (init_syslink_device(dev) < 0) {
1144         Osal_printf("IPC: device init failed");
1145         return(-1);
1146     }
1148     return(0);
1152 /* De-initialize the devices */
1153 int deinit_devices(syslink_dev_t *dev)
1155     int status = EOK;
1157     if ((status = deinit_syslink_device(dev)) < 0) {
1158         fprintf( stderr, "IPC: device de-init failed %d\n", status);
1159         status = errno;
1160     }
1162     return(status);
1165 static void ipc_recover(Ptr args)
1167     syslink_dev_t * dev = (syslink_dev_t *)args;
1169     if (!disableRecovery) {
1170         /* Protect the syslink_firmware array as we recover */
1171         pthread_mutex_lock(&dev->firmwareLock);
1172         deinit_ipc(dev, syslink_firmware, TRUE);
1173         deinit_syslink_trace_device(dev);
1174         init_ipc(dev, syslink_firmware, TRUE);
1175         init_syslink_trace_device(dev);
1176         pthread_mutex_unlock(&dev->firmwareLock);
1177     }
1178     else {
1179         GT_0trace(curTrace, GT_4CLASS,
1180                   "ipc_recover: Recovery disabled.\n");
1181     }
1184 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1185                       ProcMgr_State fromState, ProcMgr_State toState,
1186                       ProcMgr_EventStatus status, Ptr args)
1188     Int ret = 0;
1189     String errString = NULL;
1190     syslink_dev_t * dev = (syslink_dev_t *)args;
1192     if (status == ProcMgr_EventStatus_Event) {
1193         switch (toState) {
1194             case ProcMgr_State_Mmu_Fault:
1195                 errString = "MMU Fault";
1196                 break;
1197             case ProcMgr_State_Error:
1198                 errString = "Exception";
1199                 break;
1200             case ProcMgr_State_Watchdog:
1201                 errString = "Watchdog";
1202                 break;
1203             default:
1204                 errString = "Unexpected State";
1205                 ret = -1;
1206                 break;
1207         }
1208         GT_2trace (curTrace, GT_4CLASS,
1209                    "syslink_error_cb: Received Error Callback for %s : %s\n",
1210                    MultiProc_getName(procId), errString);
1211         /* Don't allow re-schedule of recovery until complete */
1212         pthread_mutex_lock(&dev->lock);
1213         if (ret != -1 && dev->recover == FALSE) {
1214             /* Schedule recovery. */
1215             dev->recover = TRUE;
1216             /* Activate a thread to handle the recovery. */
1217             GT_0trace (curTrace, GT_4CLASS,
1218                        "syslink_error_cb: Scheduling recovery...");
1219             OsalThread_activate(dev->ipc_recovery_work);
1220         }
1221         else {
1222             GT_0trace (curTrace, GT_4CLASS,
1223                        "syslink_error_cb: Recovery already scheduled.");
1224         }
1225         pthread_mutex_unlock(&dev->lock);
1226     }
1227     else if (status == ProcMgr_EventStatus_Canceled) {
1228         GT_1trace (curTrace, GT_3CLASS,
1229                    "SysLink Error Callback Cancelled for %s",
1230                    MultiProc_getName(procId));
1231     }
1232     else {
1233         GT_1trace (curTrace, GT_4CLASS,
1234                    "SysLink Error Callback Unexpected Event for %s",
1235                    MultiProc_getName(procId));
1236     }
1238     return ret;
1241 /*
1242  * Initialize the syslink ipc
1243  *
1244  * This function sets up the "kernel"-side IPC modules, and does any special
1245  * initialization required for QNX and the platform being used.  This function
1246  * also registers for error notifications and initializes the recovery thread.
1247  */
1248 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
1250     int status = 0;
1251     Ipc_Config iCfg;
1252     OsalThread_Params threadParams;
1253     ProcMgr_AttachParams attachParams;
1254     UInt16 procId;
1255     int i;
1257     if (status >= 0) {
1258         if (!recover) {
1259             /* Set up the MemoryOS module */
1260             status = MemoryOS_setup();
1261             if (status < 0)
1262                 goto memoryos_fail;
1263         }
1265         /* Setup IPC and platform-specific items */
1266         status = Ipc_setup (&iCfg);
1267         if (status < 0)
1268             goto ipcsetup_fail;
1270         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1271         if (!recover) {
1272             /* Setup Fault recovery items. */
1273             /* Create the thread object used for the interrupt handler. */
1274             threadParams.priority     = OsalThread_Priority_Medium;
1275             threadParams.priorityType = OsalThread_PriorityType_Generic;
1276             threadParams.once         = FALSE;
1277             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1278                                                         ipc_recover,
1279                                                         dev,
1280                                                         &threadParams);
1281             if (dev->ipc_recovery_work == NULL)
1282                 goto osalthreadcreate_fail;
1283         }
1284         else {
1285             pthread_mutex_lock(&dev->lock);
1286             dev->recover = FALSE;
1287             pthread_mutex_unlock(&dev->lock);
1288         }
1290         memset(procH_fileId, 0, sizeof(procH_fileId));
1292         for (i = 0; i < syslink_num_cores; i++) {
1293             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1294             if (procId >= MultiProc_MAXPROCESSORS) {
1295                 status = -1;
1296                 fprintf(stderr, "Invalid processor name specified\n");
1297                 break;
1298             }
1300             if (procH[procId]) {
1301                 GT_setFailureReason (curTrace,
1302                                      GT_4CLASS,
1303                                      "init_ipc",
1304                                      status,
1305                                      "invalid proc!");
1306                 break;
1307             }
1309             if (recover) {
1310                 /*
1311                  * if we are in recovery, we load the cores we previously
1312                  * attached to
1313                  */
1314                 firmware[i].attachOnly = false;
1315             }
1317             if ((!recover) || (firmware[i].reload)) {
1318                 status = runSlave(dev, procId, &firmware[i]);
1319                 if (status == 0) {
1320                     firmware[i].procState = RUNNING_STATE;
1321                     continue;
1322                 }
1323                 else {
1324                     break;
1325                 }
1326             }
1327             else {
1328                 /*
1329                  * During recovery, do not run cores unless they were previously
1330                  * running
1331                  */
1332                 continue;
1333             }
1334         }
1336         if (status < 0)
1337             goto tiipcsetup_fail;
1339         /* Set up rpmsg_mq */
1340         status = ti_ipc_setup();
1341         if (status < 0)
1342             goto tiipcsetup_fail;
1344         /* Set up rpmsg_rpc */
1345         status = rpmsg_rpc_setup();
1346         if (status < 0)
1347             goto rpcsetup_fail;
1349 #if defined(SYSLINK_PLATFORM_VAYU)
1350         if (gatempEnabled) {
1351             Int32 sr0ProcId;
1353             /* Set up NameServer for resource manager process */
1354             status = NameServer_setup();
1355             if (status < 0) {
1356                 goto nameserversetup_fail;
1357             }
1359             /* Set up GateMP */
1360             status = GateMP_setup(&sr0ProcId);
1361             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1362                 goto gatempsetup_fail;
1363             }
1364             else if (status == 0) {
1365                 sr0OwnerProcId = sr0ProcId;
1366             }
1367             else {
1368                 /*
1369                  * If we did not find the default gate, perhaps SR0 is
1370                  * not yet loaded. This is ok.
1371                  */
1372                 status = 0;
1373             }
1374         }
1375 #endif
1377         goto exit;
1378     }
1380 #if defined(SYSLINK_PLATFORM_VAYU)
1381 gatempsetup_fail:
1382     NameServer_destroy();
1383 nameserversetup_fail:
1384     rpmsg_rpc_destroy();
1385 #endif
1386 rpcsetup_fail:
1387     ti_ipc_destroy(recover);
1388 tiipcsetup_fail:
1389     for (i-=1; i >= 0; i--) {
1390         procId = firmware[i].proc_id;
1391         if (procId >= MultiProc_MAXPROCESSORS) {
1392             continue;
1393         }
1394         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1395                                 (Ptr)dev, errStates);
1396         if (!firmware[i].attachOnly) {
1397             ProcMgr_stop(procH[procId]);
1398             if (procH_fileId[procId]) {
1399                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1400                 procH_fileId[procId] = 0;
1401             }
1402         }
1403         ProcMgr_detach(procH[procId]);
1404         ProcMgr_close(&procH[procId]);
1405         procH[procId] = NULL;
1406         RscTable_free(&rscHandle[procId]);
1407         rscHandle[procId] = NULL;
1408     }
1409     OsalThread_delete(&dev->ipc_recovery_work);
1410 osalthreadcreate_fail:
1411     Ipc_destroy();
1412 ipcsetup_fail:
1413     MemoryOS_destroy();
1414 memoryos_fail:
1415 exit:
1416     return status;
1419 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1420     bool recover)
1422     int status = EOK;
1423     uint32_t i = 0, id = 0;
1425     if (logFilename) {
1426         /* wait a little bit for traces to finish dumping */
1427         sleep(1);
1428     }
1430     // Stop the remote cores right away
1431     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1432         if (procH[i]) {
1433             resetSlave(dev, i);
1434         }
1435     }
1437 #if defined(SYSLINK_PLATFORM_VAYU)
1438     if (gatempEnabled) {
1439         GateMP_destroy(TRUE);
1441         NameServer_destroy();
1442     }
1443 #endif
1445     rpmsg_rpc_destroy();
1447     ti_ipc_destroy(recover);
1449     if (!recover && dev->ipc_recovery_work != NULL) {
1450         OsalThread_delete (&dev->ipc_recovery_work);
1451         dev->ipc_recovery_work = NULL;
1452     }
1454     if (recover) {
1455         static FILE *log = NULL;
1456         if (logFilename) {
1457             /* Dump the trace information */
1458             Osal_printf("IPC: printing remote core trace dump");
1459             log = fopen(logFilename, "a+");
1460             if (log) {
1461                 for (id = 0; id < syslink_num_cores; id++) {
1462                     if (firmware[id].procState == RUNNING_STATE) {
1463                         if (proc_traces[id].va) {
1464                             /* print traces */
1465                             fprintf(log, "*************************************\n");
1466                             fprintf(log, "***       CORE%d TRACE DUMP        ***\n",
1467                                 firmware[i].proc_id);
1468                             fprintf(log, "*************************************\n");
1469                             for (i = (*proc_traces[id].widx + 1);
1470                                 i < (proc_traces[id].len - 8);
1471                                 i++) {
1472                                 fprintf(log, "%c",
1473                                     *(char *)((uint32_t)proc_traces[id].va + i));
1474                             }
1475                             for (i = 0; i < *proc_traces[id].widx; i++) {
1476                                 fprintf(log, "%c",
1477                                     *(char *)((uint32_t)proc_traces[id].va + i));
1478                             }
1479                         }
1480                     }
1481                 }
1482                 fflush(log);
1483                 fclose(log);
1484             }
1485             else {
1486                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1487                     logFilename);
1488                 exit(EXIT_FAILURE);
1489             }
1490         }
1491     }
1493     /* After printing trace, set all processor states to RESET */
1494     for (id = 0; id < syslink_num_cores; id++) {
1495         firmware[id].procState = RESET_STATE;
1496     }
1498     status = Ipc_destroy();
1499     if (status < 0) {
1500         printf("Ipc_destroy() failed 0x%x", status);
1501     }
1502     if (!recover) {
1503         status = MemoryOS_destroy();
1504         if (status < 0) {
1505             printf("MemoryOS_destroy() failed 0x%x", status);
1506         }
1507     }
1509     return status;
1513 /** print usage */
1514 static Void printUsage (Char * app)
1516     printf("\n\nUsage:\n");
1517 #if defined(SYSLINK_PLATFORM_OMAP5430)
1518     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1519         app);
1520     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1521     printf("      followed by the path to the executable to load on that core.\n");
1522     printf("Options:\n");
1523     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1524         " Default: 1)\n");
1525     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1526         " 5000 ms)\n");
1527 #else
1528     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1529         app);
1530     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1531     printf("      followed by the path to the executable to load on that core.\n");
1532     printf("Options:\n");
1533     printf("  -g   enable GateMP support on host\n");
1534 #endif
1535     printf("  -d   disable recovery\n");
1536     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1537     printf("              absolute path for filename)\n");
1538     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1539     printf("        and started. Perform late-attach to these cores.\n");
1541     exit (EXIT_SUCCESS);
1544 dispatch_t * syslink_dpp = NULL;
1546 int main(int argc, char *argv[])
1548     syslink_dev_t * dev = NULL;
1549     thread_pool_attr_t tattr;
1550     int status;
1551     int error = EOK;
1552     sigset_t set;
1553     int channelid = 0;
1554     int c;
1555     int hib_enable = 1;
1556     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1557     char *user_parm = NULL;
1558     struct stat          sbuf;
1559     int i = 0;
1560     char * abs_path = NULL;
1562     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1563         printf ("IPC Already Running...\n");
1564         return EXIT_FAILURE;
1565     }
1566     printf ("Starting IPC resource manager...\n");
1568     /* Parse the input args */
1569     while (1)
1570     {
1571         c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1572         if (c == -1)
1573             break;
1575         switch (c)
1576         {
1577 #if defined(SYSLINK_PLATFORM_OMAP5430)
1578         case 'H':
1579             hib_enable = atoi(optarg);
1580             if (hib_enable != 0 && hib_enable != 1) {
1581                 hib_enable = -1;
1582             }
1583             break;
1584         case 'T':
1585             hib_timeout = atoi(optarg);
1586             break;
1587 #endif
1588         case 'U':
1589             user_parm = optarg;
1590             break;
1591         case 'd':
1592             disableRecovery = true;
1593             break;
1594         case 'c':
1595             logFilename = optarg;
1596             break;
1597         case 'a':
1598             numAttach = atoi(optarg);
1599             printf("Late-attaching to %d core(s)\n", numAttach);
1600             break;
1601         case 'v':
1602             verbosity++;
1603             break;
1604 #if defined(SYSLINK_PLATFORM_VAYU)
1605         case 'g':
1606             printf("GateMP support enabled on host\n");
1607             gatempEnabled = true;
1608             break;
1609 #endif
1610         default:
1611             fprintf (stderr, "Unrecognized argument\n");
1612         }
1613     }
1615     /* Now parse the operands, which should be in the format:
1616      * "<multiproc_name> <firmware_file> ..*/
1617     for (; optind + 1 < argc; optind+=2) {
1618         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1619             printUsage(argv[0]);
1620             return (error);
1621         }
1622         syslink_firmware[syslink_num_cores].proc = argv [optind];
1623         syslink_firmware[syslink_num_cores].attachOnly =
1624             ((numAttach-- > 0) ? true : false);
1625         syslink_firmware[syslink_num_cores].reload = true;
1626         syslink_firmware[syslink_num_cores].freeString = false;
1627         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1628     }
1630     /* Get the name of the binary from the input args */
1631     if (!syslink_num_cores) {
1632         fprintf(stderr, "At least one core_id and executable must be "\
1633             "specified");
1634         printUsage(argv[0]);
1635         return (error);
1636     }
1638     /* Validate hib_enable args */
1639     if (hib_enable == -1) {
1640         fprintf (stderr, "invalid hibernation enable value\n");
1641         printUsage(argv[0]);
1642         return (error);
1643     }
1645     syslink_hib_enable = (Bool)hib_enable;
1646     syslink_hib_timeout = hib_timeout;
1648     /* Init logging for syslink */
1649     if (Osal_initlogging(verbosity) != 0) {
1650         return -1;
1651     }
1653     /* Obtain I/O privity */
1654     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1655     if (error == -1) {
1656         Osal_printf("Unable to obtain I/O privity");
1657         return (error);
1658     }
1660     /* Get the abs path for all firmware files */
1661     for (i = 0; i < syslink_num_cores; i++) {
1662         abs_path = calloc(1, PATH_MAX + 1);
1663         if (abs_path == NULL) {
1664             return -1;
1665         }
1666         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1667             fprintf (stderr, "invalid path to executable\n");
1668             return -1;
1669         }
1670         syslink_firmware[i].firmware = abs_path;
1671     }
1673     /* allocate the device structure */
1674     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1675         Osal_printf("IPC: calloc() failed");
1676         return (-1);
1677     }
1679     /* create the channel */
1680     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1681                                     _NTO_CHF_DISCONNECT |
1682                                     _NTO_CHF_COID_DISCONNECT |
1683                                     _NTO_CHF_REPLY_LEN |
1684                                     _NTO_CHF_SENDER_LEN)) < 0) {
1685         Osal_printf("Unable to create channel %d", channelid);
1686         return (channelid);
1687     }
1689     /* create the dispatch structure */
1690     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1691         Osal_printf("IPC: dispatch_create() failed");
1692         return(-1);
1693     }
1695     /*
1696      * Mask out all signals before creating a thread pool.
1697      * This prevents other threads in the thread pool
1698      * from intercepting signals such as SIGTERM.
1699      */
1700     sigfillset(&set);
1701     pthread_sigmask(SIG_BLOCK, &set, NULL);
1703     /* Initialize the thread pool */
1704     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1705     tattr.handle = dev->dpp;
1706     tattr.context_alloc = dispatch_context_alloc;
1707     tattr.context_free = dispatch_context_free;
1708     tattr.block_func = dispatch_block;
1709     tattr.unblock_func = dispatch_unblock;
1710     tattr.handler_func = dispatch_handler;
1711     tattr.lo_water = 2;
1712     tattr.hi_water = 4;
1713     tattr.increment = 1;
1714     tattr.maximum = 10;
1716     /* Create the thread pool */
1717     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1718         Osal_printf("IPC: thread pool create failed");
1719         return(-1);
1720     }
1722     /* init syslink */
1723     status = init_ipc(dev, syslink_firmware, FALSE);
1724     if (status < 0) {
1725         Osal_printf("IPC: init failed");
1726         return(-1);
1727     }
1729     /* init the syslink device */
1730     status = init_devices(dev);
1731     if (status < 0) {
1732         Osal_printf("IPC: device init failed");
1733         return(-1);
1734     }
1736 #if (_NTO_VERSION >= 800)
1737     /* Relinquish privileges */
1738     status = procmgr_ability(  0,
1739                  DENY_ALL | PROCMGR_AID_SPAWN,
1740                  DENY_ALL | PROCMGR_AID_FORK,
1741                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1742                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1743                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1744                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1745                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1746                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1747                  (uint64_t)1, (uint64_t)~0,
1748                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1749                  (uint64_t)1, (uint64_t)~0,
1750                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1752     if (status != EOK) {
1753         Osal_printf("procmgr_ability failed! errno=%d", status);
1754         return EXIT_FAILURE;
1755     }
1757     /* Reduce priority to either what defined from command line or at least nobody */
1758     if (user_parm != NULL) {
1759         if (set_ids_from_arg(user_parm) < 0) {
1760             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1761             return EXIT_FAILURE;
1762         }
1763     } else {
1764         if (setuid(99) != 0) {
1765             Osal_printf("unable to set uid - %s", strerror(errno));
1766             return EXIT_FAILURE;
1767         }
1768     }
1769 #endif
1771     /* make this a daemon process */
1772     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1773         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1774         Osal_printf("IPC: procmgr_daemon() failed");
1775         return(-1);
1776     }
1778     /* start the thread pool */
1779     thread_pool_start(dev->tpool);
1781     /* Unmask signals to be caught */
1782     sigdelset (&set, SIGINT);
1783     sigdelset (&set, SIGTERM);
1784     pthread_sigmask (SIG_BLOCK, &set, NULL);
1786     /* Wait for one of these signals */
1787     sigemptyset (&set);
1788     sigaddset (&set, SIGINT);
1789     sigaddset (&set, SIGQUIT);
1790     sigaddset (&set, SIGTERM);
1792     Osal_printf("IPC resource manager started");
1794     /* Wait for a signal */
1795     while (1)
1796     {
1797         switch (SignalWaitinfo (&set, NULL))
1798         {
1799             case SIGTERM:
1800             case SIGQUIT:
1801             case SIGINT:
1802                 error = EOK;
1803                 goto done;
1805             default:
1806                 break;
1807         }
1808     }
1810     error = EOK;
1812 done:
1813     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1815     error = thread_pool_destroy(dev->tpool);
1816     if (error < 0) {
1817         Osal_printf("IPC: thread_pool_destroy returned an error");
1818     }
1819     deinit_ipc(dev, syslink_firmware, FALSE);
1820     deinit_devices(dev);
1821     free(dev);
1823     /* Free the abs path of firmware files if necessary */
1824     for (i = 0; i < syslink_num_cores; i++) {
1825         if ((syslink_firmware[i].freeString) &&
1826             (syslink_firmware[i].firmware)) {
1827             free(syslink_firmware[i].firmware);
1828         }
1829     }
1831     return (error);