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