83360fb75dd673b06c99848ca56f911ff9a4547d
[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\n",
163                                    "Running\n" };
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                             "runSlave",
204                             status,
205                             "ProcMgr_attach failed!");
206         goto procmgrattach_fail;
207     }
209     if ((firmware_info->firmware) &&
210         (!firmware_info->attachOnly)) {
211         status = ProcMgr_load(procH[procId],
212             (String)firmware_info->firmware, 0, NULL,
213              NULL, &procH_fileId[procId]);
214         if (status < 0) {
215             GT_setFailureReason(curTrace,
216                                 GT_4CLASS,
217                                 "runSlave",
218                                 status,
219                                 "ProcMgr_load failed!");
220             goto procmgrload_fail;
221         }
222     }
224     status = Ipc_attach(procId);
225     if (status < 0) {
226         GT_setFailureReason(curTrace,
227                              GT_4CLASS,
228                              "runSlave",
229                              status,
230                              "Ipc_attach failed!");
231         goto ipcattach_fail;
232     }
234     status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
235         -1, errStates);
236     if (status < 0) {
237         goto procmgrreg_fail;
238     }
240     if (!firmware_info->attachOnly) {
241         status = ProcMgr_start(procH[procId], NULL);
242         if (status < 0) {
243             GT_setFailureReason(curTrace,
244                                 GT_4CLASS,
245                                 "runSlave",
246                                 status,
247                                 "ProcMgr_start failed!");
248             goto procmgrstart_fail;
249         }
250     }
252     Osal_printf("runSlave successful for core %d\n", procId);
254     return 0;
256 procmgrstart_fail:
257     ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
258         (Ptr)dev, errStates);
259 procmgrreg_fail:
260     Ipc_detach(procId);
261 ipcattach_fail:
262     if ((firmware_info->firmware) &&
263         (!firmware_info->attachOnly)) {
264         ProcMgr_unload(procH[procId], procH_fileId[procId]);
265     }
266 procmgrload_fail:
267     ProcMgr_detach(procH[procId]);
268 procmgrattach_fail:
269     ProcMgr_close(&procH[procId]);
270     procH[procId] = NULL;
271 procmgropen_fail:
272     RscTable_free(&rscHandle[procId]);
274     return -1;
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 + 1; /* Add one byte for carriage return */
601         nbytes = min(msg->i.nbytes, nleft);
602     }
604     /* Make sure the user has supplied a big enough buffer */
605     if (nbytes > 0) {
606         if (nbytes == nleft) {
607             /* set up the return data IOV */
608             SETIOV(&ctp->iov[0], (char *)syslink_firmware[i].firmware
609                 + ocb->ocb.offset, nbytes - 1);
611             /* add a carriage return */
612             SETIOV(&ctp->iov[1], "\n", 1);
614             nparts = 2;
615         }
616         else {
617             /* set up the return data IOV */
618             SETIOV(ctp->iov, (char *)syslink_firmware[i].firmware
619                 + ocb->ocb.offset, nbytes);
621             nparts = 1;
622         }
624         /* set up the number of bytes (returned by client's read()) */
625         _IO_SET_READ_NBYTES(ctp, nbytes);
627         ocb->ocb.offset += nbytes;
628     }
629     else {
630         _IO_SET_READ_NBYTES (ctp, 0);
632         /* reset offset */
633         ocb->ocb.offset = 0;
635         nparts = 0;
636     }
638     pthread_mutex_unlock(&dev->firmwareLock);
640     /* mark the access time as invalid (we just accessed it) */
642     if (msg->i.nbytes > 0) {
643         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
644     }
646     return (_RESMGR_NPARTS(nparts));
649 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
650     syslink_ocb_t *ocb)
652     int             status;
653     char *          buf;
654     uint16_t        procid = ocb->ocb.attr->procid;
655     int             i;
656     char *          absPath;
657     char *          ptr;
658     syslink_dev_t * dev = ocb->ocb.attr->dev;
660     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
661         return (status);
662     }
664     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
665         return (ENOSYS);
666     }
668     if (strcmp(MultiProc_getName(procid), INVALID_PROC) == 0) {
669         fprintf(stderr, "Unsupported core\n");
670         return (EPERM);
671     }
673     /* set up the number of bytes (returned by client's write()) */
674     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
676     buf = (char *) malloc(msg->i.nbytes + 1);
677     if (buf == NULL) {
678         return (ENOMEM);
679     }
681     /*
682      *  Read the data from the sender's message buffer.
683      */
684     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
685     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
686     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
687         *ptr = '\0';
688     }
690     /* Get the abs path for all firmware files */
691     absPath = calloc(1, PATH_MAX + 1);
692     if (absPath == NULL) {
693         free(buf);
694         return (ENOMEM);
695     }
696     if (NULL == realpath(buf, absPath)) {
697         fprintf(stderr, "invalid path to executable: %d\n", errno);
698         fprintf(stderr, "make sure you are specifying the full path to the "
699             "file.\n");
700         free(absPath);
701         free(buf);
702         return (ENOENT);
703     }
704     free(buf);
706     pthread_mutex_lock(&dev->firmwareLock);
708     /*
709      * Check if an entry in syslink_firmware already exists for this core.
710      * If not, create one. Otherwise just update the firmware path.
711      */
712     for (i = 0; i < syslink_num_cores; i++) {
713         if (syslink_firmware[i].proc_id == procid) {
714             break;
715         }
716     }
717     if (i == syslink_num_cores) {
718         if (syslink_num_cores < MultiProc_MAXPROCESSORS) {
719             syslink_firmware[syslink_num_cores].proc =
720                 MultiProc_getName(procid);
721             syslink_firmware[syslink_num_cores].proc_id = procid;
722             syslink_firmware[syslink_num_cores].attachOnly = false;
723             syslink_firmware[syslink_num_cores].reload = false;
724             syslink_firmware[syslink_num_cores].procState = RESET_STATE;
725             syslink_firmware[syslink_num_cores].freeString = true;
726             syslink_firmware[syslink_num_cores++].firmware = absPath;
727         }
728         else {
729             pthread_mutex_unlock(&dev->firmwareLock);
730             free(absPath);
731             return (EBADSLT);
732         }
733     }
734     else {
735         /* Free previously allocated string */
736         if ((syslink_firmware[syslink_num_cores].freeString) &&
737            (syslink_firmware[syslink_num_cores].firmware)) {
738             free(syslink_firmware[i].firmware);
739         }
740         syslink_firmware[i].firmware = absPath;
741     }
743     pthread_mutex_unlock(&dev->firmwareLock);
745     if (msg->i.nbytes > 0) {
746         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
747     }
749     return (_RESMGR_NPARTS(0));
752 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
754     int         nbytes;
755     int         nparts;
756     int         status;
757     int         nleft;
758     uint32_t    len;
759     uint16_t    procid = ocb->ocb.attr->procid;
761     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
762         return (status);
764     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
765         return (ENOSYS);
767     /* check to see where the trace buffer is */
768     if (proc_traces[procid].va == NULL) {
769         return (ENOSYS);
770     }
771     if (ocb->ocb.offset == 0) {
772         ocb->widx = *(proc_traces[procid].widx);
773         ocb->ridx = *(proc_traces[procid].ridx);
774         *(proc_traces[procid].ridx) = ocb->widx;
775     }
777     /* Check for wrap-around */
778     if (ocb->widx < ocb->ridx)
779         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
780     else
781         len = ocb->widx - ocb->ridx;
783     /* Determine the amount left to print */
784     if (ocb->widx >= ocb->ridx)
785         nleft = len - ocb->ocb.offset;
786     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
787         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
788     else
789         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
791     nbytes = min (msg->i.nbytes, nleft);
793     /* Make sure the user has supplied a big enough buffer */
794     if (nbytes > 0) {
795         /* set up the return data IOV */
796         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
797             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
798         else
799             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
801         /* set up the number of bytes (returned by client's read()) */
802         _IO_SET_READ_NBYTES (ctp, nbytes);
804         ocb->ocb.offset += nbytes;
806         nparts = 1;
807     }
808     else {
809         _IO_SET_READ_NBYTES (ctp, 0);
811         /* reset offset */
812         ocb->ocb.offset = 0;
814         nparts = 0;
815     }
817     /* mark the access time as invalid (we just accessed it) */
819     if (msg->i.nbytes > 0)
820         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
822     return (_RESMGR_NPARTS (nparts));
825 extern OsalSemaphore_Handle mqcopy_test_sem;
827 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
829     int status = _RESMGR_NOREPLY;
830     struct _msg_info info;
832     /*
833      * Try to run the default unblock for this message.
834      */
835     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
836         return status;
837     }
839     /*
840      * Check if rcvid is still valid and still has an unblock
841      * request pending.
842      */
843     if (MsgInfo(ctp->rcvid, &info) == -1 ||
844         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
845         return _RESMGR_NOREPLY;
846     }
848     if (mqcopy_test_sem)
849         OsalSemaphore_post(mqcopy_test_sem);
851     return _RESMGR_NOREPLY;
854 IOFUNC_OCB_T *
855 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
857     syslink_ocb_t *ocb = NULL;
859     /* Allocate the OCB */
860     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
861     if (ocb == NULL){
862         errno = ENOMEM;
863         return (NULL);
864     }
866     ocb->pid = ctp->info.pid;
868     return (IOFUNC_OCB_T *)(ocb);
871 void
872 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
874     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
876     if (ocb) {
877 #ifndef SYSLINK_PLATFORM_VAYU
878         GateHWSpinlock_LeaveLockForPID(ocb->pid);
879 #endif
880         free (ocb);
881     }
884 int init_slave_devices(syslink_dev_t *dev)
886     resmgr_attr_t    resmgr_attr;
887     int              i;
888     syslink_attr_t * slave_attr;
889     int              status = 0;
891     memset(&resmgr_attr, 0, sizeof resmgr_attr);
892     resmgr_attr.nparts_max = 2;
893     resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
895     /* Populate the /dev/ipc-state namespace */
896     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
897         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_state[i],
898                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_state[i]);
899         slave_attr = &dev->syslink.cattr_slave[i];
900         iofunc_attr_init(&slave_attr->attr,
901                          S_IFCHR | 0777, NULL, NULL);
902         slave_attr->attr.mount = &dev->syslink.mattr;
903         slave_attr->procid = i;
904         slave_attr->dev = (Ptr)dev;
905         iofunc_time_update(&slave_attr->attr);
906         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
907                   "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
908         dev->syslink.iofuncs_state[i].read = slave_state_read;
909         dev->syslink.iofuncs_state[i].write = slave_state_write;
911         if (-1 == (dev->syslink.resmgr_id_state[i] =
912             resmgr_attach(dev->dpp, &resmgr_attr,
913                 dev->syslink.device_name, _FTYPE_ANY, 0,
914                 &dev->syslink.cfuncs_state[i],
915                 &dev->syslink.iofuncs_state[i],
916                 &slave_attr->attr))) {
917             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
918                 status, "resmgr_attach failed");
919             return (-1);
920         }
921     }
923     /* Populate the /dev/ipc-file namespace */
924     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
925         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_file[i],
926                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_file[i]);
927         slave_attr = &dev->syslink.cattr_slave[i];
928         iofunc_attr_init(&slave_attr->attr,
929                          S_IFCHR | 0777, NULL, NULL);
930         slave_attr->attr.mount = &dev->syslink.mattr;
931         slave_attr->procid = i;
932         slave_attr->dev = (Ptr)dev;
933         iofunc_time_update(&slave_attr->attr);
934         snprintf(dev->syslink.device_name, _POSIX_PATH_MAX,
935                   "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
936         dev->syslink.iofuncs_file[i].read = slave_file_read;
937         dev->syslink.iofuncs_file[i].write = slave_file_write;
939         if (-1 == (dev->syslink.resmgr_id_file[i] =
940             resmgr_attach(dev->dpp, &resmgr_attr,
941                 dev->syslink.device_name, _FTYPE_ANY, 0,
942                 &dev->syslink.cfuncs_file[i],
943                 &dev->syslink.iofuncs_file[i],
944                 &slave_attr->attr))) {
945             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
946                 status, "resmgr_attach failed");
947             return (-1);
948         }
949     }
951     return (status);
954 int deinit_slave_devices(syslink_dev_t *dev)
956     int status = EOK;
957     int i = 0;
959     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
960         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_state[i], 0);
961         if (status < 0) {
962             Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
963                 i, errno);
964         }
965         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_file[i], 0);
966         if (status < 0) {
967             Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
968                 i, errno);
969         }
970     }
972     return (status);
975 int init_syslink_trace_device(syslink_dev_t *dev)
977     resmgr_attr_t    resmgr_attr;
978     int              i;
979     syslink_attr_t * trace_attr;
980     char             trace_name[_POSIX_PATH_MAX];
981     int              status = 0;
982     unsigned int     da = 0, pa = 0;
983     unsigned int     len;
985     memset(&resmgr_attr, 0, sizeof resmgr_attr);
986     resmgr_attr.nparts_max = 10;
987     resmgr_attr.msg_max_size = 2048;
989     for (i = 0; i < syslink_num_cores; i++) {
990         /*
991          * Initialize trace device only for cores that are running and their
992          * device is not yet setup.
993          */
994         if ((syslink_firmware[i].procState == RUNNING_STATE) &&
995             (proc_traces[i].va == NULL)) {
996             iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
997                 &dev->syslink.cfuncs_trace[i],
998                 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
999             trace_attr = &dev->syslink.cattr_trace[i];
1000             iofunc_attr_init(&trace_attr->attr,
1001                          S_IFCHR | 0777, NULL, NULL);
1002             trace_attr->attr.mount = &dev->syslink.mattr;
1003             trace_attr->procid = i;
1004             iofunc_time_update(&trace_attr->attr);
1005             snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
1006                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
1007             dev->syslink.iofuncs_trace[i].read = syslink_read;
1008             snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
1009             pa = 0;
1010             status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE,
1011                 0, &da, &pa, &len);
1012             if (status == 0) {
1013                 /* last 8 bytes are for writeIdx/readIdx */
1014                 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1015                 if (da && !pa) {
1016                     /* need to translate da->pa */
1017                     status = ProcMgr_translateAddr(
1018                         procH[syslink_firmware[i].proc_id],
1019                         (Ptr *) &pa,
1020                         ProcMgr_AddrType_MasterPhys,
1021                         (Ptr) da,
1022                         ProcMgr_AddrType_SlaveVirt);
1023                 }
1024                 else {
1025                     GT_setFailureReason(curTrace, GT_4CLASS,
1026                         "init_syslink_trace_device",
1027                         status, "not performing ProcMgr_translate");
1028                 }
1029                 /* map length aligned to page size */
1030                 proc_traces[i].va =
1031                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1032                 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1033                                                proc_traces[i].len);
1034                 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1035                     + sizeof(uint32_t));
1036                 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1037                     GT_setFailureReason(curTrace, GT_4CLASS,
1038                         "init_syslink_trace_device",
1039                         status, "mmap_device_io failed");
1040                     GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1041                     proc_traces[i].va = NULL;
1042                 }
1043                 proc_traces[i].firstRead = TRUE;
1044             }
1045             else {
1046                 GT_setFailureReason(curTrace, GT_4CLASS,
1047                     "init_syslink_trace_device",
1048                     status, "RscTable_getInfo failed");
1049                 proc_traces[i].va = NULL;
1050             }
1051             if (-1 == (dev->syslink.resmgr_id_trace[i] =
1052                        resmgr_attach(dev->dpp, &resmgr_attr,
1053                                      dev->syslink.device_name, _FTYPE_ANY, 0,
1054                                      &dev->syslink.cfuncs_trace[i],
1055                                      &dev->syslink.iofuncs_trace[i],
1056                                      &trace_attr->attr))) {
1057                 GT_setFailureReason(curTrace, GT_4CLASS,
1058                     "init_syslink_trace_device",
1059                     status, "resmgr_attach failed");
1060                 return(-1);
1061             }
1062         }
1063     }
1065     return (status);
1068 int deinit_syslink_trace_device(syslink_dev_t *dev)
1070     int status = EOK;
1071     int i = 0;
1073     for (i = 0; i < syslink_num_cores; i++) {
1074         /* Only disable trace device on cores in RESET state */
1075         if ((syslink_firmware[i].procState == RESET_STATE) &&
1076             (proc_traces[i].va != NULL)) {
1077             status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i],
1078                 0);
1079             if (status < 0) {
1080                 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1081                     i, errno);
1082                 status = errno;
1083             }
1084             if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1085                 munmap((void *)proc_traces[i].va,
1086                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1087             }
1088             proc_traces[i].va = NULL;
1089         }
1090     }
1092     return (status);
1095 /* Initialize the syslink device */
1096 int init_syslink_device(syslink_dev_t *dev)
1098     iofunc_attr_t *  attr;
1099     resmgr_attr_t    resmgr_attr;
1100     int              status = 0;
1102     pthread_mutex_init(&dev->lock, NULL);
1103     pthread_mutex_init(&dev->firmwareLock, NULL);
1105     memset(&resmgr_attr, 0, sizeof resmgr_attr);
1106     resmgr_attr.nparts_max = 10;
1107     resmgr_attr.msg_max_size = 2048;
1109     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
1110     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
1111     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1112                               IOFUNC_PC_NO_TRUNC |
1113                               IOFUNC_PC_SYNC_IO;
1114     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
1116     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
1117     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1119     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
1120                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
1122     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
1124     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
1125     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
1126     dev->syslink.iofuncs.devctl = syslink_devctl;
1127     dev->syslink.iofuncs.unblock = syslink_unblock;
1129     attr->mount = &dev->syslink.mattr;
1130     iofunc_time_update(attr);
1132     if (-1 == (dev->syslink.resmgr_id =
1133         resmgr_attach(dev->dpp, &resmgr_attr,
1134                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1135                       &dev->syslink.cfuncs,
1136                       &dev->syslink.iofuncs, attr))) {
1137         return(-1);
1138     }
1140     status = init_slave_devices(dev);
1141     if (status < 0) {
1142         return status;
1143     }
1145     status = init_syslink_trace_device(dev);
1146     if (status < 0) {
1147         return status;
1148     }
1150     return(0);
1153 /* De-initialize the syslink device */
1154 int deinit_syslink_device(syslink_dev_t *dev)
1156     int status = EOK;
1158     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
1159     if (status < 0) {
1160         Osal_printf("IPC: resmgr_detach of %s failed: %d",
1161             IPC_DEVICE_PATH, errno);
1162         status = errno;
1163     }
1165     status = deinit_syslink_trace_device(dev);
1166     if (status < 0) {
1167         Osal_printf("IPC: deinit_syslink_trace_device failed %d", status);
1168     }
1170     status = deinit_slave_devices(dev);
1171     if (status < 0) {
1172         Osal_printf("IPC: deinit_slave_devices failed %d", status);
1173     }
1175     return(status);
1179 /* Initialize the devices */
1180 int init_devices(syslink_dev_t *dev)
1182     if (init_syslink_device(dev) < 0) {
1183         Osal_printf("IPC: device init failed");
1184         return(-1);
1185     }
1187     return(0);
1191 /* De-initialize the devices */
1192 int deinit_devices(syslink_dev_t *dev)
1194     int status = EOK;
1196     if ((status = deinit_syslink_device(dev)) < 0) {
1197         fprintf( stderr, "IPC: device de-init failed %d\n", status);
1198         status = errno;
1199     }
1201     return(status);
1204 static void ipc_recover(Ptr args)
1206     syslink_dev_t * dev = (syslink_dev_t *)args;
1208     if (!disableRecovery) {
1209         /* Protect the syslink_firmware array as we recover */
1210         pthread_mutex_lock(&dev->firmwareLock);
1211         deinit_ipc(dev, syslink_firmware, TRUE);
1212         deinit_syslink_trace_device(dev);
1213         init_ipc(dev, syslink_firmware, TRUE);
1214         init_syslink_trace_device(dev);
1215         pthread_mutex_unlock(&dev->firmwareLock);
1216     }
1217     else {
1218         GT_0trace(curTrace, GT_4CLASS,
1219                   "ipc_recover: Recovery disabled.\n");
1220     }
1223 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
1224                       ProcMgr_State fromState, ProcMgr_State toState,
1225                       ProcMgr_EventStatus status, Ptr args)
1227     Int ret = 0;
1228     String errString = NULL;
1229     syslink_dev_t * dev = (syslink_dev_t *)args;
1231     if (status == ProcMgr_EventStatus_Event) {
1232         switch (toState) {
1233             case ProcMgr_State_Mmu_Fault:
1234                 errString = "MMU Fault";
1235                 break;
1236             case ProcMgr_State_Error:
1237                 errString = "Exception";
1238                 break;
1239             case ProcMgr_State_Watchdog:
1240                 errString = "Watchdog";
1241                 break;
1242             default:
1243                 errString = "Unexpected State";
1244                 ret = -1;
1245                 break;
1246         }
1247         GT_2trace (curTrace, GT_4CLASS,
1248                    "syslink_error_cb: Received Error Callback for %s : %s\n",
1249                    MultiProc_getName(procId), errString);
1250         /* Don't allow re-schedule of recovery until complete */
1251         pthread_mutex_lock(&dev->lock);
1252         if (ret != -1 && dev->recover == FALSE) {
1253             /* Schedule recovery. */
1254             dev->recover = TRUE;
1255             /* Activate a thread to handle the recovery. */
1256             GT_0trace (curTrace, GT_4CLASS,
1257                        "syslink_error_cb: Scheduling recovery...");
1258             OsalThread_activate(dev->ipc_recovery_work);
1259         }
1260         else {
1261             GT_0trace (curTrace, GT_4CLASS,
1262                        "syslink_error_cb: Recovery already scheduled.");
1263         }
1264         pthread_mutex_unlock(&dev->lock);
1265     }
1266     else if (status == ProcMgr_EventStatus_Canceled) {
1267         GT_1trace (curTrace, GT_3CLASS,
1268                    "SysLink Error Callback Cancelled for %s",
1269                    MultiProc_getName(procId));
1270     }
1271     else {
1272         GT_1trace (curTrace, GT_4CLASS,
1273                    "SysLink Error Callback Unexpected Event for %s",
1274                    MultiProc_getName(procId));
1275     }
1277     return ret;
1280 /*
1281  * Initialize the syslink ipc
1282  *
1283  * This function sets up the "kernel"-side IPC modules, and does any special
1284  * initialization required for QNX and the platform being used.  This function
1285  * also registers for error notifications and initializes the recovery thread.
1286  */
1287 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
1289     int status = 0;
1290     Ipc_Config iCfg;
1291     OsalThread_Params threadParams;
1292     UInt16 procId;
1293     int i;
1295     if (status >= 0) {
1296         if (!recover) {
1297             /* Set up the MemoryOS module */
1298             status = MemoryOS_setup();
1299             if (status < 0)
1300                 goto memoryos_fail;
1301         }
1303         /* Setup IPC and platform-specific items */
1304         status = Ipc_setup (&iCfg);
1305         if (status < 0)
1306             goto ipcsetup_fail;
1308         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1309         if (!recover) {
1310             /* Setup Fault recovery items. */
1311             /* Create the thread object used for the interrupt handler. */
1312             threadParams.priority     = OsalThread_Priority_Medium;
1313             threadParams.priorityType = OsalThread_PriorityType_Generic;
1314             threadParams.once         = FALSE;
1315             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1316                                                         ipc_recover,
1317                                                         dev,
1318                                                         &threadParams);
1319             if (dev->ipc_recovery_work == NULL)
1320                 goto osalthreadcreate_fail;
1321         }
1322         else {
1323             pthread_mutex_lock(&dev->lock);
1324             dev->recover = FALSE;
1325             pthread_mutex_unlock(&dev->lock);
1326         }
1328         memset(procH_fileId, 0, sizeof(procH_fileId));
1330         for (i = 0; i < syslink_num_cores; i++) {
1331             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1332             if (procId >= MultiProc_MAXPROCESSORS) {
1333                 status = -1;
1334                 fprintf(stderr, "Invalid processor name specified\n");
1335                 break;
1336             }
1338             if (procH[procId]) {
1339                 GT_setFailureReason (curTrace,
1340                                      GT_4CLASS,
1341                                      "init_ipc",
1342                                      status,
1343                                      "invalid proc!");
1344                 break;
1345             }
1347             if (recover) {
1348                 /*
1349                  * if we are in recovery, we load the cores we previously
1350                  * attached to
1351                  */
1352                 firmware[i].attachOnly = false;
1353             }
1355             if ((!recover) || (firmware[i].reload)) {
1356                 status = runSlave(dev, procId, &firmware[i]);
1357                 if (status == 0) {
1358                     firmware[i].procState = RUNNING_STATE;
1359                     continue;
1360                 }
1361                 else {
1362                     break;
1363                 }
1364             }
1365             else {
1366                 /*
1367                  * During recovery, do not run cores unless they were previously
1368                  * running
1369                  */
1370                 continue;
1371             }
1372         }
1374         if (status < 0)
1375             goto tiipcsetup_fail;
1377         /* Set up rpmsg_mq */
1378         status = ti_ipc_setup();
1379         if (status < 0)
1380             goto tiipcsetup_fail;
1382         /* Set up rpmsg_rpc */
1383         status = rpmsg_rpc_setup();
1384         if (status < 0)
1385             goto rpcsetup_fail;
1387 #if defined(SYSLINK_PLATFORM_VAYU)
1388         if (gatempEnabled) {
1389             Int32 sr0ProcId;
1391             /* Set up NameServer for resource manager process */
1392             status = NameServer_setup();
1393             if (status < 0) {
1394                 goto nameserversetup_fail;
1395             }
1397             /* Set up GateMP */
1398             status = GateMP_setup(&sr0ProcId);
1399             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1400                 goto gatempsetup_fail;
1401             }
1402             else if (status == 0) {
1403                 sr0OwnerProcId = sr0ProcId;
1404             }
1405             else {
1406                 /*
1407                  * If we did not find the default gate, perhaps SR0 is
1408                  * not yet loaded. This is ok.
1409                  */
1410                 status = 0;
1411             }
1412         }
1413 #endif
1415         goto exit;
1416     }
1418 #if defined(SYSLINK_PLATFORM_VAYU)
1419 gatempsetup_fail:
1420     NameServer_destroy();
1421 nameserversetup_fail:
1422     rpmsg_rpc_destroy();
1423 #endif
1424 rpcsetup_fail:
1425     ti_ipc_destroy(recover);
1426 tiipcsetup_fail:
1427     for (i-=1; i >= 0; i--) {
1428         procId = firmware[i].proc_id;
1429         if (procId >= MultiProc_MAXPROCESSORS) {
1430             continue;
1431         }
1432         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
1433                                 (Ptr)dev, errStates);
1434         if (!firmware[i].attachOnly) {
1435             ProcMgr_stop(procH[procId]);
1436             if (procH_fileId[procId]) {
1437                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1438                 procH_fileId[procId] = 0;
1439             }
1440         }
1441         ProcMgr_detach(procH[procId]);
1442         ProcMgr_close(&procH[procId]);
1443         procH[procId] = NULL;
1444         RscTable_free(&rscHandle[procId]);
1445         rscHandle[procId] = NULL;
1446     }
1447     OsalThread_delete(&dev->ipc_recovery_work);
1448 osalthreadcreate_fail:
1449     Ipc_destroy();
1450 ipcsetup_fail:
1451     MemoryOS_destroy();
1452 memoryos_fail:
1453 exit:
1454     return status;
1457 int deinit_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware,
1458     bool recover)
1460     int status = EOK;
1461     uint32_t i = 0, id = 0;
1463     if (logFilename) {
1464         /* wait a little bit for traces to finish dumping */
1465         sleep(1);
1466     }
1468     // Stop the remote cores right away
1469     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1470         if (procH[i]) {
1471             resetSlave(dev, i);
1472         }
1473     }
1475 #if defined(SYSLINK_PLATFORM_VAYU)
1476     if (gatempEnabled) {
1477         GateMP_destroy(TRUE);
1479         NameServer_destroy();
1480     }
1481 #endif
1483     rpmsg_rpc_destroy();
1485     ti_ipc_destroy(recover);
1487     if (!recover && dev->ipc_recovery_work != NULL) {
1488         OsalThread_delete (&dev->ipc_recovery_work);
1489         dev->ipc_recovery_work = NULL;
1490     }
1492     if (recover) {
1493         static FILE *log = NULL;
1494         if (logFilename) {
1495             /* Dump the trace information */
1496             Osal_printf("IPC: printing remote core trace dump");
1497             log = fopen(logFilename, "a+");
1498             if (log) {
1499                 for (id = 0; id < syslink_num_cores; id++) {
1500                     if (firmware[id].procState == RUNNING_STATE) {
1501                         if (proc_traces[id].va) {
1502                             /* print traces */
1503                             fprintf(log, "*************************************\n");
1504                             fprintf(log, "***       CORE%d TRACE DUMP        ***\n",
1505                                 firmware[i].proc_id);
1506                             fprintf(log, "*************************************\n");
1507                             for (i = (*proc_traces[id].widx + 1);
1508                                 i < (proc_traces[id].len - 8);
1509                                 i++) {
1510                                 fprintf(log, "%c",
1511                                     *(char *)((uint32_t)proc_traces[id].va + i));
1512                             }
1513                             for (i = 0; i < *proc_traces[id].widx; i++) {
1514                                 fprintf(log, "%c",
1515                                     *(char *)((uint32_t)proc_traces[id].va + i));
1516                             }
1517                         }
1518                     }
1519                 }
1520                 fflush(log);
1521                 fclose(log);
1522             }
1523             else {
1524                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1525                     logFilename);
1526                 exit(EXIT_FAILURE);
1527             }
1528         }
1529     }
1531     /* After printing trace, set all processor states to RESET */
1532     for (id = 0; id < syslink_num_cores; id++) {
1533         firmware[id].procState = RESET_STATE;
1534     }
1536     status = Ipc_destroy();
1537     if (status < 0) {
1538         printf("Ipc_destroy() failed 0x%x", status);
1539     }
1540     if (!recover) {
1541         status = MemoryOS_destroy();
1542         if (status < 0) {
1543             printf("MemoryOS_destroy() failed 0x%x", status);
1544         }
1545     }
1547     return status;
1551 /** print usage */
1552 static Void printUsage (Char * app)
1554     printf("\n\nUsage:\n");
1555 #if defined(SYSLINK_PLATFORM_OMAP5430)
1556     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1557         app);
1558     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1559     printf("      followed by the path to the executable to load on that core.\n");
1560     printf("Options:\n");
1561     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1562         " Default: 1)\n");
1563     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1564         " 5000 ms)\n");
1565 #else
1566     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1567         app);
1568     printf("  <core_id#> should be set to a core name (e.g. DSP1, IPU2)\n");
1569     printf("      followed by the path to the executable to load on that core.\n");
1570     printf("Options:\n");
1571     printf("  -g   enable GateMP support on host\n");
1572 #endif
1573     printf("  -d   disable recovery\n");
1574     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1575     printf("              absolute path for filename)\n");
1576     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1577     printf("        and started. Perform late-attach to these cores.\n");
1579     exit (EXIT_SUCCESS);
1582 dispatch_t * syslink_dpp = NULL;
1584 int main(int argc, char *argv[])
1586     syslink_dev_t * dev = NULL;
1587     thread_pool_attr_t tattr;
1588     int status;
1589     int error = EOK;
1590     sigset_t set;
1591     int channelid = 0;
1592     int c;
1593     int hib_enable = 1;
1594     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1595     char *user_parm = NULL;
1596     struct stat          sbuf;
1597     int i = 0;
1598     char * abs_path = NULL;
1600     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1601         printf ("IPC Already Running...\n");
1602         return EXIT_FAILURE;
1603     }
1604     printf ("Starting IPC resource manager...\n");
1606     /* Parse the input args */
1607     while (1)
1608     {
1609         c = getopt (argc, argv, "H:T:U:gc:dv:a:");
1610         if (c == -1)
1611             break;
1613         switch (c)
1614         {
1615 #if defined(SYSLINK_PLATFORM_OMAP5430)
1616         case 'H':
1617             hib_enable = atoi(optarg);
1618             if (hib_enable != 0 && hib_enable != 1) {
1619                 hib_enable = -1;
1620             }
1621             break;
1622         case 'T':
1623             hib_timeout = atoi(optarg);
1624             break;
1625 #endif
1626         case 'U':
1627             user_parm = optarg;
1628             break;
1629         case 'd':
1630             disableRecovery = true;
1631             break;
1632         case 'c':
1633             logFilename = optarg;
1634             break;
1635         case 'a':
1636             numAttach = atoi(optarg);
1637             printf("Late-attaching to %d core(s)\n", numAttach);
1638             break;
1639         case 'v':
1640             verbosity++;
1641             break;
1642 #if defined(SYSLINK_PLATFORM_VAYU)
1643         case 'g':
1644             printf("GateMP support enabled on host\n");
1645             gatempEnabled = true;
1646             break;
1647 #endif
1648         default:
1649             fprintf (stderr, "Unrecognized argument\n");
1650         }
1651     }
1653     /* Now parse the operands, which should be in the format:
1654      * "<multiproc_name> <firmware_file> ..*/
1655     for (; optind + 1 < argc; optind+=2) {
1656         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1657             printUsage(argv[0]);
1658             return (error);
1659         }
1660         if (strcmp(argv[optind], INVALID_PROC) == 0) {
1661             fprintf (stderr, "Unsupported core specified\n");
1662             return (error);
1663         }
1665         syslink_firmware[syslink_num_cores].proc = argv [optind];
1666         syslink_firmware[syslink_num_cores].attachOnly =
1667             ((numAttach-- > 0) ? true : false);
1668         syslink_firmware[syslink_num_cores].reload = true;
1669         syslink_firmware[syslink_num_cores].freeString = false;
1670         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1671     }
1673     /* Validate hib_enable args */
1674     if (hib_enable == -1) {
1675         fprintf (stderr, "invalid hibernation enable value\n");
1676         printUsage(argv[0]);
1677         return (error);
1678     }
1680     syslink_hib_enable = (Bool)hib_enable;
1681     syslink_hib_timeout = hib_timeout;
1683     /* Init logging for syslink */
1684     if (Osal_initlogging(verbosity) != 0) {
1685         return -1;
1686     }
1688     /* Obtain I/O privity */
1689     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1690     if (error == -1) {
1691         Osal_printf("Unable to obtain I/O privity");
1692         return (error);
1693     }
1695     /* Get the abs path for all firmware files */
1696     for (i = 0; i < syslink_num_cores; i++) {
1697         abs_path = calloc(1, PATH_MAX + 1);
1698         if (abs_path == NULL) {
1699             return -1;
1700         }
1701         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1702             fprintf (stderr, "invalid path to executable\n");
1703             return -1;
1704         }
1705         syslink_firmware[i].firmware = abs_path;
1706     }
1708     /* allocate the device structure */
1709     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1710         Osal_printf("IPC: calloc() failed");
1711         return (-1);
1712     }
1714     /* create the channel */
1715     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1716                                     _NTO_CHF_DISCONNECT |
1717                                     _NTO_CHF_COID_DISCONNECT |
1718                                     _NTO_CHF_REPLY_LEN |
1719                                     _NTO_CHF_SENDER_LEN)) < 0) {
1720         Osal_printf("Unable to create channel %d", channelid);
1721         return (channelid);
1722     }
1724     /* create the dispatch structure */
1725     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1726         Osal_printf("IPC: dispatch_create() failed");
1727         return(-1);
1728     }
1730     /*
1731      * Mask out all signals before creating a thread pool.
1732      * This prevents other threads in the thread pool
1733      * from intercepting signals such as SIGTERM.
1734      */
1735     sigfillset(&set);
1736     pthread_sigmask(SIG_BLOCK, &set, NULL);
1738     /* Initialize the thread pool */
1739     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1740     tattr.handle = dev->dpp;
1741     tattr.context_alloc = dispatch_context_alloc;
1742     tattr.context_free = dispatch_context_free;
1743     tattr.block_func = dispatch_block;
1744     tattr.unblock_func = dispatch_unblock;
1745     tattr.handler_func = dispatch_handler;
1746     tattr.lo_water = 2;
1747     tattr.hi_water = 4;
1748     tattr.increment = 1;
1749     tattr.maximum = 10;
1751     /* Create the thread pool */
1752     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1753         Osal_printf("IPC: thread pool create failed");
1754         return(-1);
1755     }
1757     /* init syslink */
1758     status = init_ipc(dev, syslink_firmware, FALSE);
1759     if (status < 0) {
1760         Osal_printf("IPC: init failed");
1761         return(-1);
1762     }
1764     /* init the syslink device */
1765     status = init_devices(dev);
1766     if (status < 0) {
1767         Osal_printf("IPC: device init failed");
1768         return(-1);
1769     }
1771 #if (_NTO_VERSION >= 800)
1772     /* Relinquish privileges */
1773     status = procmgr_ability(  0,
1774                  DENY_ALL | PROCMGR_AID_SPAWN,
1775                  DENY_ALL | PROCMGR_AID_FORK,
1776                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1777                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1778                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1779                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1780                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1781                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1782                  (uint64_t)1, (uint64_t)~0,
1783                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1784                  (uint64_t)1, (uint64_t)~0,
1785                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1787     if (status != EOK) {
1788         Osal_printf("procmgr_ability failed! errno=%d", status);
1789         return EXIT_FAILURE;
1790     }
1792     /* Reduce priority to either what defined from command line or at least nobody */
1793     if (user_parm != NULL) {
1794         if (set_ids_from_arg(user_parm) < 0) {
1795             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1796             return EXIT_FAILURE;
1797         }
1798     } else {
1799         if (setuid(99) != 0) {
1800             Osal_printf("unable to set uid - %s", strerror(errno));
1801             return EXIT_FAILURE;
1802         }
1803     }
1804 #endif
1806     /* make this a daemon process */
1807     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1808         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1809         Osal_printf("IPC: procmgr_daemon() failed");
1810         return(-1);
1811     }
1813     /* start the thread pool */
1814     thread_pool_start(dev->tpool);
1816     /* Unmask signals to be caught */
1817     sigdelset (&set, SIGINT);
1818     sigdelset (&set, SIGTERM);
1819     pthread_sigmask (SIG_BLOCK, &set, NULL);
1821     /* Wait for one of these signals */
1822     sigemptyset (&set);
1823     sigaddset (&set, SIGINT);
1824     sigaddset (&set, SIGQUIT);
1825     sigaddset (&set, SIGTERM);
1827     Osal_printf("IPC resource manager started");
1829     /* Wait for a signal */
1830     while (1)
1831     {
1832         switch (SignalWaitinfo (&set, NULL))
1833         {
1834             case SIGTERM:
1835             case SIGQUIT:
1836             case SIGINT:
1837                 error = EOK;
1838                 goto done;
1840             default:
1841                 break;
1842         }
1843     }
1845     error = EOK;
1847 done:
1848     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1850     error = thread_pool_destroy(dev->tpool);
1851     if (error < 0) {
1852         Osal_printf("IPC: thread_pool_destroy returned an error");
1853     }
1854     deinit_ipc(dev, syslink_firmware, FALSE);
1855     deinit_devices(dev);
1856     free(dev);
1858     /* Free the abs path of firmware files if necessary */
1859     for (i = 0; i < syslink_num_cores; i++) {
1860         if ((syslink_firmware[i].freeString) &&
1861             (syslink_firmware[i].firmware)) {
1862             free(syslink_firmware[i].firmware);
1863         }
1864     }
1866     return (error);