BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_reference/dev_log/Makefile b/bcm68620_release/release/host_reference/dev_log/Makefile
new file mode 100644
index 0000000..18d244e
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/Makefile
@@ -0,0 +1,43 @@
+# Stack
+#
+MOD_NAME = dev_log
+MOD_TYPE = lib
+
+ifeq ("$(ENABLE_LOG)", "y")
+ MOD_DEPS = cli utils
+ MOD_DEFS = -DENABLE_LOG
+ USE_LINT = yes
+ srcs = bcm_dev_log.c bcm_dev_log_task.c
+ ifeq ("$(FEATURE_LOG)", "y")
+ MOD_DEFS += -DTRIGGER_LOGGER_FEATURE
+ endif
+
+ ifeq ("$(DEV_LOG_DEBUG)", "y")
+ MOD_DEFS += -DDEV_LOG_DEBUG
+ endif
+
+ ifeq ("$(ENABLE_CLI)", "y")
+ srcs += bcm_dev_log_cli.c
+ endif
+
+ ifeq ("$(TOOLCHAIN)", "gcc")
+ EXTRA_CFLAGS += -Wno-format-security
+ endif
+
+ ifeq ("$(SUBSYSTEM)", "host")
+ ifeq ("$(OS_KERNEL)", "linux")
+ ifeq ("$(RELEASE_BUILD)", "y")
+ EXTRA_INCLUDES += -I$(TOP_DIR)/host_reference/dev_log_linux
+ else
+ EXTRA_INCLUDES += -I$(TOP_DIR)/host/dev_log_linux
+ endif
+ endif
+ endif
+
+ ifeq ("$(OS)", "posix")
+ ENABLE_LOG_SYSLOG ?= y
+ ifeq ("$(ENABLE_LOG_SYSLOG)", "y")
+ MOD_DEFS += -DDEV_LOG_SYSLOG
+ endif
+ endif
+endif
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.c b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.c
new file mode 100644
index 0000000..8c8cc25
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.c
@@ -0,0 +1,409 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifdef ENABLE_LOG
+
+#include "bcm_dev_log_task.h"
+#include "bcm_dev_log_task_internal.h"
+#include "bcm_dev_log.h"
+
+static bcmos_timer dev_log_timer;
+
+/* Store timestamp per every rate-limited log ID. */
+static uint64_t rate_limit_id2timestamp[DEV_LOG_RATE_LIMIT_ID__NUM_OF];
+
+const char *dev_log_basename(const char *str)
+{
+ const char *slash;
+ if ((slash = strchr(str, '/')))
+ {
+ const char *str0 = str;
+ str = strchr(slash+1, ' ');
+ /* If log format string was created by BCM_LOG macro and there is no corruption of some kind
+ * str above is guaranteed to be != NULL. However, making str!=NULL assumption makes dev_log
+ * vulnerable to bugs in the caller. In this case the following inexpensive check prevents crash
+ * in dev_Log and helps in identifying the real culprit.
+ */
+ if (!str)
+ return str0;
+ while (str[0] != '/')
+ str--;
+ str++;
+ }
+ return str;
+}
+
+#ifdef TRIGGER_LOGGER_FEATURE
+
+/* check if the message fits the level and the other criteria for a trigger
+ return 1 if yes, the message will be printed
+ and returns 0 if the message will not be printed
+*/
+static bcmos_bool check_trigger(dev_log_id_parm *xi_id, bcm_dev_log_level xi_log_level)
+{
+ /* the level of the message must be exactly the trigger level */
+ if (xi_id->trigger_log_level != xi_log_level)
+ return BCMOS_FALSE; /* do not print the message - the level does not fit */
+
+ xi_id->trigger.counter++;
+ if (xi_id->trigger.counter >= xi_id->trigger.start_threshold)
+ {
+ if (xi_id->trigger.counter >= xi_id->trigger.stop_threshold)
+ {
+ /* trigger finished, check repeat */
+ if (xi_id->trigger.repeat_threshold)
+ {
+ xi_id->trigger.repeat++;
+ if (xi_id->trigger.repeat < xi_id->trigger.repeat_threshold)
+ {
+ /* rewind trigger conditions */
+ xi_id->trigger.counter = 0;
+ }
+ }
+ }
+ else /* trigger is active : counter greater than start and less than end */
+ return BCMOS_TRUE; /* print the message */
+ }
+ return BCMOS_FALSE;/* do not print the message - still less than start threshold */
+}
+
+/* check if the message fits the level and the criteria for throttle
+ return 1 if yes, the message will be printed
+ and returns 0 if the message will not be printed
+*/
+static bcmos_bool check_throttle(dev_log_id_parm *xi_id, bcm_dev_log_level xi_log_level)
+{
+ /* check if any throttle is defined */
+ if (xi_id->throttle_log_level != DEV_LOG_LEVEL_NO_LOG)
+ return BCMOS_TRUE; /* print the message - no trigger is set */
+
+ /* the level of the message must be exactly the throttle level */
+ if (xi_id->throttle_log_level != xi_log_level)
+ return BCMOS_FALSE; /* do not print the message - the level does not fit */
+
+ xi_id->throttle.counter++;
+ if (xi_id->throttle.counter >= xi_id->throttle.threshold)
+ {
+ xi_id->throttle.counter = 0;
+ return BCMOS_TRUE;
+ }
+ return BCMOS_FALSE;/* do not print the message - still less than start threshold */
+}
+
+#endif
+
+static bcmos_timer_rc bcm_dev_log_msg_send_timer_cb(bcmos_timer *timer, long data)
+{
+ bcmos_msg *msg = (bcmos_msg *)data;
+ bcmos_msg_send(&dev_log.save_queue, msg, BCMOS_MSG_SEND_AUTO_FREE);
+ return BCMOS_TIMER_OK;
+}
+
+uint8_t bcm_dev_log_pool_occupancy_percent_get(void)
+{
+ bcmos_msg_pool_info msg_pool_info;
+ bcmos_errno error = bcmos_msg_pool_query(&dev_log.pool, &msg_pool_info);
+ if (error != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("bcmos_msg_pool_query() returned %s (%d)\n", bcmos_strerror(error), error);
+ return 0;
+ }
+ return (uint8_t)((100 * (msg_pool_info.parm.size - msg_pool_info.stat.free)) / msg_pool_info.parm.size);
+}
+
+static bcmos_bool bcm_dev_log_should_drop(
+ dev_log_id_parm *id,
+ bcm_dev_log_level log_level,
+ uint32_t rate_us,
+ dev_log_rate_limit_id rate_limit_id)
+{
+ /* If the msg pool is sufficiently full, drop all non-error messages */
+ if (!bcm_dev_log_level_is_error(log_level) &&
+ bcm_dev_log_pool_occupancy_percent_get() >= DEV_LOG_ERROR_ONLY_THRESHOLD_PERCENT)
+ {
+ bcm_dev_log_drop_report();
+ return BCMOS_TRUE;
+ }
+
+#ifdef TRIGGER_LOGGER_FEATURE
+ /* if trigger defined - ignore throttle and printing level */
+ if (id->trigger_log_level != DEV_LOG_LEVEL_NO_LOG)
+ return check_trigger(id, log_level);
+#endif
+
+ /* if trigger is not fullfilled - check other conditions */
+ if (log_level > id->log_level_print && log_level > id->log_level_save)
+ return BCMOS_TRUE;
+
+#ifdef TRIGGER_LOGGER_FEATURE
+ if (!check_throttle(id, log_level))
+ return BCMOS_TRUE;
+#endif
+
+ if (rate_us && rate_limit_id != DEV_LOG_RATE_LIMIT_ID_NONE)
+ {
+ uint64_t curr_timestamp;
+
+ /* Do rate limit. */
+ curr_timestamp = bcmos_timestamp64();
+ if (curr_timestamp - rate_limit_id2timestamp[rate_limit_id] < rate_us)
+ return BCMOS_TRUE; /* Filter out this message. */
+ rate_limit_id2timestamp[rate_limit_id] = curr_timestamp;
+ }
+
+ return BCMOS_FALSE;
+}
+
+static void _bcm_dev_log_vlog(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ uint32_t rate_us,
+ dev_log_rate_limit_id rate_limit_id,
+ const char *fmt,
+ va_list args)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+ dev_log_queue_msg *log_queue_msg;
+ bcmos_errno error = BCM_ERR_OK;
+ bcmos_msg *msg;
+
+ if (dev_log.state != BCM_DEV_LOG_STATE_ENABLED)
+ {
+ if (dev_log.flags & BCM_DEV_LOG_FLAG_DISABLED_WITH_PRINTF)
+ DEV_LOG_VPRINTF(fmt, args);
+ return;
+ }
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ /* If this ID was not registered - or registered incorrectly */
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ DEV_LOG_VPRINTF(fmt, args); /* This will allow us to debug what line caused the bug. */
+ return;
+ }
+ if ((xi_log_level >= DEV_LOG_LEVEL_NUM_OF) || (xi_log_level == DEV_LOG_LEVEL_NO_LOG))
+ {
+ DEV_LOG_ERROR_PRINTF("xi_log_level (%u) is invalid\n", xi_log_level);
+ DEV_LOG_VPRINTF(fmt, args); /* This will allow us to debug what line caused the bug. */
+ return;
+ }
+ if (id->log_type == DEV_LOG_ID_TYPE_NONE)
+ {
+ return;
+ }
+#ifdef BCM_SUBSYSTEM_HOST
+ /* Always use CALLER_FMT mode on the host to avoid portability issues with
+ * transferring va_list as an array */
+ xi_flags |= BCM_LOG_FLAG_CALLER_FMT;
+#endif
+
+ /* Update log id counters */
+ id->counters[xi_log_level]++;
+
+ if (bcm_dev_log_should_drop(id, xi_log_level, rate_us, rate_limit_id))
+ return;
+
+ msg = bcmos_msg_pool_alloc(&dev_log.pool);
+ if (!msg)
+ {
+ bcm_dev_log_drop_report();
+ return;
+ }
+ log_queue_msg = msg->data;
+ /* Create log message */
+ log_queue_msg->log_id = id;
+ log_queue_msg->time_stamp = dev_log.dev_log_parm.get_time_cb();
+ log_queue_msg->msg_level = xi_log_level;
+ log_queue_msg->flags = xi_flags;
+#ifndef BCM_SUBSYSTEM_HOST
+ /* It is not really necessary to compile out non CALLER_FMT case on the host.
+ * However, keeping unused code will make Coverity unhappy */
+ if (unlikely(xi_flags & BCM_LOG_FLAG_CALLER_FMT))
+ {
+#endif /* #ifndef BCM_SUBSYSTEM_HOST */
+ vsnprintf(log_queue_msg->u.str, MAX_DEV_LOG_STRING_SIZE, (xi_flags & BCM_LOG_FLAG_FILENAME_IN_FMT) ? dev_log_basename(fmt) : fmt, args);
+#ifndef BCM_SUBSYSTEM_HOST
+ }
+ else
+ {
+ uint32_t i;
+ uint32_t offset;
+ log_queue_msg->u.fmt_args.fmt = fmt;
+
+ offset = ((long)log_queue_msg->u.fmt_args.args % 8 == 0) ? 0 : 1; /* start on an 8-byte boundary */
+ for (i = 0; i < DEV_LOG_MAX_ARGS; i++)
+ {
+ log_queue_msg->u.fmt_args.args[i + offset] = va_arg(args, void *);
+ }
+ }
+#endif /* #ifndef BCM_SUBSYSTEM_HOST */
+
+ if (bcmos_sem_post_is_allowed())
+ {
+ error = bcmos_msg_send(&dev_log.save_queue, msg, BCMOS_MSG_SEND_AUTO_FREE);
+ }
+ else
+ {
+ bcmos_timer_parm timer_params =
+ {
+ .name = "dev_log_timer",
+ .handler = bcm_dev_log_msg_send_timer_cb,
+ };
+
+ if (!(dev_log_timer.flags & BCMOS_TIMER_FLAG_VALID))
+ bcmos_timer_create(&dev_log_timer, &timer_params);
+ /* Limitation: We don't send more than 1 logger message even if _bcm_dev_log_vlog() was called multiple timers in IRQs disabled mode because we have a single timer. */
+ if (!bcmos_timer_is_running(&dev_log_timer))
+ {
+ bcmos_timer_handler_set(&dev_log_timer, bcm_dev_log_msg_send_timer_cb, (long)msg);
+ bcmos_timer_start(&dev_log_timer, 0);
+ }
+ }
+
+ if (error != BCM_ERR_OK)
+ {
+ id->lost_msg_cnt++;
+ }
+}
+
+void bcm_dev_log_vlog(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ const char *fmt,
+ va_list args)
+{
+ _bcm_dev_log_vlog(xi_id, xi_log_level, xi_flags, 0, DEV_LOG_RATE_LIMIT_ID_NONE, fmt, args);
+}
+
+/* IMPORTANT!!!
+ * The function bcm_dev_log_log() must have even number of arguments before the '...' (see comments on header file).
+ */
+void bcm_dev_log_log(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ bcm_dev_log_vlog(xi_id, xi_log_level, xi_flags, fmt, args);
+ va_end(args);
+}
+
+void bcm_dev_log_log_ratelimit(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ uint32_t rate_us,
+ dev_log_rate_limit_id rate_limit_id,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ _bcm_dev_log_vlog(xi_id, xi_log_level, xi_flags, rate_us, rate_limit_id, fmt, args);
+ va_end(args);
+}
+
+#ifdef BCMOS_TRACE_IN_DEV_LOG
+
+static dev_log_id bcmos_trace_dev_log_id[] =
+{
+ [BCMOS_TRACE_LEVEL_NONE] = DEV_LOG_INVALID_ID,
+ [BCMOS_TRACE_LEVEL_ERROR] = DEV_LOG_INVALID_ID,
+ [BCMOS_TRACE_LEVEL_INFO] = DEV_LOG_INVALID_ID,
+ [BCMOS_TRACE_LEVEL_VERBOSE] = DEV_LOG_INVALID_ID,
+ [BCMOS_TRACE_LEVEL_DEBUG] = DEV_LOG_INVALID_ID
+};
+
+static bcm_dev_log_level bcmos_trace_dev_log_level[] =
+{
+ [BCMOS_TRACE_LEVEL_ERROR] = DEV_LOG_LEVEL_ERROR,
+ [BCMOS_TRACE_LEVEL_INFO] = DEV_LOG_LEVEL_INFO,
+ [BCMOS_TRACE_LEVEL_VERBOSE] = DEV_LOG_LEVEL_INFO,
+ [BCMOS_TRACE_LEVEL_DEBUG] = DEV_LOG_LEVEL_DEBUG
+};
+
+#endif
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_os_trace_init */
+/* */
+/* Abstract: Direct bcmos_trace() output to log */
+/* Arguments: NONE */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_os_trace_init(void)
+{
+#ifdef BCMOS_TRACE_IN_DEV_LOG
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_ERROR] = bcm_dev_log_id_register("trace_error",
+ DEV_LOG_LEVEL_ERROR, DEV_LOG_ID_TYPE_BOTH);
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_INFO] = bcm_dev_log_id_register("trace_info",
+ DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_VERBOSE] = bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_INFO];
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_DEBUG] = bcm_dev_log_id_register("trace_debug",
+ DEV_LOG_LEVEL_DEBUG, DEV_LOG_ID_TYPE_BOTH);
+ if (bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_ERROR] == DEV_LOG_INVALID_ID ||
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_INFO] == DEV_LOG_INVALID_ID ||
+ bcmos_trace_dev_log_id[BCMOS_TRACE_LEVEL_DEBUG] == DEV_LOG_INVALID_ID)
+ {
+ return BCM_ERR_NORES;
+ }
+ return BCM_ERR_OK;
+#else /* #ifdef BCMOS_TRACE_IN_DEV_LOG */
+ return BCM_ERR_NOT_SUPPORTED;
+#endif
+}
+
+#ifdef BCMOS_TRACE_IN_DEV_LOG
+
+/* Direct OS trace to dev_log */
+void bcmos_trace(bcmos_trace_level level, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ if (bcmos_trace_dev_log_id[level] != DEV_LOG_INVALID_ID && dev_log.state == BCM_DEV_LOG_STATE_ENABLED)
+ {
+ if (level == BCMOS_TRACE_LEVEL_ERROR)
+ bcm_dev_log_vlog(bcmos_trace_dev_log_id[level], bcmos_trace_dev_log_level[level], BCM_LOG_FLAG_CALLER_FMT, format, args);
+ else
+ bcm_dev_log_vlog(bcmos_trace_dev_log_id[level], bcmos_trace_dev_log_level[level], 0, format, args);
+ }
+
+ va_end(args);
+}
+
+#endif
+
+#endif /* ENABLE_LOG */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.h b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.h
new file mode 100644
index 0000000..19e156e
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log.h
@@ -0,0 +1,224 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef __BCM_DEV_LOG_H_
+#define __BCM_DEV_LOG_H_
+
+#ifdef ENABLE_LOG
+
+#include <bcmos_system.h>
+#include "bcm_dev_log_task.h"
+#ifdef ENABLE_CLI
+#include "bcm_dev_log_cli.h"
+#endif
+
+/********************************************/
+/* */
+/* Log macros */
+/* */
+/********************************************/
+
+#define MACRO_ARG_N(_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12,_13,_14,_15,_16,_17,_18,_19,_20,_21,_22,_23,_24,_25,_26,_27,_28,_29,_30,_31,_32,N,...) N
+#define MACROS_ARGS_SEQUENCE 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+#define MACRO_NUM_ARGS_HELPER(...) MACRO_ARG_N(__VA_ARGS__)
+#define MACRO_NUM_ARGS(...) MACRO_NUM_ARGS_HELPER(__VA_ARGS__, MACROS_ARGS_SEQUENCE)
+
+/* IMPORTANT! DO NOT USE THESE MACROS, USE BCM_LOG ONLY ! */
+/* These macros force number of arguments in compile time. A single macro for each number of arguments (including the format) */
+#ifdef __BASENAME__
+#define _BCM_LOG_ARGS1(level, id, flags, ...) \
+ bcm_dev_log_log(id, level, flags, STRINGIFY_EXPAND(__BASENAME__) " " STRINGIFY_EXPAND(__LINE__) "| " __VA_ARGS__)
+#else
+#define _BCM_LOG_ARGS1(level, id, flags, ...) \
+ bcm_dev_log_log(id, level, flags | BCM_LOG_FLAG_FILENAME_IN_FMT, __FILE__ " " STRINGIFY_EXPAND(__LINE__) "| " __VA_ARGS__)
+#endif
+#define _BCM_LOG_ARGS2(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS3(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS4(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS5(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS6(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS7(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS8(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS9(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS10(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS11(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS12(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS13(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS14(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS15(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS16(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS17(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS18(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS19(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS20(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS21(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS22(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS23(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS24(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS25(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS26(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS27(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS28(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS29(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS30(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS31(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS32(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS33(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS34(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS35(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS36(...) _BCM_LOG_ARGS1(__VA_ARGS__)
+#define _BCM_LOG_ARGS(n) _BCM_LOG_ARGS##n
+#define _BCM_LOG_EXPAND(n,...) _BCM_LOG_ARGS(n) (__VA_ARGS__)
+
+/*
+ * IMPORTANT! you should use only this macro for logging
+ *
+ * 1. Support prints up to DEV_LOG_MAX_ARGS parameters each with maximum size of 32bits
+ * 2. Support also prints of arguments with size 64bits but each one counted as two arguments of 32bits,
+ * so you can only print up to (DEV_LOG_MAX_ARGS/2) arguments of 64bits.
+ * Mix of 64 and 32 are allowed as long you don't exceed DEV_LOG_MAX_ARGS.
+ * 3. Any possible combination of mix 32 and 64 arguments are allowed.
+ */
+#define BCM_LOG(level, id, ...) _BCM_LOG_EXPAND(MACRO_NUM_ARGS(__VA_ARGS__), DEV_LOG_LEVEL_##level, id, 0, __VA_ARGS__)
+/* Same as BCM_LOG(), but overrides BCM_LOG() default behavior by letting the format be done in the context of the caller task. This allows using stack/heap strings
+ * for fmt and args. See comment for BCM_LOG_FLAG_CALLER_FMT. */
+#define BCM_LOG_CALLER_FMT(level, id, ...) _BCM_LOG_EXPAND(MACRO_NUM_ARGS(__VA_ARGS__), DEV_LOG_LEVEL_##level, id, BCM_LOG_FLAG_CALLER_FMT, __VA_ARGS__)
+
+/* Same as BCM_LOG(), but the level is not given as a token for concatenation, but as a regular enum. */
+#define BCM_LOG_LEVEL(level, id, ...) _BCM_LOG_EXPAND(MACRO_NUM_ARGS(__VA_ARGS__), level, id, 0, __VA_ARGS__)
+
+#define BCM_LOG_FLAG_NONE 0
+#define BCM_LOG_FLAG_NO_HEADER (1 << 0) /* Avoid inserting header to each message. */
+#define BCM_LOG_FLAG_CALLER_FMT (1 << 1) /* The log message will be formatted in the context of the caller task, not the logger task (override default behavior).
+ * This has a penalty - bcm_dev_log_log() becomes slower. */
+#define BCM_LOG_FLAG_FILENAME_IN_FMT (1 << 2) /* Indicates that __FILE__ is inserted at the beginning of the message format. */
+#define BCM_LOG_FLAG_DONT_SKIP_PRINT (1 << 3) /* The message should always be printed even if the msg pool is nearly full. */
+
+/********************************************/
+/* */
+/* Callbacks functions */
+/* */
+/********************************************/
+
+/********************************************/
+/* */
+/* Functions prototypes */
+/* */
+/********************************************/
+
+const char *dev_log_basename(const char *str);
+
+/****************************************************************************************/
+/* */
+/* Name: bcm_dev_log_log */
+/* Abstract: Log function */
+/* It is better using the macros and not the function directly. */
+/* */
+/* Arguments: */
+/* - xi_id - The Log ID this message is connected to. */
+/* (The ID we got form bcm_dev_log_id_register) */
+/* - xi_log_level - The Log level of this message */
+/* - xi_flags - Can be one of BCM_LOG_FLAG_XXX above. */
+/* - fmt - The print format */
+/* Note: The default behavior is to format the string in the logger */
+/* task context, not the caller task context, to reduce the */
+/* penalty of calling bcm_dev_log_log(). This means 'fmt' can */
+/* point only to strings in data segment, but not to head/stack. */
+/* You can override this behavior with BCM_LOG_FLAG_CALLER_FMT. */
+/* */
+/* - param1 - Format parameter No. 1. Like 'fmt', can reside only in data */
+/* segment, unless choosing BCM_LOG_FLAG_CALLER_FMT */
+/* - ... */
+/* - paramN - Format parameter No. N */
+/* */
+/* IMPORTANT! */
+/* 1. The function bcm_dev_log_log() must have even number of arguments before the '...'*/
+/* This comes from the 64bits limitation that must be align to 8bytes in some */
+/* platforms who doesn't support unaligned access, */
+/* on xponsw (x86) it doesn't matter but on device (arm) you must have that. */
+/* */
+/****************************************************************************************/
+void bcm_dev_log_log(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ const char *fmt,
+ ...) __attribute__((format(__printf__, 4, 5))); /* compiler attribute to check as printf style for arguments 4 (fmt) and 5 (all other) */
+
+void bcm_dev_log_vlog(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ const char *fmt,
+ va_list args);
+
+typedef enum
+{
+ DEV_LOG_RATE_LIMIT_ID_NONE,
+ DEV_LOG_RATE_LIMIT_ID_BWS_DBA_BD_ADD_ALLOC_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_RT_ADD_ALLOC_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_RT_ADD_ACCESS_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_QW_CBR_RT_ADD_ACCESS_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_NRT_ADD_ALLOC_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_COMPENSATION_ADD_ACCESS_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_NO_COMPENSATION_ADD_ACCESS_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_COPY_COMPENSATION_ADD_ACCESS_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_RT_SAVE_ACCESS_FOR_COMPENSATION_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_NRT_SAVE_ACCESS_FOR_COMPENSATION_FAILED,
+ DEV_LOG_RATE_LIMIT_ID_BWS_CBR_FLUSH_FAILED,
+ DEV_LOG_RATE_LIMIT_ID__NUM_OF,
+} dev_log_rate_limit_id;
+
+void bcm_dev_log_log_ratelimit(dev_log_id xi_id,
+ bcm_dev_log_level xi_log_level,
+ uint32_t xi_flags,
+ uint32_t rate_us,
+ dev_log_rate_limit_id rate_limit_id,
+ const char *fmt,
+ ...) __attribute__((format(__printf__, 6, 7))); /* compiler attribute to check as printf style for arguments 6 (fmt) and 7 (all other) */
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_os_trace_init */
+/* */
+/* Abstract: Direct bcmos_trace() output to log */
+/* Arguments: NONE */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_os_trace_init(void);
+
+#else /* #ifndef ENABLE_LOG */
+
+#define BCM_LOG(level, id, ...)
+#define BCM_LOG_CALLER_FMT(level, id, ...)
+
+#endif /* ENABLE_LOG */
+
+#endif /* __BCM_DEV_LOG_H_ */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.c b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.c
new file mode 100644
index 0000000..cdffb59
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.c
@@ -0,0 +1,684 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#include <bcmos_system.h>
+#include <bcm_dev_log.h>
+#include <bcm_dev_log_task_internal.h>
+
+/* We don't support dev_log CLI in linux kernel space */
+#ifndef __KERNEL__
+
+/* Dev log CLI session supports receiving long lines - we shall simply split them into shorter log messages. */
+#define DEV_LOG_CLI_SESSION_MAX_MSG_SIZE (MAX_DEV_LOG_STRING_NET_SIZE * 10)
+
+enum
+{
+ ID_BY_INDEX,
+ ID_BY_NAME,
+};
+
+static bcmos_errno bcm_dev_log_file_print(uint32_t file_index, int32_t xi_msgs_num, bcm_dev_log_print_cb xi_print_callback, void *arg, bcmos_bool clear)
+{
+ bcm_dev_log_file *file;
+ char log_string[MAX_DEV_LOG_STRING_SIZE];
+ int length;
+ uint32_t num_msgs;
+ uint32_t i;
+ uint32_t offset = 0;
+ bcmos_errno err = BCM_ERR_OK;
+
+ file = bcm_dev_log_file_get(file_index);
+ if (!file)
+ return BCM_ERR_PARM;
+
+ num_msgs = bcm_dev_log_get_num_of_messages(file);
+ if (xi_msgs_num && xi_msgs_num < num_msgs)
+ num_msgs = xi_msgs_num;
+
+ DEV_LOG_INFO_PRINTF("file=%p, print %d msgs from file (orig: %d)\n", (void *)file, (int)num_msgs, (int)xi_msgs_num);
+
+ /* Print file */
+ for (i = 0; (i < xi_msgs_num) || !xi_msgs_num; i++)
+ {
+ /* Read from file */
+ length = bcm_dev_log_file_read(file, &offset, log_string, sizeof(log_string));
+ if (!length)
+ break;
+ xi_print_callback(arg, log_string);
+ }
+
+ if (clear == BCMOS_TRUE)
+ err = bcm_dev_log_file_clear(file);
+
+ return err;
+}
+
+static const char *dev_log_str_style(bcm_dev_log_style style)
+{
+ static const char *strings[] =
+ {
+ [BCM_DEV_LOG_STYLE_NORMAL] = "NORMAL",
+ [BCM_DEV_LOG_STYLE_BOLD] = "BOLD",
+ [BCM_DEV_LOG_STYLE_UNDERLINE] = "UNDERLINE",
+ [BCM_DEV_LOG_STYLE_BLINK] = "BLINK",
+ [BCM_DEV_LOG_STYLE_REVERSE_VIDEO] = "REVERSE_VIDEO",
+ };
+ return strings[style > BCM_DEV_LOG_STYLE_REVERSE_VIDEO ? BCM_DEV_LOG_STYLE_REVERSE_VIDEO : style];
+}
+#ifdef TRIGGER_LOGGER_FEATURE
+static void bcm_dev_log_cli_session_print_features(bcmcli_session *session, const char *tabs, const dev_log_id_parm *id_parm)
+{
+ bcmcli_session_print(session,
+ "%sthrottle : level = %c, threshold = %-5u\n",
+ tabs,
+ log_level_str[id_parm->throttle_log_level],
+ id_parm->throttle.threshold);
+
+ bcmcli_session_print(session,
+ "%strigger : level = %c, start = %-5u, stop = %-5u, repeat = %-5u\n",
+ tabs,
+ log_level_str[id_parm->trigger_log_level],
+ id_parm->trigger.start_threshold,
+ id_parm->trigger.stop_threshold,
+ id_parm->trigger.repeat_threshold);
+}
+#endif
+
+static void bcm_dev_log_cli_session_print_id_parm(bcmcli_session *session, const char *tabs, const dev_log_id_parm *id_parm)
+{
+ bcmcli_session_print(session,
+ "name=%16s, log_type=%u, default_log_type=%u, log_level_print=%c (%u), log_level_save=%c (%u), default_log_level=%c (%u), style=%s (%u), lost_msg_cnt=%u, print_skipped_count=%u\n",
+ id_parm->name,
+ id_parm->log_type,
+ id_parm->default_log_type,
+ log_level_str[id_parm->log_level_print],
+ id_parm->log_level_print,
+ log_level_str[id_parm->log_level_save],
+ id_parm->log_level_save,
+ log_level_str[id_parm->default_log_level],
+ id_parm->default_log_level,
+ dev_log_str_style(id_parm->style),
+ id_parm->style,
+ id_parm->lost_msg_cnt,
+ id_parm->print_skipped_count);
+ bcmcli_session_print(session,
+ "%scounters = {%c %-5u,%c %-5u,%c %-5u,%c %-5u,%c %-5u,%c %-5u}\n",
+ tabs,
+ log_level_str[DEV_LOG_LEVEL_NO_LOG],
+ id_parm->counters[DEV_LOG_LEVEL_NO_LOG],
+ log_level_str[DEV_LOG_LEVEL_FATAL],
+ id_parm->counters[DEV_LOG_LEVEL_FATAL],
+ log_level_str[DEV_LOG_LEVEL_ERROR],
+ id_parm->counters[DEV_LOG_LEVEL_ERROR],
+ log_level_str[DEV_LOG_LEVEL_WARNING],
+ id_parm->counters[DEV_LOG_LEVEL_WARNING],
+ log_level_str[DEV_LOG_LEVEL_INFO],
+ id_parm->counters[DEV_LOG_LEVEL_INFO],
+ log_level_str[DEV_LOG_LEVEL_DEBUG],
+ id_parm->counters[DEV_LOG_LEVEL_DEBUG]);
+#ifdef TRIGGER_LOGGER_FEATURE
+ bcm_dev_log_cli_session_print_features(session, tabs, id_parm);
+#endif
+}
+
+static bcmos_errno bcm_dev_log_cli_print_dev_log(
+ bcmcli_session *session,
+ const bcmcli_cmd_parm parm[],
+ uint16_t n_parms)
+{
+ uint32_t i;
+ bcm_dev_log_file *file;
+
+ for (i = 0; i < DEV_LOG_MAX_FILES; i++)
+ {
+ file = bcm_dev_log_file_get(i);
+ if (!file)
+ continue;
+ bcmcli_session_print(session, TAB "file[%u]:\n", i);
+ bcmcli_session_print(session, TAB2 "max_msgs = %u\n", bcm_dev_log_get_num_of_messages(file));
+ bcmcli_session_print(session, TAB2 "file_parm:\n");
+ bcmcli_session_print(session, TAB3 "start_addr = %p\n", dev_log.files[i].file_parm.start_addr);
+ bcmcli_session_print(session, TAB3 "size = %u\n", dev_log.files[i].file_parm.size);
+ bcmcli_session_print(session, TAB3 "read_cb = %p\n", (void *)dev_log.files[i].file_parm.read_cb);
+ bcmcli_session_print(session, TAB3 "write_cb = %p\n", (void *)dev_log.files[i].file_parm.write_cb);
+ bcmcli_session_print(session, TAB3 "flags = %x\n", dev_log.files[i].file_parm.flags);
+ }
+ bcmcli_session_print(session, TAB "state = %u\n", dev_log.state);
+ bcmcli_session_print(session, TAB "msg_count = %u\n", dev_log.msg_count);
+ bcmcli_session_print(session, TAB "save_queue:\n");
+ bcmcli_session_print(session, TAB2 "is_waiting = %u\n", dev_log.save_queue.is_waiting);
+ bcmcli_session_print(session, TAB "print_queue:\n");
+ bcmcli_session_print(session, TAB2 "is_waiting = %u\n", dev_log.print_queue.is_waiting);
+ bcmcli_session_print(session, TAB "save_task:\n");
+ bcmcli_session_print(session, TAB2 "active_modules = %u\n", dev_log.save_task.active_modules);
+ bcmcli_session_print(session, TAB2 "current_module = %u\n", dev_log.save_task.current_module);
+ bcmcli_session_print(session, TAB "print_task:\n");
+ bcmcli_session_print(session, TAB2 "active_modules = %u\n", dev_log.print_task.active_modules);
+ bcmcli_session_print(session, TAB2 "current_module = %u\n", dev_log.print_task.current_module);
+
+ bcmcli_session_print(session, TAB "num_ids = %u\n", dev_log.num_ids);
+ bcmcli_session_print(session, TAB "ids[]:\n");
+ for (i = 0; i < dev_log.num_ids; i++)
+ {
+ bcmcli_session_print(session, TAB2 "ids[%2u]: ", i);
+ bcm_dev_log_cli_session_print_id_parm(session, TAB3, &dev_log.ids[i]);
+ }
+
+ for (i = 0; i < log_name_table_index; i++)
+ {
+ if (logs_names[i].first_instance == LOG_NAME_NO_INSTANCE)
+ {
+ bcmcli_session_print(session, TAB2 "%s\n", logs_names[i].name);
+ }
+ else
+ {
+ bcmcli_session_print(session, TAB2 "%s %d - %d\n", logs_names[i].name, logs_names[i].first_instance, logs_names[i].last_instance);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_logger_control(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcm_dev_log_set_control(parm[0].value.unumber != 0);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_file_print(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ return bcm_dev_log_file_print(
+ parm[0].value.unumber,
+ 0,
+ (bcm_dev_log_print_cb)bcmcli_session_print,
+ session,
+ (bcmos_bool)parm[1].value.unumber);
+}
+
+static bcmos_errno bcm_dev_log_cli_file_clear(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ bcm_dev_log_file *file = bcm_dev_log_file_get(parm[0].value.unumber);
+ if (!file)
+ return BCM_ERR_PARM;
+ return bcm_dev_log_file_clear(file);
+}
+
+static bcmos_errno bcm_dev_log_cli_file_set_flags(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log.files[parm[0].value.unumber].file_parm.flags |= (bcm_dev_log_file_flags)parm[1].value.unumber;
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_file_reset_flags(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log.files[parm[0].value.unumber].file_parm.flags = 0;
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_id_get(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+ dev_log_id_parm id_parm;
+ bcmos_errno err;
+
+ id = parm[0].value.unumber == ID_BY_INDEX ? bcm_dev_log_id_get_by_index(parm[1].value.unumber) :
+ bcm_dev_log_id_get_by_name(parm[1].value.string);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ err = bcm_dev_log_id_get(id, &id_parm);
+ if (err)
+ {
+ bcmcli_session_print(session, "Error: can get id (err: %d)\n", err);
+ return err;
+ }
+
+ bcm_dev_log_cli_session_print_id_parm(session, TAB, &id_parm);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_id_set_type(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ return bcm_dev_log_id_set_type(id, (bcm_dev_log_id_type)parm[1].value.unumber);
+}
+
+static bcmos_errno bcm_dev_log_cli_id_set_level(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ return bcm_dev_log_id_set_level(
+ id,
+ (bcm_dev_log_level)parm[1].value.unumber,
+ (bcm_dev_log_level)parm[2].value.unumber);
+}
+
+static bcmos_errno bcm_dev_log_cli_name_set_level(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_name(parm[0].value.string);
+ if (id == DEV_LOG_INVALID_ID)
+ {
+ return BCM_ERR_NOENT;
+ }
+
+ return bcm_dev_log_id_set_level(
+ id,
+ (bcm_dev_log_level)parm[1].value.unumber,
+ (bcm_dev_log_level)parm[2].value.unumber);
+}
+
+static bcmos_errno bcm_dev_log_cli_id_set_to_default(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ return bcm_dev_log_id_set_levels_and_type_to_default(id);
+}
+
+static bcmos_errno bcm_dev_log_cli_id_set_style(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+ bcm_dev_log_style style;
+
+ id = bcm_dev_log_id_get_by_index(bcmcli_find_named_parm(session, "index")->value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+ style = (bcm_dev_log_style)bcmcli_find_named_parm(session, "style")->value.unumber;
+
+ return bcm_dev_log_id_set_style(id, style);
+}
+
+static bcmos_errno bcm_dev_log_cli_id_clear_counters(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ return bcm_dev_log_id_clear_counters(id);
+}
+
+static bcmos_errno bcm_dev_log_cli_log(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+ bcm_dev_log_level log_level;
+ uint32_t count = 1;
+ const char *string;
+ bcmcli_cmd_parm *cmd_parm;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ if ((cmd_parm = bcmcli_find_named_parm(session, "count")))
+ {
+ count = cmd_parm->value.unumber;
+ if (!count)
+ {
+ count = 1;
+ }
+ }
+
+ log_level = (bcm_dev_log_level)parm[1].value.unumber;
+ string = parm[2].value.string;
+
+ while (count--)
+ {
+ bcm_dev_log_log(id, log_level, BCM_LOG_FLAG_NONE, "%5u| Message: %s\n", count, string);
+ }
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_dev_log_cli_instance_enable(
+ bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ static char log_name[MAX_DEV_LOG_ID_NAME];
+ bcmos_bool enable = (bcmos_bool)bcmcli_find_named_parm(session, "enable")->value.unumber;
+ uint32_t inst = bcmcli_find_named_parm(session, "instance")->value.unumber;
+ dev_log_id log_id;
+ bcmos_errno err;
+ uint32_t i;
+
+ for (i = 0; i < log_name_table_index; i++)
+ {
+ if (logs_names[i].first_instance != LOG_NAME_NO_INSTANCE &&
+ inst >= logs_names[i].first_instance &&
+ inst <= logs_names[i].last_instance)
+ {
+ snprintf(log_name, sizeof(log_name), "%s%u", logs_names[i].name, inst);
+ log_id = bcm_dev_log_id_get_by_name(log_name);
+ if (log_id == DEV_LOG_INVALID_ID)
+ {
+ bcmcli_session_print(session, "Error: log ID not found: %s\n", log_name);
+ return BCM_ERR_INTERNAL;
+ }
+ err = bcm_dev_log_id_set_type(log_id, enable ? DEV_LOG_ID_TYPE_BOTH : DEV_LOG_ID_TYPE_NONE);
+ if (err != BCM_ERR_OK)
+ {
+ bcmcli_session_print(session, "Error setting log type: %s\n", bcmos_strerror(err));
+ return err;
+ }
+ bcmcli_session_print(session, "Log '%s' %s\n", log_name, enable ? "enabled" : "disabled");
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+#ifdef TRIGGER_LOGGER_FEATURE
+static bcmos_errno bcm_dev_log_cli_throttle(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ return bcm_dev_log_set_throttle(id, parm[1].value.unumber, parm[2].value.unumber);
+}
+
+static bcmos_errno bcm_dev_log_cli_trigger(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+ int32_t repeat = 0;
+ bcmcli_cmd_parm *cmd_parm;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ if ((cmd_parm = bcmcli_find_named_parm(session, "repeat")))
+ repeat = cmd_parm->value.number;
+
+ return bcm_dev_log_set_trigger(id, parm[1].value.unumber, parm[2].value.unumber, parm[3].value.unumber, repeat);
+}
+
+static bcmos_errno bcm_dev_log_cli_get_features(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+ dev_log_id id;
+ dev_log_id_parm id_parm;
+ bcmos_errno err;
+
+ id = bcm_dev_log_id_get_by_index(parm[0].value.unumber);
+ if (id == DEV_LOG_INVALID_ID)
+ return BCM_ERR_NOENT;
+
+ err = bcm_dev_log_id_get(id, &id_parm);
+ if (err)
+ {
+ bcmcli_session_print(session, "Error: can get id (err: %d)\n", err);
+ return err;
+ }
+
+ bcm_dev_log_cli_session_print_features(session, TAB, &id_parm);
+
+ return BCM_ERR_OK;
+}
+#endif
+
+static int dev_log_cli_session_write_cb(bcmcli_session *cli_session, const char *buf, uint32_t size)
+{
+ bcm_dev_log_cli_session *session = bcmcli_session_user_priv(cli_session);
+ char tmp_str[DEV_LOG_CLI_SESSION_MAX_MSG_SIZE] = {};
+ char *p;
+ uint32_t tmp_str_len;
+
+ strncpy(tmp_str, buf, sizeof(tmp_str) - 1); /* leave room for the terminator */
+
+ p = tmp_str;
+ tmp_str_len = strlen(tmp_str);
+ while (tmp_str_len > session->free_len)
+ {
+ /* Not enough space in 'str' for concatenating what's in 'p' -> split it. */
+ strncat(session->str, p, session->free_len);
+ bcm_dev_log_log(
+ session->log_id, session->log_level, BCM_LOG_FLAG_NO_HEADER | BCM_LOG_FLAG_CALLER_FMT, "%s", session->str);
+ *session->str = '\0';
+ p += session->free_len;
+ tmp_str_len -= session->free_len;
+ session->free_len = MAX_DEV_LOG_STRING_NET_SIZE - 1;
+ }
+
+ /* Enough space in 'str' for concatenating what's in 'p'. */
+ strncat(session->str, p, tmp_str_len);
+ session->free_len -= tmp_str_len;
+
+ /* If the message is not terminated by '\n', do not submit the message to logger yet
+ * (rather save it, waiting for a later message with '\n'). */
+ if (session->str[strlen(session->str) - 1] == '\n')
+ {
+ bcm_dev_log_log(
+ session->log_id, session->log_level, BCM_LOG_FLAG_NO_HEADER | BCM_LOG_FLAG_CALLER_FMT, "%s", session->str);
+ *session->str = '\0';
+ session->free_len = MAX_DEV_LOG_STRING_NET_SIZE - 1;
+ }
+
+ return size;
+}
+
+bcmos_errno bcm_dev_log_cli_session_create(
+ dev_log_id log_id,
+ bcm_dev_log_level log_level,
+ bcm_dev_log_cli_session **session)
+{
+ bcmos_errno err;
+ bcmcli_session_parm session_params = { .write = dev_log_cli_session_write_cb };
+
+ *session = bcmos_calloc(sizeof(bcm_dev_log_cli_session));
+ if (*session == NULL)
+ {
+ return BCM_ERR_NOMEM;
+ }
+
+ session_params.user_priv = *session;
+ err = bcmcli_session_open(&session_params, &((*session)->session));
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_free(*session);
+ *session = NULL;
+ return err;
+ }
+
+ (*session)->log_id = log_id;
+ (*session)->log_level = log_level;
+ (*session)->free_len = MAX_DEV_LOG_STRING_NET_SIZE - 1;
+ return BCM_ERR_OK;
+}
+
+bcmcli_entry *bcm_dev_log_cli_init(bcmcli_entry *root_dir)
+{
+ bcmcli_entry *dir;
+ static bcmcli_enum_val enum_table_log_level[] =
+ {
+ { .name = "NO_LOG", .val = (long)DEV_LOG_LEVEL_NO_LOG },
+ { .name = "FATAL", .val = (long)DEV_LOG_LEVEL_FATAL },
+ { .name = "ERROR", .val = (long)DEV_LOG_LEVEL_ERROR },
+ { .name = "WARNING", .val = (long)DEV_LOG_LEVEL_WARNING},
+ { .name = "INFO", .val = (long)DEV_LOG_LEVEL_INFO },
+ { .name = "DEBUG", .val = (long)DEV_LOG_LEVEL_DEBUG },
+ BCMCLI_ENUM_LAST
+ };
+
+ if ((dir = bcmcli_dir_find(NULL, "logger")) != NULL)
+ return dir;
+
+ dir = bcmcli_dir_add(root_dir, "logger", "Dev Log", BCMCLI_ACCESS_GUEST, NULL);
+
+ {
+ BCMCLI_MAKE_CMD_NOPARM(dir, "print_dev_log", "Print Dev log", bcm_dev_log_cli_print_dev_log);
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "logger_control", "Logger Control", bcm_dev_log_cli_logger_control,
+ BCMCLI_MAKE_PARM_RANGE("enable", "enable", BCMCLI_PARM_UDECIMAL, 0, 0, 1));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "file_print", "Print logger file", bcm_dev_log_cli_file_print,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_RANGE("clear", "clear", BCMCLI_PARM_UDECIMAL, 0, 0, 1));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "file_clear", "Clear file", bcm_dev_log_cli_file_clear,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0));
+ }
+ {
+ static bcmcli_enum_val enum_table_file_flags[] =
+ {
+ { .name = "VALID", .val = (long)BCM_DEV_LOG_FILE_FLAG_VALID },
+ { .name = "WRAP_AROUND", .val = (long)BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND },
+ { .name = "STOP_WHEN_FULL", .val = (long)BCM_DEV_LOG_FILE_FLAG_STOP_WHEN_FULL },
+ BCMCLI_ENUM_LAST
+ };
+ BCMCLI_MAKE_CMD(dir, "file_set_flags", "Set file flags", bcm_dev_log_cli_file_set_flags,
+ BCMCLI_MAKE_PARM_RANGE("index", "index", BCMCLI_PARM_UDECIMAL, 0, 0, DEV_LOG_MAX_FILES-1),
+ BCMCLI_MAKE_PARM_ENUM("flags", "flags", enum_table_file_flags, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "file_reset_flags", "Reset file flags", bcm_dev_log_cli_file_reset_flags,
+ BCMCLI_MAKE_PARM_RANGE("index", "index", BCMCLI_PARM_UDECIMAL, 0, 0, DEV_LOG_MAX_FILES-1));
+ }
+ {
+ static bcmcli_cmd_parm set1[]=
+ {
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_PARM_LIST_TERMINATOR
+ };
+ static bcmcli_cmd_parm set2[] =
+ {
+ BCMCLI_MAKE_PARM("name", "name", BCMCLI_PARM_STRING, 0),
+ BCMCLI_PARM_LIST_TERMINATOR
+ };
+ static bcmcli_enum_val selector_table[] =
+ {
+ { .name = "by_index", .val = ID_BY_INDEX, .parms = set1 },
+ { .name = "by_name", .val = ID_BY_NAME, .parms = set2 },
+ BCMCLI_ENUM_LAST
+ };
+ BCMCLI_MAKE_CMD(dir, "id_get", "id_get", bcm_dev_log_cli_id_get,
+ BCMCLI_MAKE_PARM_SELECTOR("by", "by", selector_table, 0));
+ }
+ {
+ static bcmcli_enum_val enum_table[] =
+ {
+ { .name = "none", .val = (long)DEV_LOG_ID_TYPE_NONE },
+ { .name = "print", .val = (long)DEV_LOG_ID_TYPE_PRINT },
+ { .name = "save", .val = (long)DEV_LOG_ID_TYPE_SAVE },
+ { .name = "both", .val = (long)DEV_LOG_ID_TYPE_BOTH },
+ BCMCLI_ENUM_LAST
+ };
+ BCMCLI_MAKE_CMD(dir, "id_set_type", "id_set_type", bcm_dev_log_cli_id_set_type,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_type", "log_type", enum_table, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "id_set_level", "id_set_level", bcm_dev_log_cli_id_set_level,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_print", "log_level", enum_table_log_level, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_save", "log_level", enum_table_log_level, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "name_set_level", "name_set_level", bcm_dev_log_cli_name_set_level,
+ BCMCLI_MAKE_PARM("name", "name", BCMCLI_PARM_STRING, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_print", "log_level", enum_table_log_level, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_save", "log_level", enum_table_log_level, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "id_set_to_default", "id_set_to_default", bcm_dev_log_cli_id_set_to_default,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0));
+ }
+ {
+ static bcmcli_enum_val enum_table_log_style[] =
+ {
+ { .name = "normal", .val = (long)BCM_DEV_LOG_STYLE_NORMAL },
+ { .name = "bold", .val = (long)BCM_DEV_LOG_STYLE_BOLD },
+ { .name = "underline", .val = (long)BCM_DEV_LOG_STYLE_UNDERLINE },
+ { .name = "blink", .val = (long)BCM_DEV_LOG_STYLE_BLINK },
+ { .name = "reverse_video", .val = (long)BCM_DEV_LOG_STYLE_REVERSE_VIDEO },
+ BCMCLI_ENUM_LAST
+ };
+ BCMCLI_MAKE_CMD(dir, "id_set_style", "id_set_style", bcm_dev_log_cli_id_set_style,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("style", "style", enum_table_log_style, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "id_clear_counters", "id_clear_counters", bcm_dev_log_cli_id_clear_counters,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "log", "log", bcm_dev_log_cli_log,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_print", "log_level", enum_table_log_level, 0),
+ BCMCLI_MAKE_PARM("string", "string", BCMCLI_PARM_STRING, 0),
+ BCMCLI_MAKE_PARM("count", "Number of messages to send", BCMCLI_PARM_UDECIMAL, BCMCLI_PARM_FLAG_OPTIONAL));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "instance_enable", "enable/disable instance number", bcm_dev_log_cli_instance_enable,
+ BCMCLI_MAKE_PARM_ENUM("enable", "enable", bcmcli_enum_bool_table, 0),
+ BCMCLI_MAKE_PARM("instance", "instance number", BCMCLI_PARM_UDECIMAL, 0));
+ }
+#ifdef TRIGGER_LOGGER_FEATURE
+ {
+ BCMCLI_MAKE_CMD(dir, "id_set_throttle", "set throttle", bcm_dev_log_cli_throttle,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_print", "log_level", enum_table_log_level, 0),
+ BCMCLI_MAKE_PARM("throttle", "throttle", BCMCLI_PARM_UDECIMAL, 0));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "id_set_trigger", "set trigger", bcm_dev_log_cli_trigger,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM_ENUM("log_level_print", "log_level", enum_table_log_level, 0),
+ BCMCLI_MAKE_PARM("start", "start", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM("stop", "stop", BCMCLI_PARM_UDECIMAL, 0),
+ BCMCLI_MAKE_PARM("repeat", "repeat", BCMCLI_PARM_DECIMAL, BCMCLI_PARM_FLAG_OPTIONAL));
+ }
+ {
+ BCMCLI_MAKE_CMD(dir, "id_get_feature", "get feature", bcm_dev_log_cli_get_features,
+ BCMCLI_MAKE_PARM("index", "index", BCMCLI_PARM_UDECIMAL, 0));
+ }
+#endif
+ return dir;
+}
+
+#endif /* #ifndef __KERNEL__ */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.h b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.h
new file mode 100644
index 0000000..da090b4
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_cli.h
@@ -0,0 +1,55 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef BCM_DEV_LOG_CLI_H_
+#define BCM_DEV_LOG_CLI_H_
+
+#include <bcmcli.h>
+#include <bcmcli_session.h>
+#include "bcm_dev_log_task.h"
+
+typedef struct
+{
+ bcmcli_session *session;
+ dev_log_id log_id;
+ bcm_dev_log_level log_level;
+ char str[MAX_DEV_LOG_STRING_NET_SIZE];
+ uint32_t free_len;
+} bcm_dev_log_cli_session;
+
+/* create a CLI session adaptation layer that outputs to a dev log instead of to a CLI shell */
+bcmos_errno bcm_dev_log_cli_session_create(
+ dev_log_id log_id,
+ bcm_dev_log_level log_level,
+ bcm_dev_log_cli_session **session);
+
+/* initialize the dev log CLI functions */
+bcmcli_entry *bcm_dev_log_cli_init(bcmcli_entry *root_dir);
+
+#endif /* BCM_DEV_LOG_CLI_H_ */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.c b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.c
new file mode 100644
index 0000000..6665588
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.c
@@ -0,0 +1,1752 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifdef ENABLE_LOG
+
+#include "bcm_dev_log_task.h"
+#include "bcm_dev_log_task_internal.h"
+#include "bcm_dev_log.h"
+#if defined(LINUX_KERNEL_SPACE) && !defined(__KERNEL__)
+#include "bcmolt_dev_log_linux.h"
+#endif
+
+#ifdef DEV_LOG_SYSLOG
+#include <syslog.h>
+#endif
+
+#define USE_ANSI_ESCAPE_CODES
+
+#ifdef USE_ANSI_ESCAPE_CODES
+#define DEV_LOG_STYLE_NORMAL "\033[0m\033#5"
+#define DEV_LOG_STYLE_BOLD "\033[1m"
+#define DEV_LOG_STYLE_UNDERLINE "\033[4m"
+#define DEV_LOG_STYLE_BLINK "\033[5m"
+#define DEV_LOG_STYLE_REVERSE_VIDEO "\033[7m"
+#else
+#define DEV_LOG_STYLE_NORMAL " "
+#define DEV_LOG_STYLE_BOLD "*** "
+#define DEV_LOG_STYLE_UNDERLINE "___ "
+#define DEV_LOG_STYLE_BLINK "o_o "
+#define DEV_LOG_STYLE_REVERSE_VIDEO "!!! "
+#endif
+
+#define DEV_LOG_MSG_START_CHAR 0x1e /* record separator character */
+
+#define MEM_FILE_HDR_SIZE sizeof(dev_log_mem_file_header)
+
+#define LOG_MIN(a,b) (((int)(a) <= (int)(b)) ? (a) : (b))
+
+dev_log_id def_log_id;
+
+static bcm_dev_log_style dev_log_level2style[DEV_LOG_LEVEL_NUM_OF] =
+{
+ [DEV_LOG_LEVEL_FATAL] = BCM_DEV_LOG_STYLE_NORMAL,
+ [DEV_LOG_LEVEL_ERROR] = BCM_DEV_LOG_STYLE_NORMAL,
+ [DEV_LOG_LEVEL_WARNING] = BCM_DEV_LOG_STYLE_NORMAL,
+ [DEV_LOG_LEVEL_INFO] = BCM_DEV_LOG_STYLE_NORMAL,
+ [DEV_LOG_LEVEL_DEBUG] = BCM_DEV_LOG_STYLE_NORMAL,
+};
+
+static const char *dev_log_style_array[] =
+{
+ [BCM_DEV_LOG_STYLE_NORMAL] = DEV_LOG_STYLE_NORMAL,
+ [BCM_DEV_LOG_STYLE_BOLD] = DEV_LOG_STYLE_BOLD,
+ [BCM_DEV_LOG_STYLE_UNDERLINE] = DEV_LOG_STYLE_UNDERLINE,
+ [BCM_DEV_LOG_STYLE_BLINK] = DEV_LOG_STYLE_BLINK,
+ [BCM_DEV_LOG_STYLE_REVERSE_VIDEO] = DEV_LOG_STYLE_REVERSE_VIDEO,
+};
+
+bcm_dev_log dev_log = {{0}};
+const char *log_level_str = "?FEWID";
+
+static void bcm_dev_log_shutdown_msg_release(bcmos_msg *m)
+{
+ (void)m; /* do nothing, the message is statically allocated */
+}
+
+static bcmos_msg shutdown_msg = { .release = bcm_dev_log_shutdown_msg_release };
+
+static void bcm_dev_log_file_save_msg(bcm_dev_log_file *files, const char *message)
+{
+ uint32_t i;
+ uint32_t len = strlen(message) + 1; /* including 0 terminator */
+
+ for (i = 0; (i < DEV_LOG_MAX_FILES) && (files[i].file_parm.flags & BCM_DEV_LOG_FILE_FLAG_VALID); i++)
+ {
+ files[i].file_parm.write_cb(&files[i], message, len);
+ }
+}
+
+static void dev_log_save_task_handle_message(bcmos_msg *msg)
+{
+ static char log_string[MAX_DEV_LOG_STRING_SIZE];
+ uint32_t length;
+ char time_str[17];
+ dev_log_queue_msg *receive_msg = msg->data;
+ dev_log_id_parm *log_id = receive_msg->log_id;
+ bcm_dev_log_level msg_level = receive_msg->msg_level;
+
+ /* Build message header */
+ *log_string = '\0';
+ if (!(receive_msg->flags & BCM_LOG_FLAG_NO_HEADER))
+ {
+ length = sizeof(time_str);
+ dev_log.dev_log_parm.time_to_str_cb(receive_msg->time_stamp, time_str, length);
+ snprintf(
+ log_string,
+ sizeof(log_string),
+ "[%s: %c %-20s] ",
+ time_str,
+ log_level_str[msg_level],
+ log_id->name);
+ }
+
+ /* Modify the __FILE__ format so it would print the filename only without the path.
+ * If using BCM_LOG_FLAG_CALLER_FMT, it is done in caller context, because filename might be long, taking a lot of
+ * the space of the message itself. */
+ if ((receive_msg->flags & BCM_LOG_FLAG_FILENAME_IN_FMT) && !(receive_msg->flags & BCM_LOG_FLAG_CALLER_FMT))
+ receive_msg->u.fmt_args.fmt = dev_log_basename(receive_msg->u.fmt_args.fmt);
+
+ if (receive_msg->flags & BCM_LOG_FLAG_CALLER_FMT)
+ {
+ /* Copy user string to buffer */
+ strncat(log_string, receive_msg->u.str, sizeof(log_string) - strlen(log_string) - 1);
+ }
+ else
+ {
+ uint32_t offset = ((long)receive_msg->u.fmt_args.args % 8 == 0) ? 0 : 1; /* start on an 8-byte boundary */
+ va_list ap;
+ *(void **)&ap = &receive_msg->u.fmt_args.args[offset];
+
+ /* Copy user string to buffer */
+ vsnprintf(log_string + strlen(log_string),
+ sizeof(log_string) - strlen(log_string),
+ receive_msg->u.fmt_args.fmt,
+ ap);
+ }
+
+ /* Force last char to be end of string */
+ log_string[MAX_DEV_LOG_STRING_SIZE - 1] = '\0';
+
+ /* At this point, if the message is going to be sent to the print task, save the formatted string then forward it.
+ * Otherwise, we can release the message before writing it to RAM. */
+ if ((log_id->log_type & DEV_LOG_ID_TYPE_PRINT) &&
+ (msg_level <= log_id->log_level_print))
+ {
+ if (!bcm_dev_log_level_is_error(msg_level) &&
+ (receive_msg->flags & BCM_LOG_FLAG_DONT_SKIP_PRINT) != 0 &&
+ bcm_dev_log_pool_occupancy_percent_get() >= DEV_LOG_SKIP_PRINT_THRESHOLD_PERCENT)
+ {
+ log_id->print_skipped_count++;
+ bcmos_msg_free(msg);
+ }
+ else
+ {
+ strcpy(receive_msg->u.str, log_string); /* so the print task doesn't need to re-format it */
+ bcmos_msg_send(&dev_log.print_queue, msg, 0);
+ }
+ }
+ else
+ {
+ bcmos_msg_free(msg);
+ }
+
+ /* Save to file */
+ if ((log_id->log_type & DEV_LOG_ID_TYPE_SAVE) &&
+ (msg_level <= log_id->log_level_save))
+ {
+ bcm_dev_log_file_save_msg(dev_log.files, log_string);
+ }
+}
+
+static void dev_log_print_task_handle_message(bcmos_msg *msg)
+{
+ static char log_string[MAX_DEV_LOG_STRING_SIZE];
+ dev_log_queue_msg *receive_msg = msg->data;
+ dev_log_id_parm *log_id = receive_msg->log_id;
+ bcm_dev_log_level msg_level = receive_msg->msg_level;
+
+ /* make a local copy of the pre-formatted string (it was formatted in the save task) */
+ strcpy(log_string, receive_msg->u.str);
+
+ /* free the message ASAP since printing might take some time */
+ bcmos_msg_free(msg);
+
+ if (log_id->style == BCM_DEV_LOG_STYLE_NORMAL &&
+ dev_log_level2style[msg_level] == BCM_DEV_LOG_STYLE_NORMAL)
+ {
+ dev_log.dev_log_parm.print_cb(dev_log.dev_log_parm.print_cb_arg, "%s", log_string);
+ }
+ else
+ {
+ /* If style was set per log id, then use it. */
+ if (log_id->style != BCM_DEV_LOG_STYLE_NORMAL)
+ {
+ dev_log.dev_log_parm.print_cb(
+ dev_log.dev_log_parm.print_cb_arg,
+ "%s%s%s",
+ dev_log_style_array[log_id->style],
+ log_string,
+ dev_log_style_array[BCM_DEV_LOG_STYLE_NORMAL]);
+ }
+ else
+ {
+ /* Otherwise - style was set per log level. */
+ dev_log.dev_log_parm.print_cb(
+ dev_log.dev_log_parm.print_cb_arg,
+ "%s%s%s",
+ dev_log_style_array[dev_log_level2style[msg_level]],
+ log_string,
+ dev_log_style_array[BCM_DEV_LOG_STYLE_NORMAL]);
+ }
+ }
+}
+
+static int dev_log_print_task(long data)
+{
+ bcmos_msg *m;
+ bcmos_errno error;
+ const char error_str[MAX_DEV_LOG_STRING_SIZE] = "Error: Can't receive from queue - dev_log print task exit\n";
+
+ while (1)
+ {
+ error = bcmos_msg_recv(&dev_log.print_queue, BCMOS_WAIT_FOREVER, &m);
+ if (error != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("%s", error_str);
+ dev_log.dev_log_parm.print_cb(dev_log.dev_log_parm.print_cb_arg, "%s", error_str);
+ bcm_dev_log_file_save_msg(dev_log.files, error_str);
+ return (int)error;
+ }
+
+ if (m == &shutdown_msg)
+ {
+ bcmos_msg_free(m);
+ break; /* shut down gracefully */
+ }
+ else
+ {
+ dev_log_print_task_handle_message(m);
+ }
+ }
+
+ bcmos_sem_post(&dev_log.print_task_is_terminated);
+
+ return 0;
+}
+
+static int dev_log_save_task(long data)
+{
+ bcmos_msg *m;
+ bcmos_errno error;
+ const char error_str[MAX_DEV_LOG_STRING_SIZE] = "Error: Can't receive from queue - dev_log save task exit\n";
+
+ while (1)
+ {
+ error = bcmos_msg_recv(&dev_log.save_queue, BCMOS_WAIT_FOREVER, &m);
+ if (error != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("%s", error_str);
+ dev_log.dev_log_parm.print_cb(dev_log.dev_log_parm.print_cb_arg, "%s", error_str);
+ bcm_dev_log_file_save_msg(dev_log.files, error_str);
+ return (int)error;
+ }
+
+ if (m == &shutdown_msg)
+ {
+ bcmos_msg_free(m);
+ break; /* shut down gracefully */
+ }
+ else
+ {
+ dev_log_save_task_handle_message(m);
+ }
+ }
+
+ bcmos_sem_post(&dev_log.save_task_is_terminated);
+
+ return 0;
+}
+
+static int default_time_to_str(uint32_t time_stamp, char *time_str, int time_str_size)
+{
+ return snprintf(time_str, time_str_size, "%u", time_stamp);
+}
+
+static uint32_t default_get_time(void)
+{
+ return 0;
+}
+
+static int default_print(void *arg, const char *format, ...)
+{
+ va_list args;
+
+ va_start(args, format);
+ bcmos_vprintf(format, args);
+ va_end(args);
+ return 0;
+}
+
+static bcmos_errno default_open_callback_cond_reset(const bcm_dev_log_file_parm *file_parm, bcm_dev_log_file *file, bcmos_bool is_rewind)
+{
+ bcmos_errno err;
+
+ if (!file->file_parm.start_addr || file->file_parm.size <= MEM_FILE_HDR_SIZE)
+ return BCM_ERR_PARM;
+
+ /* Create file mutex */
+ err = bcmos_mutex_create(&file->u.mem_file.mutex, 0, NULL);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't create mutex (error: %d)\n", (int)err);
+ return err;
+ }
+
+ /* Check file magic string */
+ memcpy(&file->u.mem_file.file_header, (uint8_t *)file->file_parm.start_addr, MEM_FILE_HDR_SIZE);
+ if (memcmp(FILE_MAGIC_STR, file->u.mem_file.file_header.file_magic, FILE_MAGIC_STR_SIZE))
+ {
+ DEV_LOG_INFO_PRINTF("No file magic string - file is empty/corrupt\n");
+ if (!is_rewind || !file->file_parm.rewind_cb)
+ {
+ bcmos_mutex_destroy(&file->u.mem_file.mutex);
+ return BCM_ERR_NOENT;
+ }
+ return file->file_parm.rewind_cb(file);
+ }
+
+ DEV_LOG_INFO_PRINTF("Attached to existing file\n");
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno default_open_callback(const bcm_dev_log_file_parm *file_parm, bcm_dev_log_file *file)
+{
+ return default_open_callback_cond_reset(file_parm, file, BCMOS_TRUE);
+}
+
+static bcmos_errno default_close_callback(bcm_dev_log_file *file)
+{
+ bcmos_mutex_destroy(&file->u.mem_file.mutex);
+ return BCM_ERR_OK;
+}
+
+/* Look for start of msg character */
+static int get_msg_start_offset(bcm_dev_log_file *file, uint32_t offset, uint32_t max_len)
+{
+ uint8_t *buf, *msg;
+
+ buf = (uint8_t *)file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE;
+ msg = memchr(buf, DEV_LOG_MSG_START_CHAR, max_len);
+ if (!msg)
+ return -1;
+ return (msg - buf + 1);
+}
+
+/* Look for 0-terminator */
+static int get_msg_end_offset(bcm_dev_log_file *file, uint32_t offset, uint32_t max_len)
+{
+ uint8_t *buf, *end;
+
+ buf = (uint8_t *)file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE;
+ end = memchr(buf, 0, max_len);
+ if (!end)
+ return -1;
+ return (end - buf + 1);
+}
+
+static int default_read_callback(bcm_dev_log_file *log_file, uint32_t *p_offset, void *buf, uint32_t length)
+{
+ uint32_t offset = *p_offset;
+ uint32_t real_length = 0;
+ int start, end;
+
+ /* If file wrapped around, offset starts from write_offset, otherwise,
+ * it starts from the beginning
+ */
+ if (log_file->u.mem_file.file_header.file_wrap_cnt)
+ {
+ if (offset + length >= log_file->u.mem_file.file_header.data_size)
+ {
+ length = log_file->u.mem_file.file_header.data_size - offset;
+ if (length <= 0)
+ return 0;
+ }
+ offset += log_file->u.mem_file.file_header.write_offset;
+ if (offset >= log_file->u.mem_file.file_header.data_size)
+ offset -= log_file->u.mem_file.file_header.data_size;
+ /* Find beginning of the next message */
+ start = get_msg_start_offset(log_file, offset, LOG_MIN(log_file->u.mem_file.file_header.data_size - offset,
+ MAX_DEV_LOG_STRING_SIZE));
+ if (start < 0)
+ {
+ /* Didn't find any up to the end of buffer. Look from the start */
+ offset = 0;
+ if (!log_file->u.mem_file.file_header.write_offset)
+ return 0;
+ start = get_msg_start_offset(log_file, 0, LOG_MIN(log_file->u.mem_file.file_header.write_offset - 1,
+ MAX_DEV_LOG_STRING_SIZE));
+ if (start <= 0)
+ return 0;
+ }
+ offset += start;
+ }
+ else
+ {
+ /* Start beginning of message. Without wrap-around it should be right at the offset,
+ * so, it is just a precaution */
+ start = get_msg_start_offset(log_file, offset, LOG_MIN(log_file->u.mem_file.file_header.data_size - offset,
+ MAX_DEV_LOG_STRING_SIZE));
+ if (start <= 0)
+ return 0;
+ offset += start;
+ /* Stop reading when reached write_offset */
+ if (offset + length >= log_file->u.mem_file.file_header.write_offset)
+ {
+ if (offset >= log_file->u.mem_file.file_header.write_offset)
+ return 0;
+ length = log_file->u.mem_file.file_header.write_offset - offset;
+ }
+ }
+
+ /* We have the beginning. Now find the end of message and copy to the user
+ * buffer if there is enough room */
+ if (offset + length > log_file->u.mem_file.file_header.data_size)
+ {
+ uint32_t length1 = offset + length - log_file->u.mem_file.file_header.data_size; /* tail length */
+ length -= length1;
+ end = get_msg_end_offset(log_file, offset, length);
+ if (end >= 0)
+ {
+ memcpy(buf, (uint8_t *)log_file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE, end);
+ *p_offset += end + start;
+ return end;
+ }
+
+ /* Didn't find end of message in the end of file data buffer. wrap around */
+ memcpy(buf, (uint8_t *)log_file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE, length);
+ real_length = length;
+ buf = (uint8_t *)buf + length;
+ length = length1;
+ offset = 0;
+ }
+ end = get_msg_end_offset(log_file, offset, MAX_DEV_LOG_STRING_SIZE);
+ if (end <= 0)
+ {
+ /* something is wrong. msg is not terminated */
+ return 0;
+ }
+ /* If there is no room for the whole message - return overflow */
+ if (end > length)
+ return (int)BCM_ERR_OVERFLOW;
+
+ memcpy(buf, (uint8_t *)log_file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE, end);
+ real_length += end;
+
+ *p_offset += real_length + start;
+
+ return real_length;
+}
+
+static int get_num_of_overwritten_messages(uint8_t *buf, uint32_t length)
+{
+ uint8_t *p;
+ int n = 0;
+
+ do
+ {
+ p = memchr(buf, DEV_LOG_MSG_START_CHAR, length);
+ if (p == NULL)
+ break;
+ ++n;
+ length -= (p + 1 - buf);
+ buf = p + 1;
+ } while(length);
+
+ return n;
+}
+
+static int default_write_callback(bcm_dev_log_file *file, const void *buf, uint32_t length)
+{
+ uint32_t offset, next_offset;
+ uint8_t *p;
+ int n_overwritten = 0;
+
+ if ((file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_STOP_WHEN_FULL) && file->is_full)
+ return 0;
+
+ if (!length)
+ return 0;
+
+ bcmos_mutex_lock(&file->u.mem_file.mutex);
+
+ offset = file->u.mem_file.file_header.write_offset;
+ next_offset = offset + length + 1; /* 1 extra character for record delimiter */
+
+ /* Handle overflow */
+ if (next_offset >= file->u.mem_file.file_header.data_size)
+ {
+ uint32_t tail_length;
+
+ /* Split buffer in 2 */
+ tail_length = next_offset - file->u.mem_file.file_header.data_size; /* 2nd segment length */
+
+ if ((file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_STOP_WHEN_FULL) && tail_length)
+ {
+ file->is_full = BCMOS_TRUE;
+ bcmos_mutex_unlock(&file->u.mem_file.mutex);
+ return 0;
+ }
+
+ length -= tail_length;
+ /* "if (next_offset >= file->u.mem_file.file_header.data_size)" condition
+ * guarantees that there is room for at least 1 character in the end of file */
+ p = (uint8_t *)file->file_parm.start_addr + offset + MEM_FILE_HDR_SIZE;
+ if (file->u.mem_file.file_header.file_wrap_cnt)
+ n_overwritten += get_num_of_overwritten_messages(p, length + 1);
+ *p = DEV_LOG_MSG_START_CHAR;
+ if (length)
+ {
+ memcpy(p + 1, buf, length);
+ buf = (const uint8_t *)buf + length;
+ }
+ if (tail_length)
+ {
+ p = (uint8_t *)file->file_parm.start_addr + MEM_FILE_HDR_SIZE;
+ if (file->u.mem_file.file_header.file_wrap_cnt)
+ n_overwritten += get_num_of_overwritten_messages(p, tail_length);
+ memcpy(p, buf, tail_length);
+ ++file->u.mem_file.file_header.file_wrap_cnt;
+ }
+ next_offset = tail_length;
+ }
+ else
+ {
+ p = (uint8_t *)file->file_parm.start_addr + MEM_FILE_HDR_SIZE + offset;
+ if (file->u.mem_file.file_header.file_wrap_cnt)
+ n_overwritten += get_num_of_overwritten_messages(p, length + 1);
+ *(p++) = DEV_LOG_MSG_START_CHAR;
+ memcpy(p, buf, length);
+ }
+ file->u.mem_file.file_header.write_offset = next_offset;
+ file->u.mem_file.file_header.num_msgs += (1 - n_overwritten);
+
+ /* update the header */
+ memcpy((uint8_t *)file->file_parm.start_addr, &file->u.mem_file.file_header, MEM_FILE_HDR_SIZE);
+
+ /* send almost full indication if necessary */
+ if (file->almost_full.send_ind_cb &&
+ !file->almost_full.ind_sent &&
+ file->u.mem_file.file_header.write_offset > file->almost_full.threshold)
+ {
+ file->almost_full.ind_sent = (file->almost_full.send_ind_cb(file->almost_full.priv) == BCM_ERR_OK);
+ }
+
+ bcmos_mutex_unlock(&file->u.mem_file.mutex);
+
+ return length;
+}
+
+static bcmos_errno default_rewind_callback(bcm_dev_log_file *file)
+{
+ bcmos_mutex_lock(&file->u.mem_file.mutex);
+
+ DEV_LOG_INFO_PRINTF("Clear file\n");
+ file->u.mem_file.file_header.file_wrap_cnt = 0;
+ file->u.mem_file.file_header.write_offset = 0;
+ file->u.mem_file.file_header.data_size = file->file_parm.size - MEM_FILE_HDR_SIZE;
+ file->u.mem_file.file_header.num_msgs = 0;
+ strcpy(file->u.mem_file.file_header.file_magic, FILE_MAGIC_STR);
+ memcpy((uint8_t *)file->file_parm.start_addr, &file->u.mem_file.file_header, MEM_FILE_HDR_SIZE);
+ file->almost_full.ind_sent = BCMOS_FALSE;
+
+ bcmos_mutex_unlock(&file->u.mem_file.mutex);
+
+ return BCM_ERR_OK;
+}
+
+
+static void set_default_file_callbacks(bcm_dev_log_file *file)
+{
+ file->file_parm.open_cb = default_open_callback;
+ file->file_parm.close_cb = default_close_callback;
+ file->file_parm.read_cb = default_read_callback;
+ file->file_parm.write_cb = default_write_callback;
+ file->file_parm.rewind_cb = default_rewind_callback;
+}
+
+static inline bcmos_bool bcm_dev_log_is_memory_file(bcm_dev_log_file *file)
+{
+ return (file->file_parm.open_cb == default_open_callback);
+}
+
+bcmos_errno bcm_dev_log_file_clear(bcm_dev_log_file *file)
+{
+ if (!file || !(file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_VALID))
+ return BCM_ERR_PARM;
+
+ if (!file->file_parm.rewind_cb)
+ return BCM_ERR_NOT_SUPPORTED;
+
+ return file->file_parm.rewind_cb(file);
+}
+
+/* File index to file handle */
+bcm_dev_log_file *bcm_dev_log_file_get(uint32_t file_index)
+{
+ bcm_dev_log_file *file = &dev_log.files[file_index];
+
+ if ((file_index >= DEV_LOG_MAX_FILES) || !(file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_VALID))
+ return NULL;
+ return file;
+}
+
+/* Read from file */
+int bcm_dev_log_file_read(bcm_dev_log_file *file, uint32_t *offset, char *buf, uint32_t buf_len)
+{
+ int len;
+ if (!file || !buf || !(file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_VALID))
+ return (int)BCM_ERR_PARM;
+
+ len = file->file_parm.read_cb(file, offset, buf, buf_len);
+ /* If nothing more to read and CLEAR_AFTER_READ mode, read again under lock and clear if no new records */
+ if (!len && bcm_dev_log_is_memory_file(file) && (file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_CLEAR_AFTER_READ))
+ {
+ bcmos_mutex_lock(&file->u.mem_file.mutex);
+ len = file->file_parm.read_cb(file, offset, buf, buf_len);
+ if (!len)
+ file->file_parm.rewind_cb(file);
+ bcmos_mutex_unlock(&file->u.mem_file.mutex);
+ }
+ return len;
+}
+
+/* Attach file to memory buffer */
+bcmos_errno bcm_dev_log_file_attach(void *buf, uint32_t buf_len, bcm_dev_log_file *file)
+{
+ bcmos_errno rc;
+ dev_log_mem_file_header *hdr = (dev_log_mem_file_header *)buf;
+
+ if (!buf || !file || buf_len <= MEM_FILE_HDR_SIZE)
+ return BCM_ERR_PARM;
+
+ if (memcmp(FILE_MAGIC_STR, hdr->file_magic, FILE_MAGIC_STR_SIZE))
+ return BCM_ERR_NOENT;
+
+#if DEV_LOG_ENDIAN != BCM_CPU_ENDIAN
+ hdr->file_wrap_cnt = bcmos_endian_swap_u32(hdr->file_wrap_cnt);
+ hdr->write_offset = bcmos_endian_swap_u32(hdr->write_offset);
+ hdr->data_size = bcmos_endian_swap_u32(hdr->data_size);
+ hdr->num_msgs = bcmos_endian_swap_u32(hdr->num_msgs);
+#endif
+
+ memset(file, 0, sizeof(*file));
+ file->file_parm.start_addr = buf;
+ file->file_parm.size = buf_len;
+ file->file_parm.flags = BCM_DEV_LOG_FILE_FLAG_VALID;
+ set_default_file_callbacks(file);
+ rc = default_open_callback_cond_reset(&file->file_parm, file, BCMOS_FALSE);
+ if (rc)
+ return rc;
+
+ if (!file->u.mem_file.file_header.num_msgs)
+ return BCM_ERR_NOENT;
+
+ return BCM_ERR_OK;
+}
+
+/* Detach file handle from memory buffer */
+bcmos_errno bcm_dev_log_file_detach(bcm_dev_log_file *file)
+{
+ if (!file || !(file->file_parm.flags & BCM_DEV_LOG_FILE_FLAG_VALID))
+ return BCM_ERR_PARM;
+ file->file_parm.flags = BCM_DEV_LOG_FILE_FLAG_VALID;
+ bcmos_mutex_destroy(&file->u.mem_file.mutex);
+ return BCM_ERR_OK;
+}
+
+
+#ifdef BCM_OS_POSIX
+ /* Regular file callbacks */
+
+/****************************************************************************************/
+/* OPEN CALLBACK: open memory/file */
+/* file_parm - file parameters */
+/* file - file */
+/****************************************************************************************/
+static bcmos_errno _dev_log_reg_file_open(const bcm_dev_log_file_parm *file_parm, bcm_dev_log_file *file)
+{
+ bcmos_errno err = BCM_ERR_OK;
+
+ file->file_parm = *file_parm;
+ file->u.reg_file_handle = fopen((char *)file_parm->udef_parms, "w+");
+ if (!file->u.reg_file_handle)
+ {
+ bcmos_printf("DEV_LOG: can't open file %s for writing\n", (char *)file_parm->udef_parms);
+ err = BCM_ERR_IO;
+ }
+ return err;
+}
+
+/****************************************************************************************/
+/* CLOSE CALLBACK: close memory/file */
+/* file - file handle */
+/****************************************************************************************/
+static bcmos_errno _dev_log_reg_file_close(bcm_dev_log_file *file)
+{
+ if (file->u.reg_file_handle)
+ {
+ fclose(file->u.reg_file_handle);
+ file->u.reg_file_handle = NULL;
+ }
+ return BCM_ERR_OK;
+}
+
+/****************************************************************************************/
+/* REWIND CALLBACK: clears memory/file */
+/* file - file handle */
+/****************************************************************************************/
+static bcmos_errno _dev_log_reg_file_rewind(bcm_dev_log_file *file)
+{
+ bcmos_errno err = BCM_ERR_OK;
+ FILE *f;
+
+ if (file->u.reg_file_handle)
+ {
+ f = freopen((const char *)file->file_parm.udef_parms, "w+", file->u.reg_file_handle);
+ if (NULL != f)
+ {
+ file->u.reg_file_handle = f;
+ }
+ else
+ {
+ err = BCM_ERR_IO;
+ bcmos_printf("DEV_LOG: can't open file %s for writing\n", (char *)file->file_parm.udef_parms);
+ }
+
+ }
+ return err;
+}
+
+/****************************************************************************************/
+/* READ_CALLBACK: read form memory/file */
+/* offset - the offset in bytes to read from, output */
+/* buf - Where to put the result */
+/* length - Buffer length */
+/* This function should return the number of bytes actually read from file or 0 if EOF */
+/****************************************************************************************/
+static int _dev_log_reg_file_read(bcm_dev_log_file *file, uint32_t *offset, void *buf, uint32_t length)
+{
+ int n = 0;
+ if (file->u.reg_file_handle)
+ {
+ if (!fseek(file->u.reg_file_handle, SEEK_SET, *offset))
+ n = fread(buf, 1, length, file->u.reg_file_handle);
+ *offset = ftell(file->u.reg_file_handle);
+ }
+ return (n < 0) ? 0 : n;
+}
+
+/****************************************************************************************/
+/* WRITE_CALLBACK: write form memory/file */
+/* buf - The buffer that should be written */
+/* length - The number of bytes to write */
+/* This function should return the number of bytes actually written to file or 0 if EOF */
+/****************************************************************************************/
+static int _dev_log_reg_file_write(bcm_dev_log_file *file, const void *buf, uint32_t length)
+{
+ const char *cbuf = (const char *)buf;
+ int n = 0;
+ if (file->u.reg_file_handle)
+ {
+ /* Remove 0 terminator */
+ if (length && !cbuf[length-1])
+ --length;
+ n = fwrite(buf, 1, length, file->u.reg_file_handle);
+ fflush(file->u.reg_file_handle);
+ }
+ return n;
+}
+
+static void set_regular_file_callbacks(bcm_dev_log_file *file)
+{
+ file->file_parm.open_cb = _dev_log_reg_file_open;
+ file->file_parm.close_cb = _dev_log_reg_file_close;
+ file->file_parm.read_cb = _dev_log_reg_file_read;
+ file->file_parm.write_cb = _dev_log_reg_file_write;
+ file->file_parm.rewind_cb = _dev_log_reg_file_rewind;
+}
+
+#endif /* #ifdef BCM_OS_POSIX */
+
+#ifdef DEV_LOG_SYSLOG
+ /* linux syslog integration */
+/****************************************************************************************/
+/* OPEN CALLBACK: open syslog interface */
+/* file_parm->udef_parm contains optional log ident */
+/****************************************************************************************/
+static bcmos_errno _dev_log_syslog_file_open(const bcm_dev_log_file_parm *file_parm, bcm_dev_log_file *file)
+{
+ file->file_parm = *file_parm;
+ openlog((const char *)file_parm->udef_parms, 0, LOG_USER);
+ return BCM_ERR_OK;
+}
+
+/****************************************************************************************/
+/* CLOSE CALLBACK: close syslog interface */
+/****************************************************************************************/
+static bcmos_errno _dev_log_syslog_file_close(bcm_dev_log_file *file)
+{
+ closelog();
+ return BCM_ERR_OK;
+}
+
+/****************************************************************************************/
+/* REWIND CALLBACK: not supported by syslog. Return OK to prevent request failure */
+/****************************************************************************************/
+static bcmos_errno _dev_log_syslog_file_rewind(bcm_dev_log_file *file)
+{
+ return BCM_ERR_OK;
+}
+
+/****************************************************************************************/
+/* READ_CALLBACK: reading from syslog is not supported */
+/****************************************************************************************/
+static int _dev_log_syslog_file_read(bcm_dev_log_file *file, uint32_t *offset, void *buf, uint32_t length)
+{
+ return 0;
+}
+
+/****************************************************************************************/
+/* WRITE_CALLBACK: write to syslog */
+/* buf - The buffer that should be written */
+/* length - The number of bytes to write */
+/* This function should return the number of bytes actually written to file or 0 if EOF */
+/****************************************************************************************/
+static int _dev_log_syslog_file_write(bcm_dev_log_file *file, const void *buf, uint32_t length)
+{
+ const char *cbuf = (const char *)buf;
+ static int log_priority = LOG_DEBUG;
+
+ /* Identify log lovel */
+ if (cbuf && cbuf[0] == '[')
+ {
+ const char *clevel = strchr(cbuf, ' ');
+ if (clevel)
+ {
+ switch (*(clevel + 1))
+ {
+ case 'F':
+ log_priority = LOG_CRIT;
+ break;
+ case 'E':
+ log_priority = LOG_ERR;
+ break;
+ case 'W':
+ log_priority = LOG_WARNING;
+ break;
+ case 'I':
+ log_priority = LOG_INFO;
+ break;
+ case 'D':
+ log_priority = LOG_DEBUG;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ syslog(log_priority, "%s", cbuf);
+ return length;
+}
+
+static void set_syslog_file_callbacks(bcm_dev_log_file *file)
+{
+ file->file_parm.open_cb = _dev_log_syslog_file_open;
+ file->file_parm.close_cb = _dev_log_syslog_file_close;
+ file->file_parm.read_cb = _dev_log_syslog_file_read;
+ file->file_parm.write_cb = _dev_log_syslog_file_write;
+ file->file_parm.rewind_cb = _dev_log_syslog_file_rewind;
+}
+
+#endif /* #ifdef DEV_LOG_SYSLOG */
+
+static bcmos_errno bcm_dev_log_create(
+ const bcm_dev_log_parm *dev_log_parm,
+ const bcmos_task_parm *save_task_parm,
+ const bcmos_task_parm *print_task_parm,
+ const bcmos_msg_queue_parm *save_queue_parm,
+ const bcmos_msg_queue_parm *print_queue_parm,
+ const bcmos_msg_pool_parm *pool_parm)
+{
+ bcmos_errno err;
+ int i;
+
+ if (!dev_log_parm)
+ return BCM_ERR_PARM;
+
+ if (dev_log.state != BCM_DEV_LOG_STATE_UNINITIALIZED)
+ return BCM_ERR_ALREADY;
+
+ /* Set user callbacks */
+ dev_log.dev_log_parm = *dev_log_parm;
+ if (!dev_log.dev_log_parm.print_cb)
+ dev_log.dev_log_parm.print_cb = default_print;
+ if (!dev_log.dev_log_parm.get_time_cb)
+ dev_log.dev_log_parm.get_time_cb = default_get_time;
+ if (!dev_log.dev_log_parm.time_to_str_cb)
+ dev_log.dev_log_parm.time_to_str_cb = default_time_to_str;
+
+ for (i = 0; (i < DEV_LOG_MAX_FILES) && (dev_log_parm->log_file[i].flags & BCM_DEV_LOG_FILE_FLAG_VALID); i++)
+ {
+ /* Copy log files */
+ dev_log.files[i].file_parm = dev_log_parm->log_file[i];
+ if (!dev_log.files[i].file_parm.open_cb)
+ {
+ if (dev_log.files[i].file_parm.type == BCM_DEV_LOG_FILE_MEMORY)
+ set_default_file_callbacks(&dev_log.files[i]);
+#ifdef BCM_OS_POSIX
+ else if (dev_log.files[i].file_parm.type == BCM_DEV_LOG_FILE_REGULAR)
+ set_regular_file_callbacks(&dev_log.files[i]);
+#endif
+#ifdef DEV_LOG_SYSLOG
+ else if (dev_log.files[i].file_parm.type == BCM_DEV_LOG_FILE_SYSLOG)
+ set_syslog_file_callbacks(&dev_log.files[i]);
+#endif
+ else
+ {
+ DEV_LOG_ERROR_PRINTF("file%d: open_cb must be set for user-defined file\n\n", i);
+ continue;
+ }
+ }
+ err = dev_log.files[i].file_parm.open_cb(&dev_log.files[i].file_parm, &dev_log.files[i]);
+ if (err)
+ {
+ DEV_LOG_ERROR_PRINTF("file%d: open failed: %s (%d)\n\n", i, bcmos_strerror(err), err );
+ continue;
+ }
+ DEV_LOG_INFO_PRINTF("file: start_addr: 0x%p, size: %u, max msg size %u\n",
+ dev_log.files[i].file_parm.start_addr, dev_log.files[i].file_parm.size, MAX_DEV_LOG_STRING_SIZE);
+ }
+
+ /* Create pool */
+ err = bcmos_msg_pool_create(&dev_log.pool, pool_parm);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't create pool (error: %d)\n", (int)err);
+ return err;
+ }
+
+ /* Create message queues */
+ err = bcmos_msg_queue_create(&dev_log.save_queue, save_queue_parm);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("(%s) Error: Can't create save queue (error: %d)\n", __FUNCTION__, (int)err);
+ return err;
+ }
+ err = bcmos_msg_queue_create(&dev_log.print_queue, print_queue_parm);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("(%s) Error: Can't create print queue (error: %d)\n", __FUNCTION__, (int)err);
+ return err;
+ }
+
+ /* Create tasks */
+ err = bcmos_task_create(&dev_log.save_task, save_task_parm);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't spawn save task (error: %d)\n", (int)err);
+ return err;
+ }
+ err = bcmos_task_create(&dev_log.print_task, print_task_parm);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't spawn print task (error: %d)\n", (int)err);
+ return err;
+ }
+
+ bcmos_sem_create(&dev_log.save_task_is_terminated, 0, 0, "save_task_sem");
+ bcmos_sem_create(&dev_log.print_task_is_terminated, 0, 0, "print_task_sem");
+
+ dev_log.state = BCM_DEV_LOG_STATE_ENABLED;
+
+ return BCM_ERR_OK;
+}
+
+void bcm_dev_log_destroy(void)
+{
+ bcmos_errno err;
+ uint32_t i;
+ bcmos_msg_send_flags msg_flags;
+
+ if (dev_log.state == BCM_DEV_LOG_STATE_UNINITIALIZED)
+ {
+ return;
+ }
+
+ /* Send a shutdown message to each task. When received by the main loops, it will tear down the tasks gracefully.
+ * If the flag is set to tear down immediately, we'll send an URGENT teardown message, so it'll be handled before
+ * all oustanding log messages (the oustanding log messages will be freed during bcmos_msg_queue_destroy). */
+ msg_flags = BCMOS_MSG_SEND_NOLIMIT;
+ if ((dev_log.flags & BCM_DEV_LOG_FLAG_DESTROY_IMMEDIATELY) != 0)
+ msg_flags |= BCMOS_MSG_SEND_URGENT;
+
+ /* The save task depends on the print task, so we terminate the save task first. */
+ bcmos_msg_send(&dev_log.save_queue, &shutdown_msg, msg_flags);
+ bcmos_sem_wait(&dev_log.save_task_is_terminated, BCMOS_WAIT_FOREVER);
+
+ bcmos_msg_send(&dev_log.print_queue, &shutdown_msg, msg_flags);
+ bcmos_sem_wait(&dev_log.print_task_is_terminated, BCMOS_WAIT_FOREVER);
+
+ bcmos_sem_destroy(&dev_log.save_task_is_terminated);
+ bcmos_sem_destroy(&dev_log.print_task_is_terminated);
+
+ err = bcmos_task_destroy(&dev_log.save_task);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't destroy dev_log save task (error: %d)\n", (int)err);
+ }
+
+ err = bcmos_task_destroy(&dev_log.print_task);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't destroy dev_log print task (error: %d)\n", (int)err);
+ }
+
+ err = bcmos_msg_queue_destroy(&dev_log.save_queue);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't destroy save queue (error: %d)\n", (int)err);
+ }
+
+ err = bcmos_msg_queue_destroy(&dev_log.print_queue);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't destroy print queue (error: %d)\n", (int)err);
+ }
+
+ err = bcmos_msg_pool_destroy(&dev_log.pool);
+ if (err != BCM_ERR_OK)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: Can't destroy pool (error: %d)\n", (int)err);
+ }
+
+ for (i = 0; (i < DEV_LOG_MAX_FILES) && (dev_log.dev_log_parm.log_file[i].flags & BCM_DEV_LOG_FILE_FLAG_VALID); i++)
+ {
+ dev_log.files[i].file_parm.close_cb(&dev_log.files[i]);
+ }
+
+ dev_log.state = BCM_DEV_LOG_STATE_UNINITIALIZED;
+}
+
+typedef struct
+{
+ bcmos_msg msg;
+ dev_log_queue_msg log_queue_msg;
+ bcmos_bool lock;
+ bcmos_fastlock fastlock;
+} bcm_dev_log_drop_msg;
+
+typedef struct
+{
+ bcm_dev_log_drop_msg msg;
+ uint32_t drops;
+ uint32_t reported_drops;
+ bcmos_timer timer;
+ uint32_t last_report_timestamp;
+} bcm_dev_log_drop;
+
+static bcm_dev_log_drop dev_log_drop;
+
+static void bcm_dev_log_log_message_release_drop(bcmos_msg *m)
+{
+ unsigned long flags;
+
+ flags = bcmos_fastlock_lock(&dev_log_drop.msg.fastlock);
+ dev_log_drop.msg.lock = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+
+ /* Schedule a timer to report extra drops, because we may not meet DEV_LOG_DROP_REPORT_DROP_THRESHOLD soon. */
+ bcmos_timer_start(&dev_log_drop.timer, DEV_LOG_DROP_REPORT_RATE_US);
+}
+
+static void _bcm_dev_log_drop_report(void)
+{
+ bcmos_msg *msg;
+ dev_log_queue_msg *log_queue_msg;
+
+ msg = &dev_log_drop.msg.msg;
+ msg->release = bcm_dev_log_log_message_release_drop;
+ log_queue_msg = &dev_log_drop.msg.log_queue_msg;
+ log_queue_msg->flags = BCM_LOG_FLAG_DONT_SKIP_PRINT;
+ log_queue_msg->time_stamp = dev_log.dev_log_parm.get_time_cb();
+ log_queue_msg->msg_level = DEV_LOG_LEVEL_ERROR;
+ log_queue_msg->u.fmt_args.fmt = "Log message pool exhausted, dropped message count=%u\n";
+ log_queue_msg->u.fmt_args.args[0] = (const void *)(unsigned long)(dev_log_drop.drops - dev_log_drop.reported_drops);
+ log_queue_msg->u.fmt_args.args[1] =
+ log_queue_msg->u.fmt_args.args[0]; /* args[0] may or may not be skipped depending on alignment */
+ log_queue_msg->log_id = (dev_log_id_parm *)def_log_id;
+ log_queue_msg->time_stamp = dev_log.dev_log_parm.get_time_cb();
+ dev_log_drop.reported_drops = dev_log_drop.drops;
+ dev_log_drop.last_report_timestamp = bcmos_timestamp();
+
+ msg->data = log_queue_msg;
+ msg->size = sizeof(*log_queue_msg);
+ bcmos_msg_send(&dev_log.save_queue, msg, 0);
+}
+
+void bcm_dev_log_drop_report(void)
+{
+ unsigned long flags;
+
+ dev_log_drop.drops++;
+
+ flags = bcmos_fastlock_lock(&dev_log_drop.msg.fastlock);
+ /* The 1st drop report will be done immediately, because although DEV_LOG_DROP_REPORT_DROP_THRESHOLD isn't reached, the time difference is greater than
+ * DEV_LOG_DROP_REPORT_RATE_US. */
+ if (dev_log_drop.msg.lock ||
+ ((dev_log_drop.drops - dev_log_drop.reported_drops < DEV_LOG_DROP_REPORT_DROP_THRESHOLD) &&
+ (bcmos_timestamp() - dev_log_drop.last_report_timestamp < DEV_LOG_DROP_REPORT_RATE_US)))
+ {
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+ return;
+ }
+
+ dev_log_drop.msg.lock = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+
+ /* Do the actual report. */
+ _bcm_dev_log_drop_report();
+}
+
+static bcmos_timer_rc bcm_dev_log_drop_timer_cb(bcmos_timer *timer, long data)
+{
+ unsigned long flags;
+
+ flags = bcmos_fastlock_lock(&dev_log_drop.msg.fastlock);
+ if (dev_log_drop.msg.lock)
+ {
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+ /* Logger task hasn't released the lock yet (the drop message hasn't been reported yet) -> reschedule the timer. */
+ bcmos_timer_start(&dev_log_drop.timer, DEV_LOG_DROP_REPORT_RATE_US);
+ }
+ else
+ {
+ if (dev_log_drop.drops == dev_log_drop.reported_drops)
+ {
+ /* No new drops to report. */
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+ return BCMOS_TIMER_OK;
+ }
+ dev_log_drop.msg.lock = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&dev_log_drop.msg.fastlock, flags);
+
+ /* Do the actual report. */
+ _bcm_dev_log_drop_report();
+ }
+
+ return BCMOS_TIMER_OK;
+}
+
+bcmos_errno bcm_dev_log_init_default_logger_ext(
+ bcm_dev_log_parm *dev_log_parm,
+ uint32_t num_files,
+ uint32_t stack_size,
+ bcmos_task_priority priority,
+ uint32_t pool_size)
+{
+ bcmos_errno err;
+ bcmos_task_parm save_task_parm = {0};
+ bcmos_task_parm print_task_parm = {0};
+ bcmos_msg_queue_parm print_queue_parm = {0};
+ bcmos_msg_queue_parm save_queue_parm = {0};
+ bcmos_msg_pool_parm pool_parm = {0};
+ bcmos_timer_parm timer_params =
+ {
+ .name = "dev_log_drop_timer",
+ .owner = BCMOS_MODULE_ID_NONE, /* Will be called in ISR context */
+ .handler = bcm_dev_log_drop_timer_cb,
+ };
+
+ if (!dev_log_parm)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: dev_log_parm must be set\n");
+ return BCM_ERR_PARM;
+ }
+
+ save_task_parm.priority = priority;
+ save_task_parm.stack_size = stack_size;
+ save_task_parm.name = "dev_log_save";
+ save_task_parm.handler = dev_log_save_task;
+ save_task_parm.data = 0;
+
+ print_task_parm.priority = priority;
+ print_task_parm.stack_size = stack_size;
+ print_task_parm.name = "dev_log_print";
+ print_task_parm.handler = dev_log_print_task;
+ print_task_parm.data = 0;
+
+ /* It is important to avoid terminating logger task during an exception, as logger task is low priority and might have backlog of unhandled messages.
+ * Even if as a result of the exception the logger task will be in a deadlock waiting for a resource (semaphore/mutex/timer), it is in lower priority than CLI and thus should not block
+ * CLI. */
+ save_task_parm.flags = BCMOS_TASK_FLAG_NO_SUSPEND_ON_OOPS;
+ print_task_parm.flags = BCMOS_TASK_FLAG_NO_SUSPEND_ON_OOPS;
+
+ save_queue_parm.name = "dev_log_save";
+ save_queue_parm.size = 0; /* unlimited */
+ print_queue_parm.name = "dev_log_print";
+ print_queue_parm.size = 0; /* unlimited */
+
+ pool_parm.name = "dev_log";
+ pool_parm.size = pool_size;
+ pool_parm.data_size = sizeof(dev_log_queue_msg);
+
+ def_log_id = bcm_dev_log_id_register("default", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ err = bcmos_timer_create(&dev_log_drop.timer, &timer_params);
+ BCMOS_TRACE_CHECK_RETURN(err, err, "bcmos_timer_create");
+ bcmos_fastlock_init(&dev_log_drop.msg.fastlock, 0);
+
+ if (!dev_log_parm->get_time_cb)
+ dev_log_parm->get_time_cb = bcmos_timestamp;
+
+ err = bcm_dev_log_create(
+ dev_log_parm,
+ &save_task_parm,
+ &print_task_parm,
+ &save_queue_parm,
+ &print_queue_parm,
+ &pool_parm);
+ BCMOS_TRACE_CHECK_RETURN(err, err, "bcm_dev_log_create");
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_init_default_logger(void **start_addresses,
+ uint32_t *sizes,
+ bcm_dev_log_file_flags *flags,
+ uint32_t num_files,
+ uint32_t stack_size,
+ bcmos_task_priority priority,
+ uint32_t pool_size)
+{
+ bcm_dev_log_parm dev_log_parm = {0};
+ uint32_t i;
+
+ for (i = 0; i < num_files; i++)
+ {
+ dev_log_parm.log_file[i].start_addr = start_addresses[i];
+ dev_log_parm.log_file[i].size = sizes[i];
+ /* size[i] might be 0 in simulation build for sram buffer. */
+ dev_log_parm.log_file[i].flags = (sizes[i] ? BCM_DEV_LOG_FILE_FLAG_VALID : BCM_DEV_LOG_FILE_FLAG_NONE) |
+ (flags ? flags[i] : BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND);
+ }
+
+ return bcm_dev_log_init_default_logger_ext(&dev_log_parm, num_files, stack_size, priority,
+ pool_size);
+}
+
+log_name_table logs_names[DEV_LOG_MAX_IDS];
+uint8_t log_name_table_index = 0;
+
+static void dev_log_add_log_name_to_table(const char *xi_name)
+{
+ char name[MAX_DEV_LOG_ID_NAME + 1] = {};
+ char *p = name;
+ char *p_end;
+ int i = 0;
+ long val = -1;
+
+ strncpy(name, xi_name, MAX_DEV_LOG_ID_NAME);
+ while (*p)
+ {
+ /* While there are more characters to process... */
+ if (isdigit(*p))
+ {
+ /* Upon finding a digit, ... */
+ val = strtol(p, &p_end, 10); /* Read a number, ... */
+ if ((name + strlen(name)) != p_end)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: dev_log_add_log_name_to_table %s)\n", xi_name);
+ }
+ *p = '\0';
+ break;
+
+ }
+ else
+ {
+ /* Otherwise, move on to the next character. */
+ p++;
+ }
+ }
+ for (i = 0; i < log_name_table_index; i++)
+ {
+ if (strcmp(name, logs_names[i].name) == 0)
+ {
+ if (val < logs_names[i].first_instance)
+ {
+ logs_names[i].first_instance = val;
+ }
+ if (val > logs_names[i].last_instance)
+ {
+ logs_names[i].last_instance = val;
+ }
+ break;
+ }
+ }
+ if ((i == log_name_table_index) && (i < DEV_LOG_MAX_IDS))
+ {
+ strncpy(logs_names[i].name, name, MAX_DEV_LOG_ID_NAME);
+ if (val == -1)
+ {
+ val = LOG_NAME_NO_INSTANCE;
+ }
+ logs_names[i].last_instance = val;
+ logs_names[i].first_instance = val;
+ log_name_table_index++;
+ }
+}
+
+void dev_log_get_log_name_table(char *buffer, uint32_t buf_len)
+{
+ uint32_t i = 0;
+ uint32_t buf_len_free = buf_len;
+
+ buffer[0] = '\0';
+ for (i = 0; i < log_name_table_index; i++)
+ {
+ if (logs_names[i].first_instance == LOG_NAME_NO_INSTANCE)
+ {
+ snprintf(&buffer[strlen(buffer)], buf_len_free, "%s\n", logs_names[i].name);
+ }
+ else
+ {
+ snprintf(&buffer[strlen(buffer)], buf_len_free, "%s %d - %d\n", logs_names[i].name, logs_names[i].first_instance, logs_names[i].last_instance);
+ }
+ buffer[buf_len - 1] = '\0';
+ buf_len_free = buf_len - strlen(buffer);
+ if (buf_len_free <= 1)
+ {
+ DEV_LOG_ERROR_PRINTF("Error: dev_log_get_log_name_table too long\n");
+ break;
+ }
+ }
+}
+
+dev_log_id bcm_dev_log_id_register(const char *xi_name,
+ bcm_dev_log_level xi_default_log_level,
+ bcm_dev_log_id_type xi_default_log_type)
+{
+ dev_log_id_parm *new_id;
+
+ /* Check that we have room for one more ID */
+ if (dev_log.num_ids == BCM_SIZEOFARRAY(dev_log.ids))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: wrong parameters\n");
+ return DEV_LOG_INVALID_ID;
+ }
+
+ /* Get next free log_id in array and increment next_id.
+ * The new_id structure is clean because the whole dev_log array is in BSS
+ */
+ new_id = &dev_log.ids[dev_log.num_ids++];
+
+ /* Add prefix for kernel log_ids in order to avoid clash with similarly-names logs in the user space */
+#ifdef __KERNEL__
+ strcpy(new_id->name, "k_");
+#endif
+
+ /* Set log_id parameters */
+ strncat(new_id->name, xi_name, sizeof(new_id->name)-strlen(new_id->name));
+ new_id->name[MAX_DEV_LOG_ID_NAME-1] = '\0';
+
+ new_id->default_log_type = xi_default_log_type;
+ new_id->default_log_level = xi_default_log_level;
+
+ dev_log_add_log_name_to_table(new_id->name);
+
+ bcm_dev_log_id_set_levels_and_type_to_default((dev_log_id)new_id);
+ new_id->style = BCM_DEV_LOG_STYLE_NORMAL;
+
+ return (dev_log_id)new_id;
+}
+
+bcmos_errno bcm_dev_log_id_set_type(dev_log_id xi_id, bcm_dev_log_id_type xi_log_type)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+
+ /* In linux kernel we only support save */
+#ifdef __KERNEL__
+ if (xi_log_type & DEV_LOG_ID_TYPE_BOTH)
+ xi_log_type = DEV_LOG_ID_TYPE_SAVE;
+#endif
+
+ DEV_LOG_INFO_PRINTF("ID: 0x%lx, New log type: %d\n", xi_id, (int)xi_log_type);
+
+ id->log_type = xi_log_type;
+
+ /* In linux user space we need to notify kernel integration code */
+#if defined(LINUX_KERNEL_SPACE) && !defined(__KERNEL__)
+ bcm_dev_log_linux_id_set_type(xi_id, xi_log_type);
+#endif
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_id_set_level(dev_log_id xi_id, bcm_dev_log_level xi_log_level_print, bcm_dev_log_level xi_log_level_save)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+
+ if ((xi_log_level_print >= DEV_LOG_LEVEL_NUM_OF) || (xi_log_level_save >= DEV_LOG_LEVEL_NUM_OF))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: wrong parameters\n");
+ return BCM_ERR_PARM;
+ }
+
+ DEV_LOG_INFO_PRINTF("ID: 0x%p, New: xi_log_level_print=%u, xi_log_level_save=%u\n",
+ (void *)id,
+ xi_log_level_print,
+ xi_log_level_save);
+
+ id->log_level_print = xi_log_level_print;
+ id->log_level_save = xi_log_level_save;
+
+ /* In linux user space we need to notify kernel integration code */
+#if defined(LINUX_KERNEL_SPACE) && !defined(__KERNEL__)
+ bcm_dev_log_linux_id_set_level(xi_id, xi_log_level_print, xi_log_level_save);
+#endif
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_id_set_levels_and_type_to_default(dev_log_id xi_id)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+
+ id->log_level_print = id->default_log_level;
+ id->log_level_save = id->default_log_level;
+ id->log_type = id->default_log_type;
+
+#ifdef TRIGGER_LOGGER_FEATURE
+ memset(&id->throttle,0, sizeof(dev_log_id_throttle));
+ memset(&id->trigger, 0, sizeof(dev_log_id_trigger));
+ id->throttle_log_level = DEV_LOG_LEVEL_NO_LOG;
+ id->trigger_log_level = DEV_LOG_LEVEL_NO_LOG;
+#endif
+
+ /* In linux kernel space we don't support PRINT, only SAVE */
+#ifdef __KERNEL__
+ if (id->log_type & DEV_LOG_ID_TYPE_BOTH)
+ id->log_type = DEV_LOG_ID_TYPE_SAVE;
+#endif
+
+ return BCM_ERR_OK;
+}
+
+void bcm_dev_log_level_set_style(bcm_dev_log_level level, bcm_dev_log_style xi_style)
+{
+ dev_log_level2style[level] = xi_style;
+}
+
+bcmos_errno bcm_dev_log_id_set_style(dev_log_id xi_id, bcm_dev_log_style xi_style)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+ id->style = xi_style;
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_id_clear_counters(dev_log_id xi_id)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+ memset(id->counters, 0, sizeof(id->counters));
+ id->lost_msg_cnt = 0;
+ id->print_skipped_count = 0;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_id_get(dev_log_id xi_id, dev_log_id_parm *xo_id)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+
+ *xo_id = *id;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_dev_log_id_set(dev_log_id xi_id, dev_log_id_parm *parms)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+
+ *id = *parms;
+
+ return BCM_ERR_OK;
+}
+
+dev_log_id bcm_dev_log_id_get_by_index(uint32_t xi_index)
+{
+ if (xi_index >= dev_log.num_ids)
+ {
+ return DEV_LOG_INVALID_ID;
+ }
+ return (dev_log_id)&(dev_log.ids[xi_index]);
+}
+
+uint32_t bcm_dev_log_get_index_by_id(dev_log_id xi_id)
+{
+ uint32_t idx = (dev_log_id_parm *)xi_id - &dev_log.ids[0];
+ if (idx >= dev_log.num_ids)
+ idx = DEV_LOG_INVALID_INDEX;
+ return idx;
+}
+
+dev_log_id bcm_dev_log_id_get_by_name(const char *xi_name)
+{
+ uint32_t i;
+
+ if (xi_name == NULL)
+ {
+ return DEV_LOG_INVALID_ID;
+ }
+
+ for (i = 0; i<dev_log.num_ids; i++)
+ {
+ if (!strcmp(dev_log.ids[i].name, xi_name))
+ {
+ return (dev_log_id)&(dev_log.ids[i]);
+ }
+ }
+
+ DEV_LOG_ERROR_PRINTF("Error: can't find name\n");
+ return DEV_LOG_INVALID_ID;
+}
+
+uint32_t bcm_dev_log_get_num_of_entries(void)
+{
+ return dev_log.num_ids;
+}
+
+bcmos_bool bcm_dev_log_get_control(void)
+{
+ return dev_log.state == BCM_DEV_LOG_STATE_ENABLED;
+}
+
+uint32_t bcm_dev_log_get_num_of_messages(bcm_dev_log_file *file)
+{
+ return file->u.mem_file.file_header.num_msgs;
+}
+
+void bcm_dev_log_set_control(bcmos_bool control)
+{
+ if (control && dev_log.state == BCM_DEV_LOG_STATE_DISABLED)
+ dev_log.state = BCM_DEV_LOG_STATE_ENABLED;
+ else if (!control && dev_log.state == BCM_DEV_LOG_STATE_ENABLED)
+ dev_log.state = BCM_DEV_LOG_STATE_DISABLED;
+}
+
+bcm_dev_log_file_flags bcm_dev_log_get_file_flags(uint32_t file_id)
+{
+ return dev_log.files[file_id].file_parm.flags;
+}
+
+void bcm_dev_log_set_file_flags(uint32_t file_id, bcm_dev_log_file_flags flags)
+{
+ dev_log.files[file_id].file_parm.flags = flags;
+}
+
+bcm_dev_log_flags bcm_dev_log_get_flags(void)
+{
+ return dev_log.flags;
+}
+
+void bcm_dev_log_set_flags(bcm_dev_log_flags flags)
+{
+ dev_log.flags = flags;
+}
+
+void bcm_dev_log_set_print_cb(bcm_dev_log_print_cb cb)
+{
+ dev_log.dev_log_parm.print_cb = cb;
+}
+
+void bcm_dev_log_set_get_time_cb(bcm_dev_log_get_time_cb cb)
+{
+ dev_log.dev_log_parm.get_time_cb = cb;
+}
+
+void bcm_dev_log_set_time_to_str_cb(bcm_dev_log_time_to_str_cb cb)
+{
+ dev_log.dev_log_parm.time_to_str_cb = cb;
+}
+
+#ifdef TRIGGER_LOGGER_FEATURE
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_set_throttle */
+/* */
+/* Abstract: Set throttle level for the specific log is and its level */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_log_level - log level */
+/* - xi_throttle - throttle number, 0 - no throttle */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_set_throttle(dev_log_id xi_id, bcm_dev_log_level xi_log_level, uint32_t xi_throttle)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+ id->throttle_log_level = xi_log_level;
+ id->throttle.threshold = xi_throttle;
+ id->throttle.counter = 0;
+
+ return BCM_ERR_OK;
+}
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_set_trigger */
+/* */
+/* Abstract: Set trigger counters for the specific log is and its level */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_log_level - log level */
+/* - xi_start - start printing after this number, 0 - no trigger */
+/* - xi_stop - stop printing after this number, 0 - do not stop */
+/* - xi_repeat - start printing after this number, 0 - no repeat, -1 always */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_set_trigger(dev_log_id xi_id, bcm_dev_log_level xi_log_level, uint32_t xi_start, uint32_t xi_stop, int32_t xi_repeat)
+{
+ dev_log_id_parm *id = (dev_log_id_parm *)xi_id;
+
+ if (!xi_id || (xi_id == DEV_LOG_INVALID_ID))
+ {
+ DEV_LOG_ERROR_PRINTF("Error: xi_id not valid (0x%x)\n", (unsigned int)xi_id);
+ return BCM_ERR_PARM;
+ }
+ id->trigger_log_level = xi_log_level;
+ id->trigger.start_threshold = xi_start;
+ id->trigger.stop_threshold = xi_stop;
+ id->trigger.repeat_threshold = xi_repeat;
+ id->trigger.counter = 0;
+ id->trigger.repeat = 0;
+
+ return BCM_ERR_OK;
+}
+#endif /* TRIGGER_LOGGER_FEATURE */
+
+/* Get file info: max data size, used bytes */
+bcmos_errno bcm_dev_log_get_file_info(bcm_dev_log_file *file, uint32_t *file_size, uint32_t *used_bytes)
+{
+ if (!file || !file_size || !used_bytes)
+ return BCM_ERR_PARM;
+ /* Only supported for memory files */
+ if (!bcm_dev_log_is_memory_file(file))
+ return BCM_ERR_NOT_SUPPORTED;
+ *file_size = file->u.mem_file.file_header.data_size;
+ *used_bytes = (file->u.mem_file.file_header.file_wrap_cnt || file->is_full) ?
+ file->u.mem_file.file_header.data_size : file->u.mem_file.file_header.write_offset;
+ return BCM_ERR_OK;
+}
+
+/* Register indication to be sent when file utilization crosses threshold */
+bcmos_errno bcm_dev_log_almost_full_ind_register(bcm_dev_log_file *file, uint32_t used_bytes_threshold,
+ F_dev_log_file_almost_full send_ind_cb, long ind_cb_priv)
+{
+ if (!file || (used_bytes_threshold && !send_ind_cb))
+ return BCM_ERR_PARM;
+ /* Only supported for memory files */
+ if (!bcm_dev_log_is_memory_file(file))
+ return BCM_ERR_NOT_SUPPORTED;
+
+ bcmos_mutex_lock(&file->u.mem_file.mutex);
+ file->almost_full.threshold = used_bytes_threshold;
+ file->almost_full.send_ind_cb = send_ind_cb;
+ file->almost_full.priv = ind_cb_priv;
+ file->almost_full.ind_sent = BCMOS_FALSE;
+ bcmos_mutex_unlock(&file->u.mem_file.mutex);
+
+ return BCM_ERR_OK;
+}
+
+#endif /* ENABLE_LOG */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.h b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.h
new file mode 100644
index 0000000..227bb12
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task.h
@@ -0,0 +1,651 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef __BCM_DEV_LOG_TASK_H_
+#define __BCM_DEV_LOG_TASK_H_
+
+/* Because we cast from dev_log_id to pointer type in bcm_dev_log.c, we want it to be the same size as a pointer size (e.g: "typedef uint32_t dev_log_id" won't work
+ * on 64bit platform). */
+typedef unsigned long dev_log_id;
+
+#define DEV_LOG_INVALID_ID (dev_log_id)UINT_MAX
+
+#ifdef ENABLE_LOG
+
+/* Uncomment the following line to enable info prints for dev_log debugging */
+/* #define DEV_LOG_DEBUG */
+
+#include <bcmos_system.h>
+
+/********************************************/
+/* */
+/* Log macros */
+/* */
+/********************************************/
+
+/********************************************/
+/* */
+/* Defines/Typedefs */
+/* */
+/********************************************/
+
+#define STRINGIFY(x) #x
+#define STRINGIFY_EXPAND(str) STRINGIFY(str)
+
+#ifdef __KERNEL__
+#define DEV_LOG_PRINTF printk
+#define DEV_LOG_VPRINTF vprintk
+#else
+#define DEV_LOG_PRINTF bcmos_printf
+#define DEV_LOG_VPRINTF bcmos_vprintf
+#endif
+
+#ifdef DEV_LOG_DEBUG
+#define DEV_LOG_INFO_PRINTF(fmt, args...) DEV_LOG_PRINTF("(%s:" STRINGIFY_EXPAND(__LINE__) ") " fmt, __FUNCTION__, ##args)
+#else
+static inline void dev_log_info_printf_ignore(const char *fmt, ...) { }
+#define DEV_LOG_INFO_PRINTF(fmt, args...) dev_log_info_printf_ignore(fmt, ##args)
+#endif
+#define DEV_LOG_ERROR_PRINTF(fmt, args...) DEV_LOG_PRINTF("(%s:" STRINGIFY_EXPAND(__LINE__) ") " fmt, __FUNCTION__, ##args)
+
+/* IMPORTANT! when modifying DEV_LOG_MAX_ARGS,
+ * don't forget to add/remove _BCM_LOG_ARGS... macros in order to force number of arguments in compile time
+ */
+#define DEV_LOG_MAX_ARGS 36
+/* String bigger than this size will be cut */
+#define MAX_DEV_LOG_ID_NAME 32 /* Maximum size of log_id name */
+#define DEV_LOG_MAX_IDS 512
+#define DEV_LOG_MAX_FILES 2
+#define MAX_DEV_LOG_STRING_SIZE 256 /* Note that this size includes header. */
+#define MAX_DEV_LOG_HEADER_SIZE (7 + 16 + 20) /* (time=16, ID=20, delimiters=7) */
+#define MAX_DEV_LOG_STRING_NET_SIZE (MAX_DEV_LOG_STRING_SIZE - MAX_DEV_LOG_HEADER_SIZE)
+#define DEV_LOG_INVALID_INDEX UINT_MAX
+#define DEV_LOG_DROP_REPORT_RATE_US 1000000 /* 1 second */
+#define DEV_LOG_DROP_REPORT_DROP_THRESHOLD 1000
+#define DEV_LOG_ENDIAN BCMOS_ENDIAN_LITTLE
+
+/* If the log message pool utilization is >= this percentage, do not print messages (only save them).
+ * (note that error/fatal messages will not objey this rule). */
+#define DEV_LOG_SKIP_PRINT_THRESHOLD_PERCENT 50
+
+/* If the log message pool utilization is >= this percentage, drop all messages that aren't 'error' or 'fatal' level. */
+#define DEV_LOG_ERROR_ONLY_THRESHOLD_PERCENT 75
+
+/* Log level enum */
+typedef enum
+{
+ DEV_LOG_LEVEL_NO_LOG = 0,
+ DEV_LOG_LEVEL_FATAL,
+ DEV_LOG_LEVEL_ERROR,
+ DEV_LOG_LEVEL_WARNING,
+ DEV_LOG_LEVEL_INFO,
+ DEV_LOG_LEVEL_DEBUG,
+
+ DEV_LOG_LEVEL_NUM_OF
+} bcm_dev_log_level;
+
+/* Log type enum */
+typedef enum
+{
+ /* Bit[0] - Print Enable, Bit[1] - Save Enable */
+ DEV_LOG_ID_TYPE_NONE = 0, /* NO SAVE, NO PRINT*/
+ DEV_LOG_ID_TYPE_PRINT = 1,
+ DEV_LOG_ID_TYPE_SAVE = 1 << 1,
+ DEV_LOG_ID_TYPE_BOTH = DEV_LOG_ID_TYPE_PRINT | DEV_LOG_ID_TYPE_SAVE, /* SAVE & PRINT */
+} bcm_dev_log_id_type;
+
+typedef enum
+{
+ BCM_DEV_LOG_FLAG_NONE = 0,
+
+ /* Even if logger is disabled, BCM_LOG() calls are redirected to bcmos_printf(). */
+ BCM_DEV_LOG_FLAG_DISABLED_WITH_PRINTF = 1 << 0,
+
+ /* When bcm_dev_log_destroy() is called, do not wait for outstanding log messages to be drained. Discard the
+ * messages and destroy the task immediately. */
+ BCM_DEV_LOG_FLAG_DESTROY_IMMEDIATELY = 1 << 1,
+} bcm_dev_log_flags;
+
+typedef enum
+{
+ BCM_DEV_LOG_FILE_FLAG_NONE = 0,
+ BCM_DEV_LOG_FILE_FLAG_VALID = 1, /**< file is valid */
+ BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND = 1 << 1, /**< new messages will override old */
+ BCM_DEV_LOG_FILE_FLAG_STOP_WHEN_FULL = 1 << 2, /**< stop logging if the file is full */
+ BCM_DEV_LOG_FILE_FLAG_CLEAR_AFTER_READ = 1 << 4, /**< auto-clear log when it is fully read */
+} bcm_dev_log_file_flags;
+
+typedef enum
+{
+ BCM_DEV_LOG_STYLE_NORMAL,
+ BCM_DEV_LOG_STYLE_BOLD,
+ BCM_DEV_LOG_STYLE_UNDERLINE,
+ BCM_DEV_LOG_STYLE_BLINK,
+ BCM_DEV_LOG_STYLE_REVERSE_VIDEO,
+} bcm_dev_log_style;
+
+/********************************************/
+/* */
+/* Callbacks functions */
+/* */
+/********************************************/
+
+/* Default logger ID */
+extern dev_log_id def_log_id;
+
+/* Log file type */
+typedef enum
+{
+ BCM_DEV_LOG_FILE_MEMORY, /**< Memory file */
+#ifdef BCM_OS_POSIX
+ BCM_DEV_LOG_FILE_REGULAR, /**< Regular file */
+#endif
+#ifdef DEV_LOG_SYSLOG
+ BCM_DEV_LOG_FILE_SYSLOG, /**< syslog "file" */
+#endif
+ BCM_DEV_LOG_FILE_UDEF /**< User-defined file */
+} bcm_dev_log_file_type;
+
+typedef struct bcm_dev_log_file_parm bcm_dev_log_file_parm;
+typedef struct bcm_dev_log_file bcm_dev_log_file;
+
+/****************************************************************************************/
+/* OPEN CALLBACK: open memory/file */
+/* file_parm - file parameters */
+/* file - file */
+/****************************************************************************************/
+typedef bcmos_errno (*bcm_dev_log_file_open_cb)(const bcm_dev_log_file_parm *file_parm, bcm_dev_log_file *file);
+
+/****************************************************************************************/
+/* CLOSE CALLBACK: close memory/file */
+/* file - file handle */
+/****************************************************************************************/
+typedef bcmos_errno (*bcm_dev_log_file_close_cb)(bcm_dev_log_file *file);
+
+/****************************************************************************************/
+/* REWIND CALLBACK: clears memory/file */
+/* file - file handle */
+/****************************************************************************************/
+typedef bcmos_errno (*bcm_dev_log_file_rewind_cb)(bcm_dev_log_file *file);
+
+/****************************************************************************************/
+/* READ_CALLBACK: read form memory/file */
+/* offset - the offset in bytes to read from, output */
+/* buf - Where to put the result */
+/* length - Buffer length */
+/* This function should return the number of bytes actually read from file or 0 if EOF */
+/****************************************************************************************/
+typedef int (*bcm_dev_log_file_read_cb)(bcm_dev_log_file *file, uint32_t *offset, void *buf, uint32_t length);
+
+/****************************************************************************************/
+/* WRITE_CALLBACK: write form memory/file */
+/* buf - The buffer that should be written */
+/* length - The number of bytes to write */
+/* This function should return the number of bytes actually written to file or 0 if EOF */
+/****************************************************************************************/
+typedef int (*bcm_dev_log_file_write_cb)(bcm_dev_log_file *file, const void *buf, uint32_t length);
+
+/* File almost full indication callback prototype */
+typedef bcmos_errno (*F_dev_log_file_almost_full)(long priv);
+
+/* File parameters */
+struct bcm_dev_log_file_parm
+{
+ bcm_dev_log_file_type type;
+ /* File-access callbacks can be NULL for memory files, in this case start_addr */
+ /* should be a valid memory address, all read/writes options will be */
+ /* performed directly to this memory */
+ void *start_addr;
+ uint32_t size;
+ bcm_dev_log_file_open_cb open_cb;
+ bcm_dev_log_file_close_cb close_cb;
+ bcm_dev_log_file_write_cb write_cb;
+ bcm_dev_log_file_read_cb read_cb;
+ bcm_dev_log_file_rewind_cb rewind_cb;
+ bcm_dev_log_file_flags flags;
+ void *udef_parms;
+};
+
+#define FILE_MAGIC_STR_SIZE 16
+#define FILE_MAGIC_STR "@LOGFILE MAGIC@" /* length should be FILE_MAGIC_STR_SIZE (including '\0') */
+
+/* File almost full indication control info */
+typedef struct dev_log_almost_full_info
+{
+ F_dev_log_file_almost_full send_ind_cb;
+ uint32_t threshold;
+ bcmos_bool ind_sent;
+ long priv;
+} dev_log_almost_full_info;
+
+/* Memory file header */
+typedef struct dev_log_mem_file_header
+{
+ uint32_t file_wrap_cnt;
+ uint32_t write_offset;
+ uint32_t data_size;
+ uint32_t num_msgs;
+ char file_magic[FILE_MAGIC_STR_SIZE];
+ char msg_buffer[0];
+} dev_log_mem_file_header;
+
+struct bcm_dev_log_file
+{
+ bcm_dev_log_file_parm file_parm;
+ dev_log_almost_full_info almost_full;
+ bcmos_bool is_full;
+ union
+ {
+ /* Memory file */
+ struct
+ {
+ bcmos_mutex mutex; /* Mutex to lock file access while printing it */
+ dev_log_mem_file_header file_header;
+ } mem_file;
+
+#ifdef BCM_OS_POSIX
+ FILE *reg_file_handle;
+#endif
+
+ /* User-defined file handle */
+ unsigned long udef_handle;
+ } u;
+};
+
+/*******************************************************************************************************/
+/* Get time callback should return an integer representing time. If NULL time prints will be disabled. */
+/*******************************************************************************************************/
+typedef uint32_t (*bcm_dev_log_get_time_cb)(void);
+
+/********************************************************************************************************/
+/* Time to string callback receives timestamp (us) and should convert into time_str */
+/* time_str_size is the maximum number of bytes to be copied. In the end function should update the */
+/* number bytes actually written */
+/* If NULL time will printed as an unsigned integer. */
+/********************************************************************************************************/
+typedef int (*bcm_dev_log_time_to_str_cb)(uint32_t time, char *time_str, int time_str_size);
+typedef int (*bcm_dev_log_print_cb)(void *arg, const char *fmt, ...);
+
+/********************************************/
+/* */
+/* Structs */
+/* */
+/********************************************/
+
+typedef struct
+{
+ bcm_dev_log_get_time_cb get_time_cb;
+ bcm_dev_log_time_to_str_cb time_to_str_cb;
+ bcm_dev_log_print_cb print_cb;
+ void *print_cb_arg;
+ bcm_dev_log_file_parm log_file[DEV_LOG_MAX_FILES];
+} bcm_dev_log_parm;
+
+#ifdef TRIGGER_LOGGER_FEATURE
+typedef struct
+{
+ uint32_t threshold; /* every threshold messages, print one */
+ uint32_t counter; /* current index - runs from 0 to threshold, periodically */
+} dev_log_id_throttle;
+
+typedef struct
+{
+ uint32_t start_threshold; /* start printing when threshold is reached */
+ uint32_t stop_threshold; /* stop printing when threshold is reached, starting counting from start, if 0, do no stop */
+ uint32_t counter; /* current index - runs : first - from 0 to start_threshold
+ second - from start_threshold to stop_threshold */
+ int32_t repeat_threshold;/* the trigger period, how many times the trigger is set, -1 = always */
+ int32_t repeat; /* current repeat counter */
+} dev_log_id_trigger;
+#endif
+typedef struct
+{
+ char name[MAX_DEV_LOG_ID_NAME];
+ bcm_dev_log_id_type log_type;
+ bcm_dev_log_id_type default_log_type;
+ bcm_dev_log_level log_level_print;
+ bcm_dev_log_level log_level_save;
+ bcm_dev_log_level default_log_level;
+ bcm_dev_log_style style;
+ uint32_t lost_msg_cnt;
+ uint32_t print_skipped_count; /* see DEV_LOG_SKIP_PRINT_THRESHOLD_PERCENT */
+ uint32_t counters[DEV_LOG_LEVEL_NUM_OF];
+#ifdef TRIGGER_LOGGER_FEATURE
+ bcm_dev_log_level throttle_log_level;
+ dev_log_id_throttle throttle;
+ bcm_dev_log_level trigger_log_level;
+ dev_log_id_trigger trigger;
+#endif
+} dev_log_id_parm;
+
+/********************************************/
+/* */
+/* Functions prototypes */
+/* */
+/********************************************/
+
+/** Tear down the dev_log, freeing all OS resources. */
+void bcm_dev_log_destroy(void);
+
+/* This function creates default logger that supports logging on the screen and
+ * into 0 or more memory files.
+ */
+bcmos_errno bcm_dev_log_init_default_logger(void **start_addresses,
+ uint32_t *sizes,
+ bcm_dev_log_file_flags *flags,
+ uint32_t num_files,
+ uint32_t stack_size,
+ bcmos_task_priority priority,
+ uint32_t pool_size);
+
+/* This function is more flexible comparing with bcm_dev_log_init_default_logger().
+ * It creates logger that supports logging on the screen and into 0 or more
+ * memory, regular and user-defined files.
+ */
+bcmos_errno bcm_dev_log_init_default_logger_ext(
+ bcm_dev_log_parm *dev_log_parm,
+ uint32_t num_files,
+ uint32_t stack_size,
+ bcmos_task_priority priority,
+ uint32_t pool_size);
+
+/************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_register */
+/* */
+/* Abstract: Add new ID to dev_log and return it to user */
+/* */
+/* Arguments: */
+/* xi_name - ID name */
+/* xi_default_log_level - ID default log level */
+/* xi_default_log_type - ID default log type */
+/* */
+/* Return Value: */
+/* new ID */
+/* */
+/************************************************************************/
+dev_log_id bcm_dev_log_id_register(const char *xi_name,
+ bcm_dev_log_level xi_default_log_level,
+ bcm_dev_log_id_type xi_default_log_type);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_set_type */
+/* */
+/* Abstract: Set current log type for an ID */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_log_type - New log type */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_set_type(dev_log_id xi_id, bcm_dev_log_id_type xi_log_type);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_set_level */
+/* */
+/* Abstract: Set current log level for an ID */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_log_level - New log level */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_set_level(dev_log_id xi_id, bcm_dev_log_level xi_log_level_print, bcm_dev_log_level xi_log_level_save);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_set_to_default */
+/* */
+/* Abstract: Set log_type and log_level to default (creation) values for an ID */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_set_levels_and_type_to_default(dev_log_id xi_id);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_level_set_style */
+/* */
+/* Abstract: Set log style per level */
+/* */
+/* Arguments: */
+/* - xi_level - Log level */
+/* - xi_style - The style of the log, NORMAL, BOLD, UNDERLINE, BLINK, REVERSE_VIDEO */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+void bcm_dev_log_level_set_style(bcm_dev_log_level level, bcm_dev_log_style xi_style);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_set_style */
+/* */
+/* Abstract: Set log style per log id */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_style - The style of the log, NORMAL, BOLD, UNDERLINE, BLINK, REVERSE_VIDEO */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_set_style(dev_log_id xi_id, bcm_dev_log_style xi_style);
+
+/************************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_clear_counters */
+/* */
+/* Abstract: Clear counter for an ID */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/************************************************************************************************/
+bcmos_errno bcm_dev_log_id_clear_counters(dev_log_id xi_id);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_get */
+/* */
+/* Abstract: Get the ID status (type, level, counters ...) */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xo_id_status - Returned status structure */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_get(dev_log_id xi_id, dev_log_id_parm *xo_id_status);
+
+/********************************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_set */
+/* */
+/* Abstract: set the ID status (type, level, style ...) */
+/* */
+/* Arguments: */
+/* - xi_id - The ID in the Dev log (what we got form bcm_dev_log_id_register) */
+/* - xi_parms - structure to set */
+/* */
+/* Return Value: */
+/* bcmos_errno - Success code (BCM_ERR_OK) or Error code (see bcmos_errno.h) */
+/* */
+/********************************************************************************************/
+bcmos_errno bcm_dev_log_id_set(dev_log_id xi_id, dev_log_id_parm *xi_parms);
+
+/********************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_get_by_index */
+/* */
+/* Abstract: Return ID for index, if no such index return (DEV_LOG_INVALID_ID) */
+/* */
+/* Arguments: */
+/* xi_index - The index of the ID in the global array. */
+/* */
+/* Return Value: */
+/* uint32_t - The ID (DEV_LOG_INVALID_ID if index is not valid) */
+/* */
+/********************************************************************************/
+dev_log_id bcm_dev_log_id_get_by_index(uint32_t xi_index);
+
+/********************************************************************************/
+/* */
+/* Name: bcm_dev_log_get_index_by_id */
+/* */
+/* Abstract: Return ID for index, if no such index return (DEV_LOG_INVALID_ID) */
+/* */
+/* Arguments: */
+/* xi_id - Log id. */
+/* */
+/* Return Value: */
+/* uint32_t - The index ID (DEV_LOG_INVALID_INDEX if id is not valid) */
+/* */
+/********************************************************************************/
+uint32_t bcm_dev_log_get_index_by_id(dev_log_id xi_id);
+
+/********************************************************************************/
+/* */
+/* Name: bcm_dev_log_id_get_by_name */
+/* */
+/* Abstract: Return ID index for name */
+/* */
+/* Arguments: */
+/* xi__name - The name of the ID */
+/* */
+/* Return Value: */
+/* int32_t - The ID index (-1 if name is not valid) */
+/* */
+/********************************************************************************/
+dev_log_id bcm_dev_log_id_get_by_name(const char* xi_name);
+
+uint32_t bcm_dev_log_get_num_of_entries(void);
+
+bcmos_bool bcm_dev_log_get_control(void);
+void bcm_dev_log_set_control(bcmos_bool control);
+
+bcm_dev_log_file_flags bcm_dev_log_get_file_flags(uint32_t file_id);
+void bcm_dev_log_set_file_flags(uint32_t file_id, bcm_dev_log_file_flags flags);
+
+bcm_dev_log_flags bcm_dev_log_get_flags(void);
+void bcm_dev_log_set_flags(bcm_dev_log_flags flags);
+
+void bcm_dev_log_set_print_cb(bcm_dev_log_print_cb cb);
+void bcm_dev_log_set_get_time_cb(bcm_dev_log_get_time_cb cb);
+void bcm_dev_log_set_time_to_str_cb(bcm_dev_log_time_to_str_cb cb);
+
+/* File index to file handle */
+bcm_dev_log_file *bcm_dev_log_file_get(uint32_t file_index);
+
+/* Get number of messages stored in the file */
+uint32_t bcm_dev_log_get_num_of_messages(bcm_dev_log_file *file);
+
+/* Get file info: max data size, used bytes */
+bcmos_errno bcm_dev_log_get_file_info(bcm_dev_log_file *file, uint32_t *file_size, uint32_t *used_bytes);
+
+/* Read from file.
+ * \param[in] file File to read from
+ * \param[in,out] offset offset to read from. 0=read from the start
+ * \param[in,out] buf buffer to read records to
+ * \param[in] buf_len buf size
+ * \returns - number of bytes read >= 0 or bcmos_errno < 0
+ * 0 = no more records to read
+ * BCM_ERR_OVERFLOW - buffer is too short for log record
+ */
+int bcm_dev_log_file_read(bcm_dev_log_file *file, uint32_t *offset, char *buf, uint32_t buf_len);
+
+/* Clear file
+ * \param[in] file File handle
+ * \returns bcmos_errno error code
+ */
+bcmos_errno bcm_dev_log_file_clear(bcm_dev_log_file *file);
+
+/* Attach file to memory buffer.
+ * The file data can be read using bcm_dev_log_file_read or bcm_dev_log_file_read_cut
+ * \param[in] buf buffer to be interpreted as memory file
+ * \param[in] buf_len buf size
+ * \param[out] file File handle.
+ * file_handle has to be destroyed using bcm_dev_log_file_detach() when no longer needed.
+ * \returns bcmos_errno error code
+ */
+bcmos_errno bcm_dev_log_file_attach(void *buf, uint32_t buf_len, bcm_dev_log_file *file);
+
+/* Detach file handle from memory buffer.
+ * Following this call, the file handle becomes invalid
+ * \param[in] file File handle.
+ * \returns bcmos_errno error code
+ */
+bcmos_errno bcm_dev_log_file_detach(bcm_dev_log_file *file);
+
+/* Register indication to be sent when file utilization crosses threshold */
+bcmos_errno bcm_dev_log_almost_full_ind_register(bcm_dev_log_file *file, uint32_t used_bytes_threshold,
+ F_dev_log_file_almost_full send_ind_cb, long ind_cb_priv);
+
+void dev_log_get_log_name_table(char *buffer, uint32_t buf_len);
+
+void bcm_dev_log_drop_report(void);
+
+/** Helper function to determine if a given log level qualifies as an error. */
+static inline bcmos_bool bcm_dev_log_level_is_error(bcm_dev_log_level log_level)
+{
+ return log_level == DEV_LOG_LEVEL_FATAL || log_level == DEV_LOG_LEVEL_ERROR;
+}
+
+/** Returns the percentage (0 - 100) of the msg pool that is currently in use. */
+uint8_t bcm_dev_log_pool_occupancy_percent_get(void);
+
+#ifdef TRIGGER_LOGGER_FEATURE
+bcmos_errno bcm_dev_log_set_throttle(dev_log_id xi_id, bcm_dev_log_level xi_log_level, uint32_t xi_throttle);
+
+bcmos_errno bcm_dev_log_set_trigger(dev_log_id xi_id, bcm_dev_log_level xi_log_level, uint32_t xi_start, uint32_t xi_stop, int32_t xi_repeat);
+#endif /* TRIGGER_LOGGER_FEATURE */
+
+#endif /* ENABLE_LOG */
+
+#endif /* __BCM_DEV_LOG_TASK_H_ */
diff --git a/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task_internal.h b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task_internal.h
new file mode 100644
index 0000000..aaa3e81
--- /dev/null
+++ b/bcm68620_release/release/host_reference/dev_log/bcm_dev_log_task_internal.h
@@ -0,0 +1,101 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+Unless you and Broadcom execute a separate written software license
+agreement governing use of this software, this software is licensed
+to you under the terms of the GNU General Public License version 2
+(the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
+with the following added to such license:
+
+ As a special exception, the copyright holders of this software give
+ you permission to link this software with independent modules, and
+ to copy and distribute the resulting executable under terms of your
+ choice, provided that you also meet, for each linked independent
+ module, the terms and conditions of the license of that module.
+ An independent module is a module which is not derived from this
+ software. The special exception does not apply to any modifications
+ of the software.
+
+Not withstanding the above, under no circumstances may you combine
+this software in any way with any other Broadcom software provided
+under a license other than the GPL, without Broadcom's express prior
+written consent.
+
+:>
+ */
+
+#ifndef __BCM_DEV_LOG_TASK_INTERNAL_H_
+#define __BCM_DEV_LOG_TASK_INTERNAL_H_
+
+#ifdef ENABLE_LOG
+
+#include <bcmos_system.h>
+
+#define LOG_NAME_NO_INSTANCE 0xff
+#define LOG_NAME_LENGTH 100
+
+typedef enum
+{
+ BCM_DEV_LOG_STATE_UNINITIALIZED,
+ BCM_DEV_LOG_STATE_DISABLED,
+ BCM_DEV_LOG_STATE_ENABLED,
+} bcm_dev_log_state;
+
+typedef struct
+{
+ bcm_dev_log_parm dev_log_parm;
+ bcm_dev_log_file files[DEV_LOG_MAX_FILES]; /* log files */
+ uint32_t msg_count; /* Message counter */
+ dev_log_id_parm ids[DEV_LOG_MAX_IDS]; /* dev_log IDS array */
+ uint32_t num_ids; /* Number of actually registered ids */
+ bcm_dev_log_state state;
+ bcmos_msg_queue save_queue; /* Log messages to be saved to RAM (first stage of pipeline) */
+ bcmos_msg_queue print_queue; /* Log messages to be printed (second stage of pipeline) */
+ bcmos_task save_task;
+ bcmos_task print_task;
+ bcmos_sem save_task_is_terminated;
+ bcmos_sem print_task_is_terminated;
+ bcmos_msg_pool pool;
+ bcm_dev_log_flags flags; /* General flags applied on the entire feature (unlike file flags which reside in 'files' sub-structure). */
+} bcm_dev_log;
+
+typedef struct
+{
+ dev_log_id_parm *log_id;
+ uint32_t time_stamp;
+ bcm_dev_log_level msg_level;
+ uint32_t flags;
+ union
+ {
+ struct
+ {
+ const char *fmt;
+ /* Room for MAX + 1 arguments since the argument list needs to start on an 8-byte boundary - the first
+ * entry may be unused if the array doesn't naturally start on an 8-byte boundary. */
+ const void *args[DEV_LOG_MAX_ARGS + 1];
+ } fmt_args; /* Relevant in default mode - when not using BCM_LOG_FLAG_CALLER_FMT */
+ char str[MAX_DEV_LOG_STRING_SIZE]; /* Relevant only if using BCM_LOG_FLAG_CALLER_FMT */
+ } u;
+} dev_log_queue_msg;
+
+typedef struct
+{
+ char name[LOG_NAME_LENGTH];
+ uint8_t first_instance;
+ uint8_t last_instance;
+}log_name_table;
+
+extern bcm_dev_log dev_log;
+extern const char *log_level_str;
+
+extern log_name_table logs_names[DEV_LOG_MAX_IDS];
+extern uint8_t log_name_table_index;
+
+bcmos_errno _bcm_dev_log_file_clear_no_lock(uint32_t file_index);
+
+#endif /* ENABLE_LOG */
+
+#endif /* __BCM_DEV_LOG_TASK_INTERNAL_H_ */