c87c3aae29de154fb0a75c6b01e82b1c69a73b5f
[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-2013, 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>
60 #if defined(SYSLINK_PLATFORM_OMAP4430)
61 #include <login.h>
62 #endif
64 #include <IpcKnl.h>
66 /* OSAL & Utils headers */
67 #include <ti/syslink/utils/List.h>
68 #include <ti/syslink/utils/MemoryOS.h>
69 #include <ti/ipc/MultiProc.h>
70 #include <ti/ipc/NameServer.h>
71 #include <_MultiProc.h>
72 #include <_NameServer.h>
73 #include <_GateMP_daemon.h>
74 #include <OsalSemaphore.h>
75 #include <ti/syslink/utils/OsalPrint.h>
76 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
77 #include <_ipu_pm.h>
78 #endif
79 #include <ti/syslink/utils/Trace.h>
80 #include <ti/syslink/ProcMgr.h>
81 #include <Bitops.h>
82 #include <RscTable.h>
83 #if (_NTO_VERSION >= 800)
84 #include <slog2.h>
85 #endif
87 #include <ti-ipc.h>
89 #define DENY_ALL                    \
90             PROCMGR_ADN_ROOT        \
91             | PROCMGR_ADN_NONROOT   \
92             | PROCMGR_AOP_DENY      \
93             | PROCMGR_AOP_LOCK
95 // Ducati trace to slog2 static variables and defines
96 #define TRACE_BUFFER_SIZE               4096
97 // polling interval in microseconds
98 #define TRACE_POLLING_INTERVAL_US       1000000
100 #if (_NTO_VERSION >= 800)
101 static int verbosity = SLOG2_ERROR;
102 static slog2_buffer_t buffer_handle;
103 #else
104 static int verbosity = 2;
105 #endif
107 #if defined(SYSLINK_PLATFORM_VAYU)
108 static bool gatempEnabled = false;
109 #endif
110 static char trace_buffer[TRACE_BUFFER_SIZE];
111 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
112 static Bool trace_active;
113 static pthread_t thread_traces;
115 // Syslink hibernation global variables
116 Bool syslink_hib_enable = TRUE;
117 #if !defined(SYSLINK_PLATFORM_OMAP4430) && !defined(SYSLINK_PLATFORM_OMAP5430)
118 #define PM_HIB_DEFAULT_TIME 5000
119 #endif
120 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
121 Bool syslink_hib_hibernating = FALSE;
122 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
123 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
125 extern Int rpmsg_rpc_setup (Void);
126 extern Void rpmsg_rpc_destroy (Void);
127 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
129 typedef struct syslink_firmware_info_t {
130     uint16_t proc_id;
131     char * proc;
132     char * firmware;
133 } syslink_firmware_info;
134 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
135 static unsigned int syslink_num_cores = 0;
137 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
138 int deinit_ipc(syslink_dev_t * dev, bool recover);
140 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
142 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
143 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
144 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
145                                     ProcMgr_State_Error,
146                                     ProcMgr_State_Watchdog,
147                                     ProcMgr_State_EndValue};
149 typedef struct syslink_trace_info_t {
150     uintptr_t   va;
151     uint32_t    len;
152     uint32_t *  widx;
153     uint32_t *  ridx;
154     Bool        firstRead;
155 } syslink_trace_info;
157 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
159 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
161     int         nbytes;
162     int         nparts;
163     int         status;
164     int         nleft;
165     uint32_t    len;
166     uint16_t    procid = ocb->ocb.attr->procid;
168     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
169         return (status);
171     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
172         return (ENOSYS);
174     /* check to see where the trace buffer is */
175     if (proc_traces[procid].va == NULL) {
176         return (ENOSYS);
177     }
179     /* need to abort ducati trace thread if it is running as only want one reader */
180     pthread_mutex_lock(&trace_mutex);
181     if (trace_active == TRUE) {
182         trace_active = FALSE;
183         pthread_mutex_unlock(&trace_mutex);
184         // Wake up if waiting on hibernation
185         pthread_mutex_lock(&syslink_hib_mutex);
186         syslink_hib_hibernating = FALSE;
187         pthread_cond_broadcast(&syslink_hib_cond);
188         pthread_mutex_unlock(&syslink_hib_mutex);
189         pthread_join(thread_traces, NULL);
190     } else {
191         pthread_mutex_unlock(&trace_mutex);
192     }
194     if (ocb->ocb.offset == 0) {
195         ocb->widx = *(proc_traces[procid].widx);
196         ocb->ridx = *(proc_traces[procid].ridx);
197         *(proc_traces[procid].ridx) = ocb->widx;
198     }
200     /* Check for wrap-around */
201     if (ocb->widx < ocb->ridx)
202         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
203     else
204         len = ocb->widx - ocb->ridx;
206     /* Determine the amount left to print */
207     if (ocb->widx >= ocb->ridx)
208         nleft = len - ocb->ocb.offset;
209     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
210         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
211     else
212         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
214     nbytes = min (msg->i.nbytes, nleft);
216     /* Make sure the user has supplied a big enough buffer */
217     if (nbytes > 0) {
218         /* set up the return data IOV */
219         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
220             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
221         else
222             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
224         /* set up the number of bytes (returned by client's read()) */
225         _IO_SET_READ_NBYTES (ctp, nbytes);
227         ocb->ocb.offset += nbytes;
229         nparts = 1;
230     }
231     else {
232         _IO_SET_READ_NBYTES (ctp, 0);
234         /* reset offset */
235         ocb->ocb.offset = 0;
237         nparts = 0;
238     }
240     /* mark the access time as invalid (we just accessed it) */
242     if (msg->i.nbytes > 0)
243         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
245     return (_RESMGR_NPARTS (nparts));
248 extern OsalSemaphore_Handle mqcopy_test_sem;
250 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
252     int status = _RESMGR_NOREPLY;
253     struct _msg_info info;
255     /*
256      * Try to run the default unblock for this message.
257      */
258     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
259         return status;
260     }
262     /*
263      * Check if rcvid is still valid and still has an unblock
264      * request pending.
265      */
266     if (MsgInfo(ctp->rcvid, &info) == -1 ||
267         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
268         return _RESMGR_NOREPLY;
269     }
271     if (mqcopy_test_sem)
272         OsalSemaphore_post(mqcopy_test_sem);
274     return _RESMGR_NOREPLY;
277 IOFUNC_OCB_T *
278 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
280     syslink_ocb_t *ocb = NULL;
282     /* Allocate the OCB */
283     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
284     if (ocb == NULL){
285         errno = ENOMEM;
286         return (NULL);
287     }
289     ocb->pid = ctp->info.pid;
291     return (IOFUNC_OCB_T *)(ocb);
294 void
295 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
297     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
299     if (ocb) {
300 #ifndef SYSLINK_PLATFORM_VAYU
301         GateHWSpinlock_LeaveLockForPID(ocb->pid);
302 #endif
303         free (ocb);
304     }
307 int init_syslink_trace_device(syslink_dev_t *dev)
309     resmgr_attr_t    resmgr_attr;
310     int              i;
311     syslink_attr_t * trace_attr;
312     char             trace_name[_POSIX_PATH_MAX];
313     int              status = 0;
314     unsigned int     da = 0, pa = 0;
315     unsigned int     len;
317     memset(&resmgr_attr, 0, sizeof resmgr_attr);
318     resmgr_attr.nparts_max = 10;
319     resmgr_attr.msg_max_size = 2048;
321     for (i = 0; i < syslink_num_cores; i++) {
322         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
323                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
324         trace_attr = &dev->syslink.cattr_trace[i];
325         iofunc_attr_init(&trace_attr->attr,
326                          S_IFCHR | 0777, NULL, NULL);
327         trace_attr->attr.mount = &dev->syslink.mattr;
328         trace_attr->procid = i;
329         iofunc_time_update(&trace_attr->attr);
330         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
331                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
332         dev->syslink.iofuncs_trace[i].read = syslink_read;
333         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
334         pa = 0;
335         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
336         if (status == 0) {
337             /* last 8 bytes are for writeIdx/readIdx */
338             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
339             if (da && !pa) {
340                 /* need to translate da->pa */
341                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
342                                                 (Ptr *) &pa,
343                                                 ProcMgr_AddrType_MasterPhys,
344                                                 (Ptr) da,
345                                                 ProcMgr_AddrType_SlaveVirt);
346             }
347             else {
348                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
349                                     status, "not performing ProcMgr_translate");
350             }
351             /* map length aligned to page size */
352             proc_traces[i].va =
353                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
354             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
355                                                proc_traces[i].len);
356             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
357                                                sizeof(uint32_t));
358             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
359                 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
360                                     status, "mmap_device_io failed");
361                 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
362                 proc_traces[i].va = NULL;
363             }
364             proc_traces[i].firstRead = TRUE;
365         }
366         else {
367             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
368                                 status, "RscTable_getInfo failed");
369             proc_traces[i].va = NULL;
370         }
371         if (-1 == (dev->syslink.resmgr_id_trace[i] =
372                        resmgr_attach(dev->dpp, &resmgr_attr,
373                                      dev->syslink.device_name, _FTYPE_ANY, 0,
374                                      &dev->syslink.cfuncs_trace[i],
375                                      &dev->syslink.iofuncs_trace[i],
376                                      &trace_attr->attr))) {
377             GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
378                                 status, "resmgr_attach failed");
379             return(-1);
380         }
381     }
383     return (status);
386 int deinit_syslink_trace_device(syslink_dev_t *dev)
388     int status = EOK;
389     int i = 0;
391     for (i = 0; i < syslink_num_cores; i++) {
392         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
393         if (status < 0) {
394             Osal_printf("syslink: resmgr_detach failed %d", errno);
395             status = errno;
396         }
397         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
398             munmap((void *)proc_traces[i].va,
399                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
400         }
401         proc_traces[i].va = NULL;
402     }
404     return (status);
407 /* Initialize the syslink device */
408 int init_syslink_device(syslink_dev_t *dev)
410     iofunc_attr_t *  attr;
411     resmgr_attr_t    resmgr_attr;
412     int              status = 0;
414     pthread_mutex_init(&dev->lock, NULL);
416     memset(&resmgr_attr, 0, sizeof resmgr_attr);
417     resmgr_attr.nparts_max = 10;
418     resmgr_attr.msg_max_size = 2048;
420     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
421     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
422     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
423                               IOFUNC_PC_NO_TRUNC |
424                               IOFUNC_PC_SYNC_IO;
425     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
427     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
428     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
430     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
431                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
433     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
435     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
436     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
437     dev->syslink.iofuncs.devctl = syslink_devctl;
438     dev->syslink.iofuncs.unblock = syslink_unblock;
440     attr->mount = &dev->syslink.mattr;
441     iofunc_time_update(attr);
443     if (-1 == (dev->syslink.resmgr_id =
444         resmgr_attach(dev->dpp, &resmgr_attr,
445                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
446                       &dev->syslink.cfuncs,
447                       &dev->syslink.iofuncs, attr))) {
448         return(-1);
449     }
451     status = init_syslink_trace_device(dev);
452     if (status < 0) {
453         return status;
454     }
456     return(0);
459 /* De-initialize the syslink device */
460 int deinit_syslink_device(syslink_dev_t *dev)
462     int status = EOK;
464     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
465     if (status < 0) {
466         Osal_printf("syslink: resmgr_detach failed %d", errno);
467         status = errno;
468     }
470     status = deinit_syslink_trace_device(dev);
472     return(status);
476 /* Initialize the devices */
477 int init_devices(syslink_dev_t *dev)
479     if (init_syslink_device(dev) < 0) {
480         Osal_printf("syslink: syslink device init failed");
481         return(-1);
482     }
484     return(0);
488 /* De-initialize the devices */
489 int deinit_devices(syslink_dev_t *dev)
491     int status = EOK;
493     if ((status = deinit_syslink_device(dev)) < 0) {
494         fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
495         status = errno;
496     }
498     return(status);
501 static void ipc_recover(Ptr args)
503     syslink_dev_t * dev = (syslink_dev_t *)args;
505     deinit_ipc(dev, TRUE);
506     init_ipc(dev, syslink_firmware, TRUE);
507     deinit_syslink_trace_device(dev);
508     init_syslink_trace_device(dev);
511 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
512                       ProcMgr_State fromState, ProcMgr_State toState,
513                       ProcMgr_EventStatus status, Ptr args)
515     Int ret = 0;
516     String errString = NULL;
517     syslink_dev_t * dev = (syslink_dev_t *)args;
519     if (status == ProcMgr_EventStatus_Event) {
520         switch (toState) {
521             case ProcMgr_State_Mmu_Fault:
522                 errString = "MMU Fault";
523                 break;
524             case ProcMgr_State_Error:
525                 errString = "Exception";
526                 break;
527             case ProcMgr_State_Watchdog:
528                 errString = "Watchdog";
529                 break;
530             default:
531                 errString = "Unexpected State";
532                 ret = -1;
533                 break;
534         }
535         GT_2trace (curTrace, GT_4CLASS,
536                    "syslink_error_cb: Received Error Callback for %s : %s\n",
537                    MultiProc_getName(procId), errString);
538         /* Don't allow re-schedule of recovery until complete */
539         pthread_mutex_lock(&dev->lock);
540         if (ret != -1 && dev->recover == FALSE) {
541             /* Schedule recovery. */
542             dev->recover = TRUE;
543             /* Activate a thread to handle the recovery. */
544             GT_0trace (curTrace, GT_4CLASS,
545                        "syslink_error_cb: Scheduling recovery...");
546             OsalThread_activate(dev->ipc_recovery_work);
547         }
548         else {
549             GT_0trace (curTrace, GT_4CLASS,
550                        "syslink_error_cb: Recovery already scheduled.");
551         }
552         pthread_mutex_unlock(&dev->lock);
553     }
554     else if (status == ProcMgr_EventStatus_Canceled) {
555         GT_1trace (curTrace, GT_3CLASS,
556                    "SysLink Error Callback Cancelled for %s",
557                    MultiProc_getName(procId));
558     }
559     else {
560         GT_1trace (curTrace, GT_4CLASS,
561                    "SysLink Error Callback Unexpected Event for %s",
562                    MultiProc_getName(procId));
563     }
565     return ret;
568 #if defined(SYSLINK_PLATFORM_OMAP4430)
569 #define SYSLINK_CARVEOUT
570 #ifdef SYSLINK_CARVEOUT
571 #define IPU_MEM_SIZE  49 * 1024 * 1024
572 #define IPU_MEM_PHYS  0x97F00000
573 #else
574 #define IPU_MEM_SIZE  104 * 1024 * 1024
575 #define IPU_MEM_ALIGN 0x1000000
576 #endif
577 #else
578 // only need mem for DEVMEM entries, rest is allocated dynamically
579 #define IPU_MEM_SIZE  90 * 1024 * 1024
580 #define IPU_MEM_ALIGN 0x0
582 #endif
584 unsigned int syslink_ipu_mem_size = IPU_MEM_SIZE;
585 #if defined(SYSLINK_PLATFORM_OMAP5430)
586 unsigned int syslink_dsp_mem_size = IPU_MEM_SIZE;
587 #endif
589 /*
590  * Initialize the syslink ipc
591  *
592  * This function sets up the "kernel"-side IPC modules, and does any special
593  * initialization required for QNX and the platform being used.  This function
594  * also registers for error notifications and initializes the recovery thread.
595  */
596 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
598     int status = 0;
599 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
600     int32_t ret = 0;
601     uint32_t len = 0;
602 #ifndef SYSLINK_CARVEOUT
603     int64_t pa = 0;
604     void * da;
605 #endif
606     int64_t paddr = 0;
607 #endif
608     Ipc_Config iCfg;
609     OsalThread_Params threadParams;
610     ProcMgr_AttachParams attachParams;
611     UInt16 procId;
612     int i;
614 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
615     /* Map a contiguous memory section for ipu - currently hard-coded */
616     if (!recover) {
617 #ifdef SYSLINK_CARVEOUT
618         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
619                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
620                               MAP_PHYS,
621                               NOFD,
622                               IPU_MEM_PHYS);
623 #else
624 #if defined(SYSLINK_PLATFORM_OMAP5430)
625         dev->da_tesla_virt =
626 #endif
627         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
628                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
629                               MAP_ANON | MAP_PHYS | MAP_SHARED,
630                               NOFD,
631                               0);
633 #endif
635         if (dev->da_virt == MAP_FAILED) {
636             status = ENOMEM;
637             goto exit;
638         }
639     }
641     if (status >= 0) {
642 #ifdef SYSLINK_CARVEOUT
643         /* Make sure the memory is contiguous */
644         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
645         if (ret)
646             status = ret;
647         else if (len != IPU_MEM_SIZE)
648             status = ENOMEM;
649 #else
650         /* Make sure the memory is contiguous */
651         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
652                            &paddr, &len);
653         if (ret)
654             status = ret;
655         else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
656             status = ENOMEM;
657         else {
658 #if defined(SYSLINK_PLATFORM_OMAP4430)
659             pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
660             if ((pa - paddr) < 0x900000)
661                 pa += 0x900000;
662             else
663                 pa -= 0x700000;
664             da = dev->da_virt + (pa - paddr);
665 #else
666             pa = paddr;
667             da = dev->da_virt;
668 #endif
669         }
670 #endif
671         if (status != 0)
672             goto memoryos_fail;
673     }
674 #endif
676 #if defined(SYSLINK_PLATFORM_OMAP5430)
677     if (status >= 0) {
678         iCfg.pAddr_dsp = (uint32_t)pa;
679         iCfg.vAddr_dsp = (uint32_t)da;
680     }
681 #endif
682     if (status >= 0) {
683         if (!recover) {
684             /* Set up the MemoryOS module */
685             status = MemoryOS_setup();
686             if (status < 0)
687                 goto memoryos_fail;
688         }
690         /* Setup IPC and platform-specific items */
691 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
692 #ifdef SYSLINK_CARVEOUT
693         iCfg.vAddr = (uint32_t)dev->da_virt;
694         iCfg.pAddr = (uint32_t)paddr;
695 #else
696         iCfg.vAddr = (uint32_t)da;
697         iCfg.pAddr = (uint32_t)pa;
698 #endif
699 #endif
700         status = Ipc_setup (&iCfg);
701         if (status < 0)
702             goto ipcsetup_fail;
704         /* NOTE: this is for handling the procmgr event notifications to userspace list */
705         if (!recover) {
706             /* Setup Fault recovery items. */
707             /* Create the thread object used for the interrupt handler. */
708             threadParams.priority     = OsalThread_Priority_Medium;
709             threadParams.priorityType = OsalThread_PriorityType_Generic;
710             threadParams.once         = FALSE;
711             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
712                                                         ipc_recover,
713                                                         dev,
714                                                         &threadParams);
715             if (dev->ipc_recovery_work == NULL)
716                 goto osalthreadcreate_fail;
717         }
718         else {
719             pthread_mutex_lock(&dev->lock);
720             dev->recover = FALSE;
721             pthread_mutex_unlock(&dev->lock);
722         }
724         for (i = 0; i < syslink_num_cores; i++) {
725             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
726             if (procId >= MultiProc_MAXPROCESSORS || procH[procId]) {
727                 GT_setFailureReason (curTrace,
728                                      GT_4CLASS,
729                                      "init_ipc",
730                                      status,
731                                      "invalid proc!");
732                 break;
733             }
735             if (syslink_firmware[i].firmware) {
736                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
737                 if (rscHandle[procId] == NULL) {
738                     status = -1;
739                     break;
740                 }
741             }
743             status = ProcMgr_open(&procH[procId], procId);
744             if (status < 0 || procH[procId] == NULL)
745                 goto procmgropen_fail;
747             /* Load and start the remote processor. */
748             ProcMgr_getAttachParams (procH[procId], &attachParams);
749             status = ProcMgr_attach (procH[procId], &attachParams);
750             if (status < 0) {
751                 GT_setFailureReason (curTrace,
752                                      GT_4CLASS,
753                                      "init_ipc",
754                                      status,
755                                      "ProcMgr_attach failed!");
756                 goto procmgrattach_fail;
757             }
759             if (syslink_firmware[i].firmware) {
760                 status = ProcMgr_load (procH[procId],
761                                        (String)firmware[i].firmware, 0, NULL,
762                                         NULL, &procH_fileId[procId]);
763                 if (status < 0) {
764                     GT_setFailureReason (curTrace,
765                                          GT_4CLASS,
766                                          "init_ipc",
767                                          status,
768                                          "ProcMgr_load failed!");
769                     goto procmgrload_fail;
770                 }
771             }
773             status = Ipc_attach (procId);
774             if (status < 0) {
775                 GT_setFailureReason (curTrace,
776                                      GT_4CLASS,
777                                      "init_ipc",
778                                      status,
779                                      "Ipc_attach failed!");
780                 goto ipcattach_fail;
781             }
783             status = ProcMgr_start(procH[procId], NULL);
784             if (status < 0) {
785                 GT_setFailureReason (curTrace,
786                                      GT_4CLASS,
787                                      "init_ipc",
788                                      status,
789                                      "ProcMgr_start failed!");
790                 goto procmgrstart_fail;
791             }
793             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
794                                             -1, errStates);
795             if (status < 0)
796                 goto procmgrreg_fail;
798             continue;
800 procmgrreg_fail:
801             ProcMgr_stop(procH[procId]);
802 procmgrstart_fail:
803             Ipc_detach(procId);
804 ipcattach_fail:
805             if (syslink_firmware[i].firmware)
806                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
807 procmgrload_fail:
808             ProcMgr_detach(procH[procId]);
809 procmgrattach_fail:
810             ProcMgr_close(&procH[procId]);
811             procH[procId] = NULL;
812 procmgropen_fail:
813             RscTable_free(&rscHandle[procId]);
814             break;
815         }
817         if (status < 0)
818             goto tiipcsetup_fail;
820         /* Set up rpmsg_mq */
821         status = ti_ipc_setup();
822         if (status < 0)
823             goto tiipcsetup_fail;
825         /* Set up rpmsg_rpc */
826         status = rpmsg_rpc_setup();
827         if (status < 0)
828             goto rpcsetup_fail;
830 #if defined(SYSLINK_PLATFORM_VAYU)
831         if (gatempEnabled) {
832             /* Set up NameServer for resource manager process */
833             status = NameServer_setup();
834             if (status < 0) {
835                 goto nameserversetup_fail;
836             }
838             /* Set up GateMP */
839             status = GateMP_setup();
840             if (status < 0) {
841                 goto gatempsetup_fail;
842             }
843         }
844 #endif
846         goto exit;
847     }
849 #if defined(SYSLINK_PLATFORM_VAYU)
850 gatempsetup_fail:
851     NameServer_destroy();
852 nameserversetup_fail:
853     rpmsg_rpc_destroy();
854 #endif
855 rpcsetup_fail:
856     ti_ipc_destroy(recover);
857 tiipcsetup_fail:
858     for (i-=1; i >= 0; i--) {
859         procId = firmware[i].proc_id;
860         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
861                                 (Ptr)dev, errStates);
862         ProcMgr_stop(procH[procId]);
863         if (procH_fileId[procId]) {
864             ProcMgr_unload(procH[procId], procH_fileId[procId]);
865             procH_fileId[procId] = 0;
866         }
867         ProcMgr_detach(procH[procId]);
868         ProcMgr_close(&procH[procId]);
869         procH[procId] = NULL;
870         RscTable_free(&rscHandle[procId]);
871         rscHandle[procId] = NULL;
872     }
873     OsalThread_delete(&dev->ipc_recovery_work);
874 osalthreadcreate_fail:
875     Ipc_destroy();
876 ipcsetup_fail:
877     MemoryOS_destroy();
878 memoryos_fail:
879 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
880     if (dev->da_virt != MAP_FAILED)
881 #ifdef SYSLINK_CARVEOUT
882         munmap(dev->da_virt, IPU_MEM_SIZE);
883 #else
884         munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
885 #endif
886 #endif
887 exit:
888     return status;
891 int deinit_ipc(syslink_dev_t * dev, bool recover)
893     int status = EOK;
894     uint32_t i = 0, id = 0;
896     // Stop the remote cores right away
897     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
898         if (procH[i]) {
899             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
900             ProcMgr_stop(procH[i]);
901         }
902     }
904 #if defined(SYSLINK_PLATFORM_VAYU)
905     if (gatempEnabled) {
906         GateMP_destroy();
908         NameServer_destroy();
909     }
910 #endif
912     rpmsg_rpc_destroy();
914     ti_ipc_destroy(recover);
916     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
917         if (procH[i]) {
918             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
919                                       errStates);
920             Ipc_detach(i);
921             if (procH_fileId[i]) {
922                 ProcMgr_unload(procH[i], procH_fileId[i]);
923                 procH_fileId[i] = 0;
924             }
925             ProcMgr_detach(procH[i]);
926             ProcMgr_close(&procH[i]);
927             procH[i] = NULL;
928             RscTable_free(&rscHandle[i]);
929             rscHandle[i] = NULL;
930         }
931     }
933     if (!recover && dev->ipc_recovery_work != NULL) {
934         OsalThread_delete (&dev->ipc_recovery_work);
935         dev->ipc_recovery_work = NULL;
936     }
938     if (recover) {
939         static FILE *log;
940         /* Dump the trace information */
941         Osal_printf("syslink: printing remote core trace dump to"
942                     " /var/log/ducati-m3-traces.log");
943         log = fopen ("/var/log/ducati-m3-traces.log", "a+");
944         if (log) {
945             for (id = 0; id < syslink_num_cores; id++) {
946                 if (proc_traces[id].va) {
947                     /* print traces */
948                     /* wait a little bit for traces to finish dumping */
949                     sleep(1);
950                     fprintf(log, "****************************************\n");
951                     fprintf(log, "***         CORE%d TRACE DUMP         ***\n",
952                             id);
953                     fprintf(log, "****************************************\n");
954                     for (i = (*proc_traces[id].widx + 1);
955                          i < (proc_traces[id].len - 8);
956                          i++) {
957                         fprintf(log, "%c",
958                                 *(char *)((uint32_t)proc_traces[id].va + i));
959                     }
960                     for (i = 0; i < *proc_traces[id].widx; i++) {
961                         fprintf(log, "%c",
962                                 *(char *)((uint32_t)proc_traces[id].va + i));
963                     }
964                 }
965             }
966             fclose(log);
967         }
968         else {
969             GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
970                                 "error opening /var/log/ducati-m3-traces.log");
971         }
972     }
974     status = Ipc_destroy();
975     if (status < 0) {
976         printf("Ipc_destroy() failed 0x%x", status);
977     }
978     if (!recover) {
979         status = MemoryOS_destroy();
980         if (status < 0) {
981             printf("MemoryOS_destroy() failed 0x%x", status);
982         }
983 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
984         if (dev->da_virt != MAP_FAILED) {
985 #ifdef SYSLINK_CARVEOUT
986             status = munmap(dev->da_virt, IPU_MEM_SIZE);
987 #else
988             status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
989 #endif
990             if (status < 0) {
991                printf("munmap failed %d", errno);
992             }
993         }
994 #endif
995     }
997     return status;
1001 /* Read next line of available data for given 'core' and store it in buffer.
1002  * Returns the number of bytes that were written or -1 on error
1003  */
1004 static int readNextTrace(int core, char* buffer, int bufSize)
1006     char* readPtr;
1007     uint32_t readBytes, ridx, widx;
1008     syslink_trace_info* tinfo = &proc_traces[core];
1010     /* Make sure it is valid */
1011     if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
1012         return -1;
1013     }
1015     /* Check to see if something to read */
1016     if (tinfo->ridx == tinfo->widx) {
1017         return 0;
1018     }
1020     readPtr = (char*) tinfo->va;
1021     ridx = *tinfo->ridx;
1022     widx = *tinfo->widx;
1024     /* If first read, make sure that core is ready by validating ridx, widx */
1025     if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
1026         // not ready - will try again later
1027         return 0;
1028     }
1030     /* Sanity check ridx/widx to make sure they point inside the buffer */
1031     if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
1032         Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
1033             core, widx, ridx, tinfo->len);
1034         return -1;
1035     }
1037     readBytes = 0;
1038     tinfo->firstRead = FALSE;
1039     /* Read until we hit newline indicating end of trace */
1040     while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
1041         buffer[readBytes] = readPtr[ridx];
1042         readBytes++;
1043         ridx++;
1044         // Check for wrap-around
1045         if (ridx == tinfo->len) {
1046             ridx = 0;
1047         }
1048     }
1050     /* If did not find newline, abort since either not enough info or no room in buffer */
1051     if (readPtr[ridx] != '\n') {
1052         if (readBytes >= bufSize) {
1053             Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
1054                 core, readBytes, bufSize);
1055             return -1;
1056         }
1057         return 0;
1058     }
1060     /* Newline may not be valid data if this was not ready to be read */
1061     if (ridx == widx) {
1062         return 0;
1063     }
1065     /* We read a full line - null terminate and update ridx to mark data read */
1066     if (readBytes < bufSize) {
1067         buffer[readBytes] = '\0';
1068     } else {
1069         Osal_printf("C%d: No room to write NULL character", core);
1070         return -1;
1071     }
1072     readBytes++;
1073     ridx++;
1074     if (ridx == tinfo->len) {
1075         ridx = 0;
1076     }
1077     *tinfo->ridx = ridx;
1079     return readBytes;
1082 /* Thread reading ducati traces and writing them out to slog2 */
1083 static void *ducatiTraceThread(void *parm)
1085     int32_t bytesRead;
1086     int core;
1087     int err;
1088     Bool exit = FALSE;
1090     pthread_setname_np(0, "ducati-trace");
1092     pthread_mutex_lock(&trace_mutex);
1093     while ( (trace_active == TRUE) && (exit == FALSE) ) {
1094         for (core = 0; core < MultiProc_MAXPROCESSORS; core++) {
1095             while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1096 #if (_NTO_VERSION >= 800)
1097                 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1098 #else
1099                 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1100 #endif
1101                 if (trace_active == FALSE) {
1102                     break;
1103                 }
1104             }
1105             // Abort trace logger on errors as these should not occur
1106             if (bytesRead < 0) {
1107                 trace_active = FALSE;
1108             }
1109             if (trace_active == FALSE) {
1110                 break;
1111             }
1112         }
1113         if (trace_active == FALSE) {
1114             continue;
1115         }
1116         pthread_mutex_unlock(&trace_mutex);
1118         // No interrupts/events to trigger reading traces, so need to periodically poll
1119         usleep(TRACE_POLLING_INTERVAL_US);
1121         // If we are in hibernation, wait on condvar for end of hibernation
1122         pthread_mutex_lock(&syslink_hib_mutex);
1123         while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1124             err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1125             if (err != EOK) {
1126                 Osal_printf("pthread_cond_wait failed with err=%d", err);
1127                 exit = TRUE;
1128                 break;
1129             }
1130         }
1131         pthread_mutex_unlock(&syslink_hib_mutex);
1133         pthread_mutex_lock(&trace_mutex);
1134     }
1135     pthread_mutex_unlock(&trace_mutex);
1136     Osal_printf("ducati trace thread exited");
1137     return NULL;
1140 /* Initialize slog2 for Ducati traces */
1141 static int init_ducati_slog2(void)
1143 #if (_NTO_VERSION >= 800)
1144     slog2_buffer_set_config_t buffer_config;
1145     const char * buffer_set_name = "ducati";
1146     const char * buffer_name = "ducati_buffer";
1148     // Use command line verbosity for default verbosity level
1149     uint8_t verbosity_level = (uint8_t) verbosity;
1150     if ( verbosity_level > SLOG2_DEBUG2) {
1151         verbosity_level = SLOG2_DEBUG2;
1152     }
1154     // Initialize the buffer configuration
1155     buffer_config.buffer_set_name = (char *) buffer_set_name;
1156     buffer_config.num_buffers = 1;
1157     buffer_config.verbosity_level = verbosity_level;
1158     buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1159     buffer_config.buffer_config[0].num_pages = 8;
1161     // Register the Buffer Set
1162     if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1163         Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1164         return -1;
1165     }
1166 #endif
1168     return 0;
1171 /** print usage */
1172 static Void printUsage (Char * app)
1174     printf ("\n%s: [-fHT]\n", app);
1175     printf ("  -f   specify the binary file to load to the remote cores)\n");
1176 #if defined(SYSLINK_PLATFORM_OMAP5430)
1177     printf ("  -d   specify the binary file to load to the dsp)\n");
1178 #endif
1179     printf ("  -H   enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1180     printf ("  -T   specify the hibernation timeout in ms, Default: 5000 ms)\n");
1181 #if defined(SYSLINK_PLATFORM_VAYU)
1182     printf ("  -g   enable GateMP support on host\n");
1183 #endif
1184     exit (EXIT_SUCCESS);
1187 dispatch_t * syslink_dpp = NULL;
1189 int main(int argc, char *argv[])
1191     syslink_dev_t * dev = NULL;
1192     thread_pool_attr_t tattr;
1193     int status;
1194     int error = 0;
1195     sigset_t set;
1196     int channelid = 0;
1197     int c;
1198     int hib_enable = 1;
1199     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1200     char *user_parm = NULL;
1201     struct stat          sbuf;
1202     int i = 0;
1203     char * abs_path = NULL;
1205     if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1206         printf ("Syslink Already Running...\n");
1207         return EXIT_FAILURE;
1208     }
1209     printf ("Starting syslink resource manager...\n");
1211     /* Parse the input args */
1212     while (1)
1213     {
1214         c = getopt (argc, argv, "f:d:H:T:U:gv:");
1215         if (c == -1)
1216             break;
1218         switch (c)
1219         {
1220         case 'f':
1221             /* for backward compatibility, "-f" option loaded Ducati/Benelli */
1222             syslink_firmware[syslink_num_cores].firmware = optarg;
1223 #if defined(SYSLINK_PLATFORM_OMAP4430)
1224             syslink_firmware[syslink_num_cores].proc = "SYSM3";
1225 #else
1226 #ifndef SYSLINK_SYSBIOS_SMP
1227             syslink_firmware[syslink_num_cores].proc = "CORE0";
1228 #else
1229             syslink_firmware[syslink_num_cores].proc = "IPU";
1230 #endif
1231 #endif
1232             syslink_num_cores++;
1233 #ifndef SYSLINK_SYSBIOS_SMP
1234             syslink_firmware[syslink_num_cores].firmware = NULL;
1235 #if defined(SYSLINK_PLATFORM_OMAP4430)
1236             syslink_firmware[syslink_num_cores].proc = "APPM3";
1237 #else
1238             syslink_firmware[syslink_num_cores].proc = "CORE1";
1239 #endif
1240             syslink_num_cores++;
1241 #endif
1242             break;
1243 #if defined(SYSLINK_PLATFORM_OMAP5430)
1244         case 'd':
1245             syslink_firmware[syslink_num_cores].firmware = optarg;
1246             syslink_firmware[syslink_num_cores].proc = "DSP";
1247             syslink_num_cores++;
1248             break;
1249 #endif
1250         case 'H':
1251             hib_enable = atoi(optarg);
1252             if (hib_enable != 0 && hib_enable != 1) {
1253                 hib_enable = -1;
1254             }
1255             break;
1256         case 'T':
1257             hib_timeout = atoi(optarg);
1258             break;
1259         case 'U':
1260             user_parm = optarg;
1261             break;
1262         case 'v':
1263             verbosity++;
1264             break;
1265 #if defined(SYSLINK_PLATFORM_VAYU)
1266         case 'g':
1267             printf("GateMP support enabled on host\n");
1268             gatempEnabled = true;
1269             break;
1270 #endif
1271         default:
1272             fprintf (stderr, "Unrecognized argument\n");
1273         }
1274     }
1276     /* Now parse the operands, which should be in the format:
1277      * "<multiproc_name> <firmware_file> ..*/
1278     for (; optind + 1 < argc; optind+=2) {
1279         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1280             printUsage(argv[0]);
1281             return (error);
1282         }
1283         syslink_firmware[syslink_num_cores].proc = argv [optind];
1284         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1285     }
1288     /* Get the name of the binary from the input args */
1289     if (!syslink_num_cores) {
1290         fprintf(stderr, "-f or -d or <core_id> option must be specified");
1291         printUsage(argv[0]);
1292         return (error);
1293     }
1295     /* Validate hib_enable args */
1296     if (hib_enable == -1) {
1297         fprintf (stderr, "invalid hibernation enable value\n");
1298         printUsage(argv[0]);
1299         return (error);
1300     }
1302     syslink_hib_enable = (Bool)hib_enable;
1303     syslink_hib_timeout = hib_timeout;
1305     /* Init logging for syslink */
1306     if (Osal_initlogging(verbosity) != 0) {
1307         return -1;
1308     }
1310     /* Obtain I/O privity */
1311     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1312     if (error == -1) {
1313         Osal_printf("Unable to obtain I/O privity");
1314         return (error);
1315     }
1317     /* Get the abs path for all firmware files */
1318     for (i = 0; i < syslink_num_cores; i++) {
1319         abs_path = calloc(1, PATH_MAX + 1);
1320         if (abs_path == NULL) {
1321             return -1;
1322         }
1323         if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1324             fprintf (stderr, "realpath failed\n");
1325             return -1;
1326         }
1327         syslink_firmware[i].firmware = abs_path;
1328     }
1330     /* allocate the device structure */
1331     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1332         Osal_printf("syslink: calloc() failed");
1333         return (-1);
1334     }
1336     /* create the channel */
1337     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1338                                     _NTO_CHF_DISCONNECT |
1339                                     _NTO_CHF_COID_DISCONNECT |
1340                                     _NTO_CHF_REPLY_LEN |
1341                                     _NTO_CHF_SENDER_LEN)) < 0) {
1342         Osal_printf("Unable to create channel %d", channelid);
1343         return (channelid);
1344     }
1346     /* create the dispatch structure */
1347     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1348         Osal_printf("syslink:  dispatch_create() failed");
1349         return(-1);
1350     }
1352     /* Initialize the thread pool */
1353     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1354     tattr.handle = dev->dpp;
1355     tattr.context_alloc = dispatch_context_alloc;
1356     tattr.context_free = dispatch_context_free;
1357     tattr.block_func = dispatch_block;
1358     tattr.unblock_func = dispatch_unblock;
1359     tattr.handler_func = dispatch_handler;
1360     tattr.lo_water = 2;
1361     tattr.hi_water = 4;
1362     tattr.increment = 1;
1363     tattr.maximum = 10;
1365     /* Create the thread pool */
1366     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1367         Osal_printf("syslink: thread pool create failed");
1368         return(-1);
1369     }
1371     /* init syslink */
1372     status = init_ipc(dev, syslink_firmware, FALSE);
1373     if (status < 0) {
1374         Osal_printf("syslink: IPC init failed");
1375         return(-1);
1376     }
1378     /* init the syslink device */
1379     status = init_devices(dev);
1380     if (status < 0) {
1381         Osal_printf("syslink: device init failed");
1382         return(-1);
1383     }
1385 #if (_NTO_VERSION >= 800)
1386     /* Relinquish privileges */
1387     status = procmgr_ability(  0,
1388                  DENY_ALL | PROCMGR_AID_SPAWN,
1389                  DENY_ALL | PROCMGR_AID_FORK,
1390                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1391                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1392                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1393                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1394                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1395                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1396                  (uint64_t)1, (uint64_t)~0,
1397                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1398                  (uint64_t)1, (uint64_t)~0,
1399                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1401     if (status != EOK) {
1402         Osal_printf("procmgr_ability failed! errno=%d", status);
1403         return EXIT_FAILURE;
1404     }
1406     /* Reduce priority to either what defined from command line or at least nobody */
1407     if (user_parm != NULL) {
1408         if (set_ids_from_arg(user_parm) < 0) {
1409             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1410             return EXIT_FAILURE;
1411         }
1412     } else {
1413         if (setuid(99) != 0) {
1414             Osal_printf("unable to set uid - %s", strerror(errno));
1415             return EXIT_FAILURE;
1416         }
1417     }
1418 #endif
1420     /* make this a daemon process */
1421     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1422         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1423         Osal_printf("syslink:  procmgr_daemon() failed");
1424         return(-1);
1425     }
1427     /* start the thread pool */
1428     thread_pool_start(dev->tpool);
1430     /* Init slog2 and thread for Ducati traces */
1431     if (init_ducati_slog2() != 0) {
1432         return -1;
1433     }
1434     trace_active = TRUE;
1435     status = pthread_create (&thread_traces, NULL, ducatiTraceThread, NULL);
1436     if (status != EOK) {
1437         Osal_printf("pthread_create for trace thread failed err=%d", status);
1438         trace_active = FALSE;
1439     }
1441     /* Mask out unnecessary signals */
1442     sigfillset (&set);
1443     sigdelset (&set, SIGINT);
1444     sigdelset (&set, SIGTERM);
1445     pthread_sigmask (SIG_BLOCK, &set, NULL);
1447     /* Wait for one of these signals */
1448     sigemptyset (&set);
1449     sigaddset (&set, SIGINT);
1450     sigaddset (&set, SIGQUIT);
1451     sigaddset (&set, SIGTERM);
1453     Osal_printf("Syslink resource manager started");
1455     /* Wait for a signal */
1456     while (1)
1457     {
1458         switch (SignalWaitinfo (&set, NULL))
1459         {
1460             case SIGTERM:
1461             case SIGQUIT:
1462             case SIGINT:
1463                 error = EOK;
1464                 goto done;
1466             default:
1467                 break;
1468         }
1469     }
1471     error = EOK;
1473 done:
1474     GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1475     /* Stop ducatiTraceThread if running */
1476     pthread_mutex_lock(&trace_mutex);
1477     if (trace_active) {
1478         trace_active = FALSE;
1479         pthread_mutex_unlock(&trace_mutex);
1480         // Wake up if waiting on hibernation
1481         pthread_mutex_lock(&syslink_hib_mutex);
1482         syslink_hib_hibernating = FALSE;
1483         pthread_cond_broadcast(&syslink_hib_cond);
1484         pthread_mutex_unlock(&syslink_hib_mutex);
1485         error = pthread_join(thread_traces, NULL);
1486         if (error < 0) {
1487             Osal_printf("syslink: pthread_join failed with err=%d", error);
1488         }
1489     } else {
1490         pthread_mutex_unlock(&trace_mutex);
1491     }
1493     error = thread_pool_destroy(dev->tpool);
1494     if (error < 0)
1495         Osal_printf("syslink: thread_pool_destroy returned an error");
1496     deinit_ipc(dev, FALSE);
1497     deinit_devices(dev);
1498     free(dev);
1499     return (EOK);