05608df389effa28cb8e802b6b22b392de5a2bd3
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_rpc_setup (Void);
119 extern Void rpmsg_rpc_destroy (Void);
120 extern Void GateHWSpinlock_LeaveLockForPID(int pid);
122 typedef struct syslink_firmware_info_t {
123 uint16_t proc_id;
124 char * proc;
125 char * firmware;
126 } syslink_firmware_info;
127 static syslink_firmware_info syslink_firmware[MultiProc_MAXPROCESSORS];
128 static unsigned int syslink_num_cores = 0;
130 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover);
131 int deinit_ipc(syslink_dev_t * dev, bool recover);
133 static RscTable_Handle rscHandle[MultiProc_MAXPROCESSORS];
135 static ProcMgr_Handle procH[MultiProc_MAXPROCESSORS];
136 static unsigned int procH_fileId[MultiProc_MAXPROCESSORS];
137 static ProcMgr_State errStates[] = {ProcMgr_State_Mmu_Fault,
138 ProcMgr_State_Error,
139 ProcMgr_State_Watchdog,
140 ProcMgr_State_EndValue};
142 typedef struct syslink_trace_info_t {
143 uintptr_t va;
144 uint32_t len;
145 uint32_t * widx;
146 uint32_t * ridx;
147 Bool firstRead;
148 } syslink_trace_info;
150 static syslink_trace_info proc_traces[MultiProc_MAXPROCESSORS];
152 int syslink_read(resmgr_context_t *ctp, io_read_t *msg, syslink_ocb_t *ocb)
153 {
154 int nbytes;
155 int nparts;
156 int status;
157 int nleft;
158 uint32_t len;
159 uint16_t procid = ocb->ocb.attr->procid;
161 if ((status = iofunc_read_verify (ctp, msg, &ocb->ocb, NULL)) != EOK)
162 return (status);
164 if ((msg->i.xtype & _IO_XTYPE_MASK) != _IO_XTYPE_NONE)
165 return (ENOSYS);
167 /* check to see where the trace buffer is */
168 if (proc_traces[procid].va == NULL) {
169 return (ENOSYS);
170 }
172 /* need to abort ducati trace thread if it is running as only want one reader */
173 pthread_mutex_lock(&trace_mutex);
174 if (trace_active == TRUE) {
175 trace_active = FALSE;
176 pthread_mutex_unlock(&trace_mutex);
177 // Wake up if waiting on hibernation
178 pthread_mutex_lock(&syslink_hib_mutex);
179 syslink_hib_hibernating = FALSE;
180 pthread_cond_broadcast(&syslink_hib_cond);
181 pthread_mutex_unlock(&syslink_hib_mutex);
182 pthread_join(thread_traces, NULL);
183 } else {
184 pthread_mutex_unlock(&trace_mutex);
185 }
187 if (ocb->ocb.offset == 0) {
188 ocb->widx = *(proc_traces[procid].widx);
189 ocb->ridx = *(proc_traces[procid].ridx);
190 *(proc_traces[procid].ridx) = ocb->widx;
191 }
193 /* Check for wrap-around */
194 if (ocb->widx < ocb->ridx)
195 len = proc_traces[procid].len - ocb->ridx + ocb->widx;
196 else
197 len = ocb->widx - ocb->ridx;
199 /* Determine the amount left to print */
200 if (ocb->widx >= ocb->ridx)
201 nleft = len - ocb->ocb.offset;
202 else if (ocb->ocb.offset < proc_traces[procid].len - ocb->ridx)
203 nleft = proc_traces[procid].len - ocb->ridx - ocb->ocb.offset;
204 else
205 nleft = proc_traces[procid].len - ocb->ridx + ocb->widx - ocb->ocb.offset;
207 nbytes = min (msg->i.nbytes, nleft);
209 /* Make sure the user has supplied a big enough buffer */
210 if (nbytes > 0) {
211 /* set up the return data IOV */
212 if (ocb->widx < ocb->ridx && ocb->ocb.offset >= proc_traces[procid].len - ocb->ridx)
213 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ocb.offset - (proc_traces[procid].len - ocb->ridx), nbytes);
214 else
215 SETIOV (ctp->iov, (char *)proc_traces[procid].va + ocb->ridx + ocb->ocb.offset, nbytes);
217 /* set up the number of bytes (returned by client's read()) */
218 _IO_SET_READ_NBYTES (ctp, nbytes);
220 ocb->ocb.offset += nbytes;
222 nparts = 1;
223 }
224 else {
225 _IO_SET_READ_NBYTES (ctp, 0);
227 /* reset offset */
228 ocb->ocb.offset = 0;
230 nparts = 0;
231 }
233 /* mark the access time as invalid (we just accessed it) */
235 if (msg->i.nbytes > 0)
236 ocb->ocb.attr->attr.flags |= IOFUNC_ATTR_ATIME;
238 return (_RESMGR_NPARTS (nparts));
239 }
241 extern OsalSemaphore_Handle mqcopy_test_sem;
243 int syslink_unblock(resmgr_context_t *ctp, io_pulse_t *msg, syslink_ocb_t *ocb)
244 {
245 int status = _RESMGR_NOREPLY;
246 struct _msg_info info;
248 /*
249 * Try to run the default unblock for this message.
250 */
251 if ((status = iofunc_unblock_default(ctp,msg,&(ocb->ocb))) != _RESMGR_DEFAULT) {
252 return status;
253 }
255 /*
256 * Check if rcvid is still valid and still has an unblock
257 * request pending.
258 */
259 if (MsgInfo(ctp->rcvid, &info) == -1 ||
260 !(info.flags & _NTO_MI_UNBLOCK_REQ)) {
261 return _RESMGR_NOREPLY;
262 }
264 if (mqcopy_test_sem)
265 OsalSemaphore_post(mqcopy_test_sem);
267 return _RESMGR_NOREPLY;
268 }
270 IOFUNC_OCB_T *
271 syslink_ocb_calloc (resmgr_context_t * ctp, IOFUNC_ATTR_T * device)
272 {
273 syslink_ocb_t *ocb = NULL;
275 /* Allocate the OCB */
276 ocb = (syslink_ocb_t *) calloc (1, sizeof (syslink_ocb_t));
277 if (ocb == NULL){
278 errno = ENOMEM;
279 return (NULL);
280 }
282 ocb->pid = ctp->info.pid;
284 return (IOFUNC_OCB_T *)(ocb);
285 }
287 void
288 syslink_ocb_free (IOFUNC_OCB_T * i_ocb)
289 {
290 syslink_ocb_t * ocb = (syslink_ocb_t *)i_ocb;
292 if (ocb) {
293 GateHWSpinlock_LeaveLockForPID(ocb->pid);
294 free (ocb);
295 }
296 }
298 int init_syslink_trace_device(syslink_dev_t *dev)
299 {
300 resmgr_attr_t resmgr_attr;
301 int i;
302 syslink_attr_t * trace_attr;
303 char trace_name[_POSIX_PATH_MAX];
304 int status = 0;
305 unsigned int da = 0, pa = 0;
306 unsigned int len;
308 memset(&resmgr_attr, 0, sizeof resmgr_attr);
309 resmgr_attr.nparts_max = 10;
310 resmgr_attr.msg_max_size = 2048;
312 for (i = 0; i < syslink_num_cores; i++) {
313 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs_trace[i],
314 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs_trace[i]);
315 trace_attr = &dev->syslink.cattr_trace[i];
316 iofunc_attr_init(&trace_attr->attr,
317 S_IFCHR | 0777, NULL, NULL);
318 trace_attr->attr.mount = &dev->syslink.mattr;
319 trace_attr->procid = i;
320 iofunc_time_update(&trace_attr->attr);
321 snprintf (dev->syslink.device_name, _POSIX_PATH_MAX,
322 "/dev/ipc-trace%d", syslink_firmware[i].proc_id);
323 dev->syslink.iofuncs_trace[i].read = syslink_read;
324 snprintf (trace_name, _POSIX_PATH_MAX, "%d", 0);
325 pa = 0;
326 status = RscTable_getInfo(syslink_firmware[i].proc_id, TYPE_TRACE, 0, &da, &pa, &len);
327 if (status == 0) {
328 /* last 8 bytes are for writeIdx/readIdx */
329 proc_traces[i].len = len - (sizeof(uint32_t) * 2);
330 if (da && !pa) {
331 /* need to translate da->pa */
332 status = ProcMgr_translateAddr (procH[syslink_firmware[i].proc_id],
333 (Ptr *) &pa,
334 ProcMgr_AddrType_MasterPhys,
335 (Ptr) da,
336 ProcMgr_AddrType_SlaveVirt);
337 }
338 else {
339 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
340 status, "not performing ProcMgr_translate");
341 }
342 /* map length aligned to page size */
343 proc_traces[i].va =
344 mmap_device_io (((len + 0x1000 - 1) / 0x1000) * 0x1000, pa);
345 proc_traces[i].widx = (uint32_t *)(proc_traces[i].va + \
346 proc_traces[i].len);
347 proc_traces[i].ridx = (uint32_t *)((uint32_t)proc_traces[i].widx + \
348 sizeof(uint32_t));
349 if (proc_traces[i].va == MAP_DEVICE_FAILED) {
350 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
351 status, "mmap_device_io failed");
352 GT_1trace(curTrace, GT_4CLASS, "errno %d", errno);
353 proc_traces[i].va = NULL;
354 }
355 proc_traces[i].firstRead = TRUE;
356 }
357 else {
358 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
359 status, "RscTable_getInfo failed");
360 proc_traces[i].va = NULL;
361 }
362 if (-1 == (dev->syslink.resmgr_id_trace[i] =
363 resmgr_attach(dev->dpp, &resmgr_attr,
364 dev->syslink.device_name, _FTYPE_ANY, 0,
365 &dev->syslink.cfuncs_trace[i],
366 &dev->syslink.iofuncs_trace[i],
367 &trace_attr->attr))) {
368 GT_setFailureReason(curTrace, GT_4CLASS, "init_syslink_trace_device",
369 status, "resmgr_attach failed");
370 return(-1);
371 }
372 }
374 return (status);
375 }
377 int deinit_syslink_trace_device(syslink_dev_t *dev)
378 {
379 int status = EOK;
380 int i = 0;
382 for (i = 0; i < syslink_num_cores; i++) {
383 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id_trace[i], 0);
384 if (status < 0) {
385 Osal_printf("syslink: resmgr_detach failed %d", errno);
386 status = errno;
387 }
388 if (proc_traces[i].va && proc_traces[i].va != MAP_DEVICE_FAILED) {
389 munmap((void *)proc_traces[i].va,
390 ((proc_traces[i].len + 8 + 0x1000 - 1) / 0x1000) * 0x1000);
391 }
392 proc_traces[i].va = NULL;
393 }
395 return (status);
396 }
398 /* Initialize the syslink device */
399 int init_syslink_device(syslink_dev_t *dev)
400 {
401 iofunc_attr_t * attr;
402 resmgr_attr_t resmgr_attr;
403 int status = 0;
405 pthread_mutex_init(&dev->lock, NULL);
407 memset(&resmgr_attr, 0, sizeof resmgr_attr);
408 resmgr_attr.nparts_max = 10;
409 resmgr_attr.msg_max_size = 2048;
411 memset(&dev->syslink.mattr, 0, sizeof(iofunc_mount_t));
412 dev->syslink.mattr.flags = ST_NOSUID | ST_NOEXEC;
413 dev->syslink.mattr.conf = IOFUNC_PC_CHOWN_RESTRICTED |
414 IOFUNC_PC_NO_TRUNC |
415 IOFUNC_PC_SYNC_IO;
416 dev->syslink.mattr.funcs = &dev->syslink.mfuncs;
418 memset(&dev->syslink.mfuncs, 0, sizeof(iofunc_funcs_t));
419 dev->syslink.mfuncs.nfuncs = _IOFUNC_NFUNCS;
421 iofunc_func_init(_RESMGR_CONNECT_NFUNCS, &dev->syslink.cfuncs,
422 _RESMGR_IO_NFUNCS, &dev->syslink.iofuncs);
424 iofunc_attr_init(attr = &dev->syslink.cattr, S_IFCHR | 0777, NULL, NULL);
426 dev->syslink.mfuncs.ocb_calloc = syslink_ocb_calloc;
427 dev->syslink.mfuncs.ocb_free = syslink_ocb_free;
428 dev->syslink.iofuncs.devctl = syslink_devctl;
429 dev->syslink.iofuncs.unblock = syslink_unblock;
431 attr->mount = &dev->syslink.mattr;
432 iofunc_time_update(attr);
434 if (-1 == (dev->syslink.resmgr_id =
435 resmgr_attach(dev->dpp, &resmgr_attr,
436 IPC_DEVICE_PATH, _FTYPE_ANY, 0,
437 &dev->syslink.cfuncs,
438 &dev->syslink.iofuncs, attr))) {
439 return(-1);
440 }
442 status = init_syslink_trace_device(dev);
443 if (status < 0) {
444 return status;
445 }
447 return(0);
448 }
450 /* De-initialize the syslink device */
451 int deinit_syslink_device(syslink_dev_t *dev)
452 {
453 int status = EOK;
455 status = resmgr_detach(dev->dpp, dev->syslink.resmgr_id, 0);
456 if (status < 0) {
457 Osal_printf("syslink: resmgr_detach failed %d", errno);
458 status = errno;
459 }
461 status = deinit_syslink_trace_device(dev);
463 return(status);
464 }
467 /* Initialize the devices */
468 int init_devices(syslink_dev_t *dev)
469 {
470 if (init_syslink_device(dev) < 0) {
471 Osal_printf("syslink: syslink device init failed");
472 return(-1);
473 }
475 return(0);
476 }
479 /* De-initialize the devices */
480 int deinit_devices(syslink_dev_t *dev)
481 {
482 int status = EOK;
484 if ((status = deinit_syslink_device(dev)) < 0) {
485 fprintf( stderr, "syslink: syslink device de-init failed %d\n", status);
486 status = errno;
487 }
489 return(status);
490 }
492 static void ipc_recover(Ptr args)
493 {
494 syslink_dev_t * dev = (syslink_dev_t *)args;
496 deinit_ipc(dev, TRUE);
497 init_ipc(dev, syslink_firmware, TRUE);
498 deinit_syslink_trace_device(dev);
499 init_syslink_trace_device(dev);
500 }
502 Int syslink_error_cb (UInt16 procId, ProcMgr_Handle handle,
503 ProcMgr_State fromState, ProcMgr_State toState,
504 ProcMgr_EventStatus status, Ptr args)
505 {
506 Int ret = 0;
507 String errString = NULL;
508 syslink_dev_t * dev = (syslink_dev_t *)args;
510 if (status == ProcMgr_EventStatus_Event) {
511 switch (toState) {
512 case ProcMgr_State_Mmu_Fault:
513 errString = "MMU Fault";
514 break;
515 case ProcMgr_State_Error:
516 errString = "Exception";
517 break;
518 case ProcMgr_State_Watchdog:
519 errString = "Watchdog";
520 break;
521 default:
522 errString = "Unexpected State";
523 ret = -1;
524 break;
525 }
526 GT_2trace (curTrace, GT_4CLASS,
527 "syslink_error_cb: Received Error Callback for %s : %s\n",
528 MultiProc_getName(procId), errString);
529 /* Don't allow re-schedule of recovery until complete */
530 pthread_mutex_lock(&dev->lock);
531 if (ret != -1 && dev->recover == FALSE) {
532 /* Schedule recovery. */
533 dev->recover = TRUE;
534 /* Activate a thread to handle the recovery. */
535 GT_0trace (curTrace, GT_4CLASS,
536 "syslink_error_cb: Scheduling recovery...");
537 OsalThread_activate(dev->ipc_recovery_work);
538 }
539 else {
540 GT_0trace (curTrace, GT_4CLASS,
541 "syslink_error_cb: Recovery already scheduled.");
542 }
543 pthread_mutex_unlock(&dev->lock);
544 }
545 else if (status == ProcMgr_EventStatus_Canceled) {
546 GT_1trace (curTrace, GT_3CLASS,
547 "SysLink Error Callback Cancelled for %s",
548 MultiProc_getName(procId));
549 }
550 else {
551 GT_1trace (curTrace, GT_4CLASS,
552 "SysLink Error Callback Unexpected Event for %s",
553 MultiProc_getName(procId));
554 }
556 return ret;
557 }
559 #if defined(SYSLINK_PLATFORM_OMAP4430)
560 #define SYSLINK_CARVEOUT
561 #ifdef SYSLINK_CARVEOUT
562 #define IPU_MEM_SIZE 49 * 1024 * 1024
563 #define IPU_MEM_PHYS 0x97F00000
564 #else
565 #define IPU_MEM_SIZE 104 * 1024 * 1024
566 #define IPU_MEM_ALIGN 0x1000000
567 #endif
568 #else
569 // only need mem for DEVMEM entries, rest is allocated dynamically
570 #define IPU_MEM_SIZE 90 * 1024 * 1024
571 #define IPU_MEM_ALIGN 0x0
573 #endif
575 unsigned int syslink_ipu_mem_size = IPU_MEM_SIZE;
576 #if defined(SYSLINK_PLATFORM_OMAP5430)
577 unsigned int syslink_dsp_mem_size = IPU_MEM_SIZE;
578 #endif
580 /*
581 * Initialize the syslink ipc
582 *
583 * This function sets up the "kernel"-side IPC modules, and does any special
584 * initialization required for QNX and the platform being used. This function
585 * also registers for error notifications and initializes the recovery thread.
586 */
587 int init_ipc(syslink_dev_t * dev, syslink_firmware_info * firmware, bool recover)
588 {
589 int status = 0;
590 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
591 int32_t ret = 0;
592 uint32_t len = 0;
593 #ifndef SYSLINK_CARVEOUT
594 int64_t pa = 0;
595 void * da;
596 #endif
597 int64_t paddr = 0;
598 #endif
599 Ipc_Config iCfg;
600 OsalThread_Params threadParams;
601 ProcMgr_AttachParams attachParams;
602 UInt16 procId;
603 int i;
605 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
606 /* Map a contiguous memory section for ipu - currently hard-coded */
607 if (!recover) {
608 #ifdef SYSLINK_CARVEOUT
609 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE,
610 PROT_NOCACHE | PROT_READ | PROT_WRITE,
611 MAP_PHYS,
612 NOFD,
613 IPU_MEM_PHYS);
614 #else
615 #if defined(SYSLINK_PLATFORM_OMAP5430)
616 dev->da_tesla_virt =
617 #endif
618 dev->da_virt = mmap64(NULL, IPU_MEM_SIZE + IPU_MEM_ALIGN,
619 PROT_NOCACHE | PROT_READ | PROT_WRITE,
620 MAP_ANON | MAP_PHYS | MAP_SHARED,
621 NOFD,
622 0);
624 #endif
626 if (dev->da_virt == MAP_FAILED) {
627 status = ENOMEM;
628 goto exit;
629 }
630 }
632 if (status >= 0) {
633 #ifdef SYSLINK_CARVEOUT
634 /* Make sure the memory is contiguous */
635 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE, &paddr, &len);
636 if (ret)
637 status = ret;
638 else if (len != IPU_MEM_SIZE)
639 status = ENOMEM;
640 #else
641 /* Make sure the memory is contiguous */
642 ret = mem_offset64(dev->da_virt, NOFD, IPU_MEM_SIZE + IPU_MEM_ALIGN,
643 &paddr, &len);
644 if (ret)
645 status = ret;
646 else if (len != IPU_MEM_SIZE + IPU_MEM_ALIGN)
647 status = ENOMEM;
648 else {
649 #if defined(SYSLINK_PLATFORM_OMAP4430)
650 pa = (paddr + IPU_MEM_ALIGN - 1) / IPU_MEM_ALIGN * IPU_MEM_ALIGN;
651 if ((pa - paddr) < 0x900000)
652 pa += 0x900000;
653 else
654 pa -= 0x700000;
655 da = dev->da_virt + (pa - paddr);
656 #else
657 pa = paddr;
658 da = dev->da_virt;
659 #endif
660 }
661 #endif
662 if (status != 0)
663 goto memoryos_fail;
664 }
665 #endif
667 #if defined(SYSLINK_PLATFORM_OMAP5430)
668 if (status >= 0) {
669 iCfg.pAddr_dsp = (uint32_t)pa;
670 iCfg.vAddr_dsp = (uint32_t)da;
671 }
672 #endif
673 if (status >= 0) {
674 if (!recover) {
675 /* Set up the MemoryOS module */
676 status = MemoryOS_setup();
677 if (status < 0)
678 goto memoryos_fail;
679 }
681 /* Setup IPC and platform-specific items */
682 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
683 #ifdef SYSLINK_CARVEOUT
684 iCfg.vAddr = (uint32_t)dev->da_virt;
685 iCfg.pAddr = (uint32_t)paddr;
686 #else
687 iCfg.vAddr = (uint32_t)da;
688 iCfg.pAddr = (uint32_t)pa;
689 #endif
690 #endif
691 status = Ipc_setup (&iCfg);
692 if (status < 0)
693 goto ipcsetup_fail;
695 /* NOTE: this is for handling the procmgr event notifications to userspace list */
696 if (!recover) {
697 /* Setup Fault recovery items. */
698 /* Create the thread object used for the interrupt handler. */
699 threadParams.priority = OsalThread_Priority_Medium;
700 threadParams.priorityType = OsalThread_PriorityType_Generic;
701 threadParams.once = FALSE;
702 dev->ipc_recovery_work = OsalThread_create ((OsalThread_CallbackFxn)
703 ipc_recover,
704 dev,
705 &threadParams);
706 if (dev->ipc_recovery_work == NULL)
707 goto osalthreadcreate_fail;
708 }
709 else {
710 pthread_mutex_lock(&dev->lock);
711 dev->recover = FALSE;
712 pthread_mutex_unlock(&dev->lock);
713 }
715 for (i = 0; i < syslink_num_cores; i++) {
716 procId = firmware[i].proc_id = MultiProc_getId(firmware[i].proc);
717 if (procId >= MultiProc_MAXPROCESSORS || procH[procId]) {
718 GT_setFailureReason (curTrace,
719 GT_4CLASS,
720 "init_ipc",
721 status,
722 "invalid proc!");
723 break;
724 }
726 if (syslink_firmware[i].firmware) {
727 rscHandle[procId] = RscTable_alloc(firmware[i].firmware, procId);
728 if (rscHandle[procId] == NULL) {
729 status = -1;
730 break;
731 }
732 }
734 status = ProcMgr_open(&procH[procId], procId);
735 if (status < 0 || procH[procId] == NULL)
736 goto procmgropen_fail;
738 /* Load and start the remote processor. */
739 ProcMgr_getAttachParams (procH[procId], &attachParams);
740 status = ProcMgr_attach (procH[procId], &attachParams);
741 if (status < 0) {
742 GT_setFailureReason (curTrace,
743 GT_4CLASS,
744 "init_ipc",
745 status,
746 "ProcMgr_attach failed!");
747 goto procmgrattach_fail;
748 }
750 if (syslink_firmware[i].firmware) {
751 status = ProcMgr_load (procH[procId],
752 (String)firmware[i].firmware, 0, NULL,
753 NULL, &procH_fileId[procId]);
754 if (status < 0) {
755 GT_setFailureReason (curTrace,
756 GT_4CLASS,
757 "init_ipc",
758 status,
759 "ProcMgr_load failed!");
760 goto procmgrload_fail;
761 }
762 }
764 status = Ipc_attach (procId);
765 if (status < 0) {
766 GT_setFailureReason (curTrace,
767 GT_4CLASS,
768 "init_ipc",
769 status,
770 "Ipc_attach failed!");
771 goto ipcattach_fail;
772 }
774 status = ProcMgr_start(procH[procId], NULL);
775 if (status < 0) {
776 GT_setFailureReason (curTrace,
777 GT_4CLASS,
778 "init_ipc",
779 status,
780 "ProcMgr_start failed!");
781 goto procmgrstart_fail;
782 }
784 status = ProcMgr_registerNotify(procH[procId], syslink_error_cb, (Ptr)dev,
785 -1, errStates);
786 if (status < 0)
787 goto procmgrreg_fail;
789 continue;
791 procmgrreg_fail:
792 ProcMgr_stop(procH[procId]);
793 procmgrstart_fail:
794 Ipc_detach(procId);
795 ipcattach_fail:
796 if (syslink_firmware[i].firmware)
797 ProcMgr_unload(procH[procId], procH_fileId[procId]);
798 procmgrload_fail:
799 ProcMgr_detach(procH[procId]);
800 procmgrattach_fail:
801 ProcMgr_close(&procH[procId]);
802 procH[procId] = NULL;
803 procmgropen_fail:
804 RscTable_free(&rscHandle[procId]);
805 break;
806 }
808 if (status < 0)
809 goto tiipcsetup_fail;
811 /* Set up rpmsg_mq */
812 status = ti_ipc_setup();
813 if (status < 0)
814 goto tiipcsetup_fail;
816 /* Set up rpmsg_rpc */
817 status = rpmsg_rpc_setup();
818 if (status < 0)
819 goto rpcsetup_fail;
821 goto exit;
822 }
824 rpcsetup_fail:
825 ti_ipc_destroy(recover);
826 tiipcsetup_fail:
827 for (i-=1; i >= 0; i--) {
828 procId = firmware[i].proc_id;
829 ProcMgr_unregisterNotify(procH[procId], syslink_error_cb,
830 (Ptr)dev, errStates);
831 ProcMgr_stop(procH[procId]);
832 if (procH_fileId[procId]) {
833 ProcMgr_unload(procH[procId], procH_fileId[procId]);
834 procH_fileId[procId] = 0;
835 }
836 ProcMgr_detach(procH[procId]);
837 ProcMgr_close(&procH[procId]);
838 procH[procId] = NULL;
839 RscTable_free(&rscHandle[procId]);
840 rscHandle[procId] = NULL;
841 }
842 OsalThread_delete(&dev->ipc_recovery_work);
843 osalthreadcreate_fail:
844 Ipc_destroy();
845 ipcsetup_fail:
846 MemoryOS_destroy();
847 memoryos_fail:
848 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
849 if (dev->da_virt != MAP_FAILED)
850 #ifdef SYSLINK_CARVEOUT
851 munmap(dev->da_virt, IPU_MEM_SIZE);
852 #else
853 munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
854 #endif
855 #endif
856 exit:
857 return status;
858 }
860 int deinit_ipc(syslink_dev_t * dev, bool recover)
861 {
862 int status = EOK;
863 uint32_t i = 0, id = 0;
865 // Stop the remote cores right away
866 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
867 if (procH[i]) {
868 GT_1trace(curTrace, GT_4CLASS, "stopping %s", MultiProc_getName(i));
869 ProcMgr_stop(procH[i]);
870 }
871 }
873 rpmsg_rpc_destroy();
875 ti_ipc_destroy(recover);
877 for (i = 0; i < MultiProc_MAXPROCESSORS; i++) {
878 if (procH[i]) {
879 ProcMgr_unregisterNotify (procH[i], syslink_error_cb, (Ptr)dev,
880 errStates);
881 Ipc_detach(i);
882 if (procH_fileId[i]) {
883 ProcMgr_unload(procH[i], procH_fileId[i]);
884 procH_fileId[i] = 0;
885 }
886 ProcMgr_detach(procH[i]);
887 ProcMgr_close(&procH[i]);
888 procH[i] = NULL;
889 RscTable_free(&rscHandle[i]);
890 rscHandle[i] = NULL;
891 }
892 }
894 if (!recover && dev->ipc_recovery_work != NULL) {
895 OsalThread_delete (&dev->ipc_recovery_work);
896 dev->ipc_recovery_work = NULL;
897 }
899 if (recover) {
900 static FILE *log;
901 /* Dump the trace information */
902 Osal_printf("syslink: printing remote core trace dump to"
903 " /var/log/ducati-m3-traces.log");
904 log = fopen ("/var/log/ducati-m3-traces.log", "a+");
905 if (log) {
906 for (id = 0; id < syslink_num_cores; id++) {
907 if (proc_traces[id].va) {
908 /* print traces */
909 /* wait a little bit for traces to finish dumping */
910 sleep(1);
911 fprintf(log, "****************************************\n");
912 fprintf(log, "*** CORE%d TRACE DUMP ***\n",
913 id);
914 fprintf(log, "****************************************\n");
915 for (i = (*proc_traces[id].widx + 1);
916 i < (proc_traces[id].len - 8);
917 i++) {
918 fprintf(log, "%c",
919 *(char *)((uint32_t)proc_traces[id].va + i));
920 }
921 for (i = 0; i < *proc_traces[id].widx; i++) {
922 fprintf(log, "%c",
923 *(char *)((uint32_t)proc_traces[id].va + i));
924 }
925 }
926 }
927 fclose(log);
928 }
929 else {
930 GT_setFailureReason(curTrace, GT_4CLASS, "deinit_ipc", errno,
931 "error opening /var/log/ducati-m3-traces.log");
932 }
933 }
935 status = Ipc_destroy();
936 if (status < 0) {
937 printf("Ipc_destroy() failed 0x%x", status);
938 }
939 if (!recover) {
940 status = MemoryOS_destroy();
941 if (status < 0) {
942 printf("MemoryOS_destroy() failed 0x%x", status);
943 }
944 #if defined(SYSLINK_PLATFORM_OMAP4430) || defined(SYSLINK_PLATFORM_OMAP5430)
945 if (dev->da_virt != MAP_FAILED) {
946 #ifdef SYSLINK_CARVEOUT
947 status = munmap(dev->da_virt, IPU_MEM_SIZE);
948 #else
949 status = munmap(dev->da_virt, IPU_MEM_SIZE + IPU_MEM_ALIGN);
950 #endif
951 if (status < 0) {
952 printf("munmap failed %d", errno);
953 }
954 }
955 #endif
956 }
958 return status;
959 }
962 /* Read next line of available data for given 'core' and store it in buffer.
963 * Returns the number of bytes that were written or -1 on error
964 */
965 static int readNextTrace(int core, char* buffer, int bufSize)
966 {
967 char* readPtr;
968 uint32_t readBytes, ridx, widx;
969 syslink_trace_info* tinfo = &proc_traces[core];
971 /* Make sure it is valid */
972 if ( (tinfo == NULL) || (tinfo->va == NULL) ) {
973 return -1;
974 }
976 /* Check to see if something to read */
977 if (tinfo->ridx == tinfo->widx) {
978 return 0;
979 }
981 readPtr = (char*) tinfo->va;
982 ridx = *tinfo->ridx;
983 widx = *tinfo->widx;
985 /* If first read, make sure that core is ready by validating ridx, widx */
986 if ( (tinfo->firstRead == TRUE) && ((ridx != 0) || (widx >= tinfo->len)) ) {
987 // not ready - will try again later
988 return 0;
989 }
991 /* Sanity check ridx/widx to make sure they point inside the buffer */
992 if ( (ridx >= tinfo->len) || (widx >= tinfo->len) ) {
993 Osal_printf("C%d: widx=%d, ridx=%d, len=%d - out of range",
994 core, widx, ridx, tinfo->len);
995 return -1;
996 }
998 readBytes = 0;
999 tinfo->firstRead = FALSE;
1000 /* Read until we hit newline indicating end of trace */
1001 while ( (readPtr[ridx] != '\n') && (ridx != widx) && (readBytes < bufSize)) {
1002 buffer[readBytes] = readPtr[ridx];
1003 readBytes++;
1004 ridx++;
1005 // Check for wrap-around
1006 if (ridx == tinfo->len) {
1007 ridx = 0;
1008 }
1009 }
1011 /* If did not find newline, abort since either not enough info or no room in buffer */
1012 if (readPtr[ridx] != '\n') {
1013 if (readBytes >= bufSize) {
1014 Osal_printf("C%d: Insufficient size of buffer; read %d, buf %d",
1015 core, readBytes, bufSize);
1016 return -1;
1017 }
1018 return 0;
1019 }
1021 /* Newline may not be valid data if this was not ready to be read */
1022 if (ridx == widx) {
1023 return 0;
1024 }
1026 /* We read a full line - null terminate and update ridx to mark data read */
1027 if (readBytes < bufSize) {
1028 buffer[readBytes] = '\0';
1029 } else {
1030 Osal_printf("C%d: No room to write NULL character", core);
1031 return -1;
1032 }
1033 readBytes++;
1034 ridx++;
1035 if (ridx == tinfo->len) {
1036 ridx = 0;
1037 }
1038 *tinfo->ridx = ridx;
1040 return readBytes;
1041 }
1043 /* Thread reading ducati traces and writing them out to slog2 */
1044 static void *ducatiTraceThread(void *parm)
1045 {
1046 int32_t bytesRead;
1047 int core;
1048 int err;
1049 Bool exit = FALSE;
1051 pthread_setname_np(0, "ducati-trace");
1053 pthread_mutex_lock(&trace_mutex);
1054 while ( (trace_active == TRUE) && (exit == FALSE) ) {
1055 for (core = 0; core < MultiProc_MAXPROCESSORS; core++) {
1056 while ((bytesRead = readNextTrace(core, trace_buffer, TRACE_BUFFER_SIZE)) > 0) {
1057 #if (_NTO_VERSION >= 800)
1058 slog2f(buffer_handle, 0, 0, "C%d:%s", core, trace_buffer);
1059 #else
1060 slogf(42, _SLOG_NOTICE, "C%d:%s", core, trace_buffer);
1061 #endif
1062 if (trace_active == FALSE) {
1063 break;
1064 }
1065 }
1066 // Abort trace logger on errors as these should not occur
1067 if (bytesRead < 0) {
1068 trace_active = FALSE;
1069 }
1070 if (trace_active == FALSE) {
1071 break;
1072 }
1073 }
1074 if (trace_active == FALSE) {
1075 continue;
1076 }
1077 pthread_mutex_unlock(&trace_mutex);
1079 // No interrupts/events to trigger reading traces, so need to periodically poll
1080 usleep(TRACE_POLLING_INTERVAL_US);
1082 // If we are in hibernation, wait on condvar for end of hibernation
1083 pthread_mutex_lock(&syslink_hib_mutex);
1084 while ((syslink_hib_enable == TRUE) && (syslink_hib_hibernating == TRUE) ) {
1085 err = pthread_cond_wait(&syslink_hib_cond, &syslink_hib_mutex);
1086 if (err != EOK) {
1087 Osal_printf("pthread_cond_wait failed with err=%d", err);
1088 exit = TRUE;
1089 break;
1090 }
1091 }
1092 pthread_mutex_unlock(&syslink_hib_mutex);
1094 pthread_mutex_lock(&trace_mutex);
1095 }
1096 pthread_mutex_unlock(&trace_mutex);
1097 Osal_printf("ducati trace thread exited");
1098 return NULL;
1099 }
1101 /* Initialize slog2 for Ducati traces */
1102 static int init_ducati_slog2(void)
1103 {
1104 #if (_NTO_VERSION >= 800)
1105 slog2_buffer_set_config_t buffer_config;
1106 const char * buffer_set_name = "ducati";
1107 const char * buffer_name = "ducati_buffer";
1109 // Use command line verbosity for default verbosity level
1110 uint8_t verbosity_level = (uint8_t) verbosity;
1111 if ( verbosity_level > SLOG2_DEBUG2) {
1112 verbosity_level = SLOG2_DEBUG2;
1113 }
1115 // Initialize the buffer configuration
1116 buffer_config.buffer_set_name = (char *) buffer_set_name;
1117 buffer_config.num_buffers = 1;
1118 buffer_config.verbosity_level = verbosity_level;
1119 buffer_config.buffer_config[0].buffer_name = (char *) buffer_name;
1120 buffer_config.buffer_config[0].num_pages = 8;
1122 // Register the Buffer Set
1123 if( slog2_register( &buffer_config, &buffer_handle, 0 ) == -1 ) {
1124 Osal_printf("syslink error registering slogger2 buffer for Ducati!");
1125 return -1;
1126 }
1127 #endif
1129 return 0;
1130 }
1132 /** print usage */
1133 static Void printUsage (Char * app)
1134 {
1135 printf ("\n%s: [-fHT]\n", app);
1136 printf (" -f specify the binary file to load to the remote cores)\n");
1137 #if defined(SYSLINK_PLATFORM_OMAP5430)
1138 printf (" -d specify the binary file to load to the dsp)\n");
1139 #endif
1140 printf (" -H enable/disable hibernation, 1: ON, 0: OFF, Default: 1)\n");
1141 printf (" -T specify the hibernation timeout in ms, Default: 5000 ms)\n");
1143 exit (EXIT_SUCCESS);
1144 }
1146 dispatch_t * syslink_dpp = NULL;
1148 int main(int argc, char *argv[])
1149 {
1150 syslink_dev_t * dev = NULL;
1151 thread_pool_attr_t tattr;
1152 int status;
1153 int error = 0;
1154 sigset_t set;
1155 int channelid = 0;
1156 int c;
1157 int hib_enable = 1;
1158 uint32_t hib_timeout = PM_HIB_DEFAULT_TIME;
1159 char *user_parm = NULL;
1160 struct stat sbuf;
1161 int i = 0;
1162 long max_path_length = 0;
1163 char * abs_path = NULL;
1165 if (-1 != stat(IPC_DEVICE_PATH, &sbuf)) {
1166 printf ("Syslink Already Running...\n");
1167 return EXIT_FAILURE;
1168 }
1169 printf ("Starting syslink resource manager...\n");
1171 /* Parse the input args */
1172 while (1)
1173 {
1174 c = getopt (argc, argv, "f:d:H:T:U:v:");
1175 if (c == -1)
1176 break;
1178 switch (c)
1179 {
1180 case 'f':
1181 /* for backward compatibility, "-f" option loaded Ducati/Benelli */
1182 syslink_firmware[syslink_num_cores].firmware = optarg;
1183 #if defined(SYSLINK_PLATFORM_OMAP4430)
1184 syslink_firmware[syslink_num_cores].proc = "SYSM3";
1185 #else
1186 #ifndef SYSLINK_SYSBIOS_SMP
1187 syslink_firmware[syslink_num_cores].proc = "CORE0";
1188 #else
1189 syslink_firmware[syslink_num_cores].proc = "IPU";
1190 #endif
1191 #endif
1192 syslink_num_cores++;
1193 #ifndef SYSLINK_SYSBIOS_SMP
1194 syslink_firmware[syslink_num_cores].firmware = NULL;
1195 #if defined(SYSLINK_PLATFORM_OMAP4430)
1196 syslink_firmware[syslink_num_cores].proc = "APPM3";
1197 #else
1198 syslink_firmware[syslink_num_cores].proc = "CORE1";
1199 #endif
1200 syslink_num_cores++;
1201 #endif
1202 break;
1203 #if defined(SYSLINK_PLATFORM_OMAP5430)
1204 case 'd':
1205 syslink_firmware[syslink_num_cores].firmware = optarg;
1206 syslink_firmware[syslink_num_cores].proc = "DSP";
1207 syslink_num_cores++;
1208 break;
1209 #endif
1210 case 'H':
1211 hib_enable = atoi(optarg);
1212 if (hib_enable != 0 && hib_enable != 1) {
1213 hib_enable = -1;
1214 }
1215 break;
1216 case 'T':
1217 hib_timeout = atoi(optarg);
1218 break;
1219 case 'U':
1220 user_parm = optarg;
1221 break;
1222 case 'v':
1223 verbosity++;
1224 break;
1225 default:
1226 fprintf (stderr, "Unrecognized argument\n");
1227 }
1228 }
1230 /* Now parse the operands, which should be in the format:
1231 * "<multiproc_name> <firmware_file> ..*/
1232 for (; optind + 1 < argc; optind+=2) {
1233 if (syslink_num_cores == MultiProc_MAXPROCESSORS) {
1234 printUsage(argv[0]);
1235 return (error);
1236 }
1237 syslink_firmware[syslink_num_cores].proc = argv [optind];
1238 syslink_firmware[syslink_num_cores++].firmware = argv [optind+1];
1239 }
1242 /* Get the name of the binary from the input args */
1243 if (!syslink_num_cores) {
1244 fprintf(stderr, "-f or -d or <core_id> option must be specified");
1245 printUsage(argv[0]);
1246 return (error);
1247 }
1249 /* Validate hib_enable args */
1250 if (hib_enable == -1) {
1251 fprintf (stderr, "invalid hibernation enable value\n");
1252 printUsage(argv[0]);
1253 return (error);
1254 }
1256 syslink_hib_enable = (Bool)hib_enable;
1257 syslink_hib_timeout = hib_timeout;
1259 /* Init logging for syslink */
1260 if (Osal_initlogging(verbosity) != 0) {
1261 return -1;
1262 }
1264 /* Obtain I/O privity */
1265 error = ThreadCtl_r (_NTO_TCTL_IO, 0);
1266 if (error == -1) {
1267 Osal_printf("Unable to obtain I/O privity");
1268 return (error);
1269 }
1271 /* Get the abs path for all firmware files */
1272 for (i = 0; i < syslink_num_cores; i++) {
1273 max_path_length = pathconf( syslink_firmware[i].firmware, _PC_PATH_MAX );
1274 if(max_path_length == -1) {
1275 perror("pathconf failed");
1276 return -1;
1277 }
1279 abs_path = calloc(1, max_path_length + 1);
1280 if (abs_path == NULL) {
1281 return -1;
1282 }
1283 if (NULL == realpath(syslink_firmware[i].firmware, abs_path)) {
1284 fprintf (stderr, "realpath failed\n");
1285 return -1;
1286 }
1287 syslink_firmware[i].firmware = abs_path;
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);
1460 }