]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - ipc/ipcdev.git/blob - qnx/src/ipc3x_dev/ti/syslink/build/Qnx/resmgr/syslink_main.c
QNX IPC: Trace - Update Trace Device Name
[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 <_MultiProc.h>
71 #include <rprcfmt.h>
72 #include <OsalSemaphore.h>
73 #include <ti/syslink/utils/OsalPrint.h>
74 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
75 #include <_ipu_pm.h>
76 #endif
77 #include <ti/syslink/utils/Trace.h>
78 #include <ti/syslink/ProcMgr.h>
79 #include <Bitops.h>
80 #include <RscTable.h>
81 #if (_NTO_VERSION >= 800)
82 #include <slog2.h>
83 #endif
85 #include <ti-ipc.h>
87 #define DENY_ALL                    \
88             PROCMGR_ADN_ROOT        \
89             | PROCMGR_ADN_NONROOT   \
90             | PROCMGR_AOP_DENY      \
91             | PROCMGR_AOP_LOCK
93 // Ducati trace to slog2 static variables and defines
94 #define TRACE_BUFFER_SIZE               4096
95 // polling interval in microseconds
96 #define TRACE_POLLING_INTERVAL_US       1000000
98 #if (_NTO_VERSION >= 800)
99 static int verbosity = SLOG2_ERROR;
100 static slog2_buffer_t buffer_handle;
101 #else
102 static int verbosity = 2;
103 #endif
104 static char trace_buffer[TRACE_BUFFER_SIZE];
105 static pthread_mutex_t trace_mutex = PTHREAD_MUTEX_INITIALIZER;
106 static Bool trace_active;
107 static pthread_t thread_traces;
109 // Syslink hibernation global variables
110 Bool syslink_hib_enable = TRUE;
111 #if !defined(SYSLINK_PLATFORM_OMAP4430) && !defined(SYSLINK_PLATFORM_OMAP5430)
112 #define PM_HIB_DEFAULT_TIME 5000
113 #endif
114 uint32_t syslink_hib_timeout = PM_HIB_DEFAULT_TIME;
115 Bool syslink_hib_hibernating = FALSE;
116 pthread_mutex_t syslink_hib_mutex = PTHREAD_MUTEX_INITIALIZER;
117 pthread_cond_t syslink_hib_cond = PTHREAD_COND_INITIALIZER;
119 extern int rpmsg_omx_setup (void);
120 extern void rpmsg_omx_destroy (void);
121 extern int rpmsg_resmgr_setup (void);
122 extern void rpmsg_resmgr_destroy (void);
123 extern Int rpmsg_dce_setup (Void);
124 extern Void rpmsg_dce_destroy (Void);
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[NUM_REMOTE_PROCS];
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         GateHWSpinlock_LeaveLockForPID(ocb->pid);
301         free (ocb);
302     }
305 /* Initialize the syslink device */
306 int init_syslink_device(syslink_dev_t *dev)
308     iofunc_attr_t *  attr;
309     syslink_attr_t * trace_attr;
310     resmgr_attr_t    resmgr_attr;
311     int              i;
312     char             trace_name[_POSIX_PATH_MAX];
313     int              status = 0;
314     u32              da = 0, pa = 0;
315     u32              len;
317     pthread_mutex_init(&dev->lock, NULL);
319     memset(&resmgr_attr, 0, sizeof resmgr_attr);
320     resmgr_attr.nparts_max = 10;
321     resmgr_attr.msg_max_size = 2048;
323     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
324     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
325     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
326                               IOFUNC_PC_NO_TRUNC |
327                               IOFUNC_PC_SYNC_IO;
328     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
330     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
331     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
333     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
334                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
336     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
338     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
339     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
340     dev->syslink.iofuncs.devctl = syslink_devctl;
341     dev->syslink.iofuncs.unblock = syslink_unblock;
343     attr->mount = &dev->syslink.mattr;
344     iofunc_time_update(attr);
346     if (-1 == (dev->syslink.resmgr_id =
347         resmgr_attach(dev->dpp, &resmgr_attr,
348                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
349                       &dev->syslink.cfuncs,
350                       &dev->syslink.iofuncs, attr))) {
351         return(-1);
352     }
354     for (i = 0; i < syslink_num_cores; i++) {
355         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
356                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
357         trace_attr = &dev->syslink.cattr_trace[i];
358         iofunc_attr_init(&trace_attr->attr,
359                          S_IFCHR | 0777, NULL, NULL);
360         trace_attr->attr.mount = &dev->syslink.mattr;
361         trace_attr->procid = i;
362         iofunc_time_update(&trace_attr->attr);
363         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
364                   "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
365         dev->syslink.iofuncs_trace[i].read = syslink_read;
366         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
367         pa = 0;
368         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
369         if (status == 0) {
370             /* last 8 bytes are for writeIdx/readIdx */
371             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
372             if (da && !pa) {
373                 /* need to translate da->pa */
374                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
375                                                 (Ptr *) &pa,
376                                                 ProcMgr_AddrType_MasterPhys,
377                                                 (Ptr) da,
378                                                 ProcMgr_AddrType_SlaveVirt);
379             }
380             /* map length aligned to page size */
381             proc_traces[i].va =
382                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
383             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
384                                                proc_traces[i].len);
385             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
386                                                sizeof(uint32_t));
387             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
388                 proc_traces[i].va = NULL;
389             }
390             proc_traces[i].firstRead = TRUE;
391         }
392         else {
393             proc_traces[i].va = NULL;
394         }
395         if (-1 == (dev->syslink.resmgr_id_trace[i] =
396                        resmgr_attach(dev->dpp, &resmgr_attr,
397                                      dev->syslink.device_name, _FTYPE_ANY, 0,
398                                      &dev->syslink.cfuncs_trace[i],
399                                      &dev->syslink.iofuncs_trace[i],
400                                      &trace_attr->attr))) {
401             return(-1);
402         }
403     }
405     return(0);
408 /* De-initialize the syslink device */
409 int deinit_syslink_device(syslink_dev_t *dev)
411     int status = EOK;
412     int i = 0;
414     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
415     if (status < 0) {
416         Osal_printf("syslink: resmgr_detach failed %d", errno);
417         status = errno;
418     }
420     for (i = 0; i < syslink_num_cores; i++) {
421         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
422         if (status < 0) {
423             Osal_printf("syslink: resmgr_detach failed %d", errno);
424             status = errno;
425         }
426         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED)
427             munmap((void *)proc_traces[i].va,
428                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
429         proc_traces[i].va = NULL;
430     }
432     return(status);
436 /* Initialize the devices */
437 int init_devices(syslink_dev_t *dev)
439     if (init_syslink_device(dev) < 0) {
440         Osal_printf("syslink: syslink device init failed");
441         return(-1);
442     }
444     return(0);
448 /* De-initialize the devices */
449 int deinit_devices(syslink_dev_t *dev)
451     int status = EOK;
453     if ((status = deinit_syslink_device(dev)) < 0) {
454         fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
455         status = errno;
456     }
458     return(status);
461 static void ipc_recover(Ptr args)
463     syslink_dev_t * dev = (syslink_dev_t *)args;
465     deinit_ipc(dev, TRUE);
466     init_ipc(dev, syslink_firmware, TRUE);
469 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
470                       ProcMgr_State fromState, ProcMgr_State toState,
471                       ProcMgr_EventStatus status, Ptr args)
473     Int ret = 0;
474     String errString = NULL;
475     syslink_dev_t * dev = (syslink_dev_t *)args;
477     if (status == ProcMgr_EventStatus_Event) {
478         switch (toState) {
479             case ProcMgr_State_Mmu_Fault:
480                 errString = "MMU Fault";
481                 break;
482             case ProcMgr_State_Error:
483                 errString = "Exception";
484                 break;
485             case ProcMgr_State_Watchdog:
486                 errString = "Watchdog";
487                 break;
488             default:
489                 errString = "Unexpected State";
490                 ret = -1;
491                 break;
492         }
493         GT_2trace (curTrace, GT_4CLASS,
494                    "syslink_error_cb: Received Error Callback for %s : %s\n",
495                    MultiProc_getName(procId), errString);
496         /* Don't allow re-schedule of recovery until complete */
497         pthread_mutex_lock(&dev->lock);
498         if (ret != -1 && dev->recover == FALSE) {
499             /* Schedule recovery. */
500             dev->recover = TRUE;
501             /* Activate a thread to handle the recovery. */
502             GT_0trace (curTrace, GT_4CLASS,
503                        "syslink_error_cb: Scheduling recovery...");
504             OsalThread_activate(dev->ipc_recovery_work);
505         }
506         else {
507             GT_0trace (curTrace, GT_4CLASS,
508                        "syslink_error_cb: Recovery already scheduled.");
509         }
510         pthread_mutex_unlock(&dev->lock);
511     }
512     else if (status == ProcMgr_EventStatus_Canceled) {
513         GT_1trace (curTrace, GT_3CLASS,
514                    "SysLink Error Callback Cancelled for %s",
515                    MultiProc_getName(procId));
516     }
517     else {
518         GT_1trace (curTrace, GT_4CLASS,
519                    "SysLink Error Callback Unexpected Event for %s",
520                    MultiProc_getName(procId));
521     }
523     return ret;
526 #if defined(SYSLINK_PLATFORM_OMAP4430)
527 #define SYSLINK_CARVEOUT
528 #ifdef SYSLINK_CARVEOUT
529 #define IPU_MEM_SIZE  49 * 1024 * 1024
530 #define IPU_MEM_PHYS  0x97F00000
531 #else
532 #define IPU_MEM_SIZE  104 * 1024 * 1024
533 #define IPU_MEM_ALIGN 0x1000000
534 #endif
535 #else
536 // only need mem for DEVMEM entries, rest is allocated dynamically
537 #define IPU_MEM_SIZE  90 * 1024 * 1024
538 #define IPU_MEM_ALIGN 0x0
540 #endif
542 unsigned int syslink_ipu_mem_size = IPU_MEM_SIZE;
543 #if defined(SYSLINK_PLATFORM_OMAP5430)
544 unsigned int syslink_dsp_mem_size = IPU_MEM_SIZE;
545 #endif
547 /*
548  * Initialize the syslink ipc
549  *
550  * This function sets up the "kernel"-side IPC modules, and does any special
551  * initialization required for QNX and the platform being used.  This function
552  * also registers for error notifications and initializes the recovery thread.
553  */
554 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
556     int status = 0;
557 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
558     int32_t ret = 0;
559     uint32_t len = 0;
560 #ifndef SYSLINK_CARVEOUT
561     int64_t pa = 0;
562     void * da;
563 #endif
564     int64_t paddr = 0;
565 #endif
566     Ipc_Config iCfg;
567     OsalThread_Params threadParams;
568     ProcMgr_AttachParams attachParams;
569     UInt16 procId;
570     int i;
572 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
573     /* Map a contiguous memory section for ipu - currently hard-coded */
574     if (!recover) {
575 #ifdef SYSLINK_CARVEOUT
576         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
577                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
578                               MAP_PHYS,
579                               NOFD,
580                               IPU_MEM_PHYS);
581 #else
582 #if defined(SYSLINK_PLATFORM_OMAP5430)
583         dev->da_tesla_virt =
584 #endif
585         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
586                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
587                               MAP_ANON | MAP_PHYS | MAP_SHARED,
588                               NOFD,
589                               0);
591 #endif
593         if (dev->da_virt == MAP_FAILED) {
594             status = ENOMEM;
595             goto exit;
596         }
597     }
599     if (status >= 0) {
600 #ifdef SYSLINK_CARVEOUT
601         /* Make sure the memory is contiguous */
602         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
603         if (ret)
604             status = ret;
605         else if (len != IPU_MEM_SIZE)
606             status = ENOMEM;
607 #else
608         /* Make sure the memory is contiguous */
609         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
610                            &paddr, &len);
611         if (ret)
612             status = ret;
613         else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
614             status = ENOMEM;
615         else {
616 #if defined(SYSLINK_PLATFORM_OMAP4430)
617             pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
618             if ((pa - paddr) < 0x900000)
619                 pa += 0x900000;
620             else
621                 pa -= 0x700000;
622             da = dev->da_virt + (pa - paddr);
623 #else
624             pa = paddr;
625             da = dev->da_virt;
626 #endif
627         }
628 #endif
629         if (status != 0)
630             goto memoryos_fail;
631     }
632 #endif
634 #if defined(SYSLINK_PLATFORM_OMAP5430)
635     if (status >= 0) {
636         iCfg.pAddr_dsp = (uint32_t)pa;
637         iCfg.vAddr_dsp = (uint32_t)da;
638     }
639 #endif
640     if (status >= 0) {
641         if (!recover) {
642             /* Set up the MemoryOS module */
643             status = MemoryOS_setup();
644             if (status < 0)
645                 goto memoryos_fail;
646         }
648         /* Setup IPC and platform-specific items */
649 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
650 #ifdef SYSLINK_CARVEOUT
651         iCfg.vAddr = (uint32_t)dev->da_virt;
652         iCfg.pAddr = (uint32_t)paddr;
653 #else
654         iCfg.vAddr = (uint32_t)da;
655         iCfg.pAddr = (uint32_t)pa;
656 #endif
657 #endif
658         status = Ipc_setup (&iCfg);
659         if (status < 0)
660             goto ipcsetup_fail;
662         /* NOTE: this is for handling the procmgr event notifications to userspace list */
663         if (!recover) {
664             /* Setup Fault recovery items. */
665             /* Create the thread object used for the interrupt handler. */
666             threadParams.priority     = OsalThread_Priority_Medium;
667             threadParams.priorityType = OsalThread_PriorityType_Generic;
668             threadParams.once         = FALSE;
669             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
670                                                         ipc_recover,
671                                                         dev,
672                                                         &threadParams);
673             if (dev->ipc_recovery_work == NULL)
674                 goto osalthreadcreate_fail;
675         }
676         else {
677             pthread_mutex_lock(&dev->lock);
678             dev->recover = FALSE;
679             pthread_mutex_unlock(&dev->lock);
680         }
682         for (i = 0; i < syslink_num_cores; i++) {
683             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
684             if (procId >= MultiProc_MAXPROCESSORS || procH[procId]) {
685                 GT_setFailureReason (curTrace,
686                                      GT_4CLASS,
687                                      "init_ipc",
688                                      status,
689                                      "invalid proc!");
690                 break;
691             }
693             if (syslink_firmware[i].firmware) {
694                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
695                 if (rscHandle[procId] == NULL) {
696                     status = -1;
697                     break;
698                 }
699             }
701             status = ProcMgr_open(&procH[procId], procId);
702             if (status < 0 || procH[procId] == NULL)
703                 goto procmgropen_fail;
705             /* Load and start the remote processor. */
706             ProcMgr_getAttachParams (procH[procId], &attachParams);
707             status = ProcMgr_attach (procH[procId], &attachParams);
708             if (status < 0) {
709                 GT_setFailureReason (curTrace,
710                                      GT_4CLASS,
711                                      "init_ipc",
712                                      status,
713                                      "ProcMgr_attach failed!");
714                 goto procmgrattach_fail;
715             }
717             if (syslink_firmware[i].firmware) {
718                 status = ProcMgr_load (procH[procId],
719                                        (String)firmware[i].firmware, 0, NULL,
720                                         NULL, &procH_fileId[procId]);
721                 if (status < 0) {
722                     GT_setFailureReason (curTrace,
723                                          GT_4CLASS,
724                                          "init_ipc",
725                                          status,
726                                          "ProcMgr_load failed!");
727                     goto procmgrload_fail;
728                 }
729             }
731             status = Ipc_attach (procId);
732             if (status < 0) {
733                 GT_setFailureReason (curTrace,
734                                      GT_4CLASS,
735                                      "init_ipc",
736                                      status,
737                                      "Ipc_attach failed!");
738                 goto ipcattach_fail;
739             }
741             status = ProcMgr_start(procH[procId], NULL);
742             if (status < 0) {
743                 GT_setFailureReason (curTrace,
744                                      GT_4CLASS,
745                                      "init_ipc",
746                                      status,
747                                      "ProcMgr_start failed!");
748                 goto procmgrstart_fail;
749             }
751             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
752                                             -1, errStates);
753             if (status < 0)
754                 goto procmgrreg_fail;
756             continue;
758 procmgrreg_fail:
759             ProcMgr_stop(procH[procId]);
760 procmgrstart_fail:
761             Ipc_detach(procId);
762 ipcattach_fail:
763             if (syslink_firmware[i].firmware)
764                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
765 procmgrload_fail:
766             ProcMgr_detach(procH[procId]);
767 procmgrattach_fail:
768             ProcMgr_close(&procH[procId]);
769             procH[procId] = NULL;
770 procmgropen_fail:
771             RscTable_free(&rscHandle[procId]);
772             break;
773         }
775         if (status < 0)
776             goto resmgrsetup_fail;
778         /* Set up the resmgr */
779         status = rpmsg_resmgr_setup();
780         if (status < 0)
781             goto resmgrsetup_fail;
783         /* Set up rpmsg_omx */
784         status = rpmsg_omx_setup();
785         if (status < 0)
786             goto omxsetup_fail;
788         /* Set up rpmsg_dce */
789         status = rpmsg_dce_setup();
790         if (status < 0)
791             goto dcesetup_fail;
793         /* Set up rpmsg_mq */
794         status = ti_ipc_setup();
795         if (status < 0)
796             goto tiipcsetup_fail;
798         /* Set up rpmsg_rpc */
799         status = rpmsg_rpc_setup();
800         if (status < 0)
801             goto rpcsetup_fail;
803         goto exit;
804     }
806 rpcsetup_fail:
807     ti_ipc_destroy(recover);
808 tiipcsetup_fail:
809     rpmsg_dce_destroy();
810 dcesetup_fail:
811     rpmsg_omx_destroy();
812 omxsetup_fail:
813     rpmsg_resmgr_destroy();
814 resmgrsetup_fail:
815     for (i-=1; i >= 0; i--) {
816         procId = firmware[i].proc_id;
817         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
818                                 (Ptr)dev, errStates);
819         ProcMgr_stop(procH[procId]);
820         if (procH_fileId[procId]) {
821             ProcMgr_unload(procH[procId], procH_fileId[procId]);
822             procH_fileId[procId] = 0;
823         }
824         ProcMgr_detach(procH[procId]);
825         ProcMgr_close(&procH[procId]);
826         procH[procId] = NULL;
827         RscTable_free(&rscHandle[procId]);
828         rscHandle[procId] = NULL;
829     }
830     OsalThread_delete(&dev->ipc_recovery_work);
831 osalthreadcreate_fail:
832     Ipc_destroy();
833 ipcsetup_fail:
834     MemoryOS_destroy();
835 memoryos_fail:
836 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
837     if (dev->da_virt != MAP_FAILED)
838 #ifdef SYSLINK_CARVEOUT
839         munmap(dev->da_virt, IPU_MEM_SIZE);
840 #else
841         munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
842 #endif
843 #endif
844 exit:
845     return status;
848 int deinit_ipc(syslink_dev_t * dev, bool recover)
850     int status = EOK;
851     uint32_t i = 0, id = 0;
853     // Stop the remote cores right away
854     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
855         if (procH[i]) {
856             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
857             ProcMgr_stop(procH[i]);
858         }
859     }
861     rpmsg_rpc_destroy();
863     ti_ipc_destroy(recover);
865     rpmsg_dce_destroy();
867     rpmsg_omx_destroy();
869     rpmsg_resmgr_destroy();
871     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
872         if (procH[i]) {
873             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
874                                       errStates);
875             Ipc_detach(i);
876             if (procH_fileId[i]) {
877                 ProcMgr_unload(procH[i], procH_fileId[i]);
878                 procH_fileId[i] = 0;
879             }
880             ProcMgr_detach(procH[i]);
881             ProcMgr_close(&procH[i]);
882             procH[i] = NULL;
883             RscTable_free(&rscHandle[i]);
884             rscHandle[i] = NULL;
885         }
886     }
888     if (!recover && dev->ipc_recovery_work != NULL) {
889         OsalThread_delete (&dev->ipc_recovery_work);
890         dev->ipc_recovery_work = NULL;
891     }
893     if (recover) {
894         static FILE *log;
895         /* Dump the trace information */
896         Osal_printf("syslink: printing remote core trace dump to"
897                     " /var/log/ducati-m3-traces.log");
898         log = fopen ("/var/log/ducati-m3-traces.log", "a+");
899         if (log) {
900             for (id = 0; id < syslink_num_cores; id++) {
901                 if (proc_traces[id].va) {
902                     /* print traces */
903                     /* wait a little bit for traces to finish dumping */
904                     sleep(1);
905                     fprintf(log, "****************************************\n");
906                     fprintf(log, "***         CORE%d TRACE DUMP         ***\n",
907                             id);
908                     fprintf(log, "****************************************\n");
909                     for (i = (*proc_traces[id].widx + 1);
910                          i < (proc_traces[id].len - 8);
911                          i++) {
912                         fprintf(log, "%c",
913                                 *(char *)((uint32_t)proc_traces[id].va + i));
914                     }
915                     for (i = 0; i < *proc_traces[id].widx; i++) {
916                         fprintf(log, "%c",
917                                 *(char *)((uint32_t)proc_traces[id].va + i));
918                     }
919                 }
920             }
921             fclose(log);
922         }
923         else {
924             GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
925                                 "error opening /var/log/ducati-m3-traces.log");
926         }
927     }
929     status = Ipc_destroy();
930     if (status < 0) {
931         printf("Ipc_destroy() failed 0x%x", status);
932     }
933     if (!recover) {
934         status = MemoryOS_destroy();
935         if (status < 0) {
936             printf("MemoryOS_destroy() failed 0x%x", status);
937         }
938 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
939         if (dev->da_virt != MAP_FAILED) {
940 #ifdef SYSLINK_CARVEOUT
941             status = munmap(dev->da_virt, IPU_MEM_SIZE);
942 #else
943             status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
944 #endif
945             if (status < 0) {
946                printf("munmap failed %d", errno);
947             }
948         }
949 #endif
950     }
952     return status;
956 /* Read next line of available data for given 'core' and store it in buffer.
957  * Returns the number of bytes that were written or -1 on error
958  */
959 static int readNextTrace(int core, char* buffer, int bufSize)
961     char* readPtr;
962     uint32_t readBytes, ridx, widx;
963     syslink_trace_info* tinfo = &proc_traces[core];
965     /* Make sure it is valid */
966     if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
967         return -1;
968     }
970     /* Check to see if something to read */
971     if (tinfo->ridx == tinfo->widx) {
972         return 0;
973     }
975     readPtr = (char*) tinfo->va;
976     ridx = *tinfo->ridx;
977     widx = *tinfo->widx;
979     /* If first read, make sure that core is ready by validating ridx, widx */
980     if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
981         // not ready - will try again later
982         return 0;
983     }
985     /* Sanity check ridx/widx to make sure they point inside the buffer */
986     if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
987         Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
988             core, widx, ridx, tinfo->len);
989         return -1;
990     }
992     readBytes = 0;
993     tinfo->firstRead = FALSE;
994     /* Read until we hit newline indicating end of trace */
995     while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
996         buffer[readBytes] = readPtr[ridx];
997         readBytes++;
998         ridx++;
999         // Check for wrap-around
1000         if (ridx == tinfo->len) {
1001             ridx = 0;
1002         }
1003     }
1005     /* If did not find newline, abort since either not enough info or no room in buffer */
1006     if (readPtr[ridx] != '\n') {
1007         if (readBytes >= bufSize) {
1008             Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
1009                 core, readBytes, bufSize);
1010             return -1;
1011         }
1012         return 0;
1013     }
1015     /* Newline may not be valid data if this was not ready to be read */
1016     if (ridx == widx) {
1017         return 0;
1018     }
1020     /* We read a full line - null terminate and update ridx to mark data read */
1021     if (readBytes < bufSize) {
1022         buffer[readBytes] = '\0';
1023     } else {
1024         Osal_printf("C%d: No room to write NULL character", core);
1025         return -1;
1026     }
1027     readBytes++;
1028     ridx++;
1029     if (ridx == tinfo->len) {
1030         ridx = 0;
1031     }
1032     *tinfo->ridx = ridx;
1034     return readBytes;
1037 /* Thread reading ducati traces and writing them out to slog2 */
1038 static void *ducatiTraceThread(void *parm)
1040     int32_t bytesRead;
1041     int core;
1042     int err;
1043     Bool exit = FALSE;
1045     pthread_setname_np(0, "ducati-trace");
1047     pthread_mutex_lock(&trace_mutex);
1048     while ( (trace_active == TRUE) && (exit == FALSE) ) {
1049         for (core = 0; core < NUM_REMOTE_PROCS; core++) {
1050             while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1051 #if (_NTO_VERSION >= 800)
1052                 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1053 #else
1054                 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1055 #endif
1056                 if (trace_active == FALSE) {
1057                     break;
1058                 }
1059             }
1060             // Abort trace logger on errors as these should not occur
1061             if (bytesRead < 0) {
1062                 trace_active = FALSE;
1063             }
1064             if (trace_active == FALSE) {
1065                 break;
1066             }
1067         }
1068         if (trace_active == FALSE) {
1069             continue;
1070         }
1071         pthread_mutex_unlock(&trace_mutex);
1073         // No interrupts/events to trigger reading traces, so need to periodically poll
1074         usleep(TRACE_POLLING_INTERVAL_US);
1076         // If we are in hibernation, wait on condvar for end of hibernation
1077         pthread_mutex_lock(&syslink_hib_mutex);
1078         while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1079             err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1080             if (err != EOK) {
1081                 Osal_printf("pthread_cond_wait failed with err=%d", err);
1082                 exit = TRUE;
1083                 break;
1084             }
1085         }
1086         pthread_mutex_unlock(&syslink_hib_mutex);
1088         pthread_mutex_lock(&trace_mutex);
1089     }
1090     pthread_mutex_unlock(&trace_mutex);
1091     Osal_printf("ducati trace thread exited");
1092     return NULL;
1095 /* Initialize slog2 for Ducati traces */
1096 static int init_ducati_slog2(void)
1098 #if (_NTO_VERSION >= 800)
1099     slog2_buffer_set_config_t buffer_config;
1100     const char * buffer_set_name = "ducati";
1101     const char * buffer_name = "ducati_buffer";
1103     // Use command line verbosity for default verbosity level
1104     uint8_t verbosity_level = (uint8_t) verbosity;
1105     if ( verbosity_level > SLOG2_DEBUG2) {
1106         verbosity_level = SLOG2_DEBUG2;
1107     }
1109     // Initialize the buffer configuration
1110     buffer_config.buffer_set_name = (char *) buffer_set_name;
1111     buffer_config.num_buffers = 1;
1112     buffer_config.verbosity_level = verbosity_level;
1113     buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1114     buffer_config.buffer_config[0].num_pages = 8;
1116     // Register the Buffer Set
1117     if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1118         Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1119         return -1;
1120     }
1121 #endif
1123     return 0;
1126 /** print usage */
1127 static Void printUsage (Char * app)
1129     printf ("\n%s: [-fHT]\n", app);
1130     printf ("  -f   specify the binary file to load to the remote cores)\n");
1131 #if defined(SYSLINK_PLATFORM_OMAP5430)
1132     printf ("  -d   specify the binary file to load to the dsp)\n");
1133 #endif
1134     printf ("  -H   enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1135     printf ("  -T   specify the hibernation timeout in ms, Default: 5000 ms)\n");
1137     exit (EXIT_SUCCESS);
1140 dispatch_t * syslink_dpp = NULL;
1142 int main(int argc, char *argv[])
1144     syslink_dev_t * dev = NULL;
1145     thread_pool_attr_t tattr;
1146     int status;
1147     int error = 0;
1148     sigset_t set;
1149     int channelid = 0;
1150     int c;
1151     int hib_enable = 1;
1152     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1153     char *user_parm = NULL;
1154     struct stat          sbuf;
1156     if (-1 != stat("/dev/syslink", &sbuf)) {
1157         printf ("Syslink Already Running...\n");
1158         return EXIT_FAILURE;
1159     }
1160     printf ("Starting syslink resource manager...\n");
1162     /* Parse the input args */
1163     while (1)
1164     {
1165         c = getopt (argc, argv, "f:d:H:T:U:v:");
1166         if (c == -1)
1167             break;
1169         switch (c)
1170         {
1171         case 'f':
1172             /* for backward compatibility, "-f" option loaded Ducati/Benelli */
1173             syslink_firmware[syslink_num_cores].firmware = optarg;
1174 #if defined(SYSLINK_PLATFORM_OMAP4430)
1175             syslink_firmware[syslink_num_cores].proc = "SYSM3";
1176 #else
1177             syslink_firmware[syslink_num_cores].proc = "CORE0";
1178 #endif
1179             syslink_num_cores++;
1180 #ifndef SYSLINK_SYSBIOS_SMP
1181             syslink_firmware[syslink_num_cores].firmware = NULL;
1182 #if defined(SYSLINK_PLATFORM_OMAP4430)
1183             syslink_firmware[syslink_num_cores].proc = "APPM3";
1184 #else
1185             syslink_firmware[syslink_num_cores].proc = "CORE1";
1186 #endif
1187             syslink_num_cores++;
1188 #endif
1189             break;
1190 #if defined(SYSLINK_PLATFORM_OMAP5430)
1191         case 'd':
1192             syslink_firmware[syslink_num_cores].firmware = optarg;
1193             syslink_firmware[syslink_num_cores].proc = "DSP";
1194             syslink_num_cores++;
1195             break;
1196 #endif
1197         case 'H':
1198             hib_enable = atoi(optarg);
1199             if (hib_enable != 0 && hib_enable != 1) {
1200                 hib_enable = -1;
1201             }
1202             break;
1203         case 'T':
1204             hib_timeout = atoi(optarg);
1205             break;
1206         case 'U':
1207             user_parm = optarg;
1208             break;
1209         case 'v':
1210             verbosity++;
1211             break;
1212         default:
1213             fprintf (stderr, "Unrecognized argument\n");
1214         }
1215     }
1217     /* Now parse the operands, which should be in the format:
1218      * "<multiproc_name> <firmware_file> ..*/
1219     for (; optind + 1 < argc; optind+=2) {
1220         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1221             printUsage(argv[0]);
1222             return (error);
1223         }
1224         syslink_firmware[syslink_num_cores].proc = argv [optind];
1225         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1226     }
1229     /* Get the name of the binary from the input args */
1230     if (!syslink_num_cores) {
1231         fprintf(stderr, "-f or -d or <core_id> option must be specified");
1232         printUsage(argv[0]);
1233         return (error);
1234     }
1236     /* Validate hib_enable args */
1237     if (hib_enable == -1) {
1238         fprintf (stderr, "invalid hibernation enable value\n");
1239         printUsage(argv[0]);
1240         return (error);
1241     }
1243     syslink_hib_enable = (Bool)hib_enable;
1244     syslink_hib_timeout = hib_timeout;
1246     /* Init logging for syslink */
1247     if (Osal_initlogging(verbosity) != 0) {
1248         return -1;
1249     }
1251     /* Obtain I/O privity */
1252     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1253     if (error == -1) {
1254         Osal_printf("Unable to obtain I/O privity");
1255         return (error);
1256     }
1258     /* allocate the device structure */
1259     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1260         Osal_printf("syslink: calloc() failed");
1261         return (-1);
1262     }
1264     /* create the channel */
1265     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1266                                     _NTO_CHF_DISCONNECT |
1267                                     _NTO_CHF_COID_DISCONNECT |
1268                                     _NTO_CHF_REPLY_LEN |
1269                                     _NTO_CHF_SENDER_LEN)) < 0) {
1270         Osal_printf("Unable to create channel %d", channelid);
1271         return (channelid);
1272     }
1274     /* create the dispatch structure */
1275     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1276         Osal_printf("syslink:  dispatch_create() failed");
1277         return(-1);
1278     }
1280     /* Initialize the thread pool */
1281     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1282     tattr.handle = dev->dpp;
1283     tattr.context_alloc = dispatch_context_alloc;
1284     tattr.context_free = dispatch_context_free;
1285     tattr.block_func = dispatch_block;
1286     tattr.unblock_func = dispatch_unblock;
1287     tattr.handler_func = dispatch_handler;
1288     tattr.lo_water = 2;
1289     tattr.hi_water = 4;
1290     tattr.increment = 1;
1291     tattr.maximum = 10;
1293     /* Create the thread pool */
1294     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1295         Osal_printf("syslink: thread pool create failed");
1296         return(-1);
1297     }
1299     /* init syslink */
1300     status = init_ipc(dev, syslink_firmware, FALSE);
1301     if (status < 0) {
1302         Osal_printf("syslink: IPC init failed");
1303         return(-1);
1304     }
1306     /* init the syslink device */
1307     status = init_devices(dev);
1308     if (status < 0) {
1309         Osal_printf("syslink: device init failed");
1310         return(-1);
1311     }
1313 #if (_NTO_VERSION >= 800)
1314     /* Relinquish privileges */
1315     status = procmgr_ability(  0,
1316                  DENY_ALL | PROCMGR_AID_SPAWN,
1317                  DENY_ALL | PROCMGR_AID_FORK,
1318                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1319                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1320                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1321                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1322                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1323                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1324                  (uint64_t)1, (uint64_t)~0,
1325                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1326                  (uint64_t)1, (uint64_t)~0,
1327                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1329     if (status != EOK) {
1330         Osal_printf("procmgr_ability failed! errno=%d", status);
1331         return EXIT_FAILURE;
1332     }
1334     /* Reduce priority to either what defined from command line or at least nobody */
1335     if (user_parm != NULL) {
1336         if (set_ids_from_arg(user_parm) < 0) {
1337             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1338             return EXIT_FAILURE;
1339         }
1340     } else {
1341         if (setuid(99) != 0) {
1342             Osal_printf("unable to set uid - %s", strerror(errno));
1343             return EXIT_FAILURE;
1344         }
1345     }
1346 #endif
1348     /* make this a daemon process */
1349     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1350         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1351         Osal_printf("syslink:  procmgr_daemon() failed");
1352         return(-1);
1353     }
1355     /* start the thread pool */
1356     thread_pool_start(dev->tpool);
1358     /* Init slog2 and thread for Ducati traces */
1359     if (init_ducati_slog2() != 0) {
1360         return -1;
1361     }
1362     trace_active = TRUE;
1363     status = pthread_create (&thread_traces, NULL, ducatiTraceThread, NULL);
1364     if (status != EOK) {
1365         Osal_printf("pthread_create for trace thread failed err=%d", status);
1366         trace_active = FALSE;
1367     }
1369     /* Mask out unnecessary signals */
1370     sigfillset (&set);
1371     sigdelset (&set, SIGINT);
1372     sigdelset (&set, SIGTERM);
1373     pthread_sigmask (SIG_BLOCK, &set, NULL);
1375     /* Wait for one of these signals */
1376     sigemptyset (&set);
1377     sigaddset (&set, SIGINT);
1378     sigaddset (&set, SIGQUIT);
1379     sigaddset (&set, SIGTERM);
1381     Osal_printf("Syslink resource manager started");
1383     /* Wait for a signal */
1384     while (1)
1385     {
1386         switch (SignalWaitinfo (&set, NULL))
1387         {
1388             case SIGTERM:
1389             case SIGQUIT:
1390             case SIGINT:
1391                 error = EOK;
1392                 goto done;
1394             default:
1395                 break;
1396         }
1397     }
1399     error = EOK;
1401 done:
1402     GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1403     /* Stop ducatiTraceThread if running */
1404     pthread_mutex_lock(&trace_mutex);
1405     if (trace_active) {
1406         trace_active = FALSE;
1407         pthread_mutex_unlock(&trace_mutex);
1408         // Wake up if waiting on hibernation
1409         pthread_mutex_lock(&syslink_hib_mutex);
1410         syslink_hib_hibernating = FALSE;
1411         pthread_cond_broadcast(&syslink_hib_cond);
1412         pthread_mutex_unlock(&syslink_hib_mutex);
1413         error = pthread_join(thread_traces, NULL);
1414         if (error < 0) {
1415             Osal_printf("syslink: pthread_join failed with err=%d", error);
1416         }
1417     } else {
1418         pthread_mutex_unlock(&trace_mutex);
1419     }
1421     error = thread_pool_destroy(dev->tpool);
1422     if (error < 0)
1423         Osal_printf("syslink: thread_pool_destroy returned an error");
1424     deinit_ipc(dev, FALSE);
1425     deinit_devices(dev);
1426     free(dev);
1427     return (EOK);