]> 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
Merge remote-tracking branch 'vincent-ext/3.00.00.13_eng' into 12_eng
[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 Void GateHWSpinlock_LeaveLockForPID(int pid);
127 typedef struct syslink_firmware_info_t {
128     uint16_t proc_id;
129     char * proc;
130     char * firmware;
131 } syslink_firmware_info;
132 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
133 static unsigned int syslink_num_cores = 0;
135 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
136 int deinit_ipc(syslink_dev_t * dev, bool recover);
138 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
140 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
141 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
142 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
143                                     ProcMgr_State_Error,
144                                     ProcMgr_State_Watchdog,
145                                     ProcMgr_State_EndValue};
147 typedef struct syslink_trace_info_t {
148     uintptr_t   va;
149     uint32_t    len;
150     uint32_t *  widx;
151     uint32_t *  ridx;
152     Bool        firstRead;
153 } syslink_trace_info;
155 static syslink_trace_info proc_traces[NUM_REMOTE_PROCS];
157 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
159     int         nbytes;
160     int         nparts;
161     int         status;
162     int         nleft;
163     uint32_t    len;
164     uint16_t    procid = ocb->ocb.attr->procid;
166     if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
167         return (status);
169     if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
170         return (ENOSYS);
172     /* check to see where the trace buffer is */
173     if (proc_traces[procid].va == NULL) {
174         return (ENOSYS);
175     }
177     /* need to abort ducati trace thread if it is running as only want one reader */
178     pthread_mutex_lock(&trace_mutex);
179     if (trace_active == TRUE) {
180         trace_active = FALSE;
181         pthread_mutex_unlock(&trace_mutex);
182         // Wake up if waiting on hibernation
183         pthread_mutex_lock(&syslink_hib_mutex);
184         syslink_hib_hibernating = FALSE;
185         pthread_cond_broadcast(&syslink_hib_cond);
186         pthread_mutex_unlock(&syslink_hib_mutex);
187         pthread_join(thread_traces, NULL);
188     } else {
189         pthread_mutex_unlock(&trace_mutex);
190     }
192     if (ocb->ocb.offset == 0) {
193         ocb->widx = *(proc_traces[procid].widx);
194         ocb->ridx = *(proc_traces[procid].ridx);
195         *(proc_traces[procid].ridx) = ocb->widx;
196     }
198     /* Check for wrap-around */
199     if (ocb->widx < ocb->ridx)
200         len = proc_traces[procid].len - ocb->ridx + ocb->widx;
201     else
202         len = ocb->widx - ocb->ridx;
204     /* Determine the amount left to print */
205     if (ocb->widx >= ocb->ridx)
206         nleft = len - ocb->ocb.offset;
207     else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
208         nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
209     else
210         nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
212     nbytes = min (msg->i.nbytes, nleft);
214     /* Make sure the user has supplied a big enough buffer */
215     if (nbytes > 0) {
216         /* set up the return data IOV */
217         if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
218             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
219         else
220             SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
222         /* set up the number of bytes (returned by client's read()) */
223         _IO_SET_READ_NBYTES (ctp, nbytes);
225         ocb->ocb.offset += nbytes;
227         nparts = 1;
228     }
229     else {
230         _IO_SET_READ_NBYTES (ctp, 0);
232         /* reset offset */
233         ocb->ocb.offset = 0;
235         nparts = 0;
236     }
238     /* mark the access time as invalid (we just accessed it) */
240     if (msg->i.nbytes > 0)
241         ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
243     return (_RESMGR_NPARTS (nparts));
246 extern OsalSemaphore_Handle mqcopy_test_sem;
248 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
250     int status = _RESMGR_NOREPLY;
251     struct _msg_info info;
253     /*
254      * Try to run the default unblock for this message.
255      */
256     if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
257         return status;
258     }
260     /*
261      * Check if rcvid is still valid and still has an unblock
262      * request pending.
263      */
264     if (MsgInfo(ctp->rcvid, &info) == -1 ||
265         !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
266         return _RESMGR_NOREPLY;
267     }
269     if (mqcopy_test_sem)
270         OsalSemaphore_post(mqcopy_test_sem);
272     return _RESMGR_NOREPLY;
275 IOFUNC_OCB_T *
276 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
278     syslink_ocb_t *ocb = NULL;
280     /* Allocate the OCB */
281     ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
282     if (ocb == NULL){
283         errno = ENOMEM;
284         return (NULL);
285     }
287     ocb->pid = ctp->info.pid;
289     return (IOFUNC_OCB_T *)(ocb);
292 void
293 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
295     syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
297     if (ocb) {
298         GateHWSpinlock_LeaveLockForPID(ocb->pid);
299         free (ocb);
300     }
303 /* Initialize the syslink device */
304 int init_syslink_device(syslink_dev_t *dev)
306     iofunc_attr_t *  attr;
307     syslink_attr_t * trace_attr;
308     resmgr_attr_t    resmgr_attr;
309     int              i;
310     char             trace_name[_POSIX_PATH_MAX];
311     int              status = 0;
312     u32              da = 0, pa = 0;
313     u32              len;
315     pthread_mutex_init(&dev->lock, NULL);
317     memset(&resmgr_attr, 0, sizeof resmgr_attr);
318     resmgr_attr.nparts_max = 10;
319     resmgr_attr.msg_max_size = 2048;
321     memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
322     dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
323     dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
324                               IOFUNC_PC_NO_TRUNC |
325                               IOFUNC_PC_SYNC_IO;
326     dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
328     memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
329     dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
331     iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
332                     _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
334     iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
336     dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
337     dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
338     dev->syslink.iofuncs.devctl = syslink_devctl;
339     dev->syslink.iofuncs.unblock = syslink_unblock;
341     attr->mount = &dev->syslink.mattr;
342     iofunc_time_update(attr);
344     if (-1 == (dev->syslink.resmgr_id =
345         resmgr_attach(dev->dpp, &resmgr_attr,
346                       IPC_DEVICE_PATH, _FTYPE_ANY, 0,
347                       &dev->syslink.cfuncs,
348                       &dev->syslink.iofuncs, attr))) {
349         return(-1);
350     }
352     for (i = 0; i < syslink_num_cores; i++) {
353         iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
354                          _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
355         trace_attr = &dev->syslink.cattr_trace[i];
356         iofunc_attr_init(&trace_attr->attr,
357                          S_IFCHR | 0777, NULL, NULL);
358         trace_attr->attr.mount = &dev->syslink.mattr;
359         trace_attr->procid = i;
360         iofunc_time_update(&trace_attr->attr);
361         snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
362                   "/dev/syslink-trace%d", syslink_firmware[i].proc_id);
363         dev->syslink.iofuncs_trace[i].read = syslink_read;
364         snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
365         pa = 0;
366         status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
367         if (status == 0) {
368             /* last 8 bytes are for writeIdx/readIdx */
369             proc_traces[i].len = len - (sizeof(uint32_t) * 2);
370             if (da && !pa) {
371                 /* need to translate da->pa */
372                 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
373                                                 (Ptr *) &pa,
374                                                 ProcMgr_AddrType_MasterPhys,
375                                                 (Ptr) da,
376                                                 ProcMgr_AddrType_SlaveVirt);
377             }
378             /* map length aligned to page size */
379             proc_traces[i].va =
380                     mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
381             proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
382                                                proc_traces[i].len);
383             proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
384                                                sizeof(uint32_t));
385             if (proc_traces[i].va == MAP_DEVICE_FAILED) {
386                 proc_traces[i].va = NULL;
387             }
388             proc_traces[i].firstRead = TRUE;
389         }
390         else {
391             proc_traces[i].va = NULL;
392         }
393         if (-1 == (dev->syslink.resmgr_id_trace[i] =
394                        resmgr_attach(dev->dpp, &resmgr_attr,
395                                      dev->syslink.device_name, _FTYPE_ANY, 0,
396                                      &dev->syslink.cfuncs_trace[i],
397                                      &dev->syslink.iofuncs_trace[i],
398                                      &trace_attr->attr))) {
399             return(-1);
400         }
401     }
403     return(0);
406 /* De-initialize the syslink device */
407 int deinit_syslink_device(syslink_dev_t *dev)
409     int status = EOK;
410     int i = 0;
412     status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
413     if (status < 0) {
414         Osal_printf("syslink: resmgr_detach failed %d", errno);
415         status = errno;
416     }
418     for (i = 0; i < syslink_num_cores; i++) {
419         status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
420         if (status < 0) {
421             Osal_printf("syslink: resmgr_detach failed %d", errno);
422             status = errno;
423         }
424         if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED)
425             munmap((void *)proc_traces[i].va,
426                    ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
427         proc_traces[i].va = NULL;
428     }
430     return(status);
434 /* Initialize the devices */
435 int init_devices(syslink_dev_t *dev)
437     if (init_syslink_device(dev) < 0) {
438         Osal_printf("syslink: syslink device init failed");
439         return(-1);
440     }
442     return(0);
446 /* De-initialize the devices */
447 int deinit_devices(syslink_dev_t *dev)
449     int status = EOK;
451     if ((status = deinit_syslink_device(dev)) < 0) {
452         fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
453         status = errno;
454     }
456     return(status);
459 static void ipc_recover(Ptr args)
461     syslink_dev_t * dev = (syslink_dev_t *)args;
463     deinit_ipc(dev, TRUE);
464     init_ipc(dev, syslink_firmware, TRUE);
467 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
468                       ProcMgr_State fromState, ProcMgr_State toState,
469                       ProcMgr_EventStatus status, Ptr args)
471     Int ret = 0;
472     String errString = NULL;
473     syslink_dev_t * dev = (syslink_dev_t *)args;
475     if (status == ProcMgr_EventStatus_Event) {
476         switch (toState) {
477             case ProcMgr_State_Mmu_Fault:
478                 errString = "MMU Fault";
479                 break;
480             case ProcMgr_State_Error:
481                 errString = "Exception";
482                 break;
483             case ProcMgr_State_Watchdog:
484                 errString = "Watchdog";
485                 break;
486             default:
487                 errString = "Unexpected State";
488                 ret = -1;
489                 break;
490         }
491         GT_2trace (curTrace, GT_4CLASS,
492                    "syslink_error_cb: Received Error Callback for %s : %s\n",
493                    MultiProc_getName(procId), errString);
494         /* Don't allow re-schedule of recovery until complete */
495         pthread_mutex_lock(&dev->lock);
496         if (ret != -1 && dev->recover == FALSE) {
497             /* Schedule recovery. */
498             dev->recover = TRUE;
499             /* Activate a thread to handle the recovery. */
500             GT_0trace (curTrace, GT_4CLASS,
501                        "syslink_error_cb: Scheduling recovery...");
502             OsalThread_activate(dev->ipc_recovery_work);
503         }
504         else {
505             GT_0trace (curTrace, GT_4CLASS,
506                        "syslink_error_cb: Recovery already scheduled.");
507         }
508         pthread_mutex_unlock(&dev->lock);
509     }
510     else if (status == ProcMgr_EventStatus_Canceled) {
511         GT_1trace (curTrace, GT_3CLASS,
512                    "SysLink Error Callback Cancelled for %s",
513                    MultiProc_getName(procId));
514     }
515     else {
516         GT_1trace (curTrace, GT_4CLASS,
517                    "SysLink Error Callback Unexpected Event for %s",
518                    MultiProc_getName(procId));
519     }
521     return ret;
524 #if defined(SYSLINK_PLATFORM_OMAP4430)
525 #define SYSLINK_CARVEOUT
526 #ifdef SYSLINK_CARVEOUT
527 #define IPU_MEM_SIZE  49 * 1024 * 1024
528 #define IPU_MEM_PHYS  0x97F00000
529 #else
530 #define IPU_MEM_SIZE  104 * 1024 * 1024
531 #define IPU_MEM_ALIGN 0x1000000
532 #endif
533 #else
534 // only need mem for DEVMEM entries, rest is allocated dynamically
535 #define IPU_MEM_SIZE  90 * 1024 * 1024
536 #define IPU_MEM_ALIGN 0x0
538 #endif
540 unsigned int syslink_ipu_mem_size = IPU_MEM_SIZE;
541 #if defined(SYSLINK_PLATFORM_OMAP5430)
542 unsigned int syslink_dsp_mem_size = IPU_MEM_SIZE;
543 #endif
545 /*
546  * Initialize the syslink ipc
547  *
548  * This function sets up the "kernel"-side IPC modules, and does any special
549  * initialization required for QNX and the platform being used.  This function
550  * also registers for error notifications and initializes the recovery thread.
551  */
552 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
554     int status = 0;
555 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
556     int32_t ret = 0;
557     uint32_t len = 0;
558 #ifndef SYSLINK_CARVEOUT
559     int64_t pa = 0;
560     void * da;
561 #endif
562     int64_t paddr = 0;
563 #endif
564     Ipc_Config iCfg;
565     OsalThread_Params threadParams;
566     ProcMgr_AttachParams attachParams;
567     UInt16 procId;
568     int i;
570 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
571     /* Map a contiguous memory section for ipu - currently hard-coded */
572     if (!recover) {
573 #ifdef SYSLINK_CARVEOUT
574         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
575                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
576                               MAP_PHYS,
577                               NOFD,
578                               IPU_MEM_PHYS);
579 #else
580 #if defined(SYSLINK_PLATFORM_OMAP5430)
581         dev->da_tesla_virt =
582 #endif
583         dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
584                               PROT_NOCACHE | PROT_READ | PROT_WRITE,
585                               MAP_ANON | MAP_PHYS | MAP_SHARED,
586                               NOFD,
587                               0);
589 #endif
591         if (dev->da_virt == MAP_FAILED) {
592             status = ENOMEM;
593             goto exit;
594         }
595     }
597     if (status >= 0) {
598 #ifdef SYSLINK_CARVEOUT
599         /* Make sure the memory is contiguous */
600         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
601         if (ret)
602             status = ret;
603         else if (len != IPU_MEM_SIZE)
604             status = ENOMEM;
605 #else
606         /* Make sure the memory is contiguous */
607         ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
608                            &paddr, &len);
609         if (ret)
610             status = ret;
611         else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
612             status = ENOMEM;
613         else {
614 #if defined(SYSLINK_PLATFORM_OMAP4430)
615             pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
616             if ((pa - paddr) < 0x900000)
617                 pa += 0x900000;
618             else
619                 pa -= 0x700000;
620             da = dev->da_virt + (pa - paddr);
621 #else
622             pa = paddr;
623             da = dev->da_virt;
624 #endif
625         }
626 #endif
627         if (status != 0)
628             goto memoryos_fail;
629     }
630 #endif
632 #if defined(SYSLINK_PLATFORM_OMAP5430)
633     if (status >= 0) {
634         iCfg.pAddr_dsp = (uint32_t)pa;
635         iCfg.vAddr_dsp = (uint32_t)da;
636     }
637 #endif
638     if (status >= 0) {
639         if (!recover) {
640             /* Set up the MemoryOS module */
641             status = MemoryOS_setup();
642             if (status < 0)
643                 goto memoryos_fail;
644         }
646         /* Setup IPC and platform-specific items */
647 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
648 #ifdef SYSLINK_CARVEOUT
649         iCfg.vAddr = (uint32_t)dev->da_virt;
650         iCfg.pAddr = (uint32_t)paddr;
651 #else
652         iCfg.vAddr = (uint32_t)da;
653         iCfg.pAddr = (uint32_t)pa;
654 #endif
655 #endif
656         status = Ipc_setup (&iCfg);
657         if (status < 0)
658             goto ipcsetup_fail;
660         /* NOTE: this is for handling the procmgr event notifications to userspace list */
661         if (!recover) {
662             /* Setup Fault recovery items. */
663             /* Create the thread object used for the interrupt handler. */
664             threadParams.priority     = OsalThread_Priority_Medium;
665             threadParams.priorityType = OsalThread_PriorityType_Generic;
666             threadParams.once         = FALSE;
667             dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
668                                                         ipc_recover,
669                                                         dev,
670                                                         &threadParams);
671             if (dev->ipc_recovery_work == NULL)
672                 goto osalthreadcreate_fail;
673         }
674         else {
675             pthread_mutex_lock(&dev->lock);
676             dev->recover = FALSE;
677             pthread_mutex_unlock(&dev->lock);
678         }
680         for (i = 0; i < syslink_num_cores; i++) {
681             procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
682             if (procId >= MultiProc_MAXPROCESSORS || procH[procId]) {
683                 GT_setFailureReason (curTrace,
684                                      GT_4CLASS,
685                                      "init_ipc",
686                                      status,
687                                      "invalid proc!");
688                 break;
689             }
691             if (syslink_firmware[i].firmware) {
692                 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
693                 if (rscHandle[procId] == NULL) {
694                     status = -1;
695                     break;
696                 }
697             }
699             status = ProcMgr_open(&procH[procId], procId);
700             if (status < 0 || procH[procId] == NULL)
701                 goto procmgropen_fail;
703             /* Load and start the remote processor. */
704             ProcMgr_getAttachParams (procH[procId], &attachParams);
705             status = ProcMgr_attach (procH[procId], &attachParams);
706             if (status < 0) {
707                 GT_setFailureReason (curTrace,
708                                      GT_4CLASS,
709                                      "init_ipc",
710                                      status,
711                                      "ProcMgr_attach failed!");
712                 goto procmgrattach_fail;
713             }
715             if (syslink_firmware[i].firmware) {
716                 status = ProcMgr_load (procH[procId],
717                                        (String)firmware[i].firmware, 0, NULL,
718                                         NULL, &procH_fileId[procId]);
719                 if (status < 0) {
720                     GT_setFailureReason (curTrace,
721                                          GT_4CLASS,
722                                          "init_ipc",
723                                          status,
724                                          "ProcMgr_load failed!");
725                     goto procmgrload_fail;
726                 }
727             }
729             status = Ipc_attach (procId);
730             if (status < 0) {
731                 GT_setFailureReason (curTrace,
732                                      GT_4CLASS,
733                                      "init_ipc",
734                                      status,
735                                      "Ipc_attach failed!");
736                 goto ipcattach_fail;
737             }
739             status = ProcMgr_start(procH[procId], NULL);
740             if (status < 0) {
741                 GT_setFailureReason (curTrace,
742                                      GT_4CLASS,
743                                      "init_ipc",
744                                      status,
745                                      "ProcMgr_start failed!");
746                 goto procmgrstart_fail;
747             }
749             status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
750                                             -1, errStates);
751             if (status < 0)
752                 goto procmgrreg_fail;
754             continue;
756 procmgrreg_fail:
757             ProcMgr_stop(procH[procId]);
758 procmgrstart_fail:
759             Ipc_detach(procId);
760 ipcattach_fail:
761             if (syslink_firmware[i].firmware)
762                 ProcMgr_unload(procH[procId], procH_fileId[procId]);
763 procmgrload_fail:
764             ProcMgr_detach(procH[procId]);
765 procmgrattach_fail:
766             ProcMgr_close(&procH[procId]);
767             procH[procId] = NULL;
768 procmgropen_fail:
769             RscTable_free(&rscHandle[procId]);
770             break;
771         }
773         if (status < 0)
774             goto resmgrsetup_fail;
776         /* Set up the resmgr */
777         status = rpmsg_resmgr_setup();
778         if (status < 0)
779             goto resmgrsetup_fail;
781         /* Set up rpmsg_omx */
782         status = rpmsg_omx_setup();
783         if (status < 0)
784             goto omxsetup_fail;
786         /* Set up rpmsg_dce */
787         status = rpmsg_dce_setup();
788         if (status < 0)
789             goto dcesetup_fail;
791         /* Set up rpmsg_mq */
792         status = ti_ipc_setup();
793         if (status < 0)
794             goto tiipcsetup_fail;
796         goto exit;
797     }
799 tiipcsetup_fail:
800     rpmsg_dce_destroy();
801 dcesetup_fail:
802     rpmsg_omx_destroy();
803 omxsetup_fail:
804     rpmsg_resmgr_destroy();
805 resmgrsetup_fail:
806     for (i-=1; i >= 0; i--) {
807         procId = firmware[i].proc_id;
808         ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
809                                 (Ptr)dev, errStates);
810         ProcMgr_stop(procH[procId]);
811         if (procH_fileId[procId]) {
812             ProcMgr_unload(procH[procId], procH_fileId[procId]);
813             procH_fileId[procId] = 0;
814         }
815         ProcMgr_detach(procH[procId]);
816         ProcMgr_close(&procH[procId]);
817         procH[procId] = NULL;
818         RscTable_free(&rscHandle[procId]);
819         rscHandle[procId] = NULL;
820     }
821     OsalThread_delete(&dev->ipc_recovery_work);
822 osalthreadcreate_fail:
823     Ipc_destroy();
824 ipcsetup_fail:
825     MemoryOS_destroy();
826 memoryos_fail:
827 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
828     if (dev->da_virt != MAP_FAILED)
829 #ifdef SYSLINK_CARVEOUT
830         munmap(dev->da_virt, IPU_MEM_SIZE);
831 #else
832         munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
833 #endif
834 #endif
835 exit:
836     return status;
839 int deinit_ipc(syslink_dev_t * dev, bool recover)
841     int status = EOK;
842     uint32_t i = 0, id = 0;
844     // Stop the remote cores right away
845     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
846         if (procH[i]) {
847             GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
848             ProcMgr_stop(procH[i]);
849         }
850     }
852     ti_ipc_destroy(recover);
854     rpmsg_dce_destroy();
856     rpmsg_omx_destroy();
858     rpmsg_resmgr_destroy();
860     for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
861         if (procH[i]) {
862             ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
863                                       errStates);
864             Ipc_detach(i);
865             if (procH_fileId[i]) {
866                 ProcMgr_unload(procH[i], procH_fileId[i]);
867                 procH_fileId[i] = 0;
868             }
869             ProcMgr_detach(procH[i]);
870             ProcMgr_close(&procH[i]);
871             procH[i] = NULL;
872             RscTable_free(&rscHandle[i]);
873             rscHandle[i] = NULL;
874         }
875     }
877     if (!recover && dev->ipc_recovery_work != NULL) {
878         OsalThread_delete (&dev->ipc_recovery_work);
879         dev->ipc_recovery_work = NULL;
880     }
882     if (recover) {
883         static FILE *log;
884         /* Dump the trace information */
885         Osal_printf("syslink: printing remote core trace dump to"
886                     " /var/log/ducati-m3-traces.log");
887         log = fopen ("/var/log/ducati-m3-traces.log", "a+");
888         if (log) {
889             for (id = 0; id < syslink_num_cores; id++) {
890                 if (proc_traces[id].va) {
891                     /* print traces */
892                     /* wait a little bit for traces to finish dumping */
893                     sleep(1);
894                     fprintf(log, "****************************************\n");
895                     fprintf(log, "***         CORE%d TRACE DUMP         ***\n",
896                             id);
897                     fprintf(log, "****************************************\n");
898                     for (i = (*proc_traces[id].widx + 1);
899                          i < (proc_traces[id].len - 8);
900                          i++) {
901                         fprintf(log, "%c",
902                                 *(char *)((uint32_t)proc_traces[id].va + i));
903                     }
904                     for (i = 0; i < *proc_traces[id].widx; i++) {
905                         fprintf(log, "%c",
906                                 *(char *)((uint32_t)proc_traces[id].va + i));
907                     }
908                 }
909             }
910             fclose(log);
911         }
912         else {
913             GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
914                                 "error opening /var/log/ducati-m3-traces.log");
915         }
916     }
918     status = Ipc_destroy();
919     if (status < 0) {
920         printf("Ipc_destroy() failed 0x%x", status);
921     }
922     if (!recover) {
923         status = MemoryOS_destroy();
924         if (status < 0) {
925             printf("MemoryOS_destroy() failed 0x%x", status);
926         }
927 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
928         if (dev->da_virt != MAP_FAILED) {
929 #ifdef SYSLINK_CARVEOUT
930             status = munmap(dev->da_virt, IPU_MEM_SIZE);
931 #else
932             status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
933 #endif
934             if (status < 0) {
935                printf("munmap failed %d", errno);
936             }
937         }
938 #endif
939     }
941     return status;
945 /* Read next line of available data for given 'core' and store it in buffer.
946  * Returns the number of bytes that were written or -1 on error
947  */
948 static int readNextTrace(int core, char* buffer, int bufSize)
950     char* readPtr;
951     uint32_t readBytes, ridx, widx;
952     syslink_trace_info* tinfo = &proc_traces[core];
954     /* Make sure it is valid */
955     if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
956         return -1;
957     }
959     /* Check to see if something to read */
960     if (tinfo->ridx == tinfo->widx) {
961         return 0;
962     }
964     readPtr = (char*) tinfo->va;
965     ridx = *tinfo->ridx;
966     widx = *tinfo->widx;
968     /* If first read, make sure that core is ready by validating ridx, widx */
969     if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
970         // not ready - will try again later
971         return 0;
972     }
974     /* Sanity check ridx/widx to make sure they point inside the buffer */
975     if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
976         Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
977             core, widx, ridx, tinfo->len);
978         return -1;
979     }
981     readBytes = 0;
982     tinfo->firstRead = FALSE;
983     /* Read until we hit newline indicating end of trace */
984     while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
985         buffer[readBytes] = readPtr[ridx];
986         readBytes++;
987         ridx++;
988         // Check for wrap-around
989         if (ridx == tinfo->len) {
990             ridx = 0;
991         }
992     }
994     /* If did not find newline, abort since either not enough info or no room in buffer */
995     if (readPtr[ridx] != '\n') {
996         if (readBytes >= bufSize) {
997             Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
998                 core, readBytes, bufSize);
999             return -1;
1000         }
1001         return 0;
1002     }
1004     /* Newline may not be valid data if this was not ready to be read */
1005     if (ridx == widx) {
1006         return 0;
1007     }
1009     /* We read a full line - null terminate and update ridx to mark data read */
1010     if (readBytes < bufSize) {
1011         buffer[readBytes] = '\0';
1012     } else {
1013         Osal_printf("C%d: No room to write NULL character", core);
1014         return -1;
1015     }
1016     readBytes++;
1017     ridx++;
1018     if (ridx == tinfo->len) {
1019         ridx = 0;
1020     }
1021     *tinfo->ridx = ridx;
1023     return readBytes;
1026 /* Thread reading ducati traces and writing them out to slog2 */
1027 static void *ducatiTraceThread(void *parm)
1029     int32_t bytesRead;
1030     int core;
1031     int err;
1032     Bool exit = FALSE;
1034     pthread_setname_np(0, "ducati-trace");
1036     pthread_mutex_lock(&trace_mutex);
1037     while ( (trace_active == TRUE) && (exit == FALSE) ) {
1038         for (core = 0; core < NUM_REMOTE_PROCS; core++) {
1039             while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1040 #if (_NTO_VERSION >= 800)
1041                 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1042 #else
1043                 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1044 #endif
1045                 if (trace_active == FALSE) {
1046                     break;
1047                 }
1048             }
1049             // Abort trace logger on errors as these should not occur
1050             if (bytesRead < 0) {
1051                 trace_active = FALSE;
1052             }
1053             if (trace_active == FALSE) {
1054                 break;
1055             }
1056         }
1057         if (trace_active == FALSE) {
1058             continue;
1059         }
1060         pthread_mutex_unlock(&trace_mutex);
1062         // No interrupts/events to trigger reading traces, so need to periodically poll
1063         usleep(TRACE_POLLING_INTERVAL_US);
1065         // If we are in hibernation, wait on condvar for end of hibernation
1066         pthread_mutex_lock(&syslink_hib_mutex);
1067         while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1068             err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1069             if (err != EOK) {
1070                 Osal_printf("pthread_cond_wait failed with err=%d", err);
1071                 exit = TRUE;
1072                 break;
1073             }
1074         }
1075         pthread_mutex_unlock(&syslink_hib_mutex);
1077         pthread_mutex_lock(&trace_mutex);
1078     }
1079     pthread_mutex_unlock(&trace_mutex);
1080     Osal_printf("ducati trace thread exited");
1081     return NULL;
1084 /* Initialize slog2 for Ducati traces */
1085 static int init_ducati_slog2(void)
1087 #if (_NTO_VERSION >= 800)
1088     slog2_buffer_set_config_t buffer_config;
1089     const char * buffer_set_name = "ducati";
1090     const char * buffer_name = "ducati_buffer";
1092     // Use command line verbosity for default verbosity level
1093     uint8_t verbosity_level = (uint8_t) verbosity;
1094     if ( verbosity_level > SLOG2_DEBUG2) {
1095         verbosity_level = SLOG2_DEBUG2;
1096     }
1098     // Initialize the buffer configuration
1099     buffer_config.buffer_set_name = (char *) buffer_set_name;
1100     buffer_config.num_buffers = 1;
1101     buffer_config.verbosity_level = verbosity_level;
1102     buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1103     buffer_config.buffer_config[0].num_pages = 8;
1105     // Register the Buffer Set
1106     if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1107         Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1108         return -1;
1109     }
1110 #endif
1112     return 0;
1115 /** print usage */
1116 static Void printUsage (Char * app)
1118     printf ("\n%s: [-fHT]\n", app);
1119     printf ("  -f   specify the binary file to load to the remote cores)\n");
1120 #if defined(SYSLINK_PLATFORM_OMAP5430)
1121     printf ("  -d   specify the binary file to load to the dsp)\n");
1122 #endif
1123     printf ("  -H   enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1124     printf ("  -T   specify the hibernation timeout in ms, Default: 5000 ms)\n");
1126     exit (EXIT_SUCCESS);
1129 dispatch_t * syslink_dpp = NULL;
1131 int main(int argc, char *argv[])
1133     syslink_dev_t * dev = NULL;
1134     thread_pool_attr_t tattr;
1135     int status;
1136     int error = 0;
1137     sigset_t set;
1138     int channelid = 0;
1139     int c;
1140     int hib_enable = 1;
1141     uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1142     char *user_parm = NULL;
1143     struct stat          sbuf;
1145     if (-1 != stat("/dev/syslink", &sbuf)) {
1146         printf ("Syslink Already Running...\n");
1147         return EXIT_FAILURE;
1148     }
1149     printf ("Starting syslink resource manager...\n");
1151     /* Parse the input args */
1152     while (1)
1153     {
1154         c = getopt (argc, argv, "f:d:H:T:U:v:");
1155         if (c == -1)
1156             break;
1158         switch (c)
1159         {
1160         case 'f':
1161             /* for backward compatibility, "-f" option loaded Ducati/Benelli */
1162             syslink_firmware[syslink_num_cores].firmware = optarg;
1163 #if defined(SYSLINK_PLATFORM_OMAP4430)
1164             syslink_firmware[syslink_num_cores].proc = "SYSM3";
1165 #else
1166             syslink_firmware[syslink_num_cores].proc = "CORE0";
1167 #endif
1168             syslink_num_cores++;
1169 #ifndef SYSLINK_SYSBIOS_SMP
1170             syslink_firmware[syslink_num_cores].firmware = NULL;
1171 #if defined(SYSLINK_PLATFORM_OMAP4430)
1172             syslink_firmware[syslink_num_cores].proc = "APPM3";
1173 #else
1174             syslink_firmware[syslink_num_cores].proc = "CORE1";
1175 #endif
1176             syslink_num_cores++;
1177 #endif
1178             break;
1179 #if defined(SYSLINK_PLATFORM_OMAP5430)
1180         case 'd':
1181             syslink_firmware[syslink_num_cores].firmware = optarg;
1182             syslink_firmware[syslink_num_cores].proc = "DSP";
1183             syslink_num_cores++;
1184             break;
1185 #endif
1186         case 'H':
1187             hib_enable = atoi(optarg);
1188             if (hib_enable != 0 && hib_enable != 1) {
1189                 hib_enable = -1;
1190             }
1191             break;
1192         case 'T':
1193             hib_timeout = atoi(optarg);
1194             break;
1195         case 'U':
1196             user_parm = optarg;
1197             break;
1198         case 'v':
1199             verbosity++;
1200             break;
1201         default:
1202             fprintf (stderr, "Unrecognized argument\n");
1203         }
1204     }
1206     /* Now parse the operands, which should be in the format:
1207      * "<multiproc_name> <firmware_file> ..*/
1208     for (; optind + 1 < argc; optind+=2) {
1209         if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1210             printUsage(argv[0]);
1211             return (error);
1212         }
1213         syslink_firmware[syslink_num_cores].proc = argv [optind];
1214         syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1215     }
1218     /* Get the name of the binary from the input args */
1219     if (!syslink_num_cores) {
1220         fprintf(stderr, "-f or -d or <core_id> option must be specified");
1221         printUsage(argv[0]);
1222         return (error);
1223     }
1225     /* Validate hib_enable args */
1226     if (hib_enable == -1) {
1227         fprintf (stderr, "invalid hibernation enable value\n");
1228         printUsage(argv[0]);
1229         return (error);
1230     }
1232     syslink_hib_enable = (Bool)hib_enable;
1233     syslink_hib_timeout = hib_timeout;
1235     /* Init logging for syslink */
1236     if (Osal_initlogging(verbosity) != 0) {
1237         return -1;
1238     }
1240     /* Obtain I/O privity */
1241     error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1242     if (error == -1) {
1243         Osal_printf("Unable to obtain I/O privity");
1244         return (error);
1245     }
1247     /* allocate the device structure */
1248     if (NULL == (dev = calloc(1, sizeof(syslink_dev_t)))) {
1249         Osal_printf("syslink: calloc() failed");
1250         return (-1);
1251     }
1253     /* create the channel */
1254     if ((channelid = ChannelCreate_r (_NTO_CHF_UNBLOCK |
1255                                     _NTO_CHF_DISCONNECT |
1256                                     _NTO_CHF_COID_DISCONNECT |
1257                                     _NTO_CHF_REPLY_LEN |
1258                                     _NTO_CHF_SENDER_LEN)) < 0) {
1259         Osal_printf("Unable to create channel %d", channelid);
1260         return (channelid);
1261     }
1263     /* create the dispatch structure */
1264     if (NULL == (dev->dpp = syslink_dpp = dispatch_create_channel (channelid, 0))) {
1265         Osal_printf("syslink:  dispatch_create() failed");
1266         return(-1);
1267     }
1269     /* Initialize the thread pool */
1270     memset (&tattr, 0x00, sizeof (thread_pool_attr_t));
1271     tattr.handle = dev->dpp;
1272     tattr.context_alloc = dispatch_context_alloc;
1273     tattr.context_free = dispatch_context_free;
1274     tattr.block_func = dispatch_block;
1275     tattr.unblock_func = dispatch_unblock;
1276     tattr.handler_func = dispatch_handler;
1277     tattr.lo_water = 2;
1278     tattr.hi_water = 4;
1279     tattr.increment = 1;
1280     tattr.maximum = 10;
1282     /* Create the thread pool */
1283     if ((dev->tpool = thread_pool_create(&tattr, 0)) == NULL) {
1284         Osal_printf("syslink: thread pool create failed");
1285         return(-1);
1286     }
1288     /* init syslink */
1289     status = init_ipc(dev, syslink_firmware, FALSE);
1290     if (status < 0) {
1291         Osal_printf("syslink: IPC init failed");
1292         return(-1);
1293     }
1295     /* init the syslink device */
1296     status = init_devices(dev);
1297     if (status < 0) {
1298         Osal_printf("syslink: device init failed");
1299         return(-1);
1300     }
1302 #if (_NTO_VERSION >= 800)
1303     /* Relinquish privileges */
1304     status = procmgr_ability(  0,
1305                  DENY_ALL | PROCMGR_AID_SPAWN,
1306                  DENY_ALL | PROCMGR_AID_FORK,
1307                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PEER,
1308                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_MEM_PHYS,
1309                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_INTERRUPT,
1310                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_PATHSPACE,
1311                  PROCMGR_ADN_NONROOT | PROCMGR_AOP_ALLOW | PROCMGR_AID_RSRCDBMGR,
1312                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETUID,
1313                  (uint64_t)1, (uint64_t)~0,
1314                  PROCMGR_ADN_ROOT | PROCMGR_AOP_ALLOW | PROCMGR_AOP_LOCK | PROCMGR_AOP_SUBRANGE | PROCMGR_AID_SETGID,
1315                  (uint64_t)1, (uint64_t)~0,
1316                  PROCMGR_ADN_ROOT | PROCMGR_AOP_DENY | PROCMGR_AOP_LOCK | PROCMGR_AID_EOL);
1318     if (status != EOK) {
1319         Osal_printf("procmgr_ability failed! errno=%d", status);
1320         return EXIT_FAILURE;
1321     }
1323     /* Reduce priority to either what defined from command line or at least nobody */
1324     if (user_parm != NULL) {
1325         if (set_ids_from_arg(user_parm) < 0) {
1326             Osal_printf("unable to set uid/gid - %s", strerror(errno));
1327             return EXIT_FAILURE;
1328         }
1329     } else {
1330         if (setuid(99) != 0) {
1331             Osal_printf("unable to set uid - %s", strerror(errno));
1332             return EXIT_FAILURE;
1333         }
1334     }
1335 #endif
1337     /* make this a daemon process */
1338     if (-1 == procmgr_daemon(EXIT_SUCCESS,
1339         PROCMGR_DAEMON_NOCLOSE | PROCMGR_DAEMON_NODEVNULL)) {
1340         Osal_printf("syslink:  procmgr_daemon() failed");
1341         return(-1);
1342     }
1344     /* start the thread pool */
1345     thread_pool_start(dev->tpool);
1347     /* Init slog2 and thread for Ducati traces */
1348     if (init_ducati_slog2() != 0) {
1349         return -1;
1350     }
1351     trace_active = TRUE;
1352     status = pthread_create (&thread_traces, NULL, ducatiTraceThread, NULL);
1353     if (status != EOK) {
1354         Osal_printf("pthread_create for trace thread failed err=%d", status);
1355         trace_active = FALSE;
1356     }
1358     /* Mask out unnecessary signals */
1359     sigfillset (&set);
1360     sigdelset (&set, SIGINT);
1361     sigdelset (&set, SIGTERM);
1362     pthread_sigmask (SIG_BLOCK, &set, NULL);
1364     /* Wait for one of these signals */
1365     sigemptyset (&set);
1366     sigaddset (&set, SIGINT);
1367     sigaddset (&set, SIGQUIT);
1368     sigaddset (&set, SIGTERM);
1370     Osal_printf("Syslink resource manager started");
1372     /* Wait for a signal */
1373     while (1)
1374     {
1375         switch (SignalWaitinfo (&set, NULL))
1376         {
1377             case SIGTERM:
1378             case SIGQUIT:
1379             case SIGINT:
1380                 error = EOK;
1381                 goto done;
1383             default:
1384                 break;
1385         }
1386     }
1388     error = EOK;
1390 done:
1391     GT_0trace(curTrace, GT_4CLASS, "Syslink resource manager exiting \n");
1392     /* Stop ducatiTraceThread if running */
1393     pthread_mutex_lock(&trace_mutex);
1394     if (trace_active) {
1395         trace_active = FALSE;
1396         pthread_mutex_unlock(&trace_mutex);
1397         // Wake up if waiting on hibernation
1398         pthread_mutex_lock(&syslink_hib_mutex);
1399         syslink_hib_hibernating = FALSE;
1400         pthread_cond_broadcast(&syslink_hib_cond);
1401         pthread_mutex_unlock(&syslink_hib_mutex);
1402         error = pthread_join(thread_traces, NULL);
1403         if (error < 0) {
1404             Osal_printf("syslink: pthread_join failed with err=%d", error);
1405         }
1406     } else {
1407         pthread_mutex_unlock(&trace_mutex);
1408     }
1410     error = thread_pool_destroy(dev->tpool);
1411     if (error < 0)
1412         Osal_printf("syslink: thread_pool_destroy returned an error");
1413     deinit_ipc(dev, FALSE);
1414     deinit_devices(dev);
1415     free(dev);
1416     return (EOK);