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