376f146e0f712dea7c1ea612c3ae62ddea0b9f80
[ipc/ipcdev.git] / qnx / src / ipc3x_dev / ti / syslink / build / Qnx / resmgr / syslink_main.c
1 /*
2  *  @file       syslink_main.c
3  *
4  *  @brief      ipc main
5  *
6  *
7  *  @ver        02.00.00.46_alpha1
8  *
9  *  ============================================================================
10  *
11  *  Copyright (c) 2011-2015, 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(IPC_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(IPC_PLATFORM_VAYU)
100 static bool gatempEnabled = false;
101 static Int32 sr0OwnerProcId = -1;
102 #endif
104 // IPC hibernation global variables
105 Bool ipc_hib_enable = TRUE;
106 #if !defined(IPC_PLATFORM_OMAP5430)
107 #define PM_HIB_DEFAULT_TIME 5000
108 #endif
109 uint32_t ipc_hib_timeout = PM_HIB_DEFAULT_TIME;
110 Bool ipc_hib_hibernating = FALSE;
111 pthread_mutex_t ipc_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
112 pthread_cond_t ipc_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 ipc_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 } ipc_firmware_info;
128 static ipc_firmware_info ipc_firmware[MultiProc_MAXPROCESSORS];
130 /* Number of valid entries in ipc_firmware array */
131 static unsigned int ipc_num_cores = 0;
133 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
134     bool recover);
135 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
136     bool recover);
137 int init_ipc_trace_device(ipc_dev_t *dev);
138 int deinit_ipc_trace_device(ipc_dev_t *dev);
140 Int ipc_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\n",
158                                    "Running\n" };
160 typedef struct ipc_trace_info_t {
161     uintptr_t   va;
162     uint32_t    len;
163     uint32_t *  widx;
164     uint32_t *  ridx;
165     Bool        firstRead;
166 } ipc_trace_info;
168 static ipc_trace_info proc_traces[MultiProc_MAXPROCESSORS];
170 static int runSlave(ipc_dev_t *dev, uint16_t procId,
171     ipc_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                             "runSlave",
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                                 "runSlave",
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                              "runSlave",
224                              status,
225                              "Ipc_attach failed!");
226         goto ipcattach_fail;
227     }
229     status = ProcMgr_registerNotify(procH[procId], ipc_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                                 "runSlave",
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], ipc_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(ipc_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], ipc_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 /* Add firmware entry after IPC is setup */
300 static void addFirmware(uint16_t procId)
302     ipc_firmware[ipc_num_cores].proc =
303         MultiProc_getName(procId);
304     ipc_firmware[ipc_num_cores].proc_id = procId;
305     ipc_firmware[ipc_num_cores].attachOnly = false;
306     ipc_firmware[ipc_num_cores].reload = false;
307     ipc_firmware[ipc_num_cores].procState = RESET_STATE;
308     ipc_firmware[ipc_num_cores].freeString = false;
309     ipc_firmware[ipc_num_cores++].firmware = NULL;
311     return;
314 static int slave_state_read(resmgr_context_t *ctp, io_read_t *msg,
315     ipc_ocb_t *ocb)
317     int             nbytes;
318     int             nparts;
319     int             status;
320     int             nleft;
321     int             i;
322     uint16_t        procId = ocb->ocb.attr->procid;
323     ipc_dev_t * dev = ocb->ocb.attr->dev;
325     if ((status = iofunc_read_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
326         return (status);
327     }
329     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
330         return (ENOSYS);
331     }
333     pthread_mutex_lock(&dev->firmwareLock);
335     for (i = 0; i < ipc_num_cores; i++) {
336         if (ipc_firmware[i].proc_id == procId) {
337             break;
338         }
339     }
340     if (i == ipc_num_cores) {
341         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
342             addFirmware(procId);
343         }
344         else {
345             pthread_mutex_unlock(&dev->firmwareLock);
346             return (EBADSLT);
347         }
348     }
350     if (ocb->ocb.offset == 0) {
351         /* latch onto new state, so that we print out complete strings */
352         ipc_firmware[i].readProcState = ipc_firmware[i].procState;
353     }
355     nleft = strlen(procStateNames[ipc_firmware[i].readProcState])
356         - ocb->ocb.offset; /* the state is expressed in one byte */
357     nbytes = min(msg->i.nbytes, nleft);
359     /* Make sure the user has supplied a big enough buffer */
360     if (nbytes > 0) {
361         /* set up the return data IOV */
362         SETIOV(ctp->iov,
363             (char *)procStateNames[ipc_firmware[i].readProcState]
364             + ocb->ocb.offset, nbytes);
366         pthread_mutex_unlock(&dev->firmwareLock);
368         /* set up the number of bytes (returned by client's read()) */
369         _IO_SET_READ_NBYTES(ctp, nbytes);
371         ocb->ocb.offset += nbytes;
373         nparts = 1;
374     }
375     else {
376         pthread_mutex_unlock(&dev->firmwareLock);
378         _IO_SET_READ_NBYTES (ctp, 0);
380         /* reset offset */
381         ocb->ocb.offset = 0;
383         nparts = 0;
384     }
386     /* mark the access time as invalid (we just accessed it) */
388     if (msg->i.nbytes > 0) {
389         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
390     }
392     return (_RESMGR_NPARTS(nparts));
395 static int slave_state_write(resmgr_context_t *ctp, io_write_t *msg,
396     ipc_ocb_t *ocb)
398     int             status;
399     char *          buf;
400     uint16_t        procId = ocb->ocb.attr->procid;
401     int             i;
402     char *          ptr;
403     ipc_dev_t * dev = ocb->ocb.attr->dev;
404     Int32           sr0ProcId;
406     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
407         return (status);
408     }
410     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
411         return (ENOSYS);
412     }
414     /* set up the number of bytes (returned by client's write()) */
415     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
417     buf = (char *) malloc(msg->i.nbytes + 1);
418     if (buf == NULL) {
419         return (ENOMEM);
420     }
422     /*
423      *  Read the data from the sender's message buffer.
424      */
425     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
426     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
427     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
428         *ptr = '\0';
429     }
431     pthread_mutex_lock(&dev->firmwareLock);
432     for (i = 0; i < ipc_num_cores; i++) {
433         if (ipc_firmware[i].proc_id == procId) {
434             break;
435         }
436     }
437     if (i == ipc_num_cores) {
438         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
439             addFirmware(procId);
440         }
441         else {
442             pthread_mutex_unlock(&dev->firmwareLock);
443             return (EBADSLT);
444         }
445     }
447     if (strcmp("1", buf) == 0) {
448         if ((ipc_firmware[i].procState == RESET_STATE) &&
449            (ipc_firmware[i].firmware != NULL)) {
450             status = runSlave(ocb->ocb.attr->dev, procId, &ipc_firmware[i]);
451             if (status < 0) {
452                 pthread_mutex_unlock(&dev->firmwareLock);
453                 free(buf);
454                 fprintf(stderr, "IPC: failed to run slave core %s\n",
455                     MultiProc_getName(procId));
456                 return (EIO);
457             }
458 #if defined(IPC_PLATFORM_VAYU)
459             if (gatempEnabled) {
460                 if (sr0OwnerProcId == -1) {
461                     /* Set up GateMP */
462                     status = GateMP_setup(&sr0ProcId);
463                     if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
464                         resetSlave(ocb->ocb.attr->dev, procId);
465                         pthread_mutex_unlock(&dev->firmwareLock);
466                         free(buf);
467                         fprintf(stderr, "GateMP_setup failed\n");
468                         return (EIO);
469                     }
470                     else if (status == 0) {
471                         /* We have discovered an owner for SR0 */
472                         sr0OwnerProcId = sr0ProcId;
473                     }
474                 }
475                 else {
476                     /*
477                      * We have already identified SR0 owner and setup GateMP.
478                      * Do nothing.
479                      */
480                 }
481             }
482 #endif
483             printf("Core is now running with image '%s'\n",
484                 ipc_firmware[i].firmware);
485             ipc_firmware[i].procState = RUNNING_STATE;
486             ipc_firmware[i].reload = true;
487             status = init_ipc_trace_device(dev);
488             if (status < 0) {
489 #if defined(IPC_PLATFORM_VAYU)
490                 if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
491                     sr0OwnerProcId = -1;
492                     GateMP_destroy(FALSE);
493                 }
494 #endif
495                 resetSlave(ocb->ocb.attr->dev, procId);
496                 pthread_mutex_unlock(&dev->firmwareLock);
497                 free(buf);
498                 fprintf(stderr, "IPC: init_ipc_trace_device failed %d\n",
499                     status);
500                 return (EIO);
501             }
502             printf("Core %s has been started.\n", MultiProc_getName(procId));
503         }
504     }
505     else if (strcmp("0", buf) == 0) {
506         if (ipc_firmware[i].procState == RUNNING_STATE) {
507 #if defined(IPC_PLATFORM_VAYU)
508             if ((gatempEnabled) && (procId == sr0OwnerProcId)) {
509                 sr0OwnerProcId = -1;
510                 status = GateMP_destroy(FALSE);
511                 if (status < 0) {
512                     pthread_mutex_unlock(&dev->firmwareLock);
513                     free(buf);
514                     fprintf(stderr, "Core %s cannot be reset. GateMP may still"
515                         " be in use by host\n", MultiProc_getName(procId));
516                     return (EIO);
517                 }
518             }
519 #endif
520             status = resetSlave(ocb->ocb.attr->dev, procId);
521             if (status < 0) {
522                 pthread_mutex_unlock(&dev->firmwareLock);
523                 free(buf);
524                 fprintf(stderr, "IPC: failed to reset slave core %s\n",
525                     MultiProc_getName(procId));
526                 return (EIO);
527             }
528             ipc_firmware[i].procState = RESET_STATE;
529             ipc_firmware[i].reload = false;
530             status = deinit_ipc_trace_device(dev);
531             if (status < 0) {
532                 pthread_mutex_unlock(&dev->firmwareLock);
533                 free(buf);
534                 fprintf(stderr, "IPC: deinit_ipc_trace_device failed %d\n",
535                     status);
536                 return (EIO);
537             }
538             printf("Core %s has been reset.\n", MultiProc_getName(procId));
539         }
540     }
541     else {
542         /* ignore the input as it is not recognized */
543         fprintf(stderr, "Unrecognized input\n");
544     }
546     pthread_mutex_unlock(&dev->firmwareLock);
548     free(buf);
550     if (msg->i.nbytes > 0) {
551         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
552     }
554     return (_RESMGR_NPARTS(0));
557 static int slave_file_read(resmgr_context_t *ctp, io_read_t *msg,
558     ipc_ocb_t *ocb)
560     int             nbytes;
561     int             nparts;
562     int             status;
563     int             nleft;
564     int             i;
565     uint16_t        procId = ocb->ocb.attr->procid;
566     ipc_dev_t * dev = ocb->ocb.attr->dev;
568     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK) {
569         return (status);
570     }
572     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
573         return (ENOSYS);
574     }
576     pthread_mutex_lock(&dev->firmwareLock);
577     for (i = 0; i < ipc_num_cores; i++) {
578         if (ipc_firmware[i].proc_id == procId) {
579             break;
580         }
581     }
583     if (i == ipc_num_cores) {
584         if ((ipc_num_cores < MultiProc_MAXPROCESSORS)) {
585             addFirmware(procId);
586         }
587         else {
588             pthread_mutex_unlock(&dev->firmwareLock);
589             return (EBADSLT);
590         }
591     }
593     if (ipc_firmware[i].firmware == NULL) {
594         nbytes = 0;
595     }
596     else {
597         nleft = strlen(ipc_firmware[i].firmware)
598             - ocb->ocb.offset + 1; /* Add one byte for carriage return */
599         nbytes = min(msg->i.nbytes, nleft);
600     }
602     /* Make sure the user has supplied a big enough buffer */
603     if (nbytes > 0) {
604         if (nbytes == nleft) {
605             /* set up the return data IOV */
606             SETIOV(&ctp->iov[0], (char *)ipc_firmware[i].firmware
607                 + ocb->ocb.offset, nbytes - 1);
609             /* add a carriage return */
610             SETIOV(&ctp->iov[1], "\n", 1);
612             nparts = 2;
613         }
614         else {
615             /* set up the return data IOV */
616             SETIOV(ctp->iov, (char *)ipc_firmware[i].firmware
617                 + ocb->ocb.offset, nbytes);
619             nparts = 1;
620         }
622         /* set up the number of bytes (returned by client's read()) */
623         _IO_SET_READ_NBYTES(ctp, nbytes);
625         ocb->ocb.offset += nbytes;
626     }
627     else {
628         _IO_SET_READ_NBYTES (ctp, 0);
630         /* reset offset */
631         ocb->ocb.offset = 0;
633         nparts = 0;
634     }
636     pthread_mutex_unlock(&dev->firmwareLock);
638     /* mark the access time as invalid (we just accessed it) */
640     if (msg->i.nbytes > 0) {
641         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
642     }
644     return (_RESMGR_NPARTS(nparts));
647 static int slave_file_write(resmgr_context_t *ctp, io_write_t *msg,
648     ipc_ocb_t *ocb)
650     int             status;
651     char *          buf;
652     uint16_t        procId = ocb->ocb.attr->procid;
653     int             i;
654     char *          absPath;
655     char *          ptr;
656     ipc_dev_t * dev = ocb->ocb.attr->dev;
658     if ((status = iofunc_write_verify(ctp, msg, &ocb->ocb, NULL)) != EOK) {
659         return (status);
660     }
662     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE) {
663         return (ENOSYS);
664     }
666     /* set up the number of bytes (returned by client's write()) */
667     _IO_SET_WRITE_NBYTES (ctp, msg->i.nbytes);
669     buf = (char *) malloc(msg->i.nbytes + 1);
670     if (buf == NULL) {
671         return (ENOMEM);
672     }
674     /*
675      *  Read the data from the sender's message buffer.
676      */
677     resmgr_msgread(ctp, buf, msg->i.nbytes, sizeof(msg->i));
678     buf[msg->i.nbytes] = '\0'; /* just in case the text is not NULL terminated */
679     if((ptr = strchr(buf, '\n')) != NULL) { /* Remove line feed if any */
680         *ptr = '\0';
681     }
683     /* Get the abs path for all firmware files */
684     absPath = calloc(1, PATH_MAX + 1);
685     if (absPath == NULL) {
686         free(buf);
687         return (ENOMEM);
688     }
689     if (NULL == realpath(buf, absPath)) {
690         fprintf(stderr, "invalid path to executable: %d\n", errno);
691         fprintf(stderr, "make sure you are specifying the full path to the "
692             "file.\n");
693         free(absPath);
694         free(buf);
695         return (ENOENT);
696     }
697     free(buf);
699     pthread_mutex_lock(&dev->firmwareLock);
701     /*
702      * Check if an entry in ipc_firmware already exists for this core.
703      * If not, create one. Otherwise just update the firmware path.
704      */
705     for (i = 0; i < ipc_num_cores; i++) {
706         if (ipc_firmware[i].proc_id == procId) {
707             break;
708         }
709     }
710     if (i == ipc_num_cores) {
711         if (ipc_num_cores < MultiProc_MAXPROCESSORS) {
712             addFirmware(procId);
713             ipc_firmware[ipc_num_cores - 1].freeString = true;
714             ipc_firmware[ipc_num_cores - 1].firmware = absPath;
715         }
716         else {
717             pthread_mutex_unlock(&dev->firmwareLock);
718             free(absPath);
719             return (EBADSLT);
720         }
721     }
722     else {
723         /* Free previously allocated string */
724         if ((ipc_firmware[i].freeString) &&
725            (ipc_firmware[i].firmware)) {
726             free(ipc_firmware[i].firmware);
727         }
728         ipc_firmware[i].firmware = absPath;
729     }
731     pthread_mutex_unlock(&dev->firmwareLock);
733     if (msg->i.nbytes > 0) {
734         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_MTIME | IOFUNC_ATTR_CTIME;
735     }
737     return (_RESMGR_NPARTS(0));
740 int ipc_read(resmgr_context_t *ctp, io_read_t *msg, ipc_ocb_t *ocb)
742     int         nbytes;
743     int         nparts;
744     int         status;
745     int         nleft;
746     uint32_t    len;
747     uint16_t    procid = ocb->ocb.attr->procid;
749     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
750         return (status);
752     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
753         return (ENOSYS);
755     /* check to see where the trace buffer is */
756     if (proc_traces[procid].va == NULL) {
757         return (ENOSYS);
758     }
759     if (ocb->ocb.offset == 0) {
760         ocb->widx = *(proc_traces[procid].widx);
761         ocb->ridx = *(proc_traces[procid].ridx);
762         *(proc_traces[procid].ridx) = ocb->widx;
763     }
765     /* Check for wrap-around */
766     if (ocb->widx < ocb->ridx)
767         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
768     else
769         len = ocb->widx - ocb->ridx;
771     /* Determine the amount left to print */
772     if (ocb->widx >= ocb->ridx)
773         nleft = len - ocb->ocb.offset;
774     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
775         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
776     else
777         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
779     nbytes = min (msg->i.nbytes, nleft);
781     /* Make sure the user has supplied a big enough buffer */
782     if (nbytes > 0) {
783         /* set up the return data IOV */
784         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
785             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
786         else
787             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
789         /* set up the number of bytes (returned by client's read()) */
790         _IO_SET_READ_NBYTES (ctp, nbytes);
792         ocb->ocb.offset += nbytes;
794         nparts = 1;
795     }
796     else {
797         _IO_SET_READ_NBYTES (ctp, 0);
799         /* reset offset */
800         ocb->ocb.offset = 0;
802         nparts = 0;
803     }
805     /* mark the access time as invalid (we just accessed it) */
807     if (msg->i.nbytes > 0)
808         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
810     return (_RESMGR_NPARTS (nparts));
813 extern OsalSemaphore_Handle mqcopy_test_sem;
815 int ipc_unblock(resmgr_context_t *ctp, io_pulse_t *msg, ipc_ocb_t *ocb)
817     int status = _RESMGR_NOREPLY;
818     struct _msg_info info;
820     /*
821      * Try to run the default unblock for this message.
822      */
823     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
824         return status;
825     }
827     /*
828      * Check if rcvid is still valid and still has an unblock
829      * request pending.
830      */
831     if (MsgInfo(ctp->rcvid, &info) == -1 ||
832         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
833         return _RESMGR_NOREPLY;
834     }
836     if (mqcopy_test_sem)
837         OsalSemaphore_post(mqcopy_test_sem);
839     return _RESMGR_NOREPLY;
842 IOFUNC_OCB_T *
843 ipc_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
845     ipc_ocb_t *ocb = NULL;
847     /* Allocate the OCB */
848     ocb = (ipc_ocb_t *) calloc (1, sizeof (ipc_ocb_t));
849     if (ocb == NULL){
850         errno = ENOMEM;
851         return (NULL);
852     }
854     ocb->pid = ctp->info.pid;
856     return (IOFUNC_OCB_T *)(ocb);
859 void
860 ipc_ocb_free (IOFUNC_OCB_T * i_ocb)
862     ipc_ocb_t * ocb = (ipc_ocb_t *)i_ocb;
864     if (ocb) {
865 #ifndef IPC_PLATFORM_VAYU
866         GateHWSpinlock_LeaveLockForPID(ocb->pid);
867 #endif
868         free (ocb);
869     }
872 int init_slave_devices(ipc_dev_t *dev)
874     resmgr_attr_t    resmgr_attr;
875     int              i;
876     ipc_attr_t * slave_attr;
877     int              status = 0;
879     memset(&resmgr_attr, 0, sizeof resmgr_attr);
880     resmgr_attr.nparts_max = 2;
881     resmgr_attr.msg_max_size = _POSIX_PATH_MAX;
883     /* Populate the /dev/ipc-state namespace */
884     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
885         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_state[i],
886                          _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_state[i]);
887         slave_attr = &dev->ipc.cattr_slave[i];
888         iofunc_attr_init(&slave_attr->attr,
889                          S_IFCHR | 0777, NULL, NULL);
890         slave_attr->attr.mount = &dev->ipc.mattr;
891         slave_attr->procid = i;
892         slave_attr->dev = (Ptr)dev;
893         iofunc_time_update(&slave_attr->attr);
894         snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
895                   "%s-state/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
896         dev->ipc.iofuncs_state[i].read = slave_state_read;
897         dev->ipc.iofuncs_state[i].write = slave_state_write;
899         if (-1 == (dev->ipc.resmgr_id_state[i] =
900             resmgr_attach(dev->dpp, &resmgr_attr,
901                 dev->ipc.device_name, _FTYPE_ANY, 0,
902                 &dev->ipc.cfuncs_state[i],
903                 &dev->ipc.iofuncs_state[i],
904                 &slave_attr->attr))) {
905             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
906                 status, "resmgr_attach failed");
907             return (-1);
908         }
909     }
911     /* Populate the /dev/ipc-file namespace */
912     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
913         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs_file[i],
914                          _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_file[i]);
915         slave_attr = &dev->ipc.cattr_slave[i];
916         iofunc_attr_init(&slave_attr->attr,
917                          S_IFCHR | 0777, NULL, NULL);
918         slave_attr->attr.mount = &dev->ipc.mattr;
919         slave_attr->procid = i;
920         slave_attr->dev = (Ptr)dev;
921         iofunc_time_update(&slave_attr->attr);
922         snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
923                   "%s-file/%s", IPC_DEVICE_PATH, MultiProc_getName(i));
924         dev->ipc.iofuncs_file[i].read = slave_file_read;
925         dev->ipc.iofuncs_file[i].write = slave_file_write;
927         if (-1 == (dev->ipc.resmgr_id_file[i] =
928             resmgr_attach(dev->dpp, &resmgr_attr,
929                 dev->ipc.device_name, _FTYPE_ANY, 0,
930                 &dev->ipc.cfuncs_file[i],
931                 &dev->ipc.iofuncs_file[i],
932                 &slave_attr->attr))) {
933             GT_setFailureReason(curTrace, GT_4CLASS, "init_slave_devices",
934                 status, "resmgr_attach failed");
935             return (-1);
936         }
937     }
939     return (status);
942 int deinit_slave_devices(ipc_dev_t *dev)
944     int status = EOK;
945     int i = 0;
947     for (i = 1; i < MultiProc_getNumProcessors(); i++) {
948         status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_state[i], 0);
949         if (status < 0) {
950             Osal_printf("IPC: resmgr_detach of state device %d failed: %d",
951                 i, errno);
952         }
953         status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_file[i], 0);
954         if (status < 0) {
955             Osal_printf("IPC: resmgr_detach of file device %d failed: %d",
956                 i, errno);
957         }
958     }
960     return (status);
963 int init_ipc_trace_device(ipc_dev_t *dev)
965     resmgr_attr_t    resmgr_attr;
966     int              i;
967     ipc_attr_t * trace_attr;
968     char             trace_name[_POSIX_PATH_MAX];
969     int              status = 0;
970     unsigned int     da = 0, pa = 0;
971     unsigned int     len;
973     memset(&resmgr_attr, 0, sizeof resmgr_attr);
974     resmgr_attr.nparts_max = 10;
975     resmgr_attr.msg_max_size = 2048;
977     for (i = 0; i < ipc_num_cores; i++) {
978         /*
979          * Initialize trace device only for cores that are running and their
980          * device is not yet setup.
981          */
982         if ((ipc_firmware[i].procState == RUNNING_STATE) &&
983             (proc_traces[i].va == NULL)) {
984             iofunc_func_init(_RESMGR_CONNECT_NFUNCS,
985                 &dev->ipc.cfuncs_trace[i],
986                 _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs_trace[i]);
987             trace_attr = &dev->ipc.cattr_trace[i];
988             iofunc_attr_init(&trace_attr->attr,
989                          S_IFCHR | 0777, NULL, NULL);
990             trace_attr->attr.mount = &dev->ipc.mattr;
991             trace_attr->procid = i;
992             iofunc_time_update(&trace_attr->attr);
993             snprintf(dev->ipc.device_name, _POSIX_PATH_MAX,
994                 "%s-trace/%s", IPC_DEVICE_PATH,
995                 MultiProc_getName(ipc_firmware[i].proc_id));
996             dev->ipc.iofuncs_trace[i].read = ipc_read;
997             snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
998             pa = 0;
999             status = RscTable_getInfo(ipc_firmware[i].proc_id, TYPE_TRACE,
1000                 0, &da, &pa, &len);
1001             if (status == 0) {
1002                 /* last 8 bytes are for writeIdx/readIdx */
1003                 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
1004                 if (da && !pa) {
1005                     /* need to translate da->pa */
1006                     status = ProcMgr_translateAddr(
1007                         procH[ipc_firmware[i].proc_id],
1008                         (Ptr *) &pa,
1009                         ProcMgr_AddrType_MasterPhys,
1010                         (Ptr) da,
1011                         ProcMgr_AddrType_SlaveVirt);
1012                 }
1013                 else {
1014                     GT_setFailureReason(curTrace, GT_4CLASS,
1015                         "init_ipc_trace_device",
1016                         status, "not performing ProcMgr_translate");
1017                 }
1018                 /* map length aligned to page size */
1019                 proc_traces[i].va =
1020                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
1021                 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
1022                                                proc_traces[i].len);
1023                 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx
1024                     + sizeof(uint32_t));
1025                 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
1026                     GT_setFailureReason(curTrace, GT_4CLASS,
1027                         "init_ipc_trace_device",
1028                         status, "mmap_device_io failed");
1029                     GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
1030                     proc_traces[i].va = NULL;
1031                 }
1032                 proc_traces[i].firstRead = TRUE;
1033             }
1034             else {
1035                 GT_setFailureReason(curTrace, GT_4CLASS,
1036                     "init_ipc_trace_device",
1037                     status, "RscTable_getInfo failed");
1038                 proc_traces[i].va = NULL;
1039             }
1040             if (-1 == (dev->ipc.resmgr_id_trace[i] =
1041                        resmgr_attach(dev->dpp, &resmgr_attr,
1042                                      dev->ipc.device_name, _FTYPE_ANY, 0,
1043                                      &dev->ipc.cfuncs_trace[i],
1044                                      &dev->ipc.iofuncs_trace[i],
1045                                      &trace_attr->attr))) {
1046                 GT_setFailureReason(curTrace, GT_4CLASS,
1047                     "init_ipc_trace_device",
1048                     status, "resmgr_attach failed");
1049                 return(-1);
1050             }
1051         }
1052     }
1054     return (status);
1057 int deinit_ipc_trace_device(ipc_dev_t *dev)
1059     int status = EOK;
1060     int i = 0;
1062     for (i = 0; i < ipc_num_cores; i++) {
1063         /* Only disable trace device on cores in RESET state */
1064         if ((ipc_firmware[i].procState == RESET_STATE) &&
1065             (proc_traces[i].va != NULL)) {
1066             status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id_trace[i],
1067                 0);
1068             if (status < 0) {
1069                 Osal_printf("IPC: resmgr_detach of trace device %d failed: %d",
1070                     i, errno);
1071                 status = errno;
1072             }
1073             if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
1074                 munmap((void *)proc_traces[i].va,
1075                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
1076             }
1077             proc_traces[i].va = NULL;
1078         }
1079     }
1081     return (status);
1084 /* Initialize the ipc device */
1085 int init_ipc_device(ipc_dev_t *dev)
1087     iofunc_attr_t *  attr;
1088     resmgr_attr_t    resmgr_attr;
1089     int              status = 0;
1091     pthread_mutex_init(&dev->lock, NULL);
1092     pthread_mutex_init(&dev->firmwareLock, NULL);
1094     memset(&resmgr_attr, 0, sizeof resmgr_attr);
1095     resmgr_attr.nparts_max = 10;
1096     resmgr_attr.msg_max_size = 2048;
1098     memset(&dev->ipc.mattr, 0, sizeof(iofunc_mount_t));
1099     dev->ipc.mattr.flags = ST_NOSUID | ST_NOEXEC;
1100     dev->ipc.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
1101                               IOFUNC_PC_NO_TRUNC |
1102                               IOFUNC_PC_SYNC_IO;
1103     dev->ipc.mattr.funcs = &dev->ipc.mfuncs;
1105     memset(&dev->ipc.mfuncs, 0, sizeof(iofunc_funcs_t));
1106     dev->ipc.mfuncs.nfuncs = _IOFUNC_NFUNCS;
1108     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->ipc.cfuncs,
1109                     _RESMGR_IO_NFUNCS, &dev->ipc.iofuncs);
1111     iofunc_attr_init(attr = &dev->ipc.cattr, S_IFCHR | 0777, NULL, NULL);
1113     dev->ipc.mfuncs.ocb_calloc = ipc_ocb_calloc;
1114     dev->ipc.mfuncs.ocb_free = ipc_ocb_free;
1115     dev->ipc.iofuncs.devctl = ipc_devctl;
1116     dev->ipc.iofuncs.unblock = ipc_unblock;
1118     attr->mount = &dev->ipc.mattr;
1119     iofunc_time_update(attr);
1121     if (-1 == (dev->ipc.resmgr_id =
1122         resmgr_attach(dev->dpp, &resmgr_attr,
1123                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
1124                       &dev->ipc.cfuncs,
1125                       &dev->ipc.iofuncs, attr))) {
1126         return(-1);
1127     }
1129     status = init_slave_devices(dev);
1130     if (status < 0) {
1131         return status;
1132     }
1134     status = init_ipc_trace_device(dev);
1135     if (status < 0) {
1136         return status;
1137     }
1139     return(0);
1142 /* De-initialize the ipc device */
1143 int deinit_ipc_device(ipc_dev_t *dev)
1145     int status = EOK;
1147     status = resmgr_detach(dev->dpp, dev->ipc.resmgr_id, 0);
1148     if (status < 0) {
1149         Osal_printf("IPC: resmgr_detach of %s failed: %d",
1150             IPC_DEVICE_PATH, errno);
1151         status = errno;
1152     }
1154     status = deinit_ipc_trace_device(dev);
1155     if (status < 0) {
1156         Osal_printf("IPC: deinit_ipc_trace_device failed %d", status);
1157     }
1159     status = deinit_slave_devices(dev);
1160     if (status < 0) {
1161         Osal_printf("IPC: deinit_slave_devices failed %d", status);
1162     }
1164     pthread_mutex_destroy(&dev->lock);
1165     pthread_mutex_destroy(&dev->firmwareLock);
1167     return(status);
1171 /* Initialize the devices */
1172 int init_devices(ipc_dev_t *dev)
1174     if (init_ipc_device(dev) < 0) {
1175         Osal_printf("IPC: device init failed");
1176         return(-1);
1177     }
1179     return(0);
1183 /* De-initialize the devices */
1184 int deinit_devices(ipc_dev_t *dev)
1186     int status = EOK;
1188     if ((status = deinit_ipc_device(dev)) < 0) {
1189         fprintf( stderr, "IPC: device de-init failed %d\n", status);
1190         status = errno;
1191     }
1193     return(status);
1196 static void ipc_recover(Ptr args)
1198     ipc_dev_t * dev = (ipc_dev_t *)args;
1200     if (!disableRecovery) {
1201         /* Protect the ipc_firmware array as we recover */
1202         pthread_mutex_lock(&dev->firmwareLock);
1203         deinit_ipc(dev, ipc_firmware, TRUE);
1204         deinit_ipc_trace_device(dev);
1205         init_ipc(dev, ipc_firmware, TRUE);
1206         init_ipc_trace_device(dev);
1207         pthread_mutex_unlock(&dev->firmwareLock);
1208     }
1209     else {
1210         GT_0trace(curTrace, GT_4CLASS,
1211                   "ipc_recover: Recovery disabled.\n");
1212     }
1215 Int ipc_error_cb (UInt16 procId, ProcMgr_Handle handle,
1216                       ProcMgr_State fromState, ProcMgr_State toState,
1217                       ProcMgr_EventStatus status, Ptr args)
1219     Int ret = 0;
1220     String errString = NULL;
1221     ipc_dev_t * dev = (ipc_dev_t *)args;
1223     if (status == ProcMgr_EventStatus_Event) {
1224         switch (toState) {
1225             case ProcMgr_State_Mmu_Fault:
1226                 errString = "MMU Fault";
1227                 break;
1228             case ProcMgr_State_Error:
1229                 errString = "Exception";
1230                 break;
1231             case ProcMgr_State_Watchdog:
1232                 errString = "Watchdog";
1233                 break;
1234             default:
1235                 errString = "Unexpected State";
1236                 ret = -1;
1237                 break;
1238         }
1239         GT_2trace (curTrace, GT_4CLASS,
1240                    "ipc_error_cb: Received Error Callback for %s : %s\n",
1241                    MultiProc_getName(procId), errString);
1242         /* Don't allow re-schedule of recovery until complete */
1243         pthread_mutex_lock(&dev->lock);
1244         if (ret != -1 && dev->recover == FALSE) {
1245             /* Schedule recovery. */
1246             dev->recover = TRUE;
1247             /* Activate a thread to handle the recovery. */
1248             GT_0trace (curTrace, GT_4CLASS,
1249                        "ipc_error_cb: Scheduling recovery...");
1250             OsalThread_activate(dev->ipc_recovery_work);
1251         }
1252         else {
1253             GT_0trace (curTrace, GT_4CLASS,
1254                        "ipc_error_cb: Recovery already scheduled.");
1255         }
1256         pthread_mutex_unlock(&dev->lock);
1257     }
1258     else if (status == ProcMgr_EventStatus_Canceled) {
1259         GT_1trace (curTrace, GT_3CLASS,
1260                    "Ipc Error Callback Cancelled for %s",
1261                    MultiProc_getName(procId));
1262     }
1263     else {
1264         GT_1trace (curTrace, GT_4CLASS,
1265                    "Ipc Error Callback Unexpected Event for %s",
1266                    MultiProc_getName(procId));
1267     }
1269     return ret;
1272 /*
1273  * Initialize ipc
1274  *
1275  * This function sets up the "kernel"-side IPC modules, and does any special
1276  * initialization required for QNX and the platform being used.  This function
1277  * also registers for error notifications and initializes the recovery thread.
1278  */
1279 int init_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware, bool recover)
1281     int status = 0;
1282     Ipc_Config iCfg;
1283     OsalThread_Params threadParams;
1284     UInt16 procId;
1285     int i;
1287     if (status >= 0) {
1288         if (!recover) {
1289             /* Set up the MemoryOS module */
1290             status = MemoryOS_setup();
1291             if (status < 0)
1292                 goto memoryos_fail;
1293         }
1295         /* Setup IPC and platform-specific items */
1296         status = Ipc_setup (&iCfg);
1297         if (status < 0)
1298             goto ipcsetup_fail;
1300         /* NOTE: this is for handling the procmgr event notifications to userspace list */
1301         if (!recover) {
1302             /* Setup Fault recovery items. */
1303             /* Create the thread object used for the interrupt handler. */
1304             threadParams.priority     = OsalThread_Priority_Medium;
1305             threadParams.priorityType = OsalThread_PriorityType_Generic;
1306             threadParams.once         = FALSE;
1307             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
1308                                                         ipc_recover,
1309                                                         dev,
1310                                                         &threadParams);
1311             if (dev->ipc_recovery_work == NULL)
1312                 goto osalthreadcreate_fail;
1313         }
1314         else {
1315             pthread_mutex_lock(&dev->lock);
1316             dev->recover = FALSE;
1317             pthread_mutex_unlock(&dev->lock);
1318         }
1320         memset(procH_fileId, 0, sizeof(procH_fileId));
1322         for (i = 0; i < ipc_num_cores; i++) {
1323             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
1324             if (procId >= MultiProc_MAXPROCESSORS) {
1325                 status = -1;
1326                 fprintf(stderr, "Invalid processor name specified\n");
1327                 break;
1328             }
1330             if (procH[procId]) {
1331                 GT_setFailureReason (curTrace,
1332                                      GT_4CLASS,
1333                                      "init_ipc",
1334                                      status,
1335                                      "invalid proc!");
1336                 break;
1337             }
1339             if (recover) {
1340                 /*
1341                  * if we are in recovery, we load the cores we previously
1342                  * attached to
1343                  */
1344                 firmware[i].attachOnly = false;
1345             }
1347             if ((!recover) || (firmware[i].reload)) {
1348                 status = runSlave(dev, procId, &firmware[i]);
1349                 if (status == 0) {
1350                     firmware[i].procState = RUNNING_STATE;
1351                     continue;
1352                 }
1353                 else {
1354                     fprintf(stderr, "Failed to run core %s\n",
1355                         MultiProc_getName(procId));
1356                     break;
1357                 }
1358             }
1359             else {
1360                 /*
1361                  * During recovery, do not run cores unless they were previously
1362                  * running
1363                  */
1364                 continue;
1365             }
1366         }
1368         if (status < 0)
1369             goto tiipcsetup_fail;
1371         /* Set up rpmsg_mq */
1372         status = ti_ipc_setup();
1373         if (status < 0)
1374             goto tiipcsetup_fail;
1376         /* Set up rpmsg_rpc */
1377         status = rpmsg_rpc_setup();
1378         if (status < 0)
1379             goto rpcsetup_fail;
1381 #if defined(IPC_PLATFORM_VAYU)
1382         if (gatempEnabled) {
1383             Int32 sr0ProcId;
1385             /* Set up NameServer for resource manager process */
1386             status = NameServer_setup();
1387             if (status < 0) {
1388                 goto nameserversetup_fail;
1389             }
1391             /* Set up GateMP */
1392             status = GateMP_setup(&sr0ProcId);
1393             if ((status < 0) && (status != GateMP_E_NOTFOUND)) {
1394                 goto gatempsetup_fail;
1395             }
1396             else if (status == 0) {
1397                 sr0OwnerProcId = sr0ProcId;
1398             }
1399             else {
1400                 /*
1401                  * If we did not find the default gate, perhaps SR0 is
1402                  * not yet loaded. This is ok.
1403                  */
1404                 status = 0;
1405             }
1406         }
1407 #endif
1409         goto exit;
1410     }
1412 #if defined(IPC_PLATFORM_VAYU)
1413 gatempsetup_fail:
1414     NameServer_destroy();
1415 nameserversetup_fail:
1416     rpmsg_rpc_destroy();
1417 #endif
1418 rpcsetup_fail:
1419     ti_ipc_destroy(recover);
1420 tiipcsetup_fail:
1421     for (i-=1; i >= 0; i--) {
1422         procId = firmware[i].proc_id;
1423         if (procId >= MultiProc_MAXPROCESSORS) {
1424             continue;
1425         }
1426         ProcMgr_unregisterNotify(procH[procId], ipc_error_cb,
1427                                 (Ptr)dev, errStates);
1428         if (!firmware[i].attachOnly) {
1429             ProcMgr_stop(procH[procId]);
1430             if (procH_fileId[procId]) {
1431                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
1432                 procH_fileId[procId] = 0;
1433             }
1434         }
1435         ProcMgr_detach(procH[procId]);
1436         ProcMgr_close(&procH[procId]);
1437         procH[procId] = NULL;
1438         RscTable_free(&rscHandle[procId]);
1439         rscHandle[procId] = NULL;
1440     }
1441     OsalThread_delete(&dev->ipc_recovery_work);
1442 osalthreadcreate_fail:
1443     Ipc_destroy();
1444 ipcsetup_fail:
1445     MemoryOS_destroy();
1446 memoryos_fail:
1447 exit:
1448     return status;
1451 int deinit_ipc(ipc_dev_t * dev, ipc_firmware_info * firmware,
1452     bool recover)
1454     int status = EOK;
1455     uint32_t i = 0, id = 0;
1457     if (logFilename) {
1458         /* wait a little bit for traces to finish dumping */
1459         sleep(1);
1460     }
1462     // Stop the remote cores right away
1463     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
1464         if (procH[i]) {
1465             resetSlave(dev, i);
1466         }
1467     }
1469 #if defined(IPC_PLATFORM_VAYU)
1470     if (gatempEnabled) {
1471         GateMP_destroy(TRUE);
1473         NameServer_destroy();
1474     }
1475 #endif
1477     rpmsg_rpc_destroy();
1479     ti_ipc_destroy(recover);
1481     if (!recover && dev->ipc_recovery_work != NULL) {
1482         OsalThread_delete (&dev->ipc_recovery_work);
1483         dev->ipc_recovery_work = NULL;
1484     }
1486     if (recover) {
1487         static FILE *log = NULL;
1488         if (logFilename) {
1489             /* Dump the trace information */
1490             Osal_printf("IPC: printing remote core trace dump");
1491             log = fopen(logFilename, "a+");
1492             if (log) {
1493                 for (id = 0; id < ipc_num_cores; id++) {
1494                     if (firmware[id].procState == RUNNING_STATE) {
1495                         if (proc_traces[id].va) {
1496                             /* print traces */
1497                             fprintf(log, "*************************************\n");
1498                             fprintf(log, "***        %s TRACE DUMP        ***\n",
1499                                 firmware[id].proc);
1500                             fprintf(log, "*************************************\n");
1501                             for (i = (*proc_traces[id].widx + 1);
1502                                 i < (proc_traces[id].len - 8);
1503                                 i++) {
1504                                 fprintf(log, "%c",
1505                                     *(char *)((uint32_t)proc_traces[id].va + i));
1506                             }
1507                             for (i = 0; (i < *proc_traces[id].widx) && (i < proc_traces[id].len - 8); i++) {
1508                                 fprintf(log, "%c",
1509                                     *(char *)((uint32_t)proc_traces[id].va + i));
1510                             }
1511                         }
1512                     }
1513                 }
1514                 fflush(log);
1515                 fclose(log);
1516             }
1517             else {
1518                 fprintf(stderr, "\nERROR: unable to open crash dump file %s\n",
1519                     logFilename);
1520                 exit(EXIT_FAILURE);
1521             }
1522         }
1523     }
1525     /* After printing trace, set all processor states to RESET */
1526     for (id = 0; id < ipc_num_cores; id++) {
1527         firmware[id].procState = RESET_STATE;
1528     }
1530     status = Ipc_destroy();
1531     if (status < 0) {
1532         printf("Ipc_destroy() failed 0x%x", status);
1533     }
1534     if (!recover) {
1535         status = MemoryOS_destroy();
1536         if (status < 0) {
1537             printf("MemoryOS_destroy() failed 0x%x", status);
1538         }
1539     }
1541     return status;
1545 /** print usage */
1546 static Void printUsage (Char * app)
1548     printf("\n\nUsage:\n");
1549 #if defined(IPC_PLATFORM_OMAP5430)
1550     printf("\n%s: [-HTdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1551         app);
1552     printf("  <core_id#> should be set to a core name (e.g. IPU, DSP)\n");
1553     printf("      followed by the path to the executable to load on that core.\n");
1554     printf("Options:\n");
1555     printf("  -H <arg>    enable/disable hibernation, 1: ON, 0: OFF,"
1556         " Default: 1)\n");
1557     printf("  -T <arg>    specify the hibernation timeout in ms, Default:"
1558         " 5000 ms)\n");
1559 #else
1560     printf("\n%s: [-gdca] <core_id1> <executable1> [<core_id2> <executable2> ...]\n",
1561         app);
1562     printf("  <core_id#> should be set to a core name (e.g. DSP1, DSP2, IPU1, IPU2)\n");
1563     printf("      followed by the path to the executable to load on that core.\n");
1564     printf("Options:\n");
1565     printf("  -g   enable GateMP support on host\n");
1566 #endif
1567     printf("  -d   disable recovery\n");
1568     printf("  -c <file>   generate dump of slave trace during crashes (use\n");
1569     printf("              absolute path for filename)\n");
1570     printf("  -a<n> specify that the first n cores have been pre-loaded\n");
1571     printf("        and started. Perform late-attach to these cores.\n");
1573     exit (EXIT_SUCCESS);
1576 dispatch_t * ipc_dpp = NULL;
1578 int main(int argc, char *argv[])
1580     ipc_dev_t * dev = NULL;
1581     thread_pool_attr_t tattr;
1582     int status;
1583     int error = EOK;
1584     sigset_t set;
1585     int channelid = 0;
1586     int c;
1587     int hib_enable = 1;
1588     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1589     struct stat          sbuf;
1590     int i = 0;
1591     char * abs_path = NULL;
1593     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1594         printf ("IPC Already Running...\n");
1595         return EXIT_FAILURE;
1596     }
1597     printf ("Starting IPC resource manager...\n");
1599     /* Parse the input args */
1600     while (1)
1601     {
1602         c = getopt (argc, argv, "H:T:gc:dv:a:");
1603         if (c == -1)
1604             break;
1606         switch (c)
1607         {
1608 #if defined(IPC_PLATFORM_OMAP5430)
1609         case 'H':
1610             hib_enable = atoi(optarg);
1611             if (hib_enable != 0 && hib_enable != 1) {
1612                 hib_enable = -1;
1613             }
1614             break;
1615         case 'T':
1616             hib_timeout = atoi(optarg);
1617             break;
1618 #endif
1619         case 'd':
1620             disableRecovery = true;
1621             break;
1622         case 'c':
1623             logFilename = optarg;
1624             break;
1625         case 'a':
1626             numAttach = atoi(optarg);
1627             printf("Late-attaching to %d core(s)\n", numAttach);
1628             break;
1629         case 'v':
1630             verbosity++;
1631             break;
1632 #if defined(IPC_PLATFORM_VAYU)
1633         case 'g':
1634             printf("GateMP support enabled on host\n");
1635             gatempEnabled = true;
1636             break;
1637 #endif
1638         default:
1639             fprintf (stderr, "Unrecognized argument\n");
1640         }
1641     }
1643     /* Now parse the operands, which should be in the format:
1644      * "<multiproc_name> <firmware_file> ..*/
1645     for (; optind + 1 < argc; optind+=2) {
1646         if (ipc_num_cores == MultiProc_MAXPROCESSORS) {
1647             printUsage(argv[0]);
1648             return (error);
1649         }
1651         ipc_firmware[ipc_num_cores].proc = argv [optind];
1652         ipc_firmware[ipc_num_cores].attachOnly =
1653             ((numAttach-- > 0) ? true : false);
1654         ipc_firmware[ipc_num_cores].reload = true;
1655         ipc_firmware[ipc_num_cores].freeString = false;
1656         ipc_firmware[ipc_num_cores++].firmware = argv [optind+1];
1657     }
1659     /* Validate hib_enable args */
1660     if (hib_enable == -1) {
1661         fprintf (stderr, "invalid hibernation enable value\n");
1662         printUsage(argv[0]);
1663         return (error);
1664     }
1666     ipc_hib_enable = (Bool)hib_enable;
1667     ipc_hib_timeout = hib_timeout;
1669     /* Init logging for ipc */
1670     if (Osal_initlogging(verbosity) != 0) {
1671         return -1;
1672     }
1674     /* Obtain I/O privity */
1675     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1676     if (error == -1) {
1677         Osal_printf("Unable to obtain I/O privity");
1678         return (error);
1679     }
1681     /* Get the abs path for all firmware files */
1682     for (i = 0; i < ipc_num_cores; i++) {
1683         abs_path = calloc(1, PATH_MAX + 1);
1684         if (abs_path == NULL) {
1685             return -1;
1686         }
1687         if (NULL == realpath(ipc_firmware[i].firmware, abs_path)) {
1688             fprintf (stderr, "invalid path to executable\n");
1689             return -1;
1690         }
1691         ipc_firmware[i].firmware = abs_path;
1692     }
1694     /* allocate the device structure */
1695     if (NULL == (dev = calloc(1, sizeof(ipc_dev_t)))) {
1696         Osal_printf("IPC: calloc() failed");
1697         return (-1);
1698     }
1700     /* create the channel */
1701     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1702                                     _NTO_CHF_DISCONNECT |
1703                                     _NTO_CHF_COID_DISCONNECT |
1704                                     _NTO_CHF_REPLY_LEN |
1705                                     _NTO_CHF_SENDER_LEN)) < 0) {
1706         Osal_printf("Unable to create channel %d", channelid);
1707         return (channelid);
1708     }
1710     /* create the dispatch structure */
1711     if (NULL == (dev->dpp = ipc_dpp = dispatch_create_channel (channelid, 0))) {
1712         Osal_printf("IPC: dispatch_create() failed");
1713         return(-1);
1714     }
1716     /*
1717      * Mask out all signals before creating a thread pool.
1718      * This prevents other threads in the thread pool
1719      * from intercepting signals such as SIGTERM.
1720      */
1721     sigfillset(&set);
1722     pthread_sigmask(SIG_BLOCK, &set, NULL);
1724     /* Initialize the thread pool */
1725     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1726     tattr.handle = dev->dpp;
1727     tattr.context_alloc = dispatch_context_alloc;
1728     tattr.context_free = dispatch_context_free;
1729     tattr.block_func = dispatch_block;
1730     tattr.unblock_func = dispatch_unblock;
1731     tattr.handler_func = dispatch_handler;
1732     tattr.lo_water = 2;
1733     tattr.hi_water = 4;
1734     tattr.increment = 1;
1735     tattr.maximum = 10;
1737     /* Create the thread pool */
1738     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1739         Osal_printf("IPC: thread pool create failed");
1740         return(-1);
1741     }
1743     /* init ipc */
1744     status = init_ipc(dev, ipc_firmware, FALSE);
1745     if (status < 0) {
1746         Osal_printf("IPC: init failed");
1747         return(-1);
1748     }
1750     /* init the ipc device */
1751     status = init_devices(dev);
1752     if (status < 0) {
1753         Osal_printf("IPC: device init failed");
1754         return(-1);
1755     }
1757     /* make this a daemon process */
1758     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1759         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1760         Osal_printf("IPC: procmgr_daemon() failed");
1761         return(-1);
1762     }
1764     /* start the thread pool */
1765     thread_pool_start(dev->tpool);
1767     /* Unmask signals to be caught */
1768     sigdelset (&set, SIGINT);
1769     sigdelset (&set, SIGTERM);
1770     pthread_sigmask (SIG_BLOCK, &set, NULL);
1772     /* Wait for one of these signals */
1773     sigemptyset (&set);
1774     sigaddset (&set, SIGINT);
1775     sigaddset (&set, SIGQUIT);
1776     sigaddset (&set, SIGTERM);
1778     Osal_printf("IPC resource manager started");
1780     /* Wait for a signal */
1781     while (1)
1782     {
1783         switch (SignalWaitinfo (&set, NULL))
1784         {
1785             case SIGTERM:
1786             case SIGQUIT:
1787             case SIGINT:
1788                 error = EOK;
1789                 goto done;
1791             default:
1792                 break;
1793         }
1794     }
1796     error = EOK;
1798 done:
1799     GT_0trace(curTrace, GT_4CLASS, "IPC resource manager exiting \n");
1801     error = thread_pool_destroy(dev->tpool);
1802     if (error < 0) {
1803         Osal_printf("IPC: thread_pool_destroy returned an error");
1804     }
1805     deinit_ipc(dev, ipc_firmware, FALSE);
1806     deinit_devices(dev);
1807     free(dev);
1809     /* Free the abs path of firmware files if necessary */
1810     for (i = 0; i < ipc_num_cores; i++) {
1811         if ((ipc_firmware[i].freeString) &&
1812             (ipc_firmware[i].firmware)) {
1813             free(ipc_firmware[i].firmware);
1814         }
1815     }
1817     return (error);