BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_customized/os_abstraction/Makefile b/bcm68620_release/release/host_customized/os_abstraction/Makefile
new file mode 100644
index 0000000..258f45f
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/Makefile
@@ -0,0 +1,51 @@
+# OS abstraction layer
+#
+MOD_NAME = os
+MOD_TYPE = lib
+MOD_INC_DIRS = $(SRC_DIR) $(SRC_DIR)/$(OS)
+MOD_INC_DIRS += $(OS_PLATFORM_DIR) $(CONFIG_DIR)
+MOD_SUPPRESS_OS_DEP = y
+
+ifeq ("$(OS)", "threadx")
+ MOD_DEPS = threadx bsp
+ MOD_INC_DIRS += $(SUBSYSTEM)/sys/inc
+ MOD_DEFS = -DBCMOS_TRACE_IN_DEV_LOG
+endif
+
+ifeq ("$(OS)", "posix")
+ ENABLE_MSG_QUEUE_DOMAIN_SOCKET ?= y
+ ENABLE_MSG_QUEUE_UDP_SOCKET ?= y
+endif
+
+ifeq ("$(ENABLE_MSG_QUEUE_DOMAIN_SOCKET)", "y")
+ MOD_DEFS += -DBCMOS_MSG_QUEUE_DOMAIN_SOCKET
+endif
+
+ifeq ("$(ENABLE_MSG_QUEUE_UDP_SOCKET)", "y")
+ MOD_DEFS += -DBCMOS_MSG_QUEUE_UDP_SOCKET
+endif
+
+ifeq ("$(BUF_IN_DMA_MEM)", "y")
+ EXTRA_CFLAGS += -DBCMOS_BUF_IN_DMA_MEM
+ BUF_DATA_UNIT_SIZE ?= 1024
+ EXTRA_CFLAGS += -DBCMOS_BUF_DATA_UNIT_SIZE=$(BUF_DATA_UNIT_SIZE)
+endif
+
+ifneq ("$(BUF_POOL_SIZE)", "")
+ ifeq ("$(BUF_POOL_BUF_SIZE)", "")
+ BUF_POOL_BUF_SIZE = 4096
+ endif
+ EXTRA_CFLAGS += -DBCMOS_BUF_POOL_SIZE=$(BUF_POOL_SIZE) -DBCMOS_BUF_POOL_BUF_SIZE=$(BUF_POOL_BUF_SIZE)
+endif
+
+srcs = bcmos_common.c bcmos_errno.c bcmos_hash_table.c bcmos_rw_lock.c $(OS)/bcmos_system.c
+
+ifeq ("$(DEBUG)", "y")
+ MOD_DEFS += -DBCMOS_MEM_DEBUG -DBCMOS_SYS_UNITTEST
+endif
+
+ifeq ("$(SUBSYSTEM)", "embedded")
+ USE_LINT = yes
+endif
+
+#EXTRA_DEFINES += -DBCMOS_SYS_UNITTEST
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.c b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.c
new file mode 100644
index 0000000..d2d552a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.c
@@ -0,0 +1,2772 @@
+/*
+<: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"
+
+/* task control blocks */
+STAILQ_HEAD(task_list, bcmos_task) task_list = STAILQ_HEAD_INITIALIZER(task_list);
+
+/* module control blocks */
+bcmos_module *bcmos_modules[BCMOS_MODULE_ID__NUM_OF];
+
+/* event control blocks */
+bcmos_event *bcmos_events[BCMOS_EVENT_ID__NUM_OF];
+
+/* Global trace level */
+bcmos_trace_level bcmos_sys_trace_level = BCMOS_TRACE_LEVEL_ERROR;
+
+/* Global OS mutex */
+bcmos_mutex bcmos_res_lock;
+
+/* Total memory occupied by block pools */
+uint32_t bcmos_total_blk_pool_size;
+
+/* Total memory occupied by message pools */
+uint32_t bcmos_total_msg_pool_size;
+
+f_bcmolt_sw_error_handler sw_error_handler;
+
+/* Block pools */
+static STAILQ_HEAD(blk_pool_list, bcmos_blk_pool) blk_pool_list = STAILQ_HEAD_INITIALIZER(blk_pool_list);
+
+/* Message pools */
+static STAILQ_HEAD(msg_pool_list, bcmos_blk_pool) msg_pool_list = STAILQ_HEAD_INITIALIZER(msg_pool_list);
+
+/* Message queues */
+static STAILQ_HEAD(msg_queue_list, bcmos_msg_queue) msg_queue_list = STAILQ_HEAD_INITIALIZER(msg_queue_list);
+
+/* Message queue groups */
+static STAILQ_HEAD(msg_qgroup_list, bcmos_msg_qgroup) msg_qgroup_list = STAILQ_HEAD_INITIALIZER(msg_qgroup_list);
+
+/* Lock used to protect msg registration / deregistration */
+static bcmos_fastlock bcmos_msg_register_lock;
+
+/* Shutdown mode: when this is set, we expect message handler deregistration to happen while messages are still being
+ * sent/received. We should handle this gracefully. */
+static bcmos_bool bcmos_msg_shutdown_mode = BCMOS_FALSE;
+
+/* Timer management block */
+typedef struct bcmos_timer_pool
+{
+ bcmos_fastlock lock; /* Pool protection lock */
+ bcmos_sys_timer sys_timer; /* System timer handle */
+ uint32_t num_active_timers; /* Number of active timers in the pool */
+#ifdef BCMOS_TIMER_RB_TREE
+ RB_HEAD(bcmos_timers, bcmos_timer) pool; /* Timer pool. RB tree */
+#else
+ TAILQ_HEAD(bcmos_timers, bcmos_timer) pool; /* Timer pool: TAILQ */
+#endif
+} bcmos_timer_pool;
+
+static int32_t _bcmos_timer_compare(bcmos_timer *t1, bcmos_timer *t2);
+
+/*
+ * Macros for RB-TREE and TAILQ-based timer tool implementations
+ */
+
+#ifdef BCMOS_TIMER_RB_TREE
+
+#ifdef __arm__
+/* ARM compiler doesn't like unused inline functions. Disable the warning */
+#pragma diag_suppress 177
+#endif
+
+/* Generate RB tree functions */
+RB_GENERATE_INLINE(bcmos_timers, bcmos_timer, entry, _bcmos_timer_compare)
+
+#define TMR_POOL_INIT(tmr_pool) RB_INIT(&(tmr_pool)->pool)
+#define TMR_POOL_INSERT(tmr_pool, tmr) RB_INSERT(bcmos_timers, &(tmr_pool)->pool, tmr)
+#define TMR_POOL_REMOVE(tmr_pool, tmr) RB_REMOVE(bcmos_timers, &(tmr_pool)->pool, tmr)
+#define TMR_POOL_FIRST(tmr_pool) RB_MIN(bcmos_timers, &(tmr_pool)->pool)
+
+#else
+
+#define TMR_POOL_INIT(tmr_pool) TAILQ_INIT(&(tmr_pool)->pool)
+
+#define TMR_POOL_INSERT(tmr_pool, tmr) \
+ do { \
+ bcmos_timer *_last = TAILQ_LAST(&(tmr_pool)->pool, bcmos_timers); \
+ if (_last) \
+ { \
+ if (_bcmos_timer_compare(tmr, _last) >= 0) \
+ { \
+ TAILQ_INSERT_TAIL(&(tmr_pool)->pool, tmr, entry); \
+ } \
+ else \
+ { \
+ bcmos_timer *_t; \
+ uint32_t iter = 0; \
+ TAILQ_FOREACH(_t, &(tmr_pool)->pool, entry) \
+ { \
+ BUG_ON(iter >= (tmr_pool)->num_active_timers);\
+ ++iter; \
+ if (_bcmos_timer_compare(tmr, _t) <= 0) \
+ { \
+ TAILQ_INSERT_BEFORE(_t, tmr, entry); \
+ break; \
+ } \
+ } \
+ } \
+ } \
+ else \
+ { \
+ TAILQ_INSERT_HEAD(&(tmr_pool)->pool, tmr, entry); \
+ } \
+ ++(tmr_pool)->num_active_timers; \
+ } while (0)
+
+#define TMR_POOL_REMOVE(tmr_pool, tmr) \
+ do { \
+ BUG_ON(!(tmr_pool)->num_active_timers); \
+ TAILQ_REMOVE(&(tmr_pool)->pool, tmr, entry); \
+ TAILQ_NEXT(tmr, entry) = NULL; \
+ --(tmr_pool)->num_active_timers; \
+ } while (0)
+
+#define TMR_POOL_FIRST(tmr_pool) TAILQ_FIRST(&(tmr_pool)->pool)
+
+#endif
+
+#define BCMOS_TIMER_IS_RUNNING(tmr) ((tmr->flags & BCMOS_TIMER_FLAG_RUNNING) != 0)
+#define BCMOS_TIMER_IS_EXPIRED(tmr) ((tmr->flags & BCMOS_TIMER_FLAG_EXPIRED) != 0)
+#define BCMOS_TIMER_IS_VALID(tmr) ((tmr->flags & BCMOS_TIMER_FLAG_VALID) != 0)
+#define BCMOS_TIMER_IS_ACTIVE(tmr) ((tmr->flags & BCMOS_TIMER_FLAG_ACTIVE) != 0)
+
+static bcmos_bool bcmos_initialized;
+static bcmos_timer_pool tmr_pool;
+static void _sys_timer_handler(void *data);
+
+/*
+ * Print variables
+ */
+
+static bcmos_print_redirect_mode print_redirect_mode;
+static bcmos_print_redirect_cb print_redirect_cb;
+static void *print_redirect_cb_data;
+static bcmos_mutex bcmos_print_lock;
+#ifdef BCMOS_BUF_POOL_SIZE
+static bcmos_blk_pool sys_buf_pool;
+static bcmos_errno bcmos_buf_pool_create(void);
+#endif
+
+/** Initialize system library
+ * \ingroup system
+ * Must be called before any other system function
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_init(void)
+{
+ bcmos_errno rc;
+
+ if (bcmos_initialized)
+ return BCM_ERR_OK;
+ rc = bcmos_sys_init();
+ bcmos_mutex_create(&bcmos_res_lock, 0, "res_lock");
+ bcmos_mutex_create(&bcmos_print_lock, 0, "print_lock");
+ TMR_POOL_INIT(&tmr_pool);
+ bcmos_fastlock_init(&tmr_pool.lock, 0);
+ bcmos_fastlock_init(&bcmos_msg_register_lock, 0);
+ rc = rc ? rc : bcmos_sys_timer_create(&tmr_pool.sys_timer, _sys_timer_handler, &tmr_pool);
+
+ /* Create default buffer pool if so requested by compilation options */
+#ifdef BCMOS_BUF_POOL_SIZE
+ rc = rc ? rc : bcmos_buf_pool_create();
+#endif
+
+ if (!rc)
+ {
+ bcmos_initialized = BCMOS_TRUE;
+ }
+
+ return rc;
+}
+
+/** Cleanup system library
+ * \ingroup system
+ */
+void bcmos_exit(void)
+{
+ if (!bcmos_initialized)
+ return;
+ bcmos_sys_timer_destroy(&tmr_pool.sys_timer);
+ bcmos_mutex_destroy(&bcmos_print_lock);
+ bcmos_mutex_destroy(&bcmos_res_lock);
+#ifdef BCMOS_BUF_POOL_SIZE
+ bcmos_blk_pool_reset(&sys_buf_pool);
+ bcmos_blk_pool_destroy(&sys_buf_pool);
+#endif
+ bcmos_sys_exit();
+ bcmos_initialized = BCMOS_FALSE;
+}
+
+/*
+ * Common task services
+ */
+
+/* Query task info */
+bcmos_errno bcmos_task_query(const bcmos_task *task, bcmos_task_parm *parm)
+{
+ if (task == NULL || task->magic != BCMOS_TASK_MAGIC || parm == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ *parm = task->parm;
+ return BCM_ERR_OK;
+}
+
+/** Task iterator
+ * \param[in] prev Previous task. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_task_get_next(bcmos_task **prev)
+{
+ bcmos_task *task;
+ if (prev == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ task = *prev;
+ if (task && task->magic != BCMOS_TASK_MAGIC)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (task)
+ {
+ task = STAILQ_NEXT(task, list);
+ }
+ else
+ {
+ task = STAILQ_FIRST(&task_list);
+ }
+ *prev = task;
+ if (!task)
+ {
+ return BCM_ERR_NO_MORE;
+ }
+ return BCM_ERR_OK;
+}
+
+/*
+ * Message queue
+ */
+
+static void _bcmos_msgq_notify(bcmos_msg_queue *q, const char *txt)
+{
+ BCMOS_TRACE_INFO("Msg queue %s: %s\n", q->q.parm.name, txt);
+}
+
+/* Decrement in-queue statistics */
+static inline void _bcmos_msgq_stat_dec(bcmos_msg_queue_nw *q)
+{
+ bcmos_msg_queue_stat *stat = &q->stat;
+ uint32_t old_in = stat->msg_in;
+
+ if (stat->msg_in == 0)
+ {
+ BCMOS_TRACE_ERR("Attempt to decrement statistics for an empty queue ('%s')\n", q->parm.name);
+ }
+ else
+ {
+ --stat->msg_in;
+ ++stat->msg_received;
+ }
+
+ if (old_in == q->parm.low_wm)
+ {
+ q->parm.notify((bcmos_msg_queue *)q, "becomes uncongested");
+ stat->is_congested = BCMOS_FALSE;
+ }
+}
+
+/* Increment in-queue statistics */
+static inline void _bcmos_msgq_stat_inc(bcmos_msg_queue_nw *q)
+{
+ bcmos_msg_queue_stat *stat = &q->stat;
+ uint32_t old_in = stat->msg_in;
+
+ ++stat->msg_in;
+ ++stat->msg_sent;
+ if (old_in == q->parm.high_wm)
+ {
+ q->parm.notify((bcmos_msg_queue *)q, "becomes congested");
+ stat->is_congested = BCMOS_TRUE;
+ }
+ if (stat->is_congested)
+ ++stat->msg_almost_full;
+}
+
+static void _bcmos_qgroup_notify(bcmos_msg_qgroup *qgroup, const char *txt)
+{
+ BCMOS_TRACE_INFO("Msg queue %s: %s\n", qgroup->parm.name, txt);
+}
+
+/* Decrement in-queue statistics for queue group */
+static inline void _bcmos_qgroup_stat_dec(bcmos_msg_qgroup *qgroup)
+{
+ bcmos_msg_queue_stat *stat = &qgroup->stat;
+ uint32_t old_in = stat->msg_in;
+
+ if (stat->msg_in == 0)
+ {
+ BCMOS_TRACE_ERR("Attempt to decrement statistics for an empty queue ('%s')\n", qgroup->parm.name);
+ }
+ else
+ {
+ --stat->msg_in;
+ ++stat->msg_received;
+ }
+
+ if (old_in == qgroup->parm.low_wm)
+ {
+ qgroup->parm.notify(qgroup, "becomes uncongested");
+ stat->is_congested = BCMOS_FALSE;
+ }
+}
+
+/* Increment in-queue statistics */
+static inline void _bcmos_qgroup_stat_inc(bcmos_msg_qgroup *qgroup)
+{
+ bcmos_msg_queue_stat *stat = &qgroup->stat;
+ uint32_t old_in = stat->msg_in;
+
+ ++stat->msg_in;
+ ++stat->msg_sent;
+ if (old_in == qgroup->parm.high_wm)
+ {
+ qgroup->parm.notify(qgroup, "becomes congested");
+ stat->is_congested = BCMOS_TRUE;
+ }
+ if (stat->is_congested)
+ ++stat->msg_almost_full;
+}
+
+
+/* Get message from queue.
+ * Urgent queue is checked 1st, then regular queue
+ * Must be called under lock!
+ * Returns msg or NULL if queue is empty
+ */
+static inline bcmos_msg *_bcmos_msg_get(bcmos_msg_queue_nw *q)
+{
+ bcmos_msg *msg;
+
+ msg = STAILQ_FIRST(&q->msgl_urg);
+ if (msg)
+ {
+ STAILQ_REMOVE_HEAD(&q->msgl_urg, next);
+ _bcmos_msgq_stat_dec(q);
+ return msg;
+ }
+
+ msg = STAILQ_FIRST(&q->msgl);
+ if (msg)
+ {
+ STAILQ_REMOVE_HEAD(&q->msgl, next);
+ _bcmos_msgq_stat_dec(q);
+ }
+
+ return msg;
+}
+
+/* Put message on queue.
+ * Must be called under lock!
+ * Returns error in case of queue overflow
+ */
+static inline bcmos_errno _bcmos_msg_put(bcmos_msg_queue_nw *q, bcmos_msg *msg, bcmos_msg_send_flags flags)
+{
+ /* Overflow check */
+ if (q->stat.msg_in >= q->parm.size)
+ {
+ if (!(flags & BCMOS_MSG_SEND_NOLIMIT))
+ {
+ ++q->stat.msg_discarded;
+ return BCM_ERR_OVERFLOW;
+ }
+ }
+ /* Put onto the relevant queue */
+ if ((flags & BCMOS_MSG_SEND_URGENT))
+ STAILQ_INSERT_TAIL(&q->msgl_urg, msg, next);
+ else
+ STAILQ_INSERT_TAIL(&q->msgl, msg, next);
+ _bcmos_msgq_stat_inc(q);
+
+ return BCM_ERR_OK;
+}
+
+/* Create message queue without wait support */
+static void bcmos_msg_queue_nw_init(bcmos_msg_queue_nw *q, const bcmos_msg_queue_parm *parm)
+{
+ q->parm = *parm;
+ STAILQ_INIT(&q->msgl);
+ STAILQ_INIT(&q->msgl_urg);
+ bcmos_fastlock_init(&q->lock, parm->flags);
+ memset(&q->stat, 0, sizeof(q->stat));
+ q->flags = 0;
+ if (!q->parm.size)
+ q->parm.size = BCMOS_MSG_QUEUE_SIZE_UNLIMITED;
+ if (!q->parm.high_wm)
+ q->parm.high_wm = BCMOS_MSG_QUEUE_SIZE_UNLIMITED;
+ if (!q->parm.low_wm)
+ q->parm.low_wm = q->parm.high_wm;
+ if (!q->parm.notify)
+ q->parm.notify = _bcmos_msgq_notify;
+}
+
+/* Destroy message list */
+static void bcmos_msg_list_destroy(bcmos_msg_list *l)
+{
+ bcmos_msg *msg, *tmp;
+ STAILQ_FOREACH_SAFE(msg, l, next, tmp)
+ {
+ STAILQ_REMOVE_HEAD(l, next);
+ bcmos_msg_free(msg);
+ }
+}
+
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+
+/* Remote queue support - common part of create/destroy */
+
+static bcmos_errno _bcmos_msg_queue_destroy_remote_ep(bcmos_msg_queue *queue)
+{
+ if (queue->q.parm.close)
+ queue->q.parm.close(queue);
+ bcmos_mutex_destroy(&queue->send_lock);
+ if (queue->send_buf)
+ bcmos_free(queue->send_buf);
+ if (queue->recv_buf)
+ bcmos_free(queue->recv_buf);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _bcmos_msg_queue_create_remote_ep(bcmos_msg_queue *queue)
+{
+ bcmos_errno rc;
+
+ /* Allocate tx and rx buffers */
+ if (!queue->q.parm.max_mtu)
+ {
+ queue->q.parm.max_mtu = BCMOS_MSG_QUEUE_DEFAULT_MAX_MTU;
+ }
+ queue->send_buf = bcmos_calloc(queue->q.parm.max_mtu);
+ if (!queue->send_buf)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "Can't allocate send_buf\n");
+ }
+
+ queue->recv_buf = bcmos_calloc(queue->q.parm.max_mtu);
+ if (!queue->recv_buf)
+ {
+ bcmos_free(queue->send_buf);
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "Can't allocate recv_buf\n");
+ }
+ bcmos_mutex_create(&queue->send_lock, 0, queue->q.parm.name);
+
+ switch (queue->q.parm.ep_type)
+ {
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+ case BCMOS_MSG_QUEUE_EP_DOMAIN_SOCKET:
+ rc = bcmos_sys_msg_queue_domain_socket_open(queue);
+ break;
+#endif
+#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
+ case BCMOS_MSG_QUEUE_EP_UDP_SOCKET:
+ rc = bcmos_sys_msg_queue_udp_socket_open(queue);
+ break;
+#endif
+#ifdef BCMOS_MSG_QUEUE_USER_DEFINED
+ case BCMOS_MSG_QUEUE_EP_USER_DEFINED:
+ if (parm.open == NULL || parm.close == NULL || parm.send==NULL || parm.recv == NULL)
+ {
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ rc = parm.open(queue);
+ break;
+#endif
+ default:
+ rc = BCM_ERR_PARM;
+ break;
+ }
+
+ if (rc)
+ {
+ _bcmos_msg_queue_destroy_remote_ep(queue);
+ }
+
+ return rc;
+}
+
+#endif /* #ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT */
+
+/* Create message queue. */
+bcmos_errno bcmos_msg_queue_create(bcmos_msg_queue *queue, const bcmos_msg_queue_parm *parm)
+{
+ bcmos_errno rc;
+
+ if (!queue || !parm)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue %p, parm %p\n", queue, parm);
+ memset(queue, 0, sizeof(*queue));
+ queue->q.parm = *parm;
+
+ if (parm->ep_type == BCMOS_MSG_QUEUE_EP_LOCAL)
+ {
+ rc = bcmos_sem_create(&queue->m, 0, parm->flags, queue->q.parm.name);
+ if (!rc)
+ bcmos_msg_queue_nw_init(&queue->q, parm);
+ }
+ else
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ {
+ rc = _bcmos_msg_queue_create_remote_ep(queue);
+ }
+#else
+ {
+ rc = BCM_ERR_PARM;
+ }
+#endif
+
+ if (rc)
+ return rc;
+
+ queue->magic = BCMOS_MSG_QUEUE_VALID;
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (queue->q.parm.name)
+ {
+ strncpy(queue->name, queue->q.parm.name, sizeof(queue->name) - 1);
+ queue->q.parm.name = queue->name;
+ }
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&msg_queue_list, queue, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ return BCM_ERR_OK;
+}
+
+/* Destroy queue */
+bcmos_errno bcmos_msg_queue_destroy(bcmos_msg_queue *queue)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (!queue || queue->magic != BCMOS_MSG_QUEUE_VALID)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue handle is invalid\n");
+ }
+ queue->magic = BCMOS_MSG_QUEUE_DELETED;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&msg_queue_list, queue, bcmos_msg_queue, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ if (queue->q.parm.ep_type == BCMOS_MSG_QUEUE_EP_LOCAL)
+ {
+ bcmos_sem_destroy(&queue->m);
+ /* Release all pending messages */
+ bcmos_msg_list_destroy(&queue->q.msgl_urg);
+ bcmos_msg_list_destroy(&queue->q.msgl);
+ }
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ else
+ {
+ rc = _bcmos_msg_queue_destroy_remote_ep(queue);
+ }
+#endif
+
+ return rc;
+}
+
+/* Get queue info */
+bcmos_errno bcmos_msg_queue_query(const bcmos_msg_queue *queue, bcmos_msg_queue_info *info)
+{
+ if (!queue || !info)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue %p, info %p\n", queue, info);
+ info->stat = queue->q.stat;
+ info->parm = queue->q.parm;
+ return BCM_ERR_OK;
+}
+
+/* Message queue iterator */
+bcmos_errno bcmos_msg_queue_get_next(const bcmos_msg_queue **prev)
+{
+ const bcmos_msg_queue *queue;
+
+ if (prev == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ queue = *prev;
+ if (queue && queue->magic != BCMOS_MSG_QUEUE_VALID)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (queue)
+ {
+ queue = STAILQ_NEXT(queue, list);
+ }
+ else
+ {
+ queue = STAILQ_FIRST(&msg_queue_list);
+ }
+ *prev = queue;
+ if (!queue)
+ {
+ return BCM_ERR_NO_MORE;
+ }
+ return BCM_ERR_OK;
+}
+
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+
+/* Pack / unpack message header.
+ * In the future we might adopt bcmolt_buf service into OS abstraction and use it
+ * for packing / unpacking.
+ */
+
+void bcmos_msg_hdr_pack(const bcmos_msg *msg, uint8_t *buf, uint32_t data_size)
+{
+ uint16_t val16;
+ uint32_t val32;
+ val16 = BCMOS_ENDIAN_CPU_TO_BIG_U16(msg->type);
+ memcpy(buf, &val16, sizeof(val16));
+ buf[2] = (uint8_t)msg->instance;
+ buf[3] = (uint8_t)msg->sender;
+ val32 = BCMOS_ENDIAN_CPU_TO_BIG_U32(data_size);
+ memcpy(&buf[4], &val32, sizeof(val32));
+}
+
+void bcmos_msg_hdr_unpack(const uint8_t *buf, bcmos_msg *msg)
+{
+ uint16_t val16;
+ uint32_t val32;
+ memcpy(&val16, buf, sizeof(val16));
+ val16 = BCMOS_ENDIAN_BIG_TO_CPU_U16(val16);
+ msg->type = (bcmos_msg_id)val16;
+ msg->instance = (bcmos_msg_instance)buf[2];
+ msg->sender = (bcmos_module_id)buf[3];
+ memcpy(&val32, &buf[4], sizeof(val32));
+ msg->size = BCMOS_ENDIAN_BIG_TO_CPU_U32(val32); /* can be overwritten by unpacker */
+ msg->handler = NULL;
+ msg->send_flags = 0;
+}
+
+/* Send message to remote EP wrapper */
+static bcmos_errno _bcmos_msg_send_to_remote_ep(bcmos_msg_queue *queue, bcmos_msg *msg, bcmos_msg_send_flags flags)
+{
+ uint8_t *buf = NULL;
+ uint32_t buf_length = 0;
+ bcmos_errno rc;
+
+ bcmos_mutex_lock(&queue->send_lock);
+ rc = queue->q.parm.pack(queue, msg, &buf, &buf_length);
+ rc = rc ? rc : queue->q.parm.send(queue, buf, buf_length);
+ bcmos_mutex_unlock(&queue->send_lock);
+
+ /* Release if sent successfully or if auto-release flag is set */
+ if (rc == BCM_ERR_OK || !(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ {
+ bcmos_msg_free(msg);
+ }
+ if (buf && queue->q.parm.free_packed)
+ {
+ queue->q.parm.free_packed(queue, buf);
+ }
+ if (rc)
+ {
+ ++queue->q.stat.msg_discarded;
+ }
+ else
+ {
+ ++queue->q.stat.msg_sent;
+ }
+
+ return rc;
+}
+
+/* Receive message from remote EP wrapper */
+static bcmos_errno _bcmos_msg_recv_from_remote_ep(bcmos_msg_queue *queue, uint32_t timeout, bcmos_msg **msg)
+{
+ uint8_t *buf = NULL;
+ uint32_t buf_length = 0;
+ bcmos_errno rc;
+
+ rc = queue->q.parm.recv(queue, timeout, &buf, &buf_length);
+ rc = rc ? rc : queue->q.parm.unpack(queue, buf, buf_length, msg);
+ if (buf && queue->q.parm.free_packed)
+ {
+ queue->q.parm.free_packed(queue, buf);
+ }
+ if (!rc)
+ {
+ ++queue->q.stat.msg_received;
+ }
+
+ return rc;
+}
+
+#endif /* BCMOS_MSG_QUEUE_REMOTE_SUPPORT */
+
+/* Send message to queue */
+bcmos_errno bcmos_msg_send(bcmos_msg_queue *queue, bcmos_msg *msg, bcmos_msg_send_flags flags)
+{
+ long lock_flags;
+ bcmos_errno rc;
+
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ if (queue->q.parm.ep_type != BCMOS_MSG_QUEUE_EP_LOCAL)
+ {
+ return _bcmos_msg_send_to_remote_ep(queue, msg, flags);
+ }
+#endif
+
+ lock_flags = bcmos_fastlock_lock(&queue->q.lock);
+ rc = _bcmos_msg_put(&queue->q, msg, flags);
+ if (rc)
+ {
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ {
+ bcmos_msg_free(msg);
+ }
+ BCMOS_TRACE_ERR("Overflow: Queue %s\n", queue->q.parm.name);
+ return rc;
+ }
+
+ /* Success */
+ if (queue->is_waiting)
+ {
+ /* Kick waiting task */
+ queue->is_waiting = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ bcmos_sem_post(&queue->m);
+ }
+ else
+ {
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* Send message to module (internal) - doesn't post any semaphores so it's safe to call under a fastlock */
+static bcmos_errno _bcmos_msg_send_to_module(
+ bcmos_module_id module_id,
+ bcmos_msg *msg,
+ bcmos_msg_send_flags flags,
+ bcmos_sem **sem_to_post)
+{
+ bcmos_module *module = _bcmos_module_get(module_id);
+ bcmos_task *task;
+ long lock_flags, q_lock_flags;
+ uint32_t active_modules;
+ bcmos_errno rc;
+ *sem_to_post = NULL;
+
+ if (!module || !msg->handler)
+ {
+ if (!module)
+ {
+ BCMOS_TRACE_ERR("Module %d doesn't exist\n", module_id);
+ rc = BCM_ERR_NOENT;
+ }
+ else
+ {
+ BCMOS_TRACE_ERR("msg->handler is not set. msg->type=%d\n", msg->type);
+ rc = BCM_ERR_PARM;
+ }
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ {
+ bcmos_msg_free(msg);
+ }
+ return rc;
+ }
+
+ task = module->my_task;
+ lock_flags = bcmos_fastlock_lock(&task->active_lock);
+ q_lock_flags = bcmos_fastlock_lock(&module->msgq.lock);
+
+ rc = _bcmos_msg_put(&module->msgq, msg, flags);
+ if (rc)
+ {
+ bcmos_fastlock_unlock(&module->msgq.lock, q_lock_flags);
+ bcmos_fastlock_unlock(&task->active_lock, lock_flags);
+
+ /* Queue overflow */
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ bcmos_msg_free(msg);
+
+ BCMOS_TRACE_ERR("Overflow: Queue %s\n", module->parm.qparm.name);
+
+ return rc;
+ }
+ bcmos_fastlock_unlock(&module->msgq.lock, q_lock_flags);
+
+ /* Success. Update active_modules task and kick the task */
+ active_modules = task->active_modules;
+ task->active_modules |= (1 << module->idx);
+ bcmos_fastlock_unlock(&task->active_lock, lock_flags);
+
+ /* Notify caller to kick task if there is a chance it was waiting */
+ if (!active_modules)
+ *sem_to_post = &task->active_sem;
+
+ return BCM_ERR_OK;
+}
+
+/* Send message to module */
+bcmos_errno bcmos_msg_send_to_module(bcmos_module_id module_id, bcmos_msg *msg, bcmos_msg_send_flags flags)
+{
+ bcmos_sem *sem_to_post;
+ bcmos_errno err = _bcmos_msg_send_to_module(module_id, msg, flags, &sem_to_post);
+ if (sem_to_post)
+ bcmos_sem_post(sem_to_post);
+ return err;
+}
+
+/* Get message from the head of message queue */
+bcmos_errno bcmos_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, bcmos_msg **msg)
+{
+ long lock_flags;
+
+ if (!queue || !msg)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue %p, msg %p\n", queue, msg);
+
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ if (queue->q.parm.ep_type != BCMOS_MSG_QUEUE_EP_LOCAL)
+ {
+ return _bcmos_msg_recv_from_remote_ep(queue, timeout, msg);
+ }
+#endif
+
+ lock_flags = bcmos_fastlock_lock(&queue->q.lock);
+ *msg = _bcmos_msg_get(&queue->q);
+ if (*msg)
+ {
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ return BCM_ERR_OK;
+ }
+ if (!timeout)
+ {
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ return BCM_ERR_NOENT;
+ }
+
+ /* Receive with wait */
+ queue->is_waiting = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+
+ /* wait for it */
+ bcmos_sem_wait(&queue->m, timeout);
+ lock_flags = bcmos_fastlock_lock(&queue->q.lock);
+ *msg = _bcmos_msg_get(&queue->q);
+ queue->is_waiting = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&queue->q.lock, lock_flags);
+ if (!*msg)
+ return BCM_ERR_TIMEOUT;
+
+ return BCM_ERR_OK;
+}
+
+
+/*
+ * Queue group support
+ */
+
+/* Create message queue group. */
+bcmos_errno bcmos_msg_qgroup_create(bcmos_msg_qgroup *qgroup, const bcmos_msg_qgroup_parm *parm)
+{
+ bcmos_errno rc;
+ bcmos_qgroup_prty prty;
+
+ if (!qgroup || !parm || !parm->nqueues || parm->nqueues>32)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue %p, parm %p nqueues %u\n", qgroup, parm, parm ? parm->nqueues: 0);
+ memset(qgroup, 0, sizeof(*qgroup));
+ rc = bcmos_sem_create(&qgroup->m, 0, parm->flags, NULL);
+ if (rc)
+ return rc;
+ qgroup->parm = *parm;
+ bcmos_fastlock_init(&qgroup->lock, parm->flags);
+ if (!qgroup->parm.size)
+ qgroup->parm.size = BCMOS_MSG_QUEUE_SIZE_UNLIMITED;
+ if (!qgroup->parm.high_wm)
+ qgroup->parm.high_wm = BCMOS_MSG_QUEUE_SIZE_UNLIMITED;
+ if (!qgroup->parm.low_wm)
+ qgroup->parm.low_wm = qgroup->parm.high_wm;
+ if (!qgroup->parm.notify)
+ qgroup->parm.notify = _bcmos_qgroup_notify;
+ qgroup->msgl = bcmos_calloc(sizeof(bcmos_msg_list) * (uint32_t)parm->nqueues);
+ if (!qgroup->msgl)
+ {
+ bcmos_msg_qgroup_destroy(qgroup);
+ return BCM_ERR_NOMEM;
+ }
+ for (prty = 0; prty < qgroup->parm.nqueues; prty++)
+ {
+ STAILQ_INIT(&qgroup->msgl[prty]);
+ }
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (qgroup->parm.name)
+ {
+ strncpy(qgroup->name, qgroup->parm.name, sizeof(qgroup->parm.name) - 1);
+ qgroup->parm.name = qgroup->name;
+ }
+ qgroup->magic = BCMOS_MSG_QGROUP_VALID;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&msg_qgroup_list, qgroup, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ return BCM_ERR_OK;
+}
+
+/** Destroy queue group
+ *
+ * \param[in] qgroup Queue group handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_qgroup_destroy(bcmos_msg_qgroup *qgroup)
+{
+ bcmos_qgroup_prty prty;
+
+ if (!qgroup || qgroup->magic != BCMOS_MSG_QGROUP_VALID)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "queue group handle is invalid\n");
+ }
+
+ qgroup->magic = BCMOS_MSG_QGROUP_DELETED;
+
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&msg_qgroup_list, qgroup, bcmos_msg_qgroup, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ bcmos_sem_destroy(&qgroup->m);
+
+ /* Release all pending messages */
+ if (qgroup->msgl)
+ {
+ for (prty = 0; prty < qgroup->parm.nqueues; prty++)
+ {
+ bcmos_msg_list_destroy(&qgroup->msgl[prty]);
+ }
+ bcmos_free(qgroup->msgl);
+ }
+ return BCM_ERR_OK;
+
+}
+
+/** Get queue group info */
+bcmos_errno bcmos_msg_qgroup_query(const bcmos_msg_qgroup *qgroup, bcmos_msg_qgroup_info *info)
+{
+ if (!qgroup || !info)
+ return BCM_ERR_PARM;
+
+ info->parm = qgroup->parm;
+ info->stat = qgroup->stat;
+
+ return BCM_ERR_OK;
+}
+
+/** Message queue group iterator
+ * \param[in] prev Previous queue group. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_msg_qgroup_get_next(const bcmos_msg_qgroup **prev)
+{
+ const bcmos_msg_qgroup *qgrp;
+
+ if (prev == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ qgrp = *prev;
+ if (qgrp && qgrp->magic != BCMOS_MSG_QGROUP_VALID)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (qgrp)
+ {
+ qgrp = STAILQ_NEXT(qgrp, list);
+ }
+ else
+ {
+ qgrp = STAILQ_FIRST(&msg_qgroup_list);
+ }
+ *prev = qgrp;
+ if (!qgrp)
+ {
+ return BCM_ERR_NO_MORE;
+ }
+ return BCM_ERR_OK;
+}
+
+/* get message from non-empty queue group queue */
+static inline bcmos_msg *_bcmos_qgroup_msg_get(bcmos_msg_qgroup *qgroup, bcmos_qgroup_prty prty)
+{
+ bcmos_msg *msg;
+ msg = STAILQ_FIRST(&qgroup->msgl[prty]);
+ BUG_ON(!msg);
+ STAILQ_REMOVE_HEAD(&qgroup->msgl[prty], next);
+ if (STAILQ_EMPTY(&qgroup->msgl[prty]))
+ {
+ qgroup->active_mask &= ~(1 << prty);
+ }
+ return msg;
+}
+
+/* Send message to queue group */
+bcmos_errno bcmos_msg_send_to_qgroup(bcmos_msg_qgroup *qgroup, bcmos_msg *msg, bcmos_qgroup_prty prty,
+ bcmos_msg_send_flags flags)
+{
+ long lock_flags;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (prty >= qgroup->parm.nqueues)
+ {
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ {
+ bcmos_msg_free(msg);
+ }
+ return BCM_ERR_PARM;
+ }
+ msg->send_flags = flags;
+
+ lock_flags = bcmos_fastlock_lock(&qgroup->lock);
+
+ /* Put into the relevant queue */
+ STAILQ_INSERT_TAIL(&qgroup->msgl[prty], msg, next);
+ qgroup->active_mask |= (1 << prty);
+ _bcmos_qgroup_stat_inc(qgroup);
+
+ /* Overflow check */
+ if ((qgroup->stat.msg_in > qgroup->parm.size))
+ {
+ bcmos_msg *m;
+ bcmos_qgroup_prty i;
+ /* Find the lowest-priority queue with data and discard the head message.
+ * The loop always finds something because we've just added a message
+ */
+ for (i = qgroup->parm.nqueues - 1; (qgroup->active_mask & (1 << i)) == 0; i--)
+ ;
+ m = _bcmos_qgroup_msg_get(qgroup, i);
+ --qgroup->stat.msg_in;
+ ++qgroup->stat.msg_discarded;
+ if (!(m->send_flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ {
+ bcmos_msg_free(m);
+ }
+ rc = BCM_ERR_OVERFLOW;
+ }
+
+ /* Kick waiting task */
+ if (qgroup->is_waiting)
+ {
+ qgroup->is_waiting = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+ bcmos_sem_post(&qgroup->m);
+ }
+ else
+ {
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+ }
+
+ return rc;
+
+}
+
+/* Get highest priority message from queue group */
+bcmos_errno bcmos_msg_recv_from_qgroup(bcmos_msg_qgroup *qgroup, uint32_t timeout, bcmos_msg **msg)
+{
+ long lock_flags;
+ bcmos_qgroup_prty prty;
+
+ if (!qgroup || !msg)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "qgroup %p, msg %p\n", qgroup, msg);
+
+ lock_flags = bcmos_fastlock_lock(&qgroup->lock);
+ if (!qgroup->active_mask)
+ {
+ if (!timeout)
+ {
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+ return BCM_ERR_NOENT;
+ }
+
+ /* Receive with wait */
+ qgroup->is_waiting = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+
+ /* wait for it */
+ bcmos_sem_wait(&qgroup->m, timeout);
+
+ /* Done waiting. Either got a message or a timeout */
+ lock_flags = bcmos_fastlock_lock(&qgroup->lock);
+ qgroup->is_waiting = BCMOS_FALSE;
+ if (!qgroup->active_mask)
+ {
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+ return BCM_ERR_TIMEOUT;
+ }
+ }
+
+ prty = (bcmos_qgroup_prty)(ffs(qgroup->active_mask) - 1);
+ BUG_ON(prty >= qgroup->parm.nqueues);
+ *msg = _bcmos_qgroup_msg_get(qgroup, prty);
+ _bcmos_qgroup_stat_dec(qgroup);
+ bcmos_fastlock_unlock(&qgroup->lock, lock_flags);
+
+ return BCM_ERR_OK;
+}
+
+
+/*
+ * Message registration and dispatch
+ */
+
+/* Hash entry */
+typedef struct msg_hash_entry msg_hash_entry;
+
+struct msg_hash_entry
+{
+ /* Key */
+ uint32_t key; /* msg_type + instance */
+
+ /* Value */
+ bcmos_module_id module_id;
+ F_bcmos_msg_handler handler;
+
+ /* List of entries with the same key */
+ SLIST_ENTRY(msg_hash_entry) list;
+};
+
+/* Hash table */
+static SLIST_HEAD(msg_hash, msg_hash_entry) msg_hash_table[BCMOS_MSG_HASH_SIZE];
+
+/* Make hash key from msg_type and instance */
+static inline uint32_t _bcmos_msg_hash_key(bcmos_msg_id msg_type, bcmos_msg_instance instance)
+{
+ return ((uint32_t)instance << 16) | (uint32_t)msg_type;
+}
+
+/* Hash function */
+static inline uint32_t _bcmos_msg_hash_func(uint32_t key)
+{
+ key ^= (key >> 9);
+ key ^= (key << 3);
+ key ^= (key >> 15);
+ return key % BCMOS_MSG_HASH_SIZE;
+}
+
+/* Find entry in hash */
+static inline msg_hash_entry *_bcmos_msg_hash_find(bcmos_msg_id msg_type, bcmos_msg_instance instance)
+{
+ uint32_t key = _bcmos_msg_hash_key(msg_type, instance);
+ uint32_t hash = _bcmos_msg_hash_func(key);
+ msg_hash_entry *entry;
+ SLIST_FOREACH(entry, &msg_hash_table[hash], list)
+ {
+ if (entry->key == key)
+ break;
+ }
+ return entry;
+}
+
+/* Register message_type+instance --> module+handler */
+bcmos_errno bcmos_msg_register(bcmos_msg_id msg_type, bcmos_msg_instance instance,
+ bcmos_module_id module_id, F_bcmos_msg_handler handler)
+{
+ uint32_t key = _bcmos_msg_hash_key(msg_type, instance);
+ uint32_t hash = _bcmos_msg_hash_func(key);
+ msg_hash_entry *entry;
+ long lock_flags;
+
+ if (!handler)
+ return BCM_ERR_PARM;
+
+ entry = bcmos_calloc(sizeof(*entry));
+ if (!entry)
+ return BCM_ERR_NOMEM;
+
+ entry->key = key;
+ entry->module_id = module_id;
+ entry->handler = handler;
+ lock_flags = bcmos_fastlock_lock(&bcmos_msg_register_lock);
+ if (_bcmos_msg_hash_find(msg_type, instance) != NULL)
+ {
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+ bcmos_free(entry);
+ return BCM_ERR_ALREADY;
+ }
+ SLIST_INSERT_HEAD(&msg_hash_table[hash], entry, list);
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmos_msg_unregister(bcmos_msg_id msg_type, bcmos_msg_instance instance, bcmos_module_id module_id)
+{
+ uint32_t key = _bcmos_msg_hash_key(msg_type, instance);
+ uint32_t hash = _bcmos_msg_hash_func(key);
+ msg_hash_entry *entry;
+ long lock_flags;
+
+ lock_flags = bcmos_fastlock_lock(&bcmos_msg_register_lock);
+ entry = _bcmos_msg_hash_find(msg_type, instance);
+ if (!entry)
+ {
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+ return BCM_ERR_NOENT;
+ }
+
+ if (entry->module_id != module_id)
+ {
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+ return BCM_ERR_INVALID_OP;
+ }
+
+ SLIST_REMOVE(&msg_hash_table[hash], entry, msg_hash_entry, list);
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+ bcmos_free(entry);
+
+ return BCM_ERR_OK;
+}
+
+void bcmos_msg_shutdown_mode_set(bcmos_bool shutdown_mode)
+{
+ bcmos_msg_shutdown_mode = shutdown_mode;
+}
+
+bcmos_bool bcmos_msg_shutdown_mode_get(void)
+{
+ return bcmos_msg_shutdown_mode;
+}
+
+/* Dispatch message to registered module */
+bcmos_errno bcmos_msg_dispatch(bcmos_msg *msg, bcmos_msg_send_flags flags)
+{
+ bcmos_errno err;
+
+ if (unlikely(bcmos_msg_shutdown_mode))
+ {
+ /* In shutdown mode, we need to acquire the same lock used to protect bcmos_msg_register() /
+ * bcmos_msg_unregister(), since we must support calling these functions concurrently. */
+ msg_hash_entry *entry;
+ bcmos_sem *sem_to_post = NULL;
+ long lock_flags = bcmos_fastlock_lock(&bcmos_msg_register_lock);
+ entry = _bcmos_msg_hash_find(msg->type, msg->instance);
+
+ if (entry)
+ {
+ msg->handler = entry->handler;
+ err = _bcmos_msg_send_to_module(entry->module_id, msg, flags, &sem_to_post);
+ }
+ else
+ {
+ /* Not found. Release automatically if requested. */
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ bcmos_msg_free(msg);
+ err = BCM_ERR_OK;
+ }
+
+ bcmos_fastlock_unlock(&bcmos_msg_register_lock, lock_flags);
+ if (sem_to_post)
+ bcmos_sem_post(sem_to_post);
+ }
+ else
+ {
+ msg_hash_entry *entry = _bcmos_msg_hash_find(msg->type, msg->instance);
+
+ if (entry)
+ {
+ msg->handler = entry->handler;
+ err = bcmos_msg_send_to_module(entry->module_id, msg, flags);
+ }
+ else
+ {
+ /* Not found. Release automatically if requested. */
+ BCMOS_TRACE_ERR("Can't dispatch unregistered msg %d:%d\n", msg->type, msg->instance);
+ if (!(flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR))
+ bcmos_msg_free(msg);
+ err = BCM_ERR_NOENT;
+ }
+ }
+
+ return err;
+}
+
+/*
+ * Task management
+ */
+
+/*
+ * Default task handler
+ */
+/*lint -e{632,633,634}
+ * There are a few warnings about
+ * implicit bcmos_errno conversion to int. It is to bothersome now
+ * to change task handler prototype everywhere and the warning is harmless
+ */
+int bcmos_dft_task_handler(long data)
+{
+ bcmos_task *task = (bcmos_task *)data;
+ long flags = 0, q_flags = 0;
+ uint32_t active_modules;
+ int last_module = 0; /* 1-based last handled module index */
+ bcmos_module *module;
+ bcmos_msg *msg;
+ int rc;
+
+
+ /* Set / validate task timeout */
+ rc = bcmos_task_timeout_set(task, task->parm.msg_wait_timeout, task->parm.timeout_handler);
+ if (rc)
+ {
+ return rc;
+ }
+
+ /* Call init callback if any */
+ if (task->parm.init_handler)
+ {
+ rc = task->parm.init_handler(task->parm.data);
+ if (rc)
+ {
+ BCMOS_TRACE_ERR("Task %s: init_handler returned error %s (%d)\n",
+ task->parm.name, bcmos_strerror((bcmos_errno)rc), rc);
+ bcmos_task_destroy(task);
+ return rc;
+ }
+ }
+
+ /* Wait for module activity */
+ while (!task->destroy_request)
+ {
+ task->current_module = BCMOS_MODULE_ID_NONE;
+
+ /* Wait for module activity */
+ rc = bcmos_sem_wait(&task->active_sem, task->parm.msg_wait_timeout);
+ if (rc == BCM_ERR_TIMEOUT)
+ {
+ F_bcmos_task_handler timeout_handler = task->parm.timeout_handler;
+
+ /* Handle possible race condition */
+ if (!timeout_handler)
+ continue;
+ rc = timeout_handler(data);
+ if (rc != BCM_ERR_OK)
+ {
+ BCMOS_TRACE_ERR("Task %s: terminated by timeout_handler. error %s (%d)\n",
+ task->parm.name, bcmos_strerror(rc), rc);
+ break;
+ }
+ /* Keep waiting */
+ continue;
+ }
+
+ /* RR active modules */
+ do
+ {
+ flags = bcmos_fastlock_lock(&task->active_lock);
+ active_modules = (task->active_modules >> last_module);
+ if (!active_modules)
+ {
+ last_module = 0;
+ active_modules = task->active_modules;
+ if (!active_modules)
+ {
+ /* No modules with work to do */
+ bcmos_fastlock_unlock(&task->active_lock, flags);
+ continue;
+ }
+ }
+ last_module += ffs(active_modules);
+ BUG_ON(last_module > BCMOS_MAX_MODULES_PER_TASK);
+ module = task->modules[last_module - 1];
+ BUG_ON(!module);
+
+ q_flags = bcmos_fastlock_lock(&module->msgq.lock);
+ /* Get message from the module's message queue */
+ msg = _bcmos_msg_get(&module->msgq);
+ if (!msg)
+ {
+ bcmos_fastlock_unlock(&module->msgq.lock, q_flags);
+ task->active_modules &= ~(1 << (last_module - 1));
+ bcmos_fastlock_unlock(&task->active_lock, flags);
+ continue;
+ }
+
+ bcmos_fastlock_unlock(&module->msgq.lock, q_flags);
+ bcmos_fastlock_unlock(&task->active_lock, flags);
+
+ /* Handle the message */
+ if (msg->handler)
+ {
+ task->current_module = module->id;
+ msg->handler(module->id, msg);
+ }
+ else
+ {
+ BCMOS_TRACE_ERR("msg->handler is not set. msg->type=%d\n", msg->type);
+ bcmos_msg_free(msg);
+ }
+
+ } while (task->active_modules);
+ }
+
+ return 0;
+}
+
+/* Set task message timeout.
+ * The function is only supported in integration mode
+ */
+bcmos_errno bcmos_task_timeout_set(bcmos_task *task, uint32_t timeout, F_bcmos_task_handler timeout_handler)
+{
+ if (task->parm.handler)
+ {
+ BCMOS_TRACE_ERR("%s: The function is only supported in integration mode (task handler == NULL)\n", task->parm.name);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ if ((timeout && timeout != BCMOS_WAIT_FOREVER) && !timeout_handler)
+ {
+ BCMOS_TRACE_ERR("%s: timeout_handler is not set\n", task->parm.name);
+ return BCM_ERR_PARM;
+ }
+
+ /* 0 means FOREVER here */
+ if (!timeout)
+ timeout = BCMOS_WAIT_FOREVER;
+
+ task->parm.timeout_handler = timeout_handler;
+ task->parm.msg_wait_timeout = timeout;
+
+ return BCM_ERR_OK;
+}
+
+/*
+ * Module
+ */
+
+/* Register module */
+bcmos_errno bcmos_module_create(bcmos_module_id module_id, bcmos_task *task, bcmos_module_parm *parm)
+{
+ bcmos_module *module;
+ bcmos_errno rc = BCM_ERR_OK;
+ int i;
+
+ if ((unsigned)module_id >= (unsigned)BCMOS_MODULE_ID__NUM_OF || !parm)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "module %d, parm %p\n", module_id, parm);
+ if (!task)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOT_SUPPORTED, "No task\n");
+ if (bcmos_modules[module_id])
+ BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "module_id %d\n", module_id);
+
+ module = bcmos_calloc(sizeof(bcmos_module));
+ if (!module)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "module_id %d\n", module_id);
+ module->id = module_id;
+ module->my_task = task;
+ module->parm = *parm;
+ module->context = (void *)parm->data;
+ bcmos_msg_queue_nw_init(&module->msgq, &parm->qparm);
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (module->parm.qparm.name)
+ {
+ strncpy(module->name, module->parm.qparm.name, sizeof(module->name) - 1);
+ module->parm.qparm.name = module->name;
+ }
+
+ /* Assign module id */
+ for (i = 0; i < BCMOS_MAX_MODULES_PER_TASK; i++)
+ {
+ if (!task->modules[i])
+ {
+ task->modules[i] = module;
+ module->idx = i;
+ break;
+ }
+ }
+ if (i == BCMOS_MAX_MODULES_PER_TASK)
+ {
+ bcmos_free(module);
+ BCMOS_TRACE_RETURN(BCM_ERR_TOO_MANY, "module_id %d\n", module_id);
+ }
+
+ bcmos_modules[module_id] = module;
+
+ /* Init module */
+ if (parm->init)
+ {
+ rc = parm->init(parm->data);
+ if (rc)
+ bcmos_module_destroy(module_id);
+ }
+
+ return rc;
+}
+
+/* Un-register module */
+bcmos_errno bcmos_module_destroy(bcmos_module_id module_id)
+{
+ bcmos_module *module = _bcmos_module_get(module_id);
+ bcmos_task *task;
+ long lock_flags, q_lock_flags;
+ bcmos_msg_list msgl_urg, msgl;
+
+ if (!module)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "module_id %d\n", module_id);
+
+ task = module->my_task;
+ lock_flags = bcmos_fastlock_lock(&task->active_lock);
+ task->modules[module->idx] = NULL;
+ task->active_modules &= ~(1 << module->idx);
+
+ /* Because we are not allowed to free memory (via bcmos_free()) when interrupts are locked, we only empty the linked list (via SLIST_INIT()) and the free comes outside the locked
+ * section. */
+ q_lock_flags = bcmos_fastlock_lock(&module->msgq.lock);
+ msgl_urg = module->msgq.msgl_urg;
+ msgl = module->msgq.msgl;
+ STAILQ_INIT(&module->msgq.msgl_urg);
+ STAILQ_INIT(&module->msgq.msgl);
+ bcmos_fastlock_unlock(&module->msgq.lock, q_lock_flags);
+ bcmos_fastlock_unlock(&task->active_lock, lock_flags);
+
+ bcmos_msg_list_destroy(&msgl_urg);
+ bcmos_msg_list_destroy(&msgl);
+
+ if (module->parm.exit)
+ module->parm.exit(module->parm.data);
+ bcmos_modules[module_id] = NULL;
+ bcmos_free(module);
+
+ return BCM_ERR_OK;
+}
+
+/* Get current module id in the current task */
+bcmos_module_id bcmos_module_current(void)
+{
+ bcmos_task *task = bcmos_task_current();
+
+ if (!task)
+ return BCMOS_MODULE_ID_NONE;
+ return task->current_module;
+}
+
+/* Get module context set by bcmos_module_context_set() */
+void *bcmos_module_context(bcmos_module_id module_id)
+{
+ bcmos_module *module = _bcmos_module_get(module_id);
+ if (!module)
+ return NULL;
+ return module->context;
+}
+
+/* Set module context */
+bcmos_errno bcmos_module_context_set(bcmos_module_id module_id, void *context)
+{
+ bcmos_module *module = _bcmos_module_get(module_id);
+
+ if (!module)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "module_id %d\n", module_id);
+ module->context = context;
+ return BCM_ERR_OK;
+}
+
+/* Query module info */
+bcmos_errno bcmos_module_query(bcmos_module_id module_id, const bcmos_task **task, bcmos_msg_queue_info *info)
+{
+ bcmos_module *module = _bcmos_module_get(module_id);
+
+ if (!module)
+ {
+ return BCM_ERR_NOENT;
+ }
+ if (task)
+ {
+ *task = module->my_task;
+ }
+ if (info)
+ {
+ info->parm = module->parm.qparm;
+ info->stat = module->msgq.stat;
+ }
+ return BCM_ERR_OK;
+}
+
+/*
+ * Events
+ */
+
+/* This function handles event arrival in module context */
+static void _bcmos_ev_in_module_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+ bcmos_event *ev = _bcmos_msg_to_event(msg);
+ uint32_t active_bits;
+ long lock_flags;
+
+ active_bits = ev->active_bits & ev->parm.mask;
+ ev->parm.handler(ev->id, active_bits);
+
+ lock_flags = bcmos_fastlock_lock(&ev->lock);
+ ev->active_bits &= ~active_bits;
+ ev->is_waiting = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+}
+
+/* Release event message. Only called in exceptional situations,
+ * such as module queue destroy. Do nothing.
+ */
+static void _bcmos_ev_msg_release(bcmos_msg *msg)
+{
+}
+
+/* Create event set */
+bcmos_errno bcmos_event_create(bcmos_event_id event_id, bcmos_event_parm *parm)
+{
+ bcmos_event *ev;
+ bcmos_module *module = NULL;
+ bcmos_errno rc;
+
+ if ((unsigned)event_id >= (unsigned)BCMOS_EVENT_ID__NUM_OF)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "event_id %d\n", event_id);
+
+ if (_bcmos_event_get(event_id))
+ BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "event_id %d\n", event_id);
+
+ if (parm && parm->module_id != BCMOS_MODULE_ID_NONE)
+ {
+ module = _bcmos_module_get(parm->module_id);
+ if (!module)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "module_id %d\n", parm->module_id);
+ if (!parm->handler || !parm->mask)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "event_id %d, handler %p, mask %x\n", event_id, parm->handler, parm->mask);
+ }
+
+ ev = bcmos_calloc(sizeof(bcmos_event));
+ if (!ev)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "event_id %d\n", event_id);
+
+ ev->id = event_id;
+ if (parm)
+ ev->parm = *parm;
+ bcmos_fastlock_init(&ev->lock, ev->parm.flags);
+ {
+ rc = bcmos_sem_create(&ev->m, 0, ev->parm.flags, ev->parm.name);
+ if (rc)
+ {
+ bcmos_free(ev);
+ return rc;
+ }
+ }
+
+ /* Initialize event message in integration mode */
+ if (ev->parm.module_id != BCMOS_MODULE_ID_NONE)
+ {
+ ev->msg.handler = _bcmos_ev_in_module_handler;
+ ev->msg.release = _bcmos_ev_msg_release;
+ ev->msg.sender = BCMOS_MODULE_ID_NONE;
+ ev->msg.type = BCMOS_MSG_ID_INTERNAL_EVENT;
+ ev->is_waiting = BCMOS_TRUE;
+ }
+
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (ev->parm.name)
+ {
+ strncpy(ev->name, ev->parm.name, sizeof(ev->name) - 1);
+ ev->parm.name = ev->name;
+ }
+
+ bcmos_events[event_id] = ev;
+
+ return BCM_ERR_OK;
+}
+
+/* Destroy event set created by bcmos_event_create() */
+bcmos_errno bcmos_event_destroy(bcmos_event_id event_id)
+{
+ return BCM_ERR_NOT_SUPPORTED;
+}
+
+/* Raise event */
+bcmos_errno bcmos_event_raise(bcmos_event_id event_id, uint32_t active_bits)
+{
+ bcmos_event *ev = _bcmos_event_get(event_id);
+ long lock_flags;
+
+ if (!ev)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "event_id %d\n", event_id);
+
+ lock_flags = bcmos_fastlock_lock(&ev->lock);
+ ev->active_bits |= active_bits;
+ if (ev->is_waiting && (ev->active_bits & ev->parm.mask))
+ {
+ ev->is_waiting = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+ if (ev->parm.module_id != BCMOS_MODULE_ID_NONE)
+ bcmos_msg_send_to_module(ev->parm.module_id, &ev->msg, BCMOS_MSG_SEND_URGENT | BCMOS_MSG_SEND_NOLIMIT);
+ else
+ bcmos_sem_post(&ev->m);
+ }
+ else
+ {
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* Wait for event */
+bcmos_errno bcmos_event_recv(bcmos_event_id event_id, uint32_t mask,
+ uint32_t timeout, uint32_t *active_bits)
+{
+ bcmos_event *ev = _bcmos_event_get(event_id);
+ long lock_flags;
+
+ BUG_ON(!active_bits);
+ if (!ev)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "event_id %d is not registered\n", event_id);
+
+ lock_flags = bcmos_fastlock_lock(&ev->lock);
+ *active_bits = ev->active_bits & mask;
+ if (*active_bits)
+ {
+ ev->active_bits &= ~ *active_bits;
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+ return BCM_ERR_OK;
+ }
+ if (!timeout)
+ {
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+ return BCM_ERR_NOENT;
+ }
+
+ /* recv with wait */
+ ev->is_waiting = BCMOS_TRUE;
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+
+ /* wait for it */
+ bcmos_sem_wait(&ev->m, timeout);
+ /* Either got event or timeout */
+ lock_flags = bcmos_fastlock_lock(&ev->lock);
+ *active_bits = ev->active_bits & mask;
+ ev->active_bits &= ~ *active_bits;
+ ev->is_waiting = BCMOS_FALSE;
+ bcmos_fastlock_unlock(&ev->lock, lock_flags);
+ /* If we wait forever and we got an event that does not match the mask we wait on (this is the only possible reason getting here if waiting forever), then we
+ * want to avoid returning BCM_ERR_TIMEOUT - it's not an error. */
+ if (timeout != BCMOS_WAIT_FOREVER && !*active_bits)
+ return BCM_ERR_TIMEOUT;
+ return BCM_ERR_OK;
+}
+
+/*
+ * Timer
+ */
+
+/* compare timestamps minding wrap-around
+ * returns delta >= 0 if ts1 >= ts2
+ */
+static inline int32_t _bcmos_timer_ts_delta(uint32_t ts1, uint32_t ts2)
+{
+ int32_t delta = (int)(ts1 - ts2);
+ return delta;
+}
+
+static int32_t _bcmos_timer_compare(struct bcmos_timer *t1, struct bcmos_timer *t2)
+{
+ int32_t delta = _bcmos_timer_ts_delta(t1->expire_at, t2->expire_at);
+#if defined(BCMOS_TIMER_RB_TREE) && !defined(BCMOS_TIMER_RB_TREE_LIST)
+ /* FreeBSD RB tree implementation doesn't support 2 nodes with the same key */
+ if (!delta)
+ delta = 1;
+#endif
+ return delta;
+}
+
+static inline void _bcmos_start_system_timer(bcmos_timer *head)
+{
+ if (head)
+ {
+ int32_t delay = _bcmos_timer_ts_delta(head->expire_at, bcmos_timestamp());
+ /* Handle rare race condition when next timer expired while we were fiddling
+ * with the pool. Just give it 1 more "tick". System handler handles all timers
+ * expired (<now .. now + PRECISION/2)
+ */
+ if (delay <= 0)
+ {
+ delay = BCMOS_TIMER_PRECISION_US / 2;
+ }
+ bcmos_sys_timer_start(&tmr_pool.sys_timer, delay);
+ }
+ else
+ {
+ bcmos_sys_timer_stop(&tmr_pool.sys_timer);
+ }
+}
+
+/*
+ * Timer pool: RB tree or TAILQ-based implementation
+ */
+static void _bcmos_timer_pool_insert(bcmos_timer *timer, uint32_t delay, bcmos_bool start_sys_timer)
+{
+ long flags;
+ bcmos_timer *head;
+
+ flags = bcmos_fastlock_lock(&tmr_pool.lock);
+ if (BCMOS_TIMER_IS_RUNNING(timer))
+ {
+ bcmos_fastlock_unlock(&tmr_pool.lock, flags);
+ return;
+ }
+ timer->period = timer->parm.periodic ? delay : 0;
+ timer->expire_at = BCMOS_ROUND_UP(bcmos_timestamp() + delay, BCMOS_TIMER_PRECISION_US / 2);
+ TMR_POOL_INSERT(&tmr_pool, timer);
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ timer->flags |= BCMOS_TIMER_FLAG_RUNNING;
+
+ /* If new timer is at the top - kick system timer */
+ if (start_sys_timer)
+ {
+ head = TMR_POOL_FIRST(&tmr_pool);
+ if (timer == head)
+ {
+ _bcmos_start_system_timer(head);
+ }
+ }
+ bcmos_fastlock_unlock(&tmr_pool.lock, flags);
+}
+
+static void _bcmos_timer_stop(bcmos_timer *timer)
+{
+ long flags;
+ bcmos_bool was_top;
+ bcmos_msg_queue_nw *queue;
+
+ /* First take running timer out of the active pool */
+ flags = bcmos_fastlock_lock(&tmr_pool.lock);
+ timer->period = 0; /* Prevent periodic timer restart */
+ if (BCMOS_TIMER_IS_RUNNING(timer))
+ {
+ timer->flags &= ~BCMOS_TIMER_FLAG_RUNNING;
+ was_top = (timer == TMR_POOL_FIRST(&tmr_pool));
+ TMR_POOL_REMOVE(&tmr_pool, timer);
+
+ /* If timer was the top - stop/restart system timer */
+ if (was_top)
+ {
+ _bcmos_start_system_timer(TMR_POOL_FIRST(&tmr_pool));
+ }
+ }
+ bcmos_fastlock_unlock(&tmr_pool.lock, flags);
+
+ /* Now timer is not in the active pool. Perhaps it is already in
+ * destination module's queue. Take it out if yes.
+ */
+ queue = timer->queue;
+ if (queue)
+ {
+ flags = bcmos_fastlock_lock(&queue->lock);
+ /* Check queue again because the previous check was unprotected */
+ if (timer->queue)
+ {
+ bcmos_msg_list *msg_list = ((timer->parm.flags & BCMOS_TIMER_PARM_FLAGS_NON_URGENT))
+ ? &queue->msgl : &queue->msgl_urg;
+ if (STAILQ_REMOVE_SAFE(msg_list, &timer->msg, bcmos_msg, next) != NULL)
+ {
+ _bcmos_msgq_stat_dec(queue);
+ }
+ timer->queue = NULL;
+ }
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ bcmos_fastlock_unlock(&queue->lock, flags);
+ }
+
+ /* If timer has already expired and we weren't able to stop it -
+ * wait for expiration callback to finish before leaving _bcmos_timer_stop()
+ */
+ if (BCMOS_TIMER_IS_EXPIRED(timer))
+ {
+ bcmos_task *t = bcmos_task_current();
+
+ /* Skip wait if timer is being stopped / restarted from inside the handler */
+ if (t != timer->task)
+ {
+ while (BCMOS_TIMER_IS_EXPIRED(timer) && BCMOS_TIMER_IS_VALID(timer))
+ {
+ bcmos_usleep(1000);
+ }
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ }
+ }
+}
+
+
+/* System timer expiration handler.
+ * Execute all timers that expired and restart system timer
+ */
+static void _sys_timer_handler(void *data)
+{
+ bcmos_timer_pool *pool = (bcmos_timer_pool *)data;
+ bcmos_timer *timer;
+ bcmos_timer_rc rc;
+ long flags;
+
+ BUG_ON(pool != &tmr_pool);
+ flags = bcmos_fastlock_lock(&pool->lock);
+ while ((timer=TMR_POOL_FIRST(pool)) != NULL)
+ {
+ /* Stop when reached timer that hasn't expired yet */
+ if (_bcmos_timer_ts_delta(timer->expire_at, bcmos_timestamp()) > BCMOS_TIMER_PRECISION_US / 2)
+ break;
+ timer->flags |= BCMOS_TIMER_FLAG_EXPIRED;
+ timer->flags &= ~BCMOS_TIMER_FLAG_RUNNING;
+ /* IT: Barrier here ? */
+ TMR_POOL_REMOVE(pool, timer);
+
+ /* Execute handler. Unlock first and re-lock in the end
+ * It is safe to unlock here because the top loop starts from MIN every time
+ */
+ bcmos_fastlock_unlock(&pool->lock, flags);
+ rc = timer->handler(timer, timer->parm.data);
+ if (!timer->parm.owner)
+ {
+ if (rc == BCMOS_TIMER_OK && timer->period)
+ {
+ uint32_t interval = timer->period;
+ timer->period = 0;
+ _bcmos_timer_pool_insert(timer, interval, BCMOS_FALSE);
+ }
+ else
+ {
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ }
+ }
+ flags = bcmos_fastlock_lock(&pool->lock);
+ }
+ /* Finally kick system timer */
+ _bcmos_start_system_timer(timer);
+ bcmos_fastlock_unlock(&pool->lock, flags);
+}
+
+/* Send timer expiration to the target module as urgent message.
+ * _bcmos_timer_in_module_handler() will get called in the module context
+ */
+static bcmos_timer_rc _bcmos_timer_send_to_module_handler(bcmos_timer *timer, long data)
+{
+ bcmos_errno rc;
+ bcmos_module *module = _bcmos_module_get(timer->parm.owner);
+ bcmos_msg_send_flags send_flags;
+ if (!module)
+ {
+ /* Shouldn't happen, unless the module was destroyed */
+ BCMOS_TRACE_ERR("_bcmos_timer_send_to_module_handler() -- no module=%u (timer->parm.handler=0x%p)\n", timer->parm.owner, timer->parm.handler);
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ return BCMOS_TIMER_STOP; /* will restart in module context if necessary */
+ }
+ timer->queue = &module->msgq;
+ send_flags = BCMOS_MSG_SEND_NOLIMIT;
+ if (!((timer->parm.flags & BCMOS_TIMER_PARM_FLAGS_NON_URGENT)))
+ send_flags |= BCMOS_MSG_SEND_URGENT;
+ rc = bcmos_msg_send_to_module(timer->parm.owner, &timer->msg, send_flags);
+ if (rc)
+ {
+ /* Shouldn't happen, unless the module was destroyed. Very short race condition here */
+ timer->queue = NULL;
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+ BCMOS_TRACE_ERR("_bcmos_timer_send_to_module_handler() --> %d\n", rc);
+ }
+ return BCMOS_TIMER_STOP; /* will restart in module context if necessary */
+}
+
+/* This function handles timer expiration in module context */
+static void _bcmos_timer_in_module_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+ bcmos_timer *timer = _bcmos_msg_to_timer(msg);
+ bcmos_module *module = _bcmos_module_get(timer->parm.owner);
+ bcmos_timer_rc rc;
+
+ /* Call timer's callback function and restart the timer if necessary */
+ timer->queue = NULL;
+ /* module can't be NULL here. it is checked anyway to keep static code analyzer happy */
+ timer->task = module ? module->my_task : (bcmos_task*)NULL;
+ rc = timer->parm.handler(timer, timer->parm.data);
+ timer->task = NULL;
+ if (rc == BCMOS_TIMER_OK && timer->period)
+ _bcmos_timer_pool_insert(timer, timer->period, BCMOS_TRUE);
+ else
+ timer->flags &= ~BCMOS_TIMER_FLAG_EXPIRED;
+}
+
+/* Release timer message. Only called in exceptional situations,
+ * such as module queue destroy. Do nothing
+ */
+static void _bcmos_timer_msg_release(bcmos_msg *msg)
+{
+}
+
+/* Create timer */
+bcmos_errno bcmos_timer_create(bcmos_timer *timer, bcmos_timer_parm *parm)
+{
+ if (!timer || !parm || !parm->handler)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "timer %p, parm %p handler %p\n", timer, parm, parm ? parm->handler : NULL);
+ if (parm->owner != BCMOS_MODULE_ID_NONE && _bcmos_module_get(parm->owner) == NULL)
+ BCMOS_TRACE_RETURN(BCM_ERR_NOENT, "module_id %d\n", parm->owner);
+ memset(timer, 0, sizeof(bcmos_timer));
+ timer->parm = *parm;
+ if (parm->owner == BCMOS_MODULE_ID_NONE)
+ timer->handler = parm->handler;
+ else
+ {
+ timer->handler = _bcmos_timer_send_to_module_handler;
+ timer->msg.handler = _bcmos_timer_in_module_handler;
+ timer->msg.release = _bcmos_timer_msg_release;
+ timer->msg.sender = BCMOS_MODULE_ID_NONE;
+ timer->msg.type = BCMOS_MSG_ID_INTERNAL_TIMER;
+ }
+ timer->flags |= BCMOS_TIMER_FLAG_VALID;
+ return BCM_ERR_OK;
+}
+
+/* Destroy timer */
+void bcmos_timer_destroy(bcmos_timer *timer)
+{
+ BUG_ON(!timer);
+ bcmos_timer_stop(timer);
+ timer->flags &= ~BCMOS_TIMER_FLAG_VALID;
+}
+
+/* (Re)start timer */
+void bcmos_timer_start(bcmos_timer *timer, uint32_t delay)
+{
+ BUG_ON(!timer);
+ BUG_ON(!BCMOS_TIMER_IS_VALID(timer));
+ if ((int32_t)delay < 0)
+ {
+ BCMOS_TRACE_ERR("Attempt to start timer (%s) for period longer than 2^31-1. Reduced to 2^31-1\n",
+ timer->parm.name ? timer->parm.name : "*unnamed*");
+ delay = 0x7fffffff;
+ }
+
+ if (BCMOS_TIMER_IS_RUNNING(timer) || BCMOS_TIMER_IS_EXPIRED(timer))
+ {
+ _bcmos_timer_stop(timer);
+ }
+ _bcmos_timer_pool_insert(timer, delay, BCMOS_TRUE);
+}
+
+/* Stop timer if running */
+void bcmos_timer_stop(bcmos_timer *timer)
+{
+ BUG_ON(!timer);
+ _bcmos_timer_stop(timer);
+}
+
+/** Set timer handler */
+bcmos_errno bcmos_timer_handler_set(bcmos_timer *timer, F_bcmos_timer_handler handler, long data)
+{
+ BUG_ON(!timer);
+ BUG_ON(!handler);
+ timer->parm.handler = handler;
+ timer->parm.data = data;
+ if (timer->parm.owner == BCMOS_MODULE_ID_NONE)
+ timer->handler = handler;
+ return BCM_ERR_OK;
+}
+
+/*
+ * Block memory pool
+ */
+
+/* Memory block structure:
+ * - bcmos_memblk
+ * - blk_size bytes of user data
+ * - [magic - for block overflow-corruption check]
+ * - [padding to align to pointer size]
+ */
+
+struct bcmos_memblk
+{
+ STAILQ_ENTRY(bcmos_memblk) next; /**< Next block pointer */
+ bcmos_blk_pool *pool; /** pool that owns the block */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /** magic number */
+#define BCMOS_MEM_MAGIC_ALLOC (('m'<<24) | ('b' << 16) | ('l' << 8) | 'k')
+#define BCMOS_MEM_MAGIC_FREE (('m'<<24) | ('b' << 16) | ('l' << 8) | '~')
+#define BCMOS_MEM_MAGIC_SUFFIX (('m'<<24) | ('b' << 16) | ('l' << 8) | 's')
+ uint32_t lineno; /** line number where the block was allocated/released. FFU */
+#endif
+};
+
+/* Create byte memory pool */
+bcmos_errno bcmos_blk_pool_create(bcmos_blk_pool *pool, const bcmos_blk_pool_parm *parm)
+{
+ uint32_t blk_size;
+
+ if (!pool || !parm || !parm->blk_size)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool %p, parm %p, blk_size=%u, num_blks=%u\n",
+ pool, parm, parm ? parm->blk_size : 0, parm ? parm->num_blks : 0);
+ }
+ if (parm->num_blks & parm->pool_size)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "One and only one of num_blks (%u) and pool_size (%u) must be set\n",
+ parm->num_blks, parm->pool_size);
+ }
+ if (parm->num_blks && parm->start != NULL)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "num_blks!=0 can't be used with start!=NULL. Use byte size instead\n");
+ }
+
+ BCM_MEMZERO_STRUCT(pool);
+ pool->parm = *parm;
+
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (pool->parm.name)
+ {
+ strncpy(pool->name, pool->parm.name, sizeof(pool->name) - 1);
+ pool->parm.name = pool->name;
+ }
+
+ /*
+ * Calculate total block size in bytes, including overheads
+ */
+ /* Round up block size to the nearest 32-bit word to make MAGIC check cheaper.
+ * It doesn't affect the actual overhead size because of the final
+ * rounding up to pointer size.
+ */
+ pool->parm.blk_size = BCMOS_ROUND_UP(pool->parm.blk_size, sizeof(uint32_t));
+ blk_size = pool->parm.blk_size + sizeof(bcmos_memblk);
+#ifdef BCMOS_MEM_DEBUG
+ blk_size += sizeof(uint32_t); /* room for magic after user data block */
+#endif
+ blk_size = BCMOS_ROUND_UP(blk_size, sizeof(void *));
+
+ /* Derive num_blks / pool_size from one another */
+ if (pool->parm.num_blks)
+ {
+ pool->parm.pool_size = parm->num_blks * blk_size;
+ }
+ else
+ {
+ pool->parm.num_blks = pool->parm.pool_size / blk_size;
+ if (!pool->parm.num_blks)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool_size (%u) is too small\n", parm->pool_size);
+ }
+ }
+
+ /* Allocate memory for the pool if "start" is not set */
+ pool->start = pool->parm.start;
+ if (!pool->start)
+ {
+ pool->start = bcmos_alloc(pool->parm.pool_size);
+ if (!pool->start)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "Can't allocate memory for block pool %s\n", parm->name);
+ }
+ }
+
+ bcmos_fastlock_init(&pool->lock, parm->flags);
+
+ /* Put all blocks on free list */
+ bcmos_blk_pool_reset(pool);
+
+ pool->magic = BCMOS_BLK_POOL_VALID;
+ if (!(pool->parm.flags & BCMOS_BLK_POOL_FLAG_MSG_POOL))
+ {
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&blk_pool_list, pool, list);
+ bcmos_total_blk_pool_size += pool->parm.pool_size;
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* Destroy memory pool */
+bcmos_errno bcmos_blk_pool_destroy(bcmos_blk_pool *pool)
+{
+ if (!pool || pool->magic != BCMOS_BLK_POOL_VALID)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool handle is invalid\n");
+ }
+ if (pool->stat.free < pool->parm.num_blks)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_STATE, "%i blocks are still allocated from the pool %s\n",
+ pool->parm.num_blks - pool->stat.free, pool->parm.name);
+ }
+ if (!(pool->parm.flags & BCMOS_BLK_POOL_FLAG_MSG_POOL))
+ {
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&blk_pool_list, pool, bcmos_blk_pool, list);
+ bcmos_total_blk_pool_size -= pool->parm.pool_size;
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ }
+ if (!pool->parm.start && pool->start)
+ {
+ bcmos_free(pool->start);
+ }
+ pool->magic = BCMOS_BLK_POOL_DELETED;
+ return BCM_ERR_OK;
+}
+
+/** Release all blocks in memory pool . Block content is not affected */
+void bcmos_blk_pool_reset(bcmos_blk_pool *pool)
+{
+ uint32_t blk_size;
+ bcmos_memblk *blk;
+ uint32_t i;
+
+ STAILQ_INIT(&pool->free_list);
+
+ blk_size = pool->parm.blk_size + sizeof(bcmos_memblk);
+#ifdef BCMOS_MEM_DEBUG
+ blk_size += sizeof(uint32_t); /* room for magic after user data block */
+#endif
+ blk_size = BCMOS_ROUND_UP(blk_size, sizeof(void *));
+
+ /* Put all blocks on free list */
+ blk = (bcmos_memblk *)pool->start;
+ for (i = 0; i < pool->parm.num_blks; i++)
+ {
+ blk->pool = pool;
+ STAILQ_INSERT_TAIL(&pool->free_list, blk, next);
+#ifdef BCMOS_MEM_DEBUG
+ *(uint32_t*)((long)blk + sizeof(bcmos_memblk) + pool->parm.blk_size) = BCMOS_MEM_MAGIC_SUFFIX;
+ blk->lineno = 0;
+ blk->magic = BCMOS_MEM_MAGIC_FREE;
+#endif
+ blk = (bcmos_memblk *)((long)blk + blk_size);
+ }
+
+ /* Init statistics */
+ memset(&pool->stat, 0, sizeof(pool->stat));
+ pool->stat.free = pool->parm.num_blks;
+}
+
+/* Allocate block from block memory pool */
+void *bcmos_blk_pool_alloc(bcmos_blk_pool *pool)
+{
+ bcmos_memblk *blk;
+ long flags;
+
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(!pool);
+ BUG_ON(pool->magic != BCMOS_BLK_POOL_VALID);
+#endif
+ flags = bcmos_fastlock_lock(&pool->lock);
+ blk = STAILQ_FIRST(&pool->free_list);
+ if (blk)
+ {
+ STAILQ_REMOVE_HEAD(&pool->free_list, next);
+ ++pool->stat.allocated;
+#ifdef BCMOS_MEM_DEBUG
+ blk->magic = BCMOS_MEM_MAGIC_ALLOC;
+#endif
+ bcmos_fastlock_unlock(&pool->lock, flags);
+ return (void *)(blk + 1);
+ }
+
+ /* No memory */
+ ++pool->stat.alloc_failed;
+ bcmos_fastlock_unlock(&pool->lock, flags);
+ return NULL;
+}
+
+/* Allocate block from block memory pool and zero the block */
+void *bcmos_blk_pool_calloc(bcmos_blk_pool *pool)
+{
+ void *ptr = bcmos_blk_pool_alloc(pool);
+ if (ptr)
+ {
+ memset(ptr, 0, pool->parm.blk_size);
+ }
+ return ptr;
+}
+
+/* Release memory allocated using bcmos_pool_byte_alloc() or bcmos_pool_blk_alloc() */
+void bcmos_blk_pool_free(void *ptr)
+{
+ bcmos_memblk *blk;
+ bcmos_blk_pool *pool;
+ long flags;
+
+ blk = (bcmos_memblk *)((long)ptr - sizeof(bcmos_memblk));
+ pool = blk->pool;
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(blk->magic != BCMOS_MEM_MAGIC_ALLOC);
+ BUG_ON(pool == NULL);
+ BUG_ON(pool->magic != BCMOS_BLK_POOL_VALID);
+ BUG_ON(*(uint32_t *)((long)ptr + pool->parm.blk_size) != BCMOS_MEM_MAGIC_SUFFIX);
+ blk->magic = BCMOS_MEM_MAGIC_FREE;
+#endif
+ flags = bcmos_fastlock_lock(&pool->lock);
+ STAILQ_INSERT_HEAD(&pool->free_list, blk, next);
+ ++pool->stat.released;
+ bcmos_fastlock_unlock(&pool->lock, flags);
+}
+
+/* Get pool info */
+bcmos_errno bcmos_blk_pool_query(const bcmos_blk_pool *pool, bcmos_blk_pool_info *info)
+{
+ if (!pool || !info)
+ {
+ return BCM_ERR_PARM;
+ }
+ info->parm = pool->parm;
+ info->stat = pool->stat;
+ info->stat.free = pool->parm.num_blks - (info->stat.allocated - info->stat.released);
+ return BCM_ERR_OK;
+}
+
+/* Block pool iterator */
+bcmos_errno bcmos_blk_pool_get_next(const bcmos_blk_pool **prev)
+{
+ const bcmos_blk_pool *pool;
+
+ if (prev == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ pool = *prev;
+ if (pool && pool->magic != BCMOS_BLK_POOL_VALID)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (pool)
+ {
+ pool = STAILQ_NEXT(pool, list);
+ }
+ else
+ {
+ pool = STAILQ_FIRST(&blk_pool_list);
+ }
+ *prev = pool;
+ if (!pool)
+ {
+ return BCM_ERR_NO_MORE;
+ }
+ return BCM_ERR_OK;
+}
+
+/*
+ * Message pool
+ */
+
+/* release message callback */
+static void _bcmos_msg_pool_release(bcmos_msg *msg)
+{
+ if (msg->data_release)
+ msg->data_release(msg);
+ bcmos_blk_pool_free(msg);
+}
+
+/* Create message pool */
+bcmos_errno bcmos_msg_pool_create(bcmos_msg_pool *pool, const bcmos_msg_pool_parm *parm)
+{
+ bcmos_blk_pool_parm pool_parm = {};
+ bcmos_memblk *blk;
+ bcmos_errno err;
+
+ if (!pool || !parm || !parm->size)
+ {
+ return BCM_ERR_PARM;
+ }
+ BCM_MEMZERO_STRUCT(pool);
+ pool->parm = *parm;
+ pool_parm.num_blks = parm->size;
+ pool_parm.blk_size = parm->data_size + sizeof(bcmos_msg);
+ pool_parm.flags = parm->flags | BCMOS_BLK_POOL_FLAG_MSG_POOL;
+ pool_parm.name = parm->name;
+
+ /* Create underlying block pool */
+ err = bcmos_blk_pool_create(&pool->blk_pool, &pool_parm);
+ if (err)
+ {
+ return err;
+ }
+ pool->parm.name = pool->blk_pool.name;
+
+ /* Pre-initialize all messages */
+ STAILQ_FOREACH(blk, &pool->blk_pool.free_list, next)
+ {
+ bcmos_msg *msg = (bcmos_msg *)(blk + 1);
+ msg->data = (void *)(msg + 1);
+ msg->size = pool->parm.data_size;
+ msg->release = _bcmos_msg_pool_release;
+ msg->data_release = parm->data_release;
+ }
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&msg_pool_list, &pool->blk_pool, list);
+ bcmos_total_msg_pool_size += pool->blk_pool.parm.pool_size;
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ return BCM_ERR_OK;
+}
+
+/** Destroy message pool */
+bcmos_errno bcmos_msg_pool_destroy(bcmos_msg_pool *pool)
+{
+ bcmos_errno rc;
+
+ rc = bcmos_blk_pool_destroy(&pool->blk_pool);
+ if (rc)
+ return rc;
+
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&msg_pool_list, &pool->blk_pool, bcmos_blk_pool, list);
+ bcmos_total_msg_pool_size -= pool->blk_pool.parm.pool_size;
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ pool->parm.size = pool->parm.data_size = 0;
+ return BCM_ERR_OK;
+}
+
+/* Allocate message from pool */
+bcmos_msg *bcmos_msg_pool_alloc(bcmos_msg_pool *pool)
+{
+ return bcmos_blk_pool_alloc(&pool->blk_pool);
+}
+
+/* Get pool info */
+bcmos_errno bcmos_msg_pool_query(const bcmos_msg_pool *pool, bcmos_msg_pool_info *info)
+{
+ bcmos_blk_pool_info pool_info;
+ bcmos_errno err;
+
+ if (!pool || !info)
+ {
+ return BCM_ERR_PARM;
+ }
+ err = bcmos_blk_pool_query(&pool->blk_pool, &pool_info);
+ if (err)
+ {
+ return err;
+ }
+ info->parm = pool->parm;
+ info->stat = pool_info.stat;
+ return BCM_ERR_OK;
+}
+
+/* Block pool iterator */
+bcmos_errno bcmos_msg_pool_get_next(const bcmos_msg_pool **prev)
+{
+ const bcmos_msg_pool *pool;
+
+ if (prev == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+ pool = *prev;
+ if (pool && pool->blk_pool.magic != BCMOS_BLK_POOL_VALID)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (pool)
+ {
+ pool = container_of(STAILQ_NEXT(&pool->blk_pool, list), bcmos_msg_pool, blk_pool);
+ }
+ else
+ {
+ pool = container_of(STAILQ_FIRST(&msg_pool_list), bcmos_msg_pool, blk_pool);
+ }
+ *prev = pool;
+ if (!pool)
+ {
+ return BCM_ERR_NO_MORE;
+ }
+ return BCM_ERR_OK;
+}
+
+/** Set up print redirection/cloning
+ * \param[in] mode redirection/cloning mode
+ * \param[in] cb redirection callback
+ * \param[in] data opaque data to be passed to cb
+ */
+bcmos_errno bcmos_print_redirect(bcmos_print_redirect_mode mode, bcmos_print_redirect_cb cb, void *data)
+{
+ if (mode != BCMOS_PRINT_REDIRECT_MODE_NONE && cb == NULL)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Redirection callback must be set\n");
+ }
+ print_redirect_mode = mode;
+ if (mode == BCMOS_PRINT_REDIRECT_MODE_NONE)
+ {
+ print_redirect_cb = NULL;
+ print_redirect_cb_data = NULL;
+ }
+ else
+ {
+ print_redirect_cb = cb;
+ print_redirect_cb_data = data;
+ }
+ return BCM_ERR_OK;
+}
+
+/* Print on the console with optional cloning / redirection */
+/*lint -e{454}*/
+int bcmos_vprintf(const char *format, va_list ap)
+{
+ int rc = 0;
+ bcmos_bool protected_section = is_irq_mode() || is_irq_disabled();
+
+ /* Only protect if in task context */
+ if (!protected_section)
+ {
+ bcmos_mutex_lock(&bcmos_print_lock);
+ }
+ if (print_redirect_mode != BCMOS_PRINT_REDIRECT_MODE_REDIRECT)
+ {
+ rc = bcmos_sys_vprintf(format, ap);
+ }
+ if (print_redirect_mode != BCMOS_PRINT_REDIRECT_MODE_NONE)
+ {
+ rc = print_redirect_cb(print_redirect_cb_data, format, ap);
+ }
+ if (!protected_section)
+ {
+ bcmos_mutex_unlock(&bcmos_print_lock);
+ }
+
+ return rc;
+}
+/*lint -e{454}*/
+
+/* Print on the console with optional cloning / redirection */
+int bcmos_printf(const char *format, ...)
+{
+ va_list args;
+ int rc;
+
+ va_start(args, format);
+ rc = bcmos_vprintf(format, args);
+ va_end(args);
+ return rc;
+}
+
+#ifndef BCMOS_PUTCHAR_INLINE
+/*lint -e{454}*/
+void bcmos_putchar(int c)
+{
+ bcmos_bool protected_section = is_irq_mode() || is_irq_disabled();
+
+ /* Only protect if in task context */
+ if (!protected_section)
+ {
+ bcmos_mutex_lock(&bcmos_print_lock);
+ }
+ putchar(c);
+ fflush(stdout);
+ if (!protected_section)
+ {
+ bcmos_mutex_unlock(&bcmos_print_lock);
+ }
+}
+/*lint +e{454}*/
+#endif
+
+#ifndef BCMOS_BUF_OS_SPECIFIC
+
+/*
+ * Buffer allocation/release
+ */
+
+#ifdef BCMOS_BUF_POOL_SIZE
+/** Create buffer pool
+ * \param[in] num Number of buffers
+ * \param[in] size Buffer size
+ * \param[in] align Buffer alignment
+ * \returns o=OK or error <0
+ */
+static bcmos_errno bcmos_buf_pool_create(void)
+{
+ bcmos_blk_pool_parm pool_parm =
+ {
+ .name = "sysbuf"
+ };
+ bcmos_errno rc;
+
+#ifndef BCMOS_BUF_POOL_BUF_SIZE
+#error BCMOS_BUF_POOL_BUF_SIZE must be defined
+#endif
+
+ /* If buffer memory should be allocated by bcmos_dma_alloc - allocate
+ * memory for the whole pool here */
+ pool_parm.blk_size = BCMOS_BUF_POOL_BUF_SIZE + sizeof(bcmos_buf) + BCMTR_BUF_EXTRA_HEADROOM +
+ 2*BCMOS_BUF_DATA_ALIGNMENT + BCMOS_BUF_DATA_GUARD;
+
+#ifdef BCMOS_BUF_IN_DMA_MEM
+ pool_parm.pool_size = (pool_parm.blk_size + sizeof(bcmos_memblk)) * BCMOS_BUF_POOL_SIZE;
+ pool_parm.start = bcmos_dma_alloc(0, pool_parm.pool_size);
+ if (!pool_parm.start)
+ return BCM_ERR_NOMEM;
+#else
+ pool_parm.num_blks = BCMOS_BUF_POOL_SIZE;
+#endif
+
+ rc = bcmos_blk_pool_create(&sys_buf_pool, &pool_parm);
+ if (rc)
+ {
+ if (pool_parm.start)
+ bcmos_dma_free(0, pool_parm.start);
+ }
+
+ return rc;
+}
+#endif
+
+/* Allocate buffer */
+bcmos_buf *bcmos_buf_alloc(uint32_t size)
+{
+ /* Allocate extra 2 * BCMOS_BUF_DATA_ALIGNMENT to make sure that neither data start nor end
+ * end up in the middle of cache line
+ */
+ bcmos_buf *buf;
+
+/* Allocate from the pool */
+#ifdef BCMOS_BUF_POOL_SIZE
+
+ if (size > BCMOS_BUF_POOL_BUF_SIZE)
+ {
+ BCMOS_TRACE_ERR("Attempt to allocate buffer bigger than buffer pool block size. %u > %u\n",
+ size, BCMOS_BUF_POOL_BUF_SIZE);
+ return NULL;
+ }
+ buf = bcmos_blk_pool_alloc(&sys_buf_pool);
+
+#else /* else of #if BCMOS_BUF_POOL_SIZE */
+ {
+ uint32_t alloc_size = sizeof(bcmos_buf) + size + BCMTR_BUF_EXTRA_HEADROOM +
+ 2*BCMOS_BUF_DATA_ALIGNMENT - 1 + BCMOS_BUF_DATA_GUARD;
+#ifdef BCMOS_BUF_DATA_UNIT_SIZE
+#if BCMOS_BUF_DATA_UNIT_SIZE & (BCMOS_BUF_DATA_UNIT_SIZE - 1)
+#error BCMOS_BUF_DATA_UNIT_SIZE must be a power of 2
+#endif
+ alloc_size = BCMOS_ROUND_UP(alloc_size, BCMOS_BUF_DATA_UNIT_SIZE);
+#endif
+#ifdef BCMOS_BUF_IN_DMA_MEM
+ buf = bcmos_dma_alloc(0, alloc_size);
+#else
+ buf = bcmos_alloc(alloc_size);
+#endif
+ }
+#endif /* end of #if BCMOS_BUF_POOL_SIZE */
+
+ if (!buf)
+ return NULL;
+ buf->start = (uint8_t *)(buf + 1) + BCMOS_BUF_DATA_GUARD;
+ buf->data = (uint8_t *)(BCMOS_ROUND_UP((long)buf->start + BCMTR_BUF_EXTRA_HEADROOM, BCMOS_BUF_DATA_ALIGNMENT));
+ buf->size = size + (buf->data - buf->start);
+ buf->len = 0;
+#ifdef BCMOS_BUF_POOL_SIZE
+ buf->pool = &sys_buf_pool;
+#else
+ buf->pool = NULL;
+#endif
+ return buf;
+}
+
+/* Release buffer */
+void bcmos_buf_free(bcmos_buf *buf)
+{
+
+#ifdef BCMOS_BUF_POOL_SIZE
+ /* Buffer might have been allocated from the system pool */
+ if (buf->pool)
+ {
+ bcmos_blk_pool_free(buf);
+ return;
+ }
+#endif
+
+#ifdef BCMOS_BUF_IN_DMA_MEM
+ bcmos_dma_free(0, buf);
+#else
+ bcmos_free(buf);
+#endif
+}
+
+#endif
+
+EXPORT_SYMBOL(bcmos_init);
+
+EXPORT_SYMBOL(bcmos_msg_queue_create);
+EXPORT_SYMBOL(bcmos_msg_queue_destroy);
+EXPORT_SYMBOL(bcmos_msg_queue_query);
+EXPORT_SYMBOL(bcmos_msg_queue_get_next);
+EXPORT_SYMBOL(bcmos_msg_send);
+EXPORT_SYMBOL(bcmos_msg_send_to_module);
+EXPORT_SYMBOL(bcmos_msg_recv);
+EXPORT_SYMBOL(bcmos_msg_register);
+EXPORT_SYMBOL(bcmos_msg_unregister);
+EXPORT_SYMBOL(bcmos_msg_dispatch);
+
+EXPORT_SYMBOL(bcmos_msg_qgroup_create);
+EXPORT_SYMBOL(bcmos_msg_qgroup_destroy);
+EXPORT_SYMBOL(bcmos_msg_qgroup_query);
+EXPORT_SYMBOL(bcmos_msg_recv_from_qgroup);
+EXPORT_SYMBOL(bcmos_msg_send_to_qgroup);
+
+EXPORT_SYMBOL(bcmos_task_timeout_set);
+EXPORT_SYMBOL(bcmos_task_get_next);
+
+EXPORT_SYMBOL(bcmos_module_create);
+EXPORT_SYMBOL(bcmos_module_destroy);
+EXPORT_SYMBOL(bcmos_module_current);
+EXPORT_SYMBOL(bcmos_module_context);
+EXPORT_SYMBOL(bcmos_module_context_set);
+EXPORT_SYMBOL(bcmos_module_query);
+
+EXPORT_SYMBOL(bcmos_event_create);
+EXPORT_SYMBOL(bcmos_event_destroy);
+EXPORT_SYMBOL(bcmos_event_raise);
+EXPORT_SYMBOL(bcmos_event_recv);
+
+EXPORT_SYMBOL(bcmos_timer_create);
+EXPORT_SYMBOL(bcmos_timer_destroy);
+EXPORT_SYMBOL(bcmos_timer_start);
+EXPORT_SYMBOL(bcmos_timer_stop);
+EXPORT_SYMBOL(bcmos_timer_handler_set);
+
+EXPORT_SYMBOL(bcmos_blk_pool_create);
+EXPORT_SYMBOL(bcmos_blk_pool_destroy);
+EXPORT_SYMBOL(bcmos_blk_pool_reset);
+EXPORT_SYMBOL(bcmos_blk_pool_alloc);
+EXPORT_SYMBOL(bcmos_blk_pool_calloc);
+EXPORT_SYMBOL(bcmos_blk_pool_free);
+EXPORT_SYMBOL(bcmos_blk_pool_query);
+EXPORT_SYMBOL(bcmos_blk_pool_get_next);
+
+EXPORT_SYMBOL(bcmos_msg_pool_create);
+EXPORT_SYMBOL(bcmos_msg_pool_alloc);
+EXPORT_SYMBOL(bcmos_msg_pool_query);
+EXPORT_SYMBOL(bcmos_msg_pool_destroy);
+EXPORT_SYMBOL(bcmos_msg_pool_get_next);
+
+EXPORT_SYMBOL(bcmos_print_redirect);
+EXPORT_SYMBOL(bcmos_printf);
+EXPORT_SYMBOL(bcmos_vprintf);
+
+#ifndef BCMOS_BUF_OS_SPECIFIC
+EXPORT_SYMBOL(bcmos_buf_alloc);
+EXPORT_SYMBOL(bcmos_buf_free);
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.h
new file mode 100644
index 0000000..da09c1c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common.h
@@ -0,0 +1,1479 @@
+/*
+<: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 BCMOS_COMMON_H_
+#define BCMOS_COMMON_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_common.h directly. Include bcmos_system.h
+#endif
+
+#include "bcmos_errno.h"
+#include "bcmos_types.h"
+#include "bcmos_queue.h"
+#include "bcmos_tree.h"
+/* Get constants, such as task, module, event id lists */
+#include "bcmos_platform.h"
+#include "bcmos_pack.h"
+#include "bcmos_sysif.h"
+
+#define MAX_TASK_NAME_SIZE 64
+#define MAX_MODULE_NAME_SIZE 64
+#define MAX_MSG_QUEUE_NAME_SIZE 64
+#define MAX_TIMER_NAME_SIZE 64
+#define MAX_POOL_NAME_SIZE 64
+#define MAX_EVENT_NAME_SIZE 64
+#define MAX_MUTEX_NAME_SIZE 64
+#define BCMOS_MSG_POOL_DEFAULT_SIZE 512
+
+/* Define bcmos_bool - the boolean type for bcmos - based on C99 standard boolean type */
+#ifndef BCMOS_BOOLEAN
+typedef _Bool bcmos_bool;
+#define BCMOS_FALSE 0
+#define BCMOS_TRUE 1
+#endif
+
+#define BCM_SIZEOFARRAY(arr) (sizeof(arr)/sizeof(*arr))
+#define BCM_SIZEOFFIELD(s, f) (sizeof(((s*)NULL)->f))
+#define BCM_MEMZERO_STRUCT(ptr) memset(ptr, 0, sizeof(*(ptr)))
+#define BCM_MEMCPY_ARRAY(dst, src) memcpy(dst, src, sizeof(dst))
+#define TAB " "
+#define TAB2 TAB TAB
+#define TAB3 TAB2 TAB
+#define TAB4 TAB2 TAB2
+
+#define CHIP_REVISION_A0 0xA0
+#define CHIP_REVISION_B0 0xB0
+
+#ifdef SIMULATION_BUILD
+#define GET_CHIP_REVISION CHIP_REVISION_A0
+#else
+extern uint32_t chip_revision;
+#define GET_CHIP_REVISION (chip_revision != 0 ? chip_revision : (chip_revision = get_chip_revision()))
+#endif
+
+typedef void (*f_bcmolt_sw_error_handler)(uint8_t pon_id, const char *file_name, uint32_t line_number);
+
+/* Similar to BUG_ON(), with the following features:
+ * 1. The condition is checked against BCM_ERR_OK.
+ * 2. In case on an error, the macro returns from the calling function with the error code. */
+#define BUG_ON_ERR_RET(f) \
+ do \
+ { \
+ bcmos_errno _err; \
+ _err = f; \
+ BUG_ON(_err != BCM_ERR_OK); \
+ return _err; \
+ } \
+ while (0)
+
+/** \addtogroup system_init
+ * @{
+ */
+
+/** Initialize system library
+ * Must be called before any other system function
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_init(void);
+
+/** Cleanup system library
+ */
+void bcmos_exit(void);
+
+/** @} system_init */
+
+/** \addtogroup system_mem
+ * @{
+ */
+
+#ifndef BCMOS_MALLOC_FREE_INLINE
+
+/** \defgroup system_heap Default Heap
+ * @{
+ */
+
+/** Allocate memory from the main heap
+ * \param[in] size
+ * \returns memory block pointer or NULL
+ */
+void *bcmos_alloc(uint32_t size);
+
+/** Release memory to the main pool
+ * \param[in] ptr
+ */
+void bcmos_free(void *ptr);
+
+/** @} system_heap */
+
+#endif /* #ifndef BCMOS_MALLOC_FREE_INLINE */
+
+/** \defgroup blk_pool Block Memory Pool
+ * \ingroup system_mem
+ * @{
+ */
+
+/** Block memory pool parameters */
+typedef struct
+{
+ const char *name; /**< Pool name */
+ uint32_t blk_size; /**< Memory block size > 0 */
+ uint32_t num_blks; /**< Number of blocks in the pool. If not set - it is derived from pool_size */
+ void *start; /**< Start address. Can be NULL */
+ uint32_t pool_size; /**< Total pool size in bytes. Only 1 of pool_size, num_blks must be set */
+ uint32_t flags; /**< TBD flags */
+#define BCMOS_BLK_POOL_FLAG_MSG_POOL 0x80000000 /* Used by message pool */
+} bcmos_blk_pool_parm;
+
+/** Block memory pool statistics */
+typedef struct bcmos_blk_pool_stat
+{
+ uint32_t allocated; /**< Number of blocks allocated */
+ uint32_t released; /**< Number of blocks released */
+ uint32_t free; /**< Number of free blocks in the pool */
+ uint32_t alloc_failed; /**< Number of allocation failures */
+} bcmos_blk_pool_stat;
+
+/** Block memory pool info */
+typedef struct bcmos_blk_pool_info
+{
+ bcmos_blk_pool_parm parm; /**< Pool parameters */
+ bcmos_blk_pool_stat stat; /**< Pool statistics */
+} bcmos_blk_pool_info;
+
+/** Block memory pool control block */
+typedef struct bcmos_blk_pool bcmos_blk_pool;
+
+/** Create block memory pool
+ * \param[in,out] pool pool control block
+ * \param[in] parm pool parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_blk_pool_create(bcmos_blk_pool *pool, const bcmos_blk_pool_parm *parm);
+
+/** Destroy block memory pool
+ * \param[in] pool pool handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_blk_pool_destroy(bcmos_blk_pool *pool);
+
+/** Allocate block from block memory pool
+ *
+ * This allocates a single unit (unit_size bytes)
+ * \param[in] pool Pool handle
+ * \return memory block pointer or NULL.
+ * It is guaranteed that the returned pointer is aligned to pointer size
+ */
+void *bcmos_blk_pool_alloc(bcmos_blk_pool *pool);
+
+/** Allocate block from block memory pool and zero the block
+ *
+ * This allocates a single unit (unit_size bytes)
+ * \param[in] pool Pool handle
+ * \return memory block pointer or NULL.
+ * It is guaranteed that the returned pointer is aligned to pointer size
+ */
+void *bcmos_blk_pool_calloc(bcmos_blk_pool *pool);
+
+/** Release memory allocated using bcmos_blk_pool_alloc()
+ *
+ * \param[in] ptr pointer
+ */
+void bcmos_blk_pool_free(void *ptr);
+
+/** Release all blocks in memory pool. Block content is not affected
+ * This function is useful when application wants to pre-initialize
+ * some portion of each memory block at init time
+ *
+ * \param[in] pool Pool handle
+ */
+void bcmos_blk_pool_reset(bcmos_blk_pool *pool);
+
+/** Get pool info
+ *
+ * The pool must be created using bcmos_blk_pool_create()
+ * \param[in] pool Block memory pool handle
+ * \param[out] info Block memory pool info
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_blk_pool_query(const bcmos_blk_pool *pool, bcmos_blk_pool_info *info);
+
+/** Block pool iterator
+ * \param[in] prev Previous block pool. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_blk_pool_get_next(const bcmos_blk_pool **prev);
+
+/** @} blk_pool */
+
+/** \defgroup byte_pool Byte Memory Pool
+ * \ingroup system_mem
+ * @{
+ */
+
+/** Byte memory pool parameters */
+typedef struct
+{
+ const char *name; /**< Pool name */
+ uint32_t size; /**< Pool size (bytes) */
+ void *start; /**< Start address. Can be NULL */
+} bcmos_byte_pool_parm;
+
+/** Byte memory pool control block */
+typedef struct bcmos_byte_pool bcmos_byte_pool;
+
+/** Create byte memory pool
+ * \param[in,out] pool pool control block
+ * \param[in] parm pool parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm);
+
+/** Destroy byte memory pool
+ * \param[in] pool pool handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool);
+
+#ifndef BCMOS_BYTE_POOL_ALLOC_FREE_INLINE
+/** Allocate memory from byte memory pool
+ *
+ * This function can only be used with byte memory pools created
+ * with unit_size==1
+ * \param[in] pool Pool handle
+ * \param[in] size Block size (bytes)
+ * \return memory block pointer or NULL
+ */
+void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size);
+
+/** Release memory allocated using bcmos_pool_byte_alloc()
+ *
+ * \param[in] ptr pointer
+ */
+void bcmos_byte_pool_free(void *ptr);
+
+#endif /* BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */
+
+/** @} byte_pool */
+
+/** @} system_mem */
+
+/** \addtogroup system_task
+ * @{
+ */
+#ifndef BCMOS_WAIT_FOREVER
+#define BCMOS_WAIT_FOREVER 0xFFFFFFFF /**< Wait timeout. Wait forever */
+#endif
+#ifndef BCMOS_NO_WAIT
+#define BCMOS_NO_WAIT 0 /**< Wait timeout. Don't wait */
+#endif
+#define BCMOS_MICROSECONDS_IN_SECONDS (1000000)
+
+/** Task priority */
+typedef enum
+{
+ BCMOS_TASK_PRIORITY_0, /**< Priority 0 - highest */
+ BCMOS_TASK_PRIORITY_1, /**< Priority 1 */
+ BCMOS_TASK_PRIORITY_2, /**< Priority 2 */
+ BCMOS_TASK_PRIORITY_3, /**< Priority 3 */
+ BCMOS_TASK_PRIORITY_4, /**< Priority 4 */
+ BCMOS_TASK_PRIORITY_5, /**< Priority 5 */
+ BCMOS_TASK_PRIORITY_6, /**< Priority 6 */
+ BCMOS_TASK_PRIORITY_7, /**< Priority 7 */
+ BCMOS_TASK_PRIORITY_8, /**< Priority 8 */
+ BCMOS_TASK_PRIORITY_9, /**< Priority 9 */
+ BCMOS_TASK_PRIORITY_10,/**< Priority 10 */
+ BCMOS_TASK_PRIORITY_11,/**< Priority 11 */
+ BCMOS_TASK_PRIORITY_12,/**< Priority 12 */
+ BCMOS_TASK_PRIORITY_13,/**< Priority 13 */
+ BCMOS_TASK_PRIORITY_14,/**< Priority 14 */
+ BCMOS_TASK_PRIORITY_15,/**< Priority 15 */
+ BCMOS_TASK_PRIORITY_16,/**< Priority 16 */
+ BCMOS_TASK_PRIORITY_17,/**< Priority 17 */
+ BCMOS_TASK_PRIORITY_18,/**< Priority 18 */
+ BCMOS_TASK_PRIORITY_19,/**< Priority 19 */
+ BCMOS_TASK_PRIORITY_20,/**< Priority 20 */
+ BCMOS_TASK_PRIORITY_21,/**< Priority 21 */
+ BCMOS_TASK_PRIORITY_22,/**< Priority 22 */
+ BCMOS_TASK_PRIORITY_23,/**< Priority 23 */
+ BCMOS_TASK_PRIORITY_24,/**< Priority 24 */
+ BCMOS_TASK_PRIORITY_25,/**< Priority 25 */
+ BCMOS_TASK_PRIORITY_26,/**< Priority 26 */
+ BCMOS_TASK_PRIORITY_27,/**< Priority 27 */
+ BCMOS_TASK_PRIORITY_28,/**< Priority 28 */
+ BCMOS_TASK_PRIORITY_29,/**< Priority 29 */
+ BCMOS_TASK_PRIORITY_30,/**< Priority 30 */
+ BCMOS_TASK_PRIORITY_31,/**< Priority 31 - lowest */
+} bcmos_task_priority;
+
+/** Task handler */
+typedef int (*F_bcmos_task_handler)(long data);
+
+/* Default task handler */
+extern int bcmos_dft_task_handler(long data);
+
+/* This flags determines whether a task is to be suspended upon OOPS condition. */
+#define BCMOS_TASK_FLAG_NO_SUSPEND_ON_OOPS (1 << 0)
+
+/** Task parameters */
+typedef struct
+{
+ const char *name; /**< Task name */
+ bcmos_task_priority priority; /**< Task priority */
+ bcmos_core core; /**< CPU core the task is locked to */
+ uint32_t stack_size; /**< Task stack size */
+ void *stack; /**< Stack location. NULL=allocate automatically */
+ F_bcmos_task_handler init_handler; /**< Optional "init" handler. Called once in the task context when it is created.
+ This callback is only supported in integration mode (handler==NULL).
+ init_handler returns bcmos_errno. If it returns value other than BCM_ERR_OK,
+ the task is destroyed */
+ F_bcmos_task_handler handler; /**< Task handler. NULL=default (integration mode) */
+ F_bcmos_task_handler timeout_handler;/**< This function is used only in integration mode (handler==NULL) if
+ msg_wait_timeout is > 0. It is called if there were no messages for the task
+ for longer than msg_wait_timeout us.
+ If timeout handler returns value other than BCM_ERR_OK, task terminates.
+ */
+ uint32_t msg_wait_timeout; /**< This parameter is used only in integration mode (handler==NULL) together with
+ timeout_handler. If > 0 and there were no messages for longer than
+ msg_wait_timeout us, timeout_handler is called.
+ */
+ long data; /**< Data passed to the task handler */
+ uint32_t flags; /**< flags */
+} bcmos_task_parm;
+
+/** Task control block */
+typedef struct bcmos_task bcmos_task;
+
+/** Create a new task
+ *
+ * \param[in,out] task Task control block
+ * \param[in] parm Task parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm);
+
+/** Set task timeout
+ *
+ * This function is only used in integration mode (handler==NULL).
+ * It sets max time the default task handler waits for message directed to one of the
+ * task's modules.
+ *
+ * \param[in,out] task Task control block
+ * \param[in] timeout Max time (us) to wait for messages. 0=FOREVER
+ * Changing timeout from infinite to finite only takes effect
+ * after message is received by any task module.
+ * \param[in] timeout_handler Handler to be called upon timeout. Must be != NULL if timeout > 0.
+ * If the handler returns error (!= BCM_ERR_OK), task terminates.
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_task_timeout_set(bcmos_task *task, uint32_t timeout, F_bcmos_task_handler timeout_handler);
+
+/** Destroy task
+ *
+ * \param[in] task Task handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_task_destroy(bcmos_task *task);
+
+/** Get current task
+ * \returns task handle or NULL if not in task context
+ */
+bcmos_task *bcmos_task_current(void);
+
+/** Query task info
+ * \param[in] task Task control block
+ * \param[out] parm Task parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_task_query(const bcmos_task *task, bcmos_task_parm *parm);
+
+/** Task iterator
+ * \param[in] prev Previous task. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_task_get_next(bcmos_task **prev);
+
+
+/** @} system_task */
+
+/** \addtogroup system_msg
+ * @{
+ */
+
+/** Message header */
+typedef struct bcmos_msg bcmos_msg;
+
+/** Message queue control block */
+typedef struct bcmos_msg_queue bcmos_msg_queue;
+
+/** Message queue group control block */
+typedef struct bcmos_msg_qgroup bcmos_msg_qgroup;
+
+#if defined(BCMOS_MSG_QUEUE_DOMAIN_SOCKET) || defined(BCMOS_MSG_QUEUE_UDP_SOCKET) || defined(BCMOS_MSG_QUEUE_USER_DEFINED)
+#define BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+#endif
+
+/** Message queue endpoint type */
+typedef enum
+{
+ BCMOS_MSG_QUEUE_EP_LOCAL, /**< Local endpoint (inter-thread communication) */
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+ BCMOS_MSG_QUEUE_EP_DOMAIN_SOCKET, /**< Domain-socket based endpoint */
+#endif
+#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
+ BCMOS_MSG_QUEUE_EP_UDP_SOCKET, /**< UDP socket-based endpoint */
+#endif
+#ifdef BCMOS_MSG_QUEUE_USER_DEFINED
+ BCMOS_MSG_QUEUE_EP_USER_DEFINED /**< User-defined endpoint */
+#endif
+} bcmos_msg_queue_ep_type;
+
+
+/** Message queue parameters */
+typedef struct
+{
+ const char *name; /**< Queue name (for logging and debugging) */
+ uint32_t size; /**< Max queue size. 0=unlimited */
+ uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */
+ uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */
+ uint32_t flags; /**< TBD flags. For example, single-core, m-core */
+ void (*notify)(bcmos_msg_queue *q, const char *txt); /***< Called when queue congestion state changes */
+ bcmos_msg_queue_ep_type ep_type; /**< Queue endpoint type */
+
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ /* Remote message queue support allows queue endpoints to be located in
+ * different processes or even processors.
+ */
+ const char *local_ep_address; /**< Queue local endpoint address */
+ const char *remote_ep_address; /**< Queue local endpoint address */
+
+ uint32_t max_mtu; /**< Max MTU size */
+#define BCMOS_MSG_QUEUE_DEFAULT_MAX_MTU (64*1024)
+
+ /** Optional "pack" callback. Not needed if 2 processes are on the same core. */
+ bcmos_errno (*pack)(bcmos_msg_queue *queue, bcmos_msg *msg, uint8_t **buf, uint32_t *buf_length);
+
+ /** Optional "unpack" callback. Not needed if 2 processes are on the same core. */
+ bcmos_errno (*unpack)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length, bcmos_msg **msg);
+
+ /** Optional callback that releases packed buffer */
+ void (*free_packed)(bcmos_msg_queue *queue, uint8_t *buf);
+
+ /** Optional "open" callback. Must be set for user-defined queue, NULL otherwise */
+ bcmos_errno (*open)(bcmos_msg_queue *queue);
+
+ /** Optional "close" callback. Must be set for user-defined queue, NULL otherwise */
+ bcmos_errno (*close)(bcmos_msg_queue *queue);
+
+ /** Optional "send" callback. Must be set for user-defined queue, NULL otherwise */
+ bcmos_errno (*send)(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length);
+
+ /** Optional "recv" callback. Must be set for user-defined queue, NULL otherwise */
+ bcmos_errno (*recv)(bcmos_msg_queue *queue, uint32_t timeout, uint8_t **buf, uint32_t *buf_length);
+#endif
+
+} bcmos_msg_queue_parm;
+
+/** Message queue statistics */
+typedef struct
+{
+ uint32_t msg_in; /**< Number of messages currently in the queue */
+ uint32_t msg_sent; /**< Number of messages successfully submitted into the queue */
+ uint32_t msg_received; /**< Number of messages received from the queue */
+ uint32_t msg_discarded; /**< Number of messages discarded because of queue overflow */
+ uint32_t msg_almost_full; /**< Number of messages submitted to queue when it was above high water mark */
+ bcmos_bool is_congested; /**< True=the queue is currently congested */
+} bcmos_msg_queue_stat;
+
+/** Message queue info */
+typedef struct
+{
+ bcmos_msg_queue_parm parm; /**< Queue parameters */
+ bcmos_msg_queue_stat stat; /**< Queue statistics */
+} bcmos_msg_queue_info;
+
+/** Message priority in queue group */
+typedef uint32_t bcmos_qgroup_prty;
+
+/** Message queue group parameters */
+typedef struct
+{
+ const char *name; /**< Queue group name (for logging and debugging) */
+ bcmos_qgroup_prty nqueues; /**< Number of queues in the group */
+ uint32_t size; /**< Total number of messages that can be stored in queue group. 0=unlimited */
+ uint32_t high_wm; /**< Optional high water mark. Log is generated when queue occupancy exceeds hwm */
+ uint32_t low_wm; /**< Optional low water mark. Log is generated when queue occupancy drops below lwm */
+ uint32_t flags; /**< TBD flags. For example, single-core, m-core */
+ void (*notify)(bcmos_msg_qgroup *qgrp, const char *txt); /***< Called when queue group congestion state changes */
+} bcmos_msg_qgroup_parm;
+
+/** Message queue group info */
+typedef struct
+{
+ bcmos_msg_qgroup_parm parm; /**< Queue group parameters */
+ bcmos_msg_queue_stat stat; /**< Queue group statistics */
+} bcmos_msg_qgroup_info;
+
+/** Message recipient instance (e.g., optical link id) */
+typedef uint16_t bcmos_msg_instance;
+
+/** Message send flags */
+typedef enum
+{
+ BCMOS_MSG_SEND_AUTO_FREE = 0x00000000, /**< Automatically release message in case of error. This is the default behaviour */
+ BCMOS_MSG_SEND_NO_FREE_ON_ERROR =0x00000001,/**< Do NOT free message in case of transmit error */
+ BCMOS_MSG_SEND_URGENT = 0x00000002, /**< Urgent message */
+ BCMOS_MSG_SEND_NOLIMIT = 0x00000004, /**< Ignore destination queue size limit */
+} bcmos_msg_send_flags;
+
+/** Registered message handler */
+typedef void (*F_bcmos_msg_handler)(bcmos_module_id module_id, bcmos_msg *msg);
+typedef bcmos_errno (*F_bcmos_module_init)(long data);
+typedef void (*F_bcmos_module_exit)(long data);
+
+/** Message header */
+struct bcmos_msg
+{
+ bcmos_msg_id type; /**< Message type */
+ bcmos_msg_instance instance;/**< Message recipient instance (e.g., optical link id) */
+ F_bcmos_msg_handler handler;/**< Message handler. Can be set by the sender or message dispatcher */
+ bcmos_module_id sender; /**< Sender module */
+ STAILQ_ENTRY(bcmos_msg) next; /**< Next message pointer */
+ void *data; /**< Message data pointer */
+ void *start; /**< Message data block start (for release) */
+ uint32_t size; /**< Message data size */
+ bcmos_msg_send_flags send_flags; /**< Flags the message was sent with */
+#define BCMOS_MSG_QUEUE_SIZE_UNLIMITED 0xFFFFFFFF /**< Unlimited queue */
+ void (*release)(bcmos_msg *); /**< Release callback */
+ void (*data_release)(bcmos_msg *); /**< Data release callback. Used when message is released to message pool */
+};
+
+/* Helper functions that pack / unpack message header for IPC */
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+
+/** Size of message header on the line for IPC */
+#define BCMOS_MSG_HDR_SIZE 8
+
+void bcmos_msg_hdr_pack(const bcmos_msg *msg, uint8_t *buf, uint32_t data_size);
+void bcmos_msg_hdr_unpack(const uint8_t *buf, bcmos_msg *msg);
+
+#endif
+
+/** Create message queue.
+ *
+ * This function can be called explicitly in "traditional" mode
+ * or implicitly by bcmos_module_create().
+ * \param[in,out] queue Queue control block
+ * \param[in] parm Queue parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_queue_create(bcmos_msg_queue *queue, const bcmos_msg_queue_parm *parm);
+
+/** Destroy queue
+ *
+ * \param[in] queue Queue handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_queue_destroy(bcmos_msg_queue *queue);
+
+/** Get queue info
+ *
+ * \param[in] queue Queue handle
+ * \param[out] info Queue information
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_queue_query(const bcmos_msg_queue *queue, bcmos_msg_queue_info *info);
+
+/** Message queue iterator
+ * \param[in] prev Previous queue. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_msg_queue_get_next(const bcmos_msg_queue **prev);
+
+/** Create message queue group.
+ *
+ * Queue group contains configurable number of queues. The queues are drained
+ * in strict priority. Priority 0 is the highest.
+ *
+ * \param[in,out] qgroup Queue group control block
+ * \param[in] parm Queue group parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_qgroup_create(bcmos_msg_qgroup *qgroup, const bcmos_msg_qgroup_parm *parm);
+
+/** Destroy queue group
+ *
+ * \param[in] qgroup Queue group handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_qgroup_destroy(bcmos_msg_qgroup *qgroup);
+
+/** Get queue group info
+ *
+ * \param[in] qgroup Queue group handle
+ * \param[out] info Queue group information
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_qgroup_query(const bcmos_msg_qgroup *qgroup, bcmos_msg_qgroup_info *info);
+
+/** Message queue group iterator
+ * \param[in] prev Previous queue group. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_msg_qgroup_get_next(const bcmos_msg_qgroup **prev);
+
+/** Send message to queue
+ *
+ * \param[in] queue Queue handle
+ * \param[in] msg Message
+ * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
+ *
+ * msg is released automatically regardless of bcmos_msg_send() outcome, unless
+ * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
+ *
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_send(bcmos_msg_queue *queue, bcmos_msg *msg, bcmos_msg_send_flags flags);
+
+/** Send message to module
+ *
+ * For module to be able to receive the message, it must be registered
+ * using bcmos_msg_register()
+ *
+ * \param[in] module_id Module id
+ * \param[in] msg Message. msg->handler must be set
+ * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
+ *
+ * msg is released automatically regardless of bcmos_msg_send_to_module() outcome, unless
+ * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
+ *
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_send_to_module(bcmos_module_id module_id, bcmos_msg *msg, bcmos_msg_send_flags flags);
+
+/** Send message to queue group
+ *
+ * \param[in] qgroup Queue group handle
+ * \param[in] msg Message
+ * \param[in] prty Message priority in range 0-nqueues_in_group-1.
+ * 0 priority is the highest. If MAX number of messages are already queues
+ * in the queue group, sending message can leave to discard of the head message
+ * queued at lower priority
+ * \param[in] flags BCMOS_MSG_SEND_AUTO_FREE or BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag
+ *
+ *
+ * msg is released automatically regardless of bcmos_msg_send_to_qgroup() outcome, unless
+ * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
+ *
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_send_to_qgroup(bcmos_msg_qgroup *qgroup, bcmos_msg *msg, bcmos_qgroup_prty prty,
+ bcmos_msg_send_flags flags);
+
+/** Get message from the head of message queue
+ *
+ * The function can lead to the calling task being suspended for a period
+ * of time or indefinitely, until message is submitted to the queue.\n
+ * The function is only used in "traditional tasks" (see \ref system_model).
+ *
+ * \param[in] queue Queue handle
+ * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
+ * \param[out] msg Message handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, bcmos_msg **msg);
+
+/** Get highest priority message from queue group
+ *
+ * The function can lead to the calling task being suspended for a period
+ * of time or indefinitely, until message is submitted to the queue group.\n
+ * The function is only used in "traditional tasks" (see \ref system_model).
+ *
+ * \param[in] qgroup Queue group handle
+ * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
+ * \param[out] msg Message handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_recv_from_qgroup(bcmos_msg_qgroup *qgroup, uint32_t timeout, bcmos_msg **msg);
+
+/** Dispatch message. Send to module that registered for it.
+ *
+ * The message must be registered using bcmos_msg_register()
+ *
+ * This function should be used if the message sender doesn't know the target module and/or
+ * message handling callback.
+ *
+ * \param[in] msg Message handle
+ * \param[in] flags flags. Combination of \ref bcmos_msg_send_flags bits
+ *
+ * msg is released automatically regardless of bcmos_msg_dispatch() outcome, unless
+ * BCMOS_MSG_SEND_NO_FREE_ON_ERROR flag is set.
+ *
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_dispatch(bcmos_msg *msg, bcmos_msg_send_flags flags);
+
+/** Register message for "push-mode" delivery.
+ *
+ * When registered message is sent to the target module and
+ * the module's task wakes up, message handler is called in the module's context.
+ *
+ * \param[in] msg_type Message type
+ * \param[in] instance Message type instance
+ * \param[in] module_id Target module id
+ * \param[in] handler Message handler
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_register(bcmos_msg_id msg_type, bcmos_msg_instance instance,
+ bcmos_module_id module_id, F_bcmos_msg_handler handler);
+
+/** Un-register message registered by bcmos_msg_register()
+ *
+ * \param[in] msg_type Message type
+ * \param[in] instance Message type instance
+ * \param[in] module_id Target module id
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_unregister(bcmos_msg_id msg_type, bcmos_msg_instance instance,
+ bcmos_module_id module_id);
+
+/** Put the OS message infrastructure in "shutdown mode".
+ *
+ * When in shutdown mode, bcmos_msg_dispatch() will return BCM_ERR_OK instead of BCM_ERR_NOENT when a handler is not
+ * found for the message. Additionally, bcmos_msg_dispatch() becomes safe to call concurrently with
+ * bcmos_msg_unregister() (this is not true in normal operation).
+ *
+ * \param[in] shutdown_mode Whether or not to enable shutdown mode
+ */
+void bcmos_msg_shutdown_mode_set(bcmos_bool shutdown_mode);
+
+/** Gets whether or not the OS message infrastructure is currently in "shutdown mode".
+ * \returns BCMOS_TRUE if we are in shutdown mode, BCMOS_FALSE otherwise
+ */
+bcmos_bool bcmos_msg_shutdown_mode_get(void);
+
+/** Helper type for storing message types alongside their handlers. */
+typedef struct
+{
+ bcmos_msg_id msg_type;
+ F_bcmos_msg_handler handler;
+} bcmos_msg_id2handler;
+
+/** Message pool */
+typedef struct bcmos_msg_pool bcmos_msg_pool;
+
+/** Message pool parameters */
+typedef struct bcmos_msg_pool_parm
+{
+ const char *name; /**< Pool name */
+ uint32_t size; /**< Number of messages in the pool */
+ uint32_t data_size; /**< Message data size */
+ uint32_t flags; /**< TBD flags */
+ void (*data_release)(bcmos_msg *msg); /**< Optional data release callback. Called when message is released to the pool */
+} bcmos_msg_pool_parm;
+
+/** Message pool statistics */
+typedef bcmos_blk_pool_stat bcmos_msg_pool_stat;
+
+/** Message pool info */
+typedef struct bcmos_msg_pool_info
+{
+ bcmos_msg_pool_parm parm; /**< Pool parameters */
+ bcmos_msg_pool_stat stat; /**< Pool statistics */
+} bcmos_msg_pool_info;
+
+/** Create message pool
+ *
+ * Create pool containing pre-allocated messages with specified data size
+ * \param[in] pool Message pool handle
+ * \param[in] parm Message pool parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_pool_create(bcmos_msg_pool *pool, const bcmos_msg_pool_parm *parm);
+
+/** Destroy message pool
+ *
+ * All messages must be released to the pool before it can be destroyed.
+ *
+ * \param[in] pool Message pool handle
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_pool_destroy(bcmos_msg_pool *pool);
+
+/** Allocate message from pool
+ *
+ * The pool must be created using bcmos_pool_create()
+ * \param[in] pool Message pool handle
+ * \returns msg pointer or NULL if the pool is empty.
+ * "data" and "release" fields in the returned message are pre-set
+ * Once no longer needed, the message must be released using bcmos_msg_free()
+ */
+bcmos_msg *bcmos_msg_pool_alloc(bcmos_msg_pool *pool);
+
+/** Allocate message from pool and clear data
+ *
+ * The pool must be created using bcmos_pool_create()
+ * \param[in] pool Message pool handle
+ * \returns msg pointer or NULL if the pool is empty.
+ * "data" and "release" fields in the returned message are pre-set
+ * Once no longer needed, the message must be released using bcmos_msg_free()
+ */
+static inline bcmos_msg *bcmos_msg_pool_calloc(bcmos_msg_pool *pool)
+{
+ bcmos_msg *msg = bcmos_msg_pool_alloc(pool);
+ if (msg)
+ {
+ memset(msg->data, 0, msg->size);
+ }
+ return msg;
+}
+
+/** Get pool info
+ *
+ * The pool must be created using bcmos_pool_create()
+ * \param[in] pool Message pool handle
+ * \param[out] info Message pool info
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_msg_pool_query(const bcmos_msg_pool *pool, bcmos_msg_pool_info *info);
+
+/** Message pool iterator
+ * \param[in] prev Previous message pool. *prev==NULL - get first
+ * \return: BCM_ERR_OK, BCM_ERR_NOENT, BCM_ERR_NO_MORE
+ */
+bcmos_errno bcmos_msg_pool_get_next(const bcmos_msg_pool **prev);
+
+/** @} system_msg */
+
+/** \addtogroup system_module
+ * @{
+ */
+
+/** Max number of modules per task. Must be <= 32 */
+#define BCMOS_MAX_MODULES_PER_TASK 8
+
+/** Module parameters */
+typedef struct
+{
+ bcmos_msg_queue_parm qparm; /**< Message queue paramaters */
+ F_bcmos_module_init init; /**< Init callback */
+ F_bcmos_module_exit exit; /**< Exit callback */
+ long data; /**< Module context initial value. Also passed to init and exit callbacks */
+} bcmos_module_parm;
+
+/** Module control block */
+typedef struct bcmos_module bcmos_module;
+
+/** Register module
+ *
+ * \param[in] module_id Module id
+ * \param[in] task Owner task ID
+ * \param[in] parm Module parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_module_create(bcmos_module_id module_id, bcmos_task *task, bcmos_module_parm *parm);
+
+/** Un-register module
+ *
+ * \param[in] module_id Module id
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_module_destroy(bcmos_module_id module_id);
+
+/** Get current module id in the current task
+ *
+ * \returns module_id
+ */
+bcmos_module_id bcmos_module_current(void);
+
+/** Get module context
+ *
+ * Module context is initialized as module_parm.data and can be modified using
+ * bcmos_module_context_set()
+ *
+ * \param[in] module_id Module_id
+ * \returns context pointer set by bcmos_module_context_set() or
+ *
+ * NULL if module_id is invalid or context is not set.
+ */
+void *bcmos_module_context(bcmos_module_id module_id);
+
+/** Set module context
+ *
+ * Context is an arbitrary structure used to store module-specific data.
+ * Usually this function is called from module init() callback
+ *
+ * \param[in] module_id Module_id
+ * \param[in] context Module context pointer
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_module_context_set(bcmos_module_id module_id, void *context);
+
+/* module control blocks */
+extern bcmos_module *bcmos_modules[BCMOS_MODULE_ID__NUM_OF];
+
+static inline bcmos_module *_bcmos_module_get(bcmos_module_id module_id)
+{
+ bcmos_module *module = bcmos_modules[module_id];
+ if ((unsigned)module_id >= BCMOS_MODULE_ID__NUM_OF)
+ return NULL;
+ return module;
+}
+
+/** Query module
+ *
+ * \param[in] module_id Module_id
+ * \param[out] task Task that owns the module
+ * \param[out] info Module queue info
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_module_query(bcmos_module_id module_id, const bcmos_task **task, bcmos_msg_queue_info *info);
+
+/** @} system_module */
+
+/** \addtogroup system_event
+ * @{
+ */
+
+/** Registered event handler */
+typedef void (*F_bcmos_event_handler)(bcmos_event_id event_id, uint32_t active_bits);
+
+/** Event parameters */
+typedef struct
+{
+ const char *name; /**< Event set name */
+ bcmos_module_id module_id; /**< Module id. The module must be registered */
+ uint32_t mask; /**< Event bits module is interested in */
+ F_bcmos_event_handler handler; /**< Event handler. Called in module's context */
+ uint32_t flags; /**< TBD flags. E.g., inter-core */
+} bcmos_event_parm;
+
+/** Event control block */
+typedef struct bcmos_event bcmos_event;
+
+/** Create event set
+ *
+ * \param[in] event_id Event set id
+ * \param[in] parm Event parameters. Used in "integration" mode. NULL in "traditional" mode
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_event_create(bcmos_event_id event_id, bcmos_event_parm *parm);
+
+/** Destroy event set created by bcmos_event_create()
+ *
+ * \param[in] event_id Event set id
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_event_destroy(bcmos_event_id event_id);
+
+/** Raise event
+ *
+ * Raised event is delivered to module(s) that registered for it
+ * using bcmos_event_register() or to the task waiting for event
+ * using bcmos_event_recv()
+ *
+ * \param[in] event_id Event set id
+ * \param[in] active_bits Active bit mask
+ * \returns 0=OK or error code <0. Can only fail if event is not registered
+ */
+bcmos_errno bcmos_event_raise(bcmos_event_id event_id, uint32_t active_bits);
+
+/** Wait for event
+ *
+ * This function is used in "traditional" mode.\n
+ * The caller can block for a time or indefinitely
+ *
+ * \param[in] event_id Event set id
+ * \param[in] mask Interesting bits. The functions returns when
+ * - timeout expires
+ * - event with (active_bits & mask) != 0 is raised
+ * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
+ * \param[out] active_bits active bits in the event set. valid only if the function returns 0
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_event_recv(bcmos_event_id event_id, uint32_t mask,
+ uint32_t timeout, uint32_t *active_bits);
+
+/* Event set array */
+extern bcmos_event *bcmos_events[BCMOS_EVENT_ID__NUM_OF];
+
+/* Get event givern the event id */
+static inline bcmos_event *_bcmos_event_get(bcmos_event_id event_id)
+{
+ bcmos_event *ev = bcmos_events[event_id];
+ if ((unsigned)event_id >= BCMOS_EVENT_ID__NUM_OF)
+ return NULL;
+ return ev;
+}
+
+/** @} system_event */
+
+/** \addtogroup system_timer
+ * @{
+ */
+
+/** Max timer duration (us) */
+#define BCMOS_MAX_TIMER_DURATION 0x80000000
+
+/** Timer control block */
+typedef struct bcmos_timer bcmos_timer;
+
+/** Timer handler completion code */
+typedef enum
+{
+ BCMOS_TIMER_OK, /**< Restart timer if periodic or keep stopped if not */
+ BCMOS_TIMER_STOP /**< Do not restart periodic timer */
+} bcmos_timer_rc;
+
+/** Timer handler
+ * \param[in] timer Expired timer handle
+ * \param[in] data User data supplied at timer creation time
+ * \returns \ref bcmos_timer_rc
+ */
+typedef bcmos_timer_rc (*F_bcmos_timer_handler)(bcmos_timer *timer, long data);
+
+typedef enum
+{
+ BCMOS_TIMER_PARM_FLAGS_URGENT = 0, /**< Default behavior. If the timer owner is set, timer expiration
+ will be delivered as an urgent message. */
+ BCMOS_TIMER_PARM_FLAGS_NON_URGENT = 1 << 0, /**< If the timer owner is set, timer expiration will be delivered as
+ a normal (non-urgent) message. */
+} bcmos_timer_parm_flags;
+
+/** Timer parameters */
+typedef struct
+{
+ const char *name; /**< Timer name */
+ bcmos_module_id owner; /**< Timer owner. If set, timer expiration is delivered to the module
+ as a message */
+ bcmos_bool periodic; /**< TRUE=periodic */
+ F_bcmos_timer_handler handler; /**< Timer handler. Called in context of owner module
+ if set or timer ISR if owner==BCMOS_MODULE_ID_NONE */
+ long data; /**< data to pass to the handler */
+ bcmos_timer_parm_flags flags; /**< Flags to change the behavior of the timer */
+} bcmos_timer_parm;
+
+#ifndef BCMOS_TIMESTAMP_INLINE
+
+/** Get current timestamp
+ * \returns the current system timestamp (us)
+ */
+uint32_t bcmos_timestamp(void);
+
+/** Get current 64 bit timestamp
+ * \returns the current system timestamp (us)
+ * \note There is no guarantee that all 64 bit carry information.
+ * However, it is guaranteed that the timestamp wraps around
+ * not oftener than every 50 days (ms resolution)
+ */
+uint64_t bcmos_timestamp64(void);
+
+#endif /* #ifndef BCMOS_TIMESTAMP_INLINE */
+
+/** Create timer
+ *
+ * \param[in,out] timer timer control block
+ * \param[in] parm timer parameters
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_timer_create(bcmos_timer *timer, bcmos_timer_parm *parm);
+
+/** Destroy timer
+ * The timer is stopped if running and destroyed
+ * \param[in] timer timer handle
+ */
+void bcmos_timer_destroy(bcmos_timer *timer);
+
+/** Set timer handler
+ *
+ * \param[in,out] timer timer control block
+ * \param[in] handler timer handler
+ * \param[in] data data to be passed to the handler
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_timer_handler_set(bcmos_timer *timer, F_bcmos_timer_handler handler, long data);
+
+/** (Re)start timer
+ * Stop timer if running and start it.
+ *
+ * \param[in] timer timer handle
+ * \param[in] delay delay in us
+ */
+void bcmos_timer_start(bcmos_timer *timer, uint32_t delay);
+
+/** Stop timer if running
+ *
+ * \param[in] timer timer handle
+ */
+void bcmos_timer_stop(bcmos_timer *timer);
+
+/** Suspend current task for a time
+ *
+ * \param[in] us sleep time (us)
+ */
+#ifndef BCMOS_USLEEP_INLINE
+void bcmos_usleep(uint32_t us);
+#endif /* #ifndef BCMOS_USLEEP_INLINE */
+
+/** @} system_timer */
+
+/** \addtogroup system_fastlock
+ * @{
+ */
+
+/** Fast lock control block */
+typedef struct bcmos_fastlock bcmos_fastlock;
+
+#ifndef BCMOS_FASTLOCK_INLINE
+
+/** Init fastlock
+ * \param[in, out] lock fast lock control block
+ * \param[in] flags flags - TBD. E.g., single core / SMP
+ */
+void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags);
+
+/** Take fast lock
+ * \param[in] lock fast lock
+ * \returns value of interrupt flags that should be used in unlock
+ */
+long bcmos_fastlock_lock(bcmos_fastlock *lock);
+
+/** Release fast lock
+ * \param[in] lock fast lock
+ * \param[in] flags interrupt flags
+ */
+void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags);
+
+#endif /* #ifndef BCMOS_FASTLOCK_INLINE */
+
+/** @} system_fastlock */
+
+/** \addtogroup system_mutex
+ * @{
+ */
+
+/** Mutex control block */
+typedef struct bcmos_mutex bcmos_mutex;
+
+#ifdef BCMOS_MUTEX_INLINE
+#define BCMOS_MUTEX_CREATE_DESTROY_INLINE
+#define BCMOS_MUTEX_LOCK_UNLOCK_INLINE
+#endif
+
+#ifndef BCMOS_MUTEX_CREATE_DESTROY_INLINE
+
+/** Create recursive mutex
+ * \param[in, out] mutex Mutex control block
+ * \param[in] flags flags - TBD. E.g., single core / SMP
+ * \param[in] name name of the mutex (if OS supports), NULL means it will be auto-generated
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name);
+
+/** Destroy mutex
+ * \param[in] mutex Mutex control block
+ */
+void bcmos_mutex_destroy(bcmos_mutex *mutex);
+
+#endif /* BCMOS_MUTEX_CREATE_DESTROY_INLINE */
+
+
+#ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE
+
+/** Lock mutex
+ * \param[in] mutex Mutex control block
+ */
+void bcmos_mutex_lock(bcmos_mutex *mutex);
+
+/** Release mutex
+ * \param[in] mutex Mutex control block
+ */
+void bcmos_mutex_unlock(bcmos_mutex *mutex);
+
+#endif /* #ifndef BCMOS_MUTEX_LOCK_UNLOCK_INLINE */
+
+/** @} system_mutex */
+
+/** \addtogroup system_sem
+ * @{
+ */
+
+/** Semaphore control block */
+typedef struct bcmos_sem bcmos_sem;
+
+#ifdef BCMOS_SEM_INLINE
+#define BCMOS_SEM_CREATE_DESTROY_INLINE
+#define BCMOS_SEM_WAIT_INLINE
+#define BCMOS_SEM_POST_INLINE
+#endif
+
+#ifndef BCMOS_SEM_CREATE_DESTROY_INLINE
+
+/** Create semaphore
+ * \param[in, out] sem semaphore control block
+ * \param[in] count initial value of semaphore counter
+ * \param[in] flags flags - TBD. E.g., single core / SMP
+ * \param[in] name name of the semaphore (if OS supports), NULL means it will be auto-generated
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name);
+
+/** Destroy semaphore
+ * \param[in] sem semaphore control block
+ */
+void bcmos_sem_destroy(bcmos_sem *sem);
+
+#endif /* BCMOS_SEM_CREATE_DESTROY_INLINE */
+
+#ifndef BCMOS_SEM_WAIT_INLINE
+
+/** Decrement semaphore counter. Wait if the counter is 0
+ *
+ * \param[in] sem semaphore control block
+ * \param[in] timeout timeout. can be 0, time in us or \ref BCMOS_WAIT_FOREVER
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout);
+
+#endif /* #ifndef BCMOS_SEM_WAIT_INLINE */
+
+#ifndef BCMOS_SEM_POST_INLINE
+/** Increment semaphore counter
+ * \param[in] sem semaphore control block
+ */
+void bcmos_sem_post(bcmos_sem *sem);
+
+#endif /* #ifndef BCMOS_SEM_POST_INLINE */
+
+/** @} system_sem */
+
+/*
+ * print support
+ */
+
+/** Print cloning/redirection mode */
+typedef enum
+{
+ BCMOS_PRINT_REDIRECT_MODE_NONE, /**< No cloning, redirection */
+ BCMOS_PRINT_REDIRECT_MODE_REDIRECT, /**< Redirect console output. Do not print on the serial console */
+ BCMOS_PRINT_REDIRECT_MODE_CLONE /**< Clone console output to redirection callback */
+} bcmos_print_redirect_mode;
+
+/** Print re-direction/cloning callback */
+typedef int (*bcmos_print_redirect_cb)(void *data, const char *format, va_list ap);
+
+/** Set up print redirection/cloning
+ * \param[in] mode redirection/cloning mode
+ * \param[in] cb redirection callback
+ * \param[in] data opaque data to be passed to cb
+ * \returns 0=OK or error <0
+ */
+bcmos_errno bcmos_print_redirect(bcmos_print_redirect_mode mode, bcmos_print_redirect_cb cb, void *data);
+
+/* Print on the console with optional cloning / redirection
+ * \param[in] format printf format
+ * \param[in] ap argument list
+ * \returns number of characters printed >= 0 or error < 0
+ */
+int bcmos_vprintf(const char *format, va_list ap);
+
+/* Print on the console with optional cloning / redirection
+ * \param[in] format printf format
+ * \returns number of characters printed >= 0 or error < 0
+ */
+int bcmos_printf(const char *format, ...);
+
+
+/** \addtogroup system_trace
+ * @{
+ */
+
+/** Trace level */
+typedef enum
+{
+ BCMOS_TRACE_LEVEL_NONE, /**< No trace output */
+ BCMOS_TRACE_LEVEL_ERROR, /**< Trace errors */
+ BCMOS_TRACE_LEVEL_WARNING, /**< Trace errors + warnings */
+ BCMOS_TRACE_LEVEL_INFO, /**< Trace errors + warnings + info */
+ BCMOS_TRACE_LEVEL_VERBOSE, /**< Trace errors + warnings + info + verbose info */
+ BCMOS_TRACE_LEVEL_DEBUG, /**< Trace everything */
+} bcmos_trace_level;
+
+extern bcmos_trace_level bcmos_sys_trace_level;
+
+#ifdef BCMOS_TRACE_PRINTF
+#define BCMOS_TRACE_INLINE
+#endif
+
+#ifndef BCMOS_TRACE_INLINE
+/** Print trace
+ *
+ * \param[in] level Record trace at level
+ * \param[in] format printf-like format
+ */
+void bcmos_trace(bcmos_trace_level level, const char *format, ...);
+#endif
+
+
+/* Print trace */
+#ifdef BCMOS_TRACE_PRINTF
+#define bcmos_trace(level, fmt, args...) bcmos_printf(fmt, ## args)
+#endif
+
+/** Set current trace level
+ * \param[in] level New trace level
+ * \returns old trace level
+ */
+static inline bcmos_trace_level bcmos_trace_level_set(bcmos_trace_level level)
+{
+ bcmos_trace_level old_level = bcmos_sys_trace_level;
+ bcmos_sys_trace_level = level;
+ return old_level;
+}
+
+/** Get current trace level
+ * \returns trace level
+ */
+static inline bcmos_trace_level bcmos_trace_level_get(void)
+{
+ return bcmos_sys_trace_level;
+}
+
+/** Print trace conditionally, depending on the current trace level
+ * \param[in] level Record trace at level
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ */
+#define BCMOS_TRACE(level, fmt, args...) \
+ do \
+ { \
+ if (level <= bcmos_sys_trace_level) \
+ bcmos_trace(level, "%s#%d> " fmt, __FUNCTION__, __LINE__, ## args); \
+ } while (0)
+
+/** Print error trace conditionally, depending on the current trace level
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ */
+
+extern f_bcmolt_sw_error_handler sw_error_handler;
+
+#define BCMOS_TRACE_ERR(fmt, args...) \
+ do \
+ { \
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_ERROR, "ERR: " fmt, ## args); \
+ if (sw_error_handler != NULL) \
+ { \
+ sw_error_handler(0xff, __FILE__, __LINE__); \
+ } \
+ _bcmos_backtrace(); \
+ } while (0)
+
+
+/** Print info trace conditionally, depending on the current trace level
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ */
+#define BCMOS_TRACE_INFO(fmt, args...) \
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "INF: " fmt, ## args)
+
+/** Print verbose info trace conditionally, depending on the current trace level
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ */
+#define BCMOS_TRACE_VERBOSE(fmt, args...) \
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_VERBOSE, "VRB: " fmt, ## args)
+
+/** Print debug trace conditionally, depending on the current trace level
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ */
+#define BCMOS_TRACE_DEBUG(fmt, args...) \
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_DEBUG, "DBG: " fmt, ## args)
+
+/** Print trace conditionally based on return code and return
+ * \param[in] rc return code
+ * \param[in] fmt printf-like format
+ * \param[in] args printf-like arguments
+ * \returns rc
+ */
+#define BCMOS_TRACE_RETURN(rc, fmt, args...) \
+ do { \
+ if (rc) \
+ BCMOS_TRACE_ERR("status:%s :" fmt, bcmos_strerror(rc), ## args); \
+ else \
+ BCMOS_TRACE_INFO("success: " fmt, ## args); \
+ return rc; \
+ } while (0)
+
+#define BCMOS_TRACE_CHECK_RETURN(cond,rc,fmt,args...) \
+ do { \
+ if (cond) \
+ {\
+ BCMOS_TRACE_ERR( #cond ": status:%s :" fmt, bcmos_strerror(rc), ## args); \
+ return rc; \
+ }\
+ } while (0)
+#define BCMOS_CHECK_RETURN(cond,err,ret) \
+ do { \
+ if (cond) \
+ {\
+ BCMOS_TRACE_ERR( #cond ": status:%s\n", bcmos_strerror(err)); \
+ return ret; \
+ }\
+ } while (0)
+#define BCMOS_CHECK_RETURN_ERROR(cond,err) BCMOS_CHECK_RETURN(cond,err,err)
+#define BCMOS_RETURN_ON_ERROR(err) BCMOS_CHECK_RETURN(BCM_ERR_OK != err, err, /*this space intentionally left blank*/)
+#define BCMOS_RETURN_IF_ERROR(err) BCMOS_CHECK_RETURN_ERROR(BCM_ERR_OK != err, err)
+
+/** @} system_trace */
+
+/*
+ * Low level services
+ */
+
+/** \addtogroup system_buf
+ * @{
+ */
+
+/** Transport/network buffer */
+typedef struct bcmos_buf bcmos_buf;
+
+/** @} system_buf */
+
+/** Round a number up to the specified power of 2 */
+#define BCMOS_ROUND_UP(n, m) (((n) + (m) - 1) & ~((m) - 1))
+
+/** Round a number up to the nearest word multiple */
+#define BCMOS_ROUND_TO_WORD(n) BCMOS_ROUND_UP(n, sizeof(size_t))
+
+/* BCMOS_DIVIDE_ROUND_UP(integer_dividend / integer_divisor) == (integer_dividend + integer_divisor - 1) / integer_divisor */
+#define BCMOS_DIVIDE_ROUND_UP(n, m) (((n) + (m) - 1) / (m))
+
+#endif /* BCMOS_SYSTEM_COMMON_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_common2.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common2.h
new file mode 100644
index 0000000..7317aac
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_common2.h
@@ -0,0 +1,676 @@
+/*
+<: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 BCMOS_COMMON2_H_
+#define BCMOS_COMMON2_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_common2.h directly. Include bcmos_system.h
+#endif
+
+#include "bcmos_endian.h"
+
+/* \addtogroup system
+ * @{
+ */
+
+#define BCMOS_MAX_NAME_LENGTH 48
+
+/** \addtogroup system_task
+ * @{
+ */
+
+/** Task control block */
+struct bcmos_task
+{
+ /* OS independent fields */
+ bcmos_task_parm parm; /**< Task creation parameters */
+ bcmos_module *modules[BCMOS_MAX_MODULES_PER_TASK];
+ uint32_t active_modules; /**< Bitmask of modules for which events are pending */
+ bcmos_sem active_sem; /**< Semaphore used to wait for module activity */
+ bcmos_fastlock active_lock; /**< Lock protecting active_modules */
+ bcmos_module_id current_module; /**< Current module */
+ bcmos_bool destroy_request; /**< Task destroy request pending */
+ bcmos_bool destroyed; /**< Set by task handler before it terminates */
+ STAILQ_ENTRY(bcmos_task) list; /**< Next task pointer */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Task name */
+ bcmos_sys_task sys_task; /**< OS-specific task extension */
+ uint32_t magic; /* magic number */
+#define BCMOS_TASK_MAGIC (('t' << 24) | ('a' << 16) | ('s' << 8) | 'k')
+#define BCMOS_TASK_MAGIC_DESTROYED (('t' << 24) | ('a' << 16) | ('s' << 8) | '~')
+};
+
+/** \addtogroup system_mem
+ * @{
+ */
+
+#ifndef BCMOS_CALLOC_INLINE
+
+/** Allocate memory from the main heap and clear it
+ * \ingroup system_heap
+ * \param[in] size
+ * \returns memory block pointer or NULL
+ */
+static inline void *bcmos_calloc(uint32_t size)
+{
+ void *ptr = bcmos_alloc(size);
+ if (ptr)
+ memset(ptr, 0, size);
+ return ptr;
+}
+#endif /* #ifndef BCMOS_CALLOC_INLINE */
+
+#ifndef BCMOS_DMA_ALLOC_FREE_INLINE
+
+/** Allocate DMA-able memory
+ * \param[in] device Device id
+ * \param[in] size Block size (bytes)
+ * \returns memory block pointer or NULL
+ */
+void *bcmos_dma_alloc(uint8_t device, uint32_t size);
+
+/** Release DMA-able memory
+ * \param[in] device Device id
+ * \param[in] ptr Block pointer
+ */
+void bcmos_dma_free(uint8_t device, void *ptr);
+
+#endif /* #ifndef BCMOS_DMA_ALLOC_FREE_INLINE */
+
+#ifndef BCMOS_VIRT_TO_PHYS_INLINE
+
+/** Convert virtual address to physical address
+ *
+ * \param[in] va Virtual address
+ * \returns - physical address va is mapped to
+ */
+unsigned long bcmos_virt_to_phys(void *va);
+
+#endif /* #ifndef BCMOS_VIRT_TO_PHYS_INLINE */
+
+/** @} */
+
+/** \addtogroup blk_pool
+ * @{
+ */
+
+/* Memory block header */
+typedef struct bcmos_memblk bcmos_memblk;
+
+/* Memory block list */
+typedef STAILQ_HEAD(, bcmos_memblk) bcmos_memblk_list;
+
+/* Block memory pool control block */
+struct bcmos_blk_pool
+{
+ bcmos_fastlock lock; /**< Pool protection lock */
+ bcmos_memblk_list free_list;/**< Free block list */
+ bcmos_blk_pool_parm parm; /**< Pool parameters */
+ bcmos_blk_pool_stat stat; /**< Pool statistics */
+ void *start; /**< Pool start pointer */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Pool name */
+ uint32_t magic; /**< magic number */
+#define BCMOS_BLK_POOL_VALID (('b'<<24) | ('l' << 16) | ('p' << 8) | 'o')
+#define BCMOS_BLK_POOL_DELETED (('b'<<24) | ('l' << 16) | ('p' << 8) | '~')
+ STAILQ_ENTRY(bcmos_blk_pool) list; /* Pool list */
+};
+
+/* Total memory occupied by all block pools */
+extern uint32_t bcmos_total_blk_pool_size;
+
+/** @} blk_pool */
+
+/** \addtogroup system_msg
+ * @{
+ */
+
+/** Release message
+ * \param[in] msg Message handle
+ */
+static inline void bcmos_msg_free(bcmos_msg *msg)
+{
+ if (msg->release)
+ {
+ msg->release(msg);
+ }
+ else
+ {
+ bcmos_free(msg);
+ }
+}
+
+typedef STAILQ_HEAD(, bcmos_msg) bcmos_msg_list;
+
+/** Simple Message queue control block.
+ * Simple message queue doesn't support waiting on.
+ * It is used in module queue mechanisms.
+ */
+typedef struct bcmos_msg_queue_nw
+{
+ bcmos_msg_queue_parm parm; /**< Queue parameters */
+ bcmos_msg_queue_stat stat; /**< Queue statistics */
+ bcmos_fastlock lock; /**< Queue protection lock */
+ bcmos_msg_list msgl; /**< Message list */
+ bcmos_msg_list msgl_urg; /**< Urgent message list */
+ uint32_t flags; /**< Queue flags */
+} bcmos_msg_queue_nw;
+
+/** Message queue control block */
+struct bcmos_msg_queue
+{
+ bcmos_msg_queue_nw q; /**< Queue control block */
+ bcmos_sem m; /**< Mutex to suspend waiting task on */
+ bcmos_bool is_waiting; /**< TRUE if task is waiting on queue */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Queue name */
+#ifdef BCMOS_MSG_QUEUE_REMOTE_SUPPORT
+ long ep; /**< Endpoint handle (e.g., socket) */
+ void *ep_extra_data; /**< Extra data - depending on ep type */
+ uint32_t ep_extra_data_size;/**< Extra data size */
+ uint8_t *send_buf; /**< Send buffer */
+ uint8_t *recv_buf; /**< Receive buffer */
+ bcmos_mutex send_lock; /**< Mutex that protects send_buf */
+#endif
+ uint32_t magic; /**< magic number */
+#define BCMOS_MSG_QUEUE_VALID (('m'<<24) | ('q' << 16) | ('u' << 8) | 'e')
+#define BCMOS_MSG_QUEUE_DELETED (('m'<<24) | ('q' << 16) | ('u' << 8) | '~')
+ STAILQ_ENTRY(bcmos_msg_queue) list; /* Queue list */
+};
+
+/** Message queue group control block */
+struct bcmos_msg_qgroup
+{
+ bcmos_msg_qgroup_parm parm; /**< Queue group parameters */
+ bcmos_msg_list *msgl; /**< Array of parm.nqueues message lists */
+ bcmos_msg_queue_stat stat; /**< Queue group statistics */
+ bcmos_sem m; /**< Mutex to suspend waiting task on */
+ bcmos_fastlock lock; /**< Queue group protection lock */
+ uint32_t active_mask; /**< Bitmask of queues containing messages */
+ bcmos_bool is_waiting; /**< TRUE if task is waiting on queue group */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Queue group name */
+ uint32_t magic; /**< magic number */
+#define BCMOS_MSG_QGROUP_VALID (('m'<<24) | ('q' << 16) | ('g' << 8) | 'r')
+#define BCMOS_MSG_QGROUP_DELETED (('m'<<24) | ('q' << 16) | ('g' << 8) | '~')
+ STAILQ_ENTRY(bcmos_msg_qgroup) list; /* Queue group list */
+};
+
+/** Message pool control block */
+struct bcmos_msg_pool
+{
+ bcmos_blk_pool blk_pool; /**< Underlying block memory pool */
+ bcmos_msg_pool_parm parm; /**< Pool parameters */
+};
+
+/* Total memory occupied by all message pools */
+extern uint32_t bcmos_total_msg_pool_size;
+
+/** @} system_msg */
+
+/** \addtogroup system_timer */
+
+/* Timer precision. Must be a multiple of 2.
+ * Timed expiration timestamp is rounded up to the nearest multiple of timer precision
+ */
+#define BCMOS_TIMER_PRECISION_US 32
+#if (BCMOS_TIMER_PRECISION_US & (BCMOS_TIMER_PRECISION_US - 1))
+ #error BCMOS_TIMER_PRECISION_US must be a multiple of 2
+#endif
+
+/* There are 2 timer implementations
+ * - DLIST-based - works well when most of active timers have the same duration
+ * - RB-tree based - more expensive in simple case, but scales better for large number of timers
+ * with arbitrary durations
+ */
+#define BCMOS_TIMER_RB_TREE
+
+/** Timer control block */
+struct bcmos_timer
+{
+ bcmos_msg msg; /**< Timer message */
+ bcmos_timer_parm parm; /**< Timer parameters */
+ F_bcmos_timer_handler handler; /**< Timer handler */
+ uint32_t period; /**< Timer period (us) if periodic */
+ uint32_t expire_at; /**< Timestamp when timer should expire */
+ uint32_t flags; /* Internal flags */
+#define BCMOS_TIMER_FLAG_RUNNING 0x00000001 /* Timer is running */
+#define BCMOS_TIMER_FLAG_EXPIRED 0x00000002 /* Timer has expired, but not yet handled */
+#define BCMOS_TIMER_FLAG_ACTIVE (BCMOS_TIMER_FLAG_RUNNING | BCMOS_TIMER_FLAG_EXPIRED)
+#define BCMOS_TIMER_FLAG_VALID 0x00000004
+ bcmos_msg_queue_nw *queue; /**< Queue expired timer is on */
+ bcmos_task *task; /**< Task that executes timer handler */
+#ifdef BCMOS_TIMER_RB_TREE
+ RB_ENTRY(bcmos_timer) entry; /**< Timer pool entry */
+#else
+ TAILQ_ENTRY(bcmos_timer) entry;
+#endif
+};
+
+/** Check if timer is running
+ * \param[in] timer Timer handle
+ * \returns TRUE if timer is running
+ */
+static inline bcmos_bool bcmos_timer_is_running(const bcmos_timer *timer)
+{
+ bcmos_bool running = ((timer->flags & BCMOS_TIMER_FLAG_RUNNING) != 0) ||
+ (timer->parm.periodic && ((timer->flags & BCMOS_TIMER_FLAG_EXPIRED) != 0));
+ return running;
+}
+
+static inline bcmos_timer *_bcmos_msg_to_timer(bcmos_msg *msg)
+{
+ BUG_ON(msg->type != BCMOS_MSG_ID_INTERNAL_TIMER);
+ return (bcmos_timer *)msg;
+}
+
+/** @} */
+
+/** \addtogroup system_module
+ * @{
+ */
+
+/** Module control block */
+struct bcmos_module
+{
+ bcmos_module_parm parm; /**< Module parameters */
+ bcmos_module_id id; /**< Module id */
+ int idx; /**< Module index in task control block */
+ bcmos_msg_queue_nw msgq; /**< Message queue */
+ bcmos_task *my_task; /**< Task the module is associated with */
+ void *context; /**< User-defined context */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Module name */
+};
+
+/** @} system_module */
+
+/** \addtogroup system_event
+ * @{
+ */
+
+/** Event control block */
+struct bcmos_event
+{
+ bcmos_msg msg; /**< Message header. Used to deliver event to module's queue */
+ bcmos_event_id id; /**< Event set id */
+ bcmos_event_parm parm; /**< Event parameters */
+ bcmos_fastlock lock; /**< Protects event control block */
+ uint32_t active_bits; /**< Active event bits */
+
+ bcmos_sem m; /**< Mutex to suspend task on. Traditional mode only */
+ bcmos_bool is_waiting; /**< TRUE if task is waiting for event */
+ char name[BCMOS_MAX_NAME_LENGTH]; /**< Event name */
+};
+
+
+static inline bcmos_event *_bcmos_msg_to_event(bcmos_msg *msg)
+{
+ BUG_ON(msg->type != BCMOS_MSG_ID_INTERNAL_EVENT);
+ return (bcmos_event *)msg;
+}
+
+/*
+ * Low level services
+ */
+
+/** \addtogroup system_buf
+ * @{
+ */
+
+#ifndef BCMOS_BUF_OS_SPECIFIC
+#define BCMOS_BUF_DATA_INLINE
+#endif
+
+#ifdef BCMOS_BUF_INLINE
+#define BCMOS_BUF_ALLOC_FREE_INLINE
+#define BCMOS_BUF_DATA_INLINE
+#endif
+
+#ifndef BCMOS_BUF_DATA_GUARD
+#define BCMOS_BUF_DATA_GUARD 0
+#endif
+
+#ifndef BCMOS_BUF_DATA_ALIGNMENT
+#define BCMOS_BUF_DATA_ALIGNMENT 64
+#endif
+
+#ifndef BCMOS_BUF_ALLOC_FREE_INLINE
+
+/** Allocate transport buffer.
+ * The buffer can accommodate up to size bytes of data.
+ * In addition it reserves BCMTR_BUF_EXTRA_HEADROOM headroom bytes
+ * for extra headers.
+ *
+ * \param[in] size Data size
+ * \returns buffer pointer or NULL if no memory
+ */
+bcmos_buf *bcmos_buf_alloc(uint32_t size);
+
+ /** Release transport buffer allocated by bcmos_buf_alloc()
+ *
+ * \param[in] buf Buffer to be released
+ */
+void bcmos_buf_free(bcmos_buf *buf);
+
+#endif /* BCMOS_BUF_ALLOC_FREE_INLINE */
+
+#ifndef BCMOS_BUF_DATA_INLINE
+
+/** Get data length
+ *
+ * \param[in] buf Buffer
+ * \returns data length
+ */
+uint32_t bcmos_buf_length(bcmos_buf *buf);
+
+/** Set data length
+ *
+ * \param[in] buf Buffer
+ * \param[in] length Data length
+ * \returns 0=OK, or BCM_ERR_OVERFLOW if length exceeds size
+ */
+bcmos_errno bcmos_buf_length_set(bcmos_buf *buf, uint32_t length);
+
+/** Get buffer data pointer.
+ * \param[in] buf Buffer
+ * \returns data pointer
+ */
+uint8_t *bcmos_buf_data(bcmos_buf *buf);
+
+#endif /* BCMOS_BUF_DATA_INLINE */
+
+#ifndef BCMOS_BUF_OS_SPECIFIC
+
+#ifndef unlikely
+#define unlikely(x) (x)
+#endif
+
+/* Generic (not os-specific) sysb implementation */
+
+/*
+ * Network / transport buffer
+ */
+
+
+/* Memory block list */
+typedef STAILQ_HEAD(, bcmos_buf) bcmos_buf_list_head;
+
+typedef struct
+{
+ bcmos_buf_list_head head; /**< Buffer list head */
+} bcmos_buf_queue;
+
+/* System buffer. We probably can use mbuf as well. */
+struct bcmos_buf
+{
+ uint8_t *start;
+ uint8_t *data;
+ bcmos_blk_pool *pool;
+ uint32_t size;
+ uint32_t len;
+ STAILQ_ENTRY(bcmos_buf) list; /**< Next buffer pointer */
+ uint8_t channel;
+};
+
+
+#ifndef BCMTR_BUF_EXTRA_HEADROOM
+#define BCMTR_BUF_EXTRA_HEADROOM 0
+#endif
+
+
+/** Initialize buffer queue
+ * \param[in] q Buffer queue
+ */
+static inline void bcmos_buf_queue_init(bcmos_buf_queue *q)
+{
+ STAILQ_INIT(&q->head);
+}
+
+/* Check if buffer queue is empty
+ * \param[in] q Buffer queue
+ * \returns TRUE if the queue is empty
+ */
+static inline bcmos_bool bcmos_buf_queue_is_empty(bcmos_buf_queue *q)
+{
+ return (bcmos_bool)STAILQ_EMPTY(&q->head);
+}
+
+/** Enqueue buffer
+ *
+ * Must be called under lock, e.g., q->lock
+ *
+ * \param[in] q Buffer queue
+ * \param[in] buf Buffer
+ */
+static inline void bcmos_buf_queue_put(bcmos_buf_queue *q, bcmos_buf *buf)
+{
+ STAILQ_INSERT_TAIL(&q->head, buf, list);
+}
+
+/* Dequeue buffer
+ *
+ * Must be called under lock, e.g., q->lock
+ *
+ * Remove and return the 1st queued buffer.
+ * \param[in] q Buffer queue
+ * \returns the buffer pointer
+ */
+static inline bcmos_buf *bcmos_buf_queue_get(bcmos_buf_queue *q)
+{
+ bcmos_buf *buf;
+ buf = STAILQ_FIRST(&q->head);
+ if (buf)
+ STAILQ_REMOVE_HEAD(&q->head, list);
+ return buf;
+}
+
+/* Peek into queue and return the 1st buffer without dequeing it
+ *
+ * Must be called under lock, e.g., q->lock
+ * \param[in] q Buffer queue
+ * \returns the buffer pointer
+ */
+static inline bcmos_buf *bcmos_buf_queue_peek(bcmos_buf_queue *q)
+{
+ return STAILQ_FIRST(&q->head);
+}
+
+/* Initialize buffer */
+static inline bcmos_buf *bcmos_buf_init(bcmos_buf *buf, uint8_t *start,
+ uint8_t *data, uint32_t size, uint32_t len)
+{
+ BUG_ON((void *)(buf +1) != start);
+ buf->start = start;
+ buf->data = data;
+ buf->size = size;
+ buf->len = len;
+ buf->pool = NULL;
+ return buf;
+}
+
+/* Get data length */
+static inline uint32_t bcmos_buf_length(bcmos_buf *buf)
+{
+ return buf->len;
+}
+
+/* Set data length */
+static inline bcmos_errno bcmos_buf_length_set(bcmos_buf *buf, uint32_t length)
+{
+ if (unlikely(length > buf->size - (buf->data - buf->start)))
+ {
+ BCMOS_TRACE_ERR("!!!%s: length=%u size=%u data=%p start=%p data-start=%u\n",
+ __FUNCTION__, length, buf->size, buf->data, buf->start, (uint32_t)(buf->data - buf->start));
+ return BCM_ERR_OVERFLOW;
+ }
+ buf->len = length;
+ return BCM_ERR_OK;
+}
+
+/* Get buffer data pointer. */
+static inline uint8_t *bcmos_buf_data(bcmos_buf *buf)
+{
+ return buf->data;
+}
+
+/* Get buffer channel. */
+static inline uint8_t bcmos_buf_channel(bcmos_buf *buf)
+{
+ return buf->channel;
+}
+
+/* Set buffer channel. */
+static inline void bcmos_buf_channel_set(bcmos_buf *buf, uint8_t channel)
+{
+ buf->channel = channel;
+}
+
+#endif /* #ifndef BCMOS_BUF_OS_SPECIFIC */
+
+/** @} bcmos_buf */
+
+/** \addtogroup system_cache
+ * @{
+ */
+
+#ifndef BCMOS_CACHE_INLINE
+
+/** Invalidate address area in data cache. Dirty cache lines content is discarded.
+ * \param[in] start Address area start
+ * \param[in] size Address area size
+ */
+void bcmos_dcache_inv(void *start, uint32_t size);
+
+/** Flush address area in data cache. Dirty cache lines are committed to memory.
+ * \param[in] start Address area start
+ * \param[in] size Address area size
+ */
+void bcmos_dcache_flush(void *start, uint32_t size);
+
+#endif /* BCMOS_CACHE_INLINE */
+
+/** Prepare for DMA write.
+ * On h/w platforms that support DMA-cache coherency, this function should
+ * perform write barrier.
+ * On platforms that don't support DMA cache coherency this function should
+ * flush the relevant dcache area
+ *
+ * \param[in] start DMA buffer start address
+ * \param[in] size DMA buffer size
+ */
+static inline void bcmos_prepare_for_dma_write(void *start, uint32_t size)
+{
+#ifdef BCMOS_DMA_CACHE_COHERENCY
+ bcmos_barrier();
+#else
+ bcmos_dcache_flush(start, size);
+#endif
+}
+
+/** Prepare for DMA read.
+ * On h/w platforms that support DMA-cache coherency, this function should
+ * perform write barrier.
+ * On platforms that don't support DMA cache coherency this function should
+ * invalidate the relevant dcache area
+ *
+ * \param[in] start DMA buffer start address
+ * \param[in] size DMA buffer size
+ */
+static inline void bcmos_prepare_for_dma_read(void *start, uint32_t size)
+{
+#ifdef BCMOS_DMA_CACHE_COHERENCY
+ bcmos_barrier();
+#else
+ bcmos_dcache_inv(start, size);
+#endif
+}
+
+/** @} system_cache */
+
+/** \addtogroup system_interrupt
+ * @{
+ */
+
+#ifdef BCMOS_INTERRUPT_INLINE
+#define BCMOS_INTERRUPT_CONNECT_DISCONNECT_INLINE
+#define BCMOS_INTERRUPT_ENABLE_DISABLE_INLINE
+#endif
+
+#ifndef BCMOS_INTERRUPT_CONNECT_DISCONNECT_INLINE
+/** Connect system interrupt
+ * \param[in] irq IRQ number
+ * \param[in] cpu CPU number (for SMP)
+ * \param[in] flags IRQ flags
+ * \param[in] isr ISR
+ * \param[in] name device name
+ * \param[in] priv Private cookie
+ * \returns 0=OK, <0- error
+ */
+int bcmos_int_connect(int irq, int cpu, int flags,
+ int (*isr)(int irq, void *priv), const char *name, void *priv);
+
+/** Disconnect system interrupt
+ * \param[in] irq IRQ number
+ * \param[in] priv Private cookie passed in bcmos_int_connect()
+ * \returns 0=OK, <0- error
+ */
+void bcmos_int_disconnect(int irq, void *priv);
+#endif
+
+#ifndef BCMOS_INTERRUPT_ENABLE_DISABLE_INLINE
+/** Unmask IRQ
+ * \param[in] irq IRQ
+ */
+void bcmos_int_enable(int irq);
+
+/** Mask IRQ
+ * \param[in] irq IRQ
+ */
+void bcmos_int_disable(int irq);
+#endif
+
+/** @} */
+
+/* Get char, put char support */
+#ifndef BCMOS_GETCHAR_INLINE
+static inline int bcmos_getchar(void)
+{
+ return getchar();
+}
+#endif
+
+#ifndef BCMOS_PUTCHAR_INLINE
+void bcmos_putchar(int c);
+#endif
+
+#ifndef BCMOS_SEM_POST_IS_ALLOWED_INLINE
+static inline bcmos_bool bcmos_sem_post_is_allowed(void)
+{
+ return BCMOS_TRUE;
+}
+#endif
+
+#endif /* BCMOS_COMMON2_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_endian.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_endian.h
new file mode 100644
index 0000000..ece41dc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_endian.h
@@ -0,0 +1,130 @@
+/*
+<: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 BCMOS_ENDIAN_H_
+#define BCMOS_ENDIAN_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_endian.h directly. Include bcmos_system.h
+#endif
+
+
+
+/** @} system_event */
+
+/** \addtogroup system_endian
+ * @{
+ */
+#ifndef BCMOS_ARCH_ENDIAN_SWAP
+
+/** Swaps the endianness of a 16-bit integer
+ * \param[in] n the original number
+ * \return number with swapped endianness
+ */
+static inline uint16_t bcmos_endian_swap_u16(uint16_t n)
+{
+ return ((n << 8 ) & 0xFF00U)|((n >> 8) & 0x00FFU);
+}
+
+/** Swaps the endianness of a 24-bit integer
+ * \param[in] n the original number
+ * \return number with swapped endianness
+ */
+static inline uint24_t bcmos_endian_swap_u24(uint24_t n)
+{
+ return (uint24_t){ .u8 = { n.u8[2], n.u8[1], n.u8[0] } };
+}
+
+/** Swaps the endianness of a 32-bit integer
+ * \param[in] n the original number
+ * \return number with swapped endianness
+ */
+static inline uint32_t bcmos_endian_swap_u32(uint32_t n)
+{
+ return ((n << 24) & 0xFF000000U)|((n << 8 ) & 0x00FF0000U)|((n >> 8) & 0x0000FF00U)|((n >> 24) & 0x000000FFU);
+}
+
+/** Swaps the endianness of a 64-bit integer
+ * \param[in] n the original number
+ * \return number with swapped endianness
+ */
+static inline uint64_t bcmos_endian_swap_u64(uint64_t n)
+{
+ return (((uint64_t)bcmos_endian_swap_u32(n & 0xFFFFFFFFU) << 32) | bcmos_endian_swap_u32((n >> 32) & 0xFFFFFFFFU));
+}
+
+#endif /* BCMOS_ARCH_ENDIAN_SWAP */
+
+#if (BCM_CPU_ENDIAN == BCMOS_ENDIAN_BIG)
+
+#define BCMOS_ENDIAN_CPU_TO_BIG_U16(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_BIG_U24(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_BIG_U32(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_BIG_U64(n) (n)
+#define BCMOS_ENDIAN_BIG_TO_CPU_U16(n) (n)
+#define BCMOS_ENDIAN_BIG_TO_CPU_U24(n) (n)
+#define BCMOS_ENDIAN_BIG_TO_CPU_U32(n) (n)
+#define BCMOS_ENDIAN_BIG_TO_CPU_U64(n) (n)
+
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U16(n) (bcmos_endian_swap_u16(n))
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U24(n) (bcmos_endian_swap_u24(n))
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U32(n) (bcmos_endian_swap_u32(n))
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U64(n) (bcmos_endian_swap_u64(n))
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U16(n) (bcmos_endian_swap_u16(n))
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U24(n) (bcmos_endian_swap_u24(n))
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U32(n) (bcmos_endian_swap_u32(n))
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U64(n) (bcmos_endian_swap_u64(n))
+
+#elif (BCM_CPU_ENDIAN == BCMOS_ENDIAN_LITTLE)
+
+#define BCMOS_ENDIAN_CPU_TO_BIG_U16(n) (bcmos_endian_swap_u16(n))
+#define BCMOS_ENDIAN_CPU_TO_BIG_U24(n) (bcmos_endian_swap_u24(n))
+#define BCMOS_ENDIAN_CPU_TO_BIG_U32(n) (bcmos_endian_swap_u32(n))
+#define BCMOS_ENDIAN_CPU_TO_BIG_U64(n) (bcmos_endian_swap_u64(n))
+#define BCMOS_ENDIAN_BIG_TO_CPU_U16(n) (bcmos_endian_swap_u16(n))
+#define BCMOS_ENDIAN_BIG_TO_CPU_U24(n) (bcmos_endian_swap_u24(n))
+#define BCMOS_ENDIAN_BIG_TO_CPU_U32(n) (bcmos_endian_swap_u32(n))
+#define BCMOS_ENDIAN_BIG_TO_CPU_U64(n) (bcmos_endian_swap_u64(n))
+
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U16(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U24(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U32(n) (n)
+#define BCMOS_ENDIAN_CPU_TO_LITTLE_U64(n) (n)
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U16(n) (n)
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U24(n) (n)
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U32(n) (n)
+#define BCMOS_ENDIAN_LITTLE_TO_CPU_U64(n) (n)
+
+#else
+#error BCM_CPU_ENDIAN must be BCMOS_ENDIAN_BIG or _LITTLE
+#endif
+
+/** @} system_endian */
+
+#endif /* BCMOS_COMMON2_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.c b/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.c
new file mode 100644
index 0000000..a2a0ff8
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.c
@@ -0,0 +1,86 @@
+/*
+<: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"
+
+/* Map error code to error string */
+const char *bcmos_strerror(bcmos_errno err)
+{
+ static const char *errstr[] = {
+ [-BCM_ERR_OK] = "OK",
+ [-BCM_ERR_IN_PROGRESS] = "In progress",
+ [-BCM_ERR_PARM] = "Error in parameters",
+ [-BCM_ERR_NOMEM] = "No memory",
+ [-BCM_ERR_NORES] = "No resources",
+ [-BCM_ERR_INTERNAL] = "Internal error",
+ [-BCM_ERR_NOENT] = "Entry doesn't exist",
+ [-BCM_ERR_NODEV] = "Device doesn't exist",
+ [-BCM_ERR_ALREADY] = "Entry already exists",
+ [-BCM_ERR_RANGE] = "Out of range",
+ [-BCM_ERR_PERM] = "No permission to perform an operation",
+ [-BCM_ERR_NOT_SUPPORTED] = "Operation is not supported",
+ [-BCM_ERR_PARSE] = "Parsing error",
+ [-BCM_ERR_INVALID_OP] = "Invalid operation",
+ [-BCM_ERR_IO] = "I/O error",
+ [-BCM_ERR_STATE] = "Object is in bad state",
+ [-BCM_ERR_DELETED] = "Object is deleted",
+ [-BCM_ERR_TOO_MANY] = "Too many objects",
+ [-BCM_ERR_NO_MORE] = "No more entries",
+ [-BCM_ERR_OVERFLOW] = "Buffer overflow",
+ [-BCM_ERR_COMM_FAIL] = "Communication failure",
+ [-BCM_ERR_NOT_CONNECTED] = "No connection with the target system",
+ [-BCM_ERR_SYSCALL_ERR] = "System call returned error",
+ [-BCM_ERR_MSG_ERROR] = "Received message is insane",
+ [-BCM_ERR_TOO_MANY_REQS] = "Too many outstanding requests",
+ [-BCM_ERR_TIMEOUT] = "Operation timed out",
+ [-BCM_ERR_TOO_MANY_FRAGS] = "Too many fragments",
+ [-BCM_ERR_NULL] = "Got NULL pointer",
+ [-BCM_ERR_READ_ONLY] = "Attempt to set read-only parameter",
+ [-BCM_ERR_ONU_ERR_RESP] = "ONU returned an error response",
+ [-BCM_ERR_MANDATORY_PARM_IS_MISSING] = "Mandatory parameter is missing",
+ [-BCM_ERR_KEY_RANGE] = "Key field out of range",
+ [-BCM_ERR_QUEUE_EMPTY] = "Rx of PCIe empty",
+ [-BCM_ERR_QUEUE_FULL] = "Tx of PCIe full",
+ [-BCM_ERR_TOO_LONG] = "Processing is taking too long, but will finish eventually",
+ [-BCM_ERR_INSUFFICIENT_LIST_MEM] = "Insufficient list memory provided",
+
+ [-BCM_ERR_OUT_OF_SYNC] = "Sequence number or operation step was out of sync",
+ [-BCM_ERR_CHECKSUM] = "Checksum error",
+ [-BCM_ERR_IMAGE_TYPE] = "Unsupported file/image type",
+ [-BCM_ERR_INCOMPLETE_TERMINATION] = "Incomplete premature termination",
+ };
+ static const char *unknown = "*unknown*";
+
+ if ((unsigned)(-err) >= sizeof(errstr)/sizeof(errstr[0]) || !errstr[-err])
+ return unknown;
+ return errstr[-err];
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(bcmos_strerror);
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.h
new file mode 100644
index 0000000..f5e892a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_errno.h
@@ -0,0 +1,91 @@
+/*
+<: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 BCMOS_ERRNO_H_
+#define BCMOS_ERRNO_H_
+
+/** \defgroup system_errno Error Codes
+ * @{
+ */
+
+/** Error codes */
+typedef enum
+{
+ BCM_ERR_OK = 0, /**< OK */
+ BCM_ERR_IN_PROGRESS = -1, /**< Operation is in progress */
+ BCM_ERR_PARM = -2, /**< Error in parameters */
+ BCM_ERR_NOMEM = -3, /**< No memory */
+ BCM_ERR_NORES = -4, /**< No resources */
+ BCM_ERR_INTERNAL = -5, /**< Internal error */
+ BCM_ERR_NOENT = -6, /**< Entry doesn't exist */
+ BCM_ERR_NODEV = -7, /**< Device doesn't exist */
+ BCM_ERR_ALREADY = -8, /**< Entry already exists */
+ BCM_ERR_RANGE = -9, /**< Out of range */
+ BCM_ERR_PERM = -10, /**< No permission to perform an operation */
+ BCM_ERR_NOT_SUPPORTED = -11, /**< Operation is not supported */
+ BCM_ERR_PARSE = -12, /**< Parsing error */
+ BCM_ERR_INVALID_OP = -13, /**< Invalid operation */
+ BCM_ERR_IO = -14, /**< I/O error */
+ BCM_ERR_STATE = -15, /**< Object is in bad state */
+ BCM_ERR_DELETED = -16, /**< Object is deleted */
+ BCM_ERR_TOO_MANY = -17, /**< Too many objects */
+ BCM_ERR_NO_MORE = -18, /**< No more entries */
+ BCM_ERR_OVERFLOW = -19, /**< Buffer overflow */
+ BCM_ERR_COMM_FAIL = -20, /**< Communication failure */
+ BCM_ERR_NOT_CONNECTED = -21, /**< No connection with the target system */
+ BCM_ERR_SYSCALL_ERR = -22, /**< System call returned error */
+ BCM_ERR_MSG_ERROR = -23, /**< Received message is insane */
+ BCM_ERR_TOO_MANY_REQS = -24, /**< Too many outstanding requests */
+ BCM_ERR_TIMEOUT = -25, /**< Operation timed out */
+ BCM_ERR_TOO_MANY_FRAGS = -26, /**< Too many fragments */
+ BCM_ERR_NULL = -27, /**< Got NULL pointer */
+ BCM_ERR_READ_ONLY = -28, /**< Attempt to set read-only parameter */
+ BCM_ERR_ONU_ERR_RESP = -29, /**< ONU returned an error response */
+ BCM_ERR_MANDATORY_PARM_IS_MISSING = -30, /**< Mandatory parameter is missing */
+ BCM_ERR_KEY_RANGE = -31, /**< Key field was out of range */
+ BCM_ERR_QUEUE_EMPTY = -32, /**< Rx PCIe queue empty */
+ BCM_ERR_QUEUE_FULL = -33, /**< Tx PCIe queue full */
+ BCM_ERR_TOO_LONG = -34, /**< Processing is taking too long, but will finish eventually */
+ BCM_ERR_INSUFFICIENT_LIST_MEM = -35, /**< Not enough memory was provided for variable-length lists */
+
+ BCM_ERR_OUT_OF_SYNC = -36, /**< Sequence number or operation step was out of sync. */
+ BCM_ERR_CHECKSUM = -37, /**< Checksum error */
+ BCM_ERR_IMAGE_TYPE = -38, /**< Unsupported file/image type */
+ BCM_ERR_INCOMPLETE_TERMINATION = -39, /**< Incomplete premature termination */
+} bcmos_errno;
+
+/** Map error code to error string
+ * \param[in] err Error code
+ * \returns Error string
+ */
+const char *bcmos_strerror(bcmos_errno err);
+
+/** @} system_errno */
+
+#endif /* BCMOS_ERRNO_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.c b/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.c
new file mode 100644
index 0000000..12e1962
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.c
@@ -0,0 +1,467 @@
+/*
+<: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_hash_table.h"
+
+#define ht_overhead sizeof(void *)
+
+/** Create a hash table using a block pool
+ * \param[in] pool_parm pointer to block pool parameters
+ * \param[in] max_data_entries Maximum entries the hash table needs to hold
+ * \param[in] entry_size Size of each entry in bytes
+ * \param[in] key_size Size of each key in bytes
+ * \return pointer to newly created hash table
+ */
+static hash_table *hash_table_create_in_pool(bcmos_blk_pool_parm *pool_parm,
+ uint32_t max_data_entries,
+ uint16_t entry_size,
+ uint8_t key_size)
+{
+ uint32_t lookup_table_entries = max_data_entries + (max_data_entries / 4);
+ hash_table *ht;
+ bcmos_errno err;
+
+ if (pool_parm == NULL)
+ {
+ BUG();
+ return NULL;
+ }
+
+ entry_size += key_size;
+
+ ht = bcmos_alloc(sizeof(hash_table));
+ if (ht == NULL)
+ {
+ BUG();
+ return NULL;
+ }
+
+ ht->obj_len = entry_size;
+ ht->key_len = key_size;
+ ht->data_offset = ht_overhead;
+ ht->ht_lookup_tbl_entries = lookup_table_entries;
+ ht->ht_max_data_entries = max_data_entries;
+ ht->look_up_entries_tbl = bcmos_alloc(lookup_table_entries * sizeof(ht_block));
+
+ if (ht->look_up_entries_tbl == NULL)
+ {
+ bcmos_free(ht);
+ BUG();
+ return NULL;
+ }
+
+ ht->ht_cur_entries = 0;
+ err = bcmos_blk_pool_create(&ht->key_data_pool, pool_parm);
+
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_free(ht->look_up_entries_tbl);
+ bcmos_free(ht);
+ BUG();
+ return NULL;
+ }
+
+ if (ht->ht_max_data_entries > ht->ht_lookup_tbl_entries)
+ {
+ BUG();
+ }
+
+ ht->obj_len -= ht->key_len;
+
+ memset(ht->look_up_entries_tbl, 0, lookup_table_entries * sizeof(ht_block));
+ return ht;
+}
+
+hash_table *hash_table_create(uint32_t max_data_entries,
+ uint16_t entry_size,
+ uint8_t key_size,
+ char *pool_name)
+{
+ bcmos_blk_pool_parm parm = {0};
+
+ parm.name = pool_name;
+ parm.blk_size = entry_size + key_size + ht_overhead;
+ parm.num_blks = max_data_entries;
+
+ return hash_table_create_in_pool(&parm, max_data_entries, entry_size, key_size);
+}
+
+/** Hash a length of bytes into a uint32_t
+ * \param[in] key Bytes to hash
+ * \param[in] len Number of bytes in key
+ * \return The hash as a uint32_t
+ */
+static uint32_t get_hash_for_key(const uint8_t *key, uint8_t len)
+{
+ uint32_t hash = 5381;
+ uint8_t i;
+ const uint8_t *tmp = key;
+ for (i = 0; i < len; tmp++, i++)
+ {
+ hash = ((hash << 5) + hash) + (*tmp);
+ }
+
+ return hash;
+}
+
+/** Gets a hash key used for the keyDataPool in the HashTable
+ * \param[in] ht Associated hashtable we are getting hash for key for
+ * \param[in] key Key we are getting hash for
+ * \return An index into the keyDataPool
+ */
+static uint32_t get_hash_val_for_key(const hash_table *ht, const uint8_t *key)
+{
+ return get_hash_for_key(key, ht->key_len) % ht->ht_lookup_tbl_entries;
+}
+
+/** Returns the location of the key within an HtBlock
+ * \param[in] ht Hash table in question
+ * \param[in] block HtBlock in question
+ * \return pointer to the data within the block
+ */
+static uint8_t *get_key_from_block_in_table(const hash_table *ht, ht_block *block)
+{
+ return(uint8_t *) block + ht->data_offset + ht->obj_len;
+}
+
+/** Gets and populates a HtBlock with all of its data
+ * \param[in] next Next block in this buckets chain
+ * \param[in] ht Hash table in question
+ * \param[in] key This blocks key
+ * \param[in] val This blocks data
+ * \return The block that we allocated and returned
+ */
+static ht_block *fill_ht_block(ht_block *next,
+ hash_table *ht,
+ const uint8_t *key,
+ const void *val)
+{
+ ht_block *dest_block = bcmos_blk_pool_alloc(&ht->key_data_pool);
+
+ if (dest_block != NULL)
+ {
+ /* storage is nextobj ptr, hash obj,
+ key which keeps all uint32_t aligned. */
+ dest_block->next_chain = next;
+
+ if (val != NULL)
+ {
+ memcpy((uint8_t *) dest_block + ht->data_offset, val, ht->obj_len);
+ }
+ else
+ {
+ memset((uint8_t *) dest_block + ht->data_offset,0,ht->obj_len);
+ }
+
+ /* Need to put key in after obj */
+ memcpy(
+ (uint8_t *) dest_block + ht->data_offset + ht->obj_len,
+ key,
+ ht->key_len);
+ }
+
+ return dest_block;
+}
+
+/** Determine whether two keys in a particular hash table match
+ * \param[in] ht Hashtable
+ * \param[in] key_a first key to compare
+ * \param[in] key_b second key to compare
+ * \return whether they are the same
+ */
+static bcmos_bool is_key_match(const hash_table *ht, const uint8_t *key_a, const uint8_t *key_b)
+{
+ return memcmp(key_a, key_b, ht->key_len) == 0;
+}
+
+/** Searches a chained bucket looking for an instance of the key. If found returns the block if found the key in.
+ * Prev guy is set to the block in the chain before the block we returned (except in the case * where there is no
+ * block before the one we returned.
+ * \param[in] ht HashTable in question
+ * \param[in] key_to_find Key we wonder if exists
+ * \param[in] chain_start Where to start looking in the chain
+ * \param[in] prev_block The previous guy before the block we returned (if exists)
+ * \return The block that matches doesExists (if exists)
+ */
+static ht_block *get_key_loc_in_chain(
+ const hash_table *ht,
+ const uint8_t *key_to_find,
+ ht_block *chain_start,
+ ht_block **prev_block)
+{
+ *prev_block = NULL;
+ while (chain_start != NULL)
+ {
+ if (is_key_match(ht, key_to_find, get_key_from_block_in_table(ht, chain_start)))
+ {
+ return chain_start;
+ }
+ *prev_block = chain_start;
+ chain_start = chain_start->next_chain;
+ }
+ return NULL;
+}
+
+bcmos_bool hash_table_remove(hash_table *ht, const uint8_t *key)
+{
+ uint32_t hash_val = get_hash_val_for_key(ht, key);
+ ht_block *prev_entry;
+ ht_block *entry = get_key_loc_in_chain(
+ ht,
+ key,
+ ht->look_up_entries_tbl[hash_val].next_chain,
+ &prev_entry);
+
+ if (entry == NULL)
+ {
+ /* No one to delete */
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ ht->ht_cur_entries--;
+ if (prev_entry == NULL)
+ {
+ /* last entry */
+ ht->look_up_entries_tbl[hash_val].next_chain = entry->next_chain;
+ }
+ else
+ {
+ prev_entry->next_chain = entry->next_chain;
+ }
+ bcmos_blk_pool_free(entry);
+ return BCMOS_TRUE;
+ }
+}
+
+/** Returns a pointer to the data within the HT
+ * \param[in] ht Hashtable in question
+ * \param[in] block_ptr HtBlock that we wonder where its data is
+ */
+static void *get_ht_data_ptr(const hash_table *ht, ht_block *block_ptr)
+{
+ return(uint8_t*)block_ptr + ht->data_offset;
+}
+
+
+/** Get an entry in the hash table
+ * \param[in] ht pointer to hash table
+ * \param[in] key pointer to key data
+ * \param[in] hash_val hash value of key
+ * \return pointer to hash table entry
+ */
+static inline void *ht_get_internal(const hash_table *ht,
+ const uint8_t *key,
+ uint32_t hash_val)
+{
+ ht_block *tmp;
+ ht_block *ret;
+ ret = get_key_loc_in_chain(
+ ht,
+ key,
+ ht->look_up_entries_tbl[hash_val].next_chain,
+ &tmp);
+ if (ret != NULL)
+ {
+ return get_ht_data_ptr(ht,ret);
+ }
+ else
+ {
+ return ret;
+ }
+}
+
+void *hash_table_get(const hash_table *ht, const uint8_t *key)
+{
+ uint32_t hashVal = get_hash_val_for_key(ht, key);
+ return ht_get_internal(ht,key,hashVal);
+}
+
+void *hash_table_put(hash_table *ht, const uint8_t *key, const void *val)
+{
+ void *ret_block;
+ uint32_t hash_val;
+ if (ht->ht_cur_entries >= ht->ht_max_data_entries)
+ {
+ return NULL;
+ }
+ hash_val = get_hash_val_for_key(ht, key);
+
+ ret_block = ht_get_internal((const hash_table *) ht, key, hash_val);
+ if (ret_block != NULL)
+ {
+ /* replace existing value with new value */
+ if (val != NULL)
+ {
+ memcpy(ret_block, val, ht->obj_len);
+ }
+ else
+ {
+ memset(ret_block, 0, ht->obj_len);
+ }
+ return ret_block;
+ }
+ else
+ {
+ ht_block *new_block=fill_ht_block(
+ ht->look_up_entries_tbl[hash_val].next_chain, ht, key, val);
+ if (new_block != NULL)
+ {
+ ht->look_up_entries_tbl[hash_val].next_chain = new_block;
+ ht->ht_cur_entries++;
+ return get_ht_data_ptr(ht,new_block);
+ }
+ else
+ {
+ return NULL;
+ }
+ }
+
+}
+
+ht_iterator ht_iterator_get(const hash_table *ht)
+{
+ ht_iterator to_ret;
+ to_ret.ht = ht;
+ to_ret.cur_idx = 0;
+ to_ret.removed_at = BCMOS_FALSE;
+ to_ret.still_valid = BCMOS_TRUE;
+ to_ret.cur_block = NULL;
+ return to_ret;
+}
+
+ht_iterator ht_iterator_get_by_key(const hash_table *ht, const uint8_t *key)
+{
+ ht_block *tmp;
+ uint32_t hash_val = get_hash_val_for_key(ht, key);
+ ht_iterator to_ret = {};
+ to_ret.ht = ht;
+ to_ret.removed_at = BCMOS_FALSE;
+ to_ret.cur_block = get_key_loc_in_chain(ht, key, ht->look_up_entries_tbl[hash_val].next_chain, &tmp);
+ to_ret.still_valid = (to_ret.cur_block != NULL);
+ to_ret.cur_idx = hash_val;
+
+ return to_ret;
+}
+
+/** Advance linear scan iterator
+ * \param[in] it Iterator to advance
+ */
+static void ht_iterator_scan_adv(ht_iterator *it)
+{
+ if (it->cur_block != NULL)
+ {
+ it->cur_block = it->cur_block->next_chain;
+ if (it->cur_block != NULL)
+ {
+ it->still_valid = BCMOS_TRUE;
+ return;
+ }
+ else
+ {
+ it->cur_idx++;
+ }
+ }
+ /* find non null entry */
+ while (it->cur_idx < it->ht->ht_lookup_tbl_entries)
+ {
+ if (it->ht->look_up_entries_tbl[it->cur_idx].next_chain != NULL)
+ {
+ it->cur_block = it->ht->look_up_entries_tbl[it->cur_idx].next_chain;
+ it->still_valid = BCMOS_TRUE;
+ return;
+ }
+ else
+ {
+ it->cur_idx++;
+ }
+ }
+ it->still_valid = BCMOS_FALSE;
+}
+
+void ht_iterator_deref(const ht_iterator *hti, uint8_t **key, void **obj)
+{
+ if (!hti->still_valid)
+ {
+ BCMOS_TRACE_ERR("%s: Invalid deref\n", __FUNCTION__);
+ }
+ else
+ {
+ *key = get_key_from_block_in_table(hti->ht, hti->cur_block);
+ *obj = get_ht_data_ptr(hti->ht, hti->cur_block); /* to data */
+ }
+}
+
+void ht_iterator_remove_at(hash_table *ht, ht_iterator *it)
+{
+ if (ht != it->ht)
+ {
+ BCMOS_TRACE_ERR("%s: Incorrect writeable hash table pointer\n", __FUNCTION__);
+ }
+ else if (it->removed_at)
+ {
+ BCMOS_TRACE_ERR("%s: No delete twice\n", __FUNCTION__);
+ }
+ else
+ {
+ uint8_t *key;
+ uint8_t *obj;
+ ht_iterator_deref(it, &key, (void **) &obj);
+ it->removed_at = BCMOS_TRUE;
+ it->still_valid = ht_iterator_next(it);
+ if (!hash_table_remove(ht, key))
+ {
+ BCMOS_TRACE_ERR("%s: Remove error\n", __FUNCTION__);
+ }
+ }
+}
+
+bcmos_bool ht_iterator_next(ht_iterator *it)
+{
+ if (it->still_valid)
+ {
+ if (it->removed_at)
+ {
+ it->removed_at = BCMOS_FALSE;
+ }
+ else
+ {
+ ht_iterator_scan_adv(it);
+ }
+ }
+ return it->still_valid; /* No entry found */
+}
+
+void hash_table_clear(hash_table *ht)
+{
+ ht_iterator it = ht_iterator_get(ht);
+ while (ht_iterator_next(&it))
+ {
+ ht_iterator_remove_at(ht, &it);
+ }
+}
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.h
new file mode 100644
index 0000000..15618d6
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_hash_table.h
@@ -0,0 +1,137 @@
+/*
+<: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 BCMOS_HASH_TABLE_H_
+#define BCMOS_HASH_TABLE_H_
+
+#include "bcmos_system.h"
+
+typedef struct ht_block ht_block;
+struct ht_block
+{
+ ht_block *next_chain;
+};
+
+typedef struct
+{
+ uint16_t obj_len;
+ uint8_t key_len;
+ uint32_t data_offset;
+ uint32_t ht_lookup_tbl_entries;
+ uint32_t ht_max_data_entries;
+ bcmos_blk_pool key_data_pool;
+ ht_block *look_up_entries_tbl;
+ uint32_t ht_cur_entries;
+} hash_table;
+
+typedef struct
+{
+ const hash_table *ht;
+ uint32_t cur_idx;
+ ht_block *cur_block;
+ bcmos_bool removed_at;
+ bcmos_bool still_valid;
+} ht_iterator;
+
+/** Create a hash table
+ * \param[in] max_data_entries Maximum entries the hash table needs to hold
+ * \param[in] entry_size Size of each entry in bytes
+ * \param[in] key_size Size of each key in bytes
+ * \param[in] pool_name Friendly name to identify the hash table's memory pool
+ * \return pointer to newly created hash table
+ */
+hash_table *hash_table_create(uint32_t max_data_entries,
+ uint16_t entry_size,
+ uint8_t key_size,
+ char *pool_name);
+
+/** Removes all entries from a HashTable.
+ * \param[in] ht Hash table to remove all entries from
+ */
+void hash_table_clear(hash_table *ht);
+
+/** Gets a pointer to an entry within the hash table (if exists)
+ * \param[in] ht Hashtable in question
+ * \param[in] key Key to look for.
+ * \return Non null if we found a data item associated with KEY.
+ */
+void *hash_table_get(const hash_table *ht, const uint8_t *key);
+
+/** Returns pointers to the key and value that an iterator is pointing at. Warning: key may not be uint32_t aligned.
+ * DO NOT DELETE THE ELEMENT THE ITERATOR POINTS AT AND AND TRY TO USE THE ITERATOR SUBSEQUENTLY. If you need to do
+ * this use ht_iterator_remove_at
+ * \param[in] hti Iterator
+ * \param[in] key Pointer to key to fill
+ * \param[in] obj Pointer to obj to fill.
+ */
+void ht_iterator_deref(const ht_iterator *hti, uint8_t **key, void **obj);
+
+/** Get an interator for traversing a hashtable.
+ * \param[in] ht Hashtable to traverse
+ * \return The iterator.
+ */
+ht_iterator ht_iterator_get(const hash_table *ht);
+
+/** Get an interator for traversing a hashtable based on an entry's key.
+ * \param[in] ht Hashtable to traverse
+ * \param[in] key key of entry to return
+ * \return The iterator.
+ */
+ht_iterator ht_iterator_get_by_key(const hash_table *ht, const uint8_t *key);
+
+/** Advances a HashTable iterator to the next location within the HashTable.
+ * \param[in] it Iterator to advance
+ * \return TRUE if there was a next element
+ */
+bcmos_bool ht_iterator_next(ht_iterator *it);
+
+/** Deletes the entry where the iterator points to and advances the iterator returning whether the advance worked or
+ * not.
+ * \param[in] ht Writable reference to the hash table (the iterator only has read permission)
+ * \param[in] it Itreator pointing at entry to delete.
+ */
+void ht_iterator_remove_at(hash_table *ht, ht_iterator *it);
+
+/** Attempts to associate key with val in the hash table. If key already exists overwrites what was at key with val.
+ * Otherwise allocates an entry within the hashtable for key and copies val into it.
+ * \param[in] ht Hashtable to add or modify
+ * \param[in] key Key to try and associate with val.
+ * \param[in] val Val to associate
+ * \return NULL if fail, else pointer to just added block.
+ */
+void *hash_table_put(hash_table *ht, const uint8_t *key, const void *val);
+
+/** Removes an entry (if exists) from the hash table.
+ * \param[in] ht HashTable to remove from.
+ * \param[in] key Key to remove
+ * \return BCMOS_TRUE if anything was removed, otherwise BCMOS_FALSE.
+ */
+bcmos_bool hash_table_remove(hash_table *ht, const uint8_t *key);
+
+#endif /* Hash.h */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_pack.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_pack.h
new file mode 100644
index 0000000..2161045
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_pack.h
@@ -0,0 +1,67 @@
+/*
+<: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 BCMOS_PACK_H_
+#define BCMOS_PACK_H_
+
+
+/*
+ * Packing macros
+ *
+ * Usage:
+ * struct __PACKED_ATTR_START__ my_packed_struct
+ * {
+ * ...
+ * } __PACKED_ATTR_END__ ;
+ *
+ */
+
+#ifdef __GNUC__
+
+#define __PACKED_ATTR_START__
+#define __PACKED_ATTR_END__ __attribute__ ((packed))
+
+#else
+
+#error define __PACKED_ATTR_START__, __PACKED_ATTR_END__ for this compiler
+
+#endif
+
+/*
+ * Macros for bit-field manipulation
+ * For each field F requires 2 constants
+ * - F_S - field shift
+ * - F_W - field width
+ */
+#define BCM_FIELD_GET(_w, _f) (((_w)>>_f ## _S) & ((1 << _f ## _W) - 1))
+#define BCM_FIELD(_f, _v) ((_v & ((1 << _f ## _W) - 1)) << _f ## _S)
+#define BCM_FIELD_SET(_w, _f, _v) (_w) |= BCM_FIELD(_f, _v)
+
+
+#endif /* BCMOS_PACK_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_platform.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_platform.h
new file mode 100644
index 0000000..7b40fb1
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_platform.h
@@ -0,0 +1,236 @@
+/*
+<: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 BCMOS_PLATFORM_H_
+#define BCMOS_PLATFORM_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_platform.h directly. Include bcmos_system.h
+#endif
+
+/** BCM68620 CPU core
+ * \ingroup system_task */
+typedef enum
+{
+ BCMOS_CPU_CORE_ANY, /**< Any core */
+
+ BCMOS_CPU_CORE__NUM_OF = 1, /**< Number of cores */
+} bcmos_core;
+
+#define MAX_NUMBER_OF_PONS_ON_ALL_DEVICES (BCMTR_MAX_OLTS * BCMTR_MAX_INSTANCES)
+
+/** BCM68620 module
+ * \ingroup system_module
+ */
+typedef enum
+{
+ BCMOS_MODULE_ID_NONE, /**< no module */
+
+#ifdef BCMOS_SYS_UNITTEST
+ BCMOS_MODULE_ID_TEST1,
+ BCMOS_MODULE_ID_TEST2,
+#endif
+ /* Each Device (BCM6862X) must have its own dedicated Device Control Module at the host */
+ BCMOS_MODULE_ID_DEV_CTRL_DEV0,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV1,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV2,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV3,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV4,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV5,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV6,
+ BCMOS_MODULE_ID_DEV_CTRL_DEV7,
+
+ /* CLI over PCIe client */
+ BCMOS_MODULE_ID_CLI_OVER_PCIE,
+
+ /* Protection switching user application */
+ BCMOS_MODULE_ID_USER_APPL_PS,
+
+ /* Remote CLI */
+ BCMOS_MODULE_ID_REMOTE_CLI_DEV0,
+
+ /* Remote logger application (To support multiple devices need to add number of devices to previous value) */
+ BCMOS_MODULE_ID_USER_APPL_REMOTE_LOGGER_DEV0 = BCMOS_MODULE_ID_REMOTE_CLI_DEV0 + BCMTR_MAX_OLTS,
+
+ /* OMCI SW download user application (To support multiple devices need to add number of devices to previous value) */
+ BCMOS_MODULE_ID_USER_APPL_OMCI_SWDL_DEV0 = BCMOS_MODULE_ID_USER_APPL_REMOTE_LOGGER_DEV0 + BCMTR_MAX_OLTS,
+
+ /* GPON mac learning / aging user application (To support multiple devices need to add number of devices to previous value)*/
+ BCMOS_MODULE_ID_USER_APPL_GPON_MAC_LEARNING_DEV0 = BCMOS_MODULE_ID_USER_APPL_OMCI_SWDL_DEV0 + BCMTR_MAX_OLTS,
+
+ /* GPON stress user application (To support multiple devices need to add number of devices to previous value)*/
+ BCMOS_MODULE_ID_USER_APPL_GPON_STRESS_DEV0 = BCMOS_MODULE_ID_USER_APPL_GPON_MAC_LEARNING_DEV0 + BCMTR_MAX_OLTS,
+
+ /* GPON DS OMCI packets user application (To support multiple devices need to add number of devices to previous value)*/
+ BCMOS_MODULE_ID_USER_APPL_GPON_DS_OMCI0_DEV0 = BCMOS_MODULE_ID_USER_APPL_GPON_STRESS_DEV0 + BCMTR_MAX_OLTS,
+
+ /* GPON SN acquisition (To support multiple devices need to add number of devices multiply with max PON number to previous value)*/
+ BCMOS_MODULE_ID_USER_APPL_GPON_SN_ACQUISITION0_DEV0 = BCMOS_MODULE_ID_USER_APPL_GPON_DS_OMCI0_DEV0 + MAX_NUMBER_OF_PONS_ON_ALL_DEVICES,
+
+ /* GPON statistics (To support multiple devices need to add number of devices multiply with max PON number to previous value) */
+ BCMOS_MODULE_ID_USER_APPL_GPON_STATISTICS0_DEV0 = BCMOS_MODULE_ID_USER_APPL_GPON_SN_ACQUISITION0_DEV0 + MAX_NUMBER_OF_PONS_ON_ALL_DEVICES,
+
+ /* GPON RSSI user application (To support multiple devices need to add number of devices multiply with max PON number to previous value) */
+ BCMOS_MODULE_ID_USER_APPL_GPON_RSSI_DEV0 = BCMOS_MODULE_ID_USER_APPL_GPON_STATISTICS0_DEV0 + MAX_NUMBER_OF_PONS_ON_ALL_DEVICES,
+
+ /* EPON OAM negotiation application (To support multiple devices need to add number of devices to previous value)*/
+ BCMOS_MODULE_ID_USER_APPL_EON = BCMOS_MODULE_ID_USER_APPL_GPON_RSSI_DEV0 + BCMTR_MAX_OLTS,
+
+ /* EPON optical monitoring application */
+ BCMOS_MODULE_ID_USER_APPL_OMON = BCMOS_MODULE_ID_USER_APPL_EON + BCMTR_MAX_OLTS,
+
+ /* EPON Host driven encryption application */
+ BCMOS_MODULE_ID_USER_APPL_EPON_HDE,
+
+ BCMOS_MODULE_ID_USER_APPL_EPON_OAM,
+
+ BCMOS_MODULE_ID_USER_APPL_DPOE_SEC,
+
+ BCMOS_MODULE_ID_USER_APPL_IMAGE_TRANSFER0 = BCMOS_MODULE_ID_USER_APPL_DPOE_SEC + BCMTR_MAX_OLTS,
+ BCMOS_MODULE_ID_USER_APPL_IMAGE_TRANSFER1,
+
+ BCMOS_MODULE_ID_USER_APPL_ONU_TUNING_DEV0,
+ BCMOS_MODULE_ID_USER_APPL_ONU_TUNING_DEV1,
+
+ BCMOS_MODULE_ID__NUM_OF, /**< Number of modules */
+ BCMOS_MODULE_ID_INVALID = BCMOS_MODULE_ID_NONE
+} bcmos_module_id;
+
+/** BCM68620 event group. Each group supports up to 32 events.
+ * \ingroup system_event
+ */
+typedef enum
+{
+#ifdef BCMOS_SYS_UNITTEST
+ BCMOS_EVENT_ID_TEST1,
+ BCMOS_EVENT_ID_TEST2,
+#else
+ BCMOS_EVENT_ID_DUMMY, /* Currently OS s/w doesn't use events.
+ Remove this constant when adding real events */
+#endif
+
+ BCMOS_EVENT_ID__NUM_OF, /**< Number of event groups */
+} bcmos_event_id;
+
+/** Message hash size
+ * \ingroup system_msg
+ */
+#define BCMOS_MSG_HASH_SIZE 512
+
+/** Maple OS message
+ * \ingroup system_msg
+ */
+typedef enum
+{
+ BCMOS_MSG_ID__BEGIN,
+
+ /* Internal messages */
+ BCMOS_MSG_ID_INTERNAL_TIMER = BCMOS_MSG_ID__BEGIN, /**< Internal "timer message" type */
+ BCMOS_MSG_ID_INTERNAL_EVENT, /**< Internal "event message" type */
+ BCMOS_MSG_ID_INTERNAL_IPC,
+
+ BCMOS_MSG_ID_INITIATE_RX_POWER,
+ BCMOS_MSG_ID_INITIATE_TRX_STATUS,
+ BCMOS_MSG_ID_INITIATE_ROGUE_SCAN,
+ BCMOS_MSG_ID_INITIATE_RSSI_READ,
+
+ BCMOS_MSG_ID_GPON_STRESS_START,
+ BCMOS_MSG_ID_GPON_STRESS_TIMEOUT,
+ BCMOS_MSG_ID_GPON_STRESS_ONU_DISCOVERED,
+ BCMOS_MSG_ID_GPON_STRESS_PON_DEACTIVATION_COMPLETED,
+ BCMOS_MSG_ID_GPON_STRESS_PON_ACTIVATION_COMPLETED,
+ BCMOS_MSG_ID_GPON_STRESS_ALL_ONUS_DEACTIVATION_COMPLETED,
+ BCMOS_MSG_ID_GPON_STRESS_ALL_ONUS_ACTIVATION_COMPLETED,
+ BCMOS_MSG_ID_GPON_STRESS_ONU_DEACTIVATION_COMPLETED,
+ BCMOS_MSG_ID_GPON_STRESS_ONU_ACTIVATION_COMPLETED,
+
+ BCMOS_MSG_ID_GPON_DS_OMCI_START,
+ BCMOS_MSG_ID_GPON_DS_OMCI_TIMEOUT,
+ BCMOS_MSG_ID_GPON_DS_OMCI_STOP,
+ BCMOS_MSG_ID_GPON_DS_OMCI_DEVICE_CONNECTED,
+ BCMOS_MSG_ID_GPON_DS_OMCI_DEVICE_DISCONNECTED,
+
+ BCMOS_MSG_ID_GPON_RSSI_START,
+
+ BCMOS_MSG_ID_GPON_STATISTICS_START,
+ BCMOS_MSG_ID_GPON_STATISTICS_TIMEOUT,
+ BCMOS_MSG_ID_GPON_STATISTICS_STOP,
+
+ BCMOS_MSG_ID_EON_START,
+ BCMOS_MSG_ID_EON_STOP,
+ BCMOS_MSG_ID_EON_PROXY_RX,
+
+ BCMOS_MSG_ID_EPON_OAM_PROXY_RX,
+ BCMOS_MSG_ID_EPON_OAM_TIMEOUT,
+
+ BCMOS_MSG_ID_DPOE_SEC_START,
+ BCMOS_MSG_ID_DPOE_SEC_RX_OAM,
+ BCMOS_MSG_ID_DPOE_SEC_RX_EAPOL,
+
+ BCMOS_MSG_ID_ONU_TUNING_START,
+ BCMOS_MSG_ID_ONU_TUNING_STOP,
+
+ BCMOS_MSG_ID__NONE,
+ BCMOS_MSG_ID__END,
+ BCMOS_MSG_ID__FORCE16 = 0x7fff
+} bcmos_msg_id;
+
+#define BCMOS_MSG_ID__NUM_OF (BCMOS_MSG_ID__END - BCMOS_MSG_ID__BEGIN)
+/*
+ * Task priorities
+ */
+
+#define TASK_PRIORITY_TRANSPORT_TX BCMOS_TASK_PRIORITY_3
+#define TASK_PRIORITY_TRANSPORT_RX BCMOS_TASK_PRIORITY_8
+#define TASK_PRIORITY_TRANSPORT_PROXY BCMOS_TASK_PRIORITY_9
+#define TASK_PRIORITY_TRANSPORT_REMOTE_CLI BCMOS_TASK_PRIORITY_9
+#define TASK_PRIORITY_DEVICE_CONTROL BCMOS_TASK_PRIORITY_10
+#define TASK_PRIORITY_USER_APPL_PS BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_EON BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_OMON BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_EPON_HDE BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_DPOE_SEC BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_MAC_LEARNING BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_STRESS BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_SN_ACQUISITION BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_DS_OMCI BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_STATISTICS BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_ONU_TUNING BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_USER_APPL_GPON_RSSI BCMOS_TASK_PRIORITY_12
+#define TASK_PRIORITY_CLI BCMOS_TASK_PRIORITY_15
+#define TASK_PRIORITY_USER_APPL_OMCI_SWDL BCMOS_TASK_PRIORITY_17
+#define TASK_PRIORITY_USER_APPL_IMAGE_TRANSFER BCMOS_TASK_PRIORITY_17
+#define TASK_PRIORITY_DEV_LOG_KERNEL BCMOS_TASK_PRIORITY_20
+#define TASK_PRIORITY_DEV_LOG BCMOS_TASK_PRIORITY_30
+#define TASK_PRIORITY_USER_APPL_REMOTE_LOGGER BCMOS_TASK_PRIORITY_30
+
+
+
+
+#endif /* BCMOS_PLATFORM_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_queue.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_queue.h
new file mode 100644
index 0000000..2172e4d
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_queue.h
@@ -0,0 +1,650 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ * $FreeBSD$
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/* #include <sys/cdefs.h> */
+
+/*
+ * This file defines four types of data structures: singly-linked lists,
+ * singly-linked tail queues, lists and tail queues.
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A singly-linked tail queue is headed by a pair of pointers, one to the
+ * head of the list and the other to the tail of the list. The elements are
+ * singly linked for minimum space and pointer manipulation overhead at the
+ * expense of O(n) removal for arbitrary elements. New elements can be added
+ * to the list after an existing element, at the head of the list, or at the
+ * end of the list. Elements being removed from the head of the tail queue
+ * should use the explicit macro for this purpose for optimum efficiency.
+ * A singly-linked tail queue may only be traversed in the forward direction.
+ * Singly-linked tail queues are ideal for applications with large datasets
+ * and few or no removals or for implementing a FIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ *
+ *
+ * SLIST LIST STAILQ TAILQ
+ * _HEAD + + + +
+ * _HEAD_INITIALIZER + + + +
+ * _ENTRY + + + +
+ * _INIT + + + +
+ * _EMPTY + + + +
+ * _FIRST + + + +
+ * _NEXT + + + +
+ * _PREV - - - +
+ * _LAST - - + +
+ * _FOREACH + + + +
+ * _FOREACH_SAFE + + + +
+ * _FOREACH_REVERSE - - - +
+ * _FOREACH_REVERSE_SAFE - - - +
+ * _INSERT_HEAD + + + +
+ * _INSERT_BEFORE - + - +
+ * _INSERT_AFTER + + + +
+ * _INSERT_TAIL - - + +
+ * _CONCAT - - + +
+ * _REMOVE_AFTER + - + -
+ * _REMOVE_HEAD + - + -
+ * _REMOVE + + + +
+ *
+ */
+#ifdef QUEUE_MACRO_DEBUG
+/* Store the last 2 places the queue element or head was altered */
+struct qm_trace {
+ char * lastfile;
+ int lastline;
+ char * prevfile;
+ int prevline;
+};
+
+#define TRACEBUF struct qm_trace trace;
+#define TRASHIT(x) do {(x) = (void *)-1;} while (0)
+
+#define QMD_TRACE_HEAD(head) do { \
+ (head)->trace.prevline = (head)->trace.lastline; \
+ (head)->trace.prevfile = (head)->trace.lastfile; \
+ (head)->trace.lastline = __LINE__; \
+ (head)->trace.lastfile = __FILE__; \
+} while (0)
+
+#define QMD_TRACE_ELEM(elem) do { \
+ (elem)->trace.prevline = (elem)->trace.lastline; \
+ (elem)->trace.prevfile = (elem)->trace.lastfile; \
+ (elem)->trace.lastline = __LINE__; \
+ (elem)->trace.lastfile = __FILE__; \
+} while (0)
+
+#else
+#define QMD_TRACE_ELEM(elem)
+#define QMD_TRACE_HEAD(head)
+#define TRACEBUF
+#define TRASHIT(x)
+#endif /* QUEUE_MACRO_DEBUG */
+
+/* Lint support requires types to be defined using typedefs.
+ No adding "struct" implicitly
+*/
+#ifdef USE_LINT
+#define _Q_TYPE_CAST(type) (type *)
+#define _Q_TYPE_FIELD(type, field) type field
+#else
+#define _Q_TYPE_CAST(type) (struct type *)
+#define _Q_TYPE_FIELD(type, field) struct type field
+#endif
+
+/*
+ * Singly-linked List declarations.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ _Q_TYPE_FIELD(type, *slh_first); /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ _Q_TYPE_FIELD(type, *sle_next); /* next element */ \
+}
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_EMPTY(head) ((head)->slh_first == NULL)
+
+#define SLIST_FIRST(head) ((head)->slh_first)
+
+#define SLIST_FOREACH(var, head, field) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var); \
+ (var) = SLIST_NEXT((var), field))
+
+#define SLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = SLIST_FIRST((head)); \
+ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != NULL; \
+ (varp) = &SLIST_NEXT((var), field))
+
+#define SLIST_INIT(head) do { \
+ SLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \
+ SLIST_NEXT((slistelm), field) = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \
+ SLIST_FIRST((head)) = (elm); \
+} while (0)
+
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if (SLIST_FIRST((head)) == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ _Q_TYPE_FIELD(type, *curelm) = SLIST_FIRST((head)); \
+ while (SLIST_NEXT(curelm, field) != (elm)) \
+ curelm = SLIST_NEXT(curelm, field); \
+ SLIST_REMOVE_AFTER(curelm, field); \
+ } \
+ TRASHIT((elm)->field.sle_next); \
+} while (0)
+
+#define SLIST_REMOVE_AFTER(elm, field) do { \
+ SLIST_NEXT(elm, field) = \
+ SLIST_NEXT(SLIST_NEXT(elm, field), field); \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \
+} while (0)
+
+/*
+ * Singly-linked Tail queue declarations.
+ */
+#define STAILQ_HEAD(name, type) \
+struct name { \
+ _Q_TYPE_FIELD(type, *stqh_first);/* first element */ \
+ _Q_TYPE_FIELD(type, **stqh_last);/* addr of last next element */ \
+}
+
+#define STAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).stqh_first }
+
+#define STAILQ_ENTRY(type) \
+struct { \
+ _Q_TYPE_FIELD(type, *stqe_next); /* next element */ \
+}
+
+/*
+ * Singly-linked Tail queue functions.
+ */
+#define STAILQ_CONCAT(head1, head2) do { \
+ if (!STAILQ_EMPTY((head2))) { \
+ *(head1)->stqh_last = (head2)->stqh_first; \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_INIT((head2)); \
+ } \
+} while (0)
+
+#define STAILQ_EMPTY(head) ((head)->stqh_first == NULL)
+
+#define STAILQ_FIRST(head) ((head)->stqh_first)
+
+#define STAILQ_FOREACH(var, head, field) \
+ for((var) = STAILQ_FIRST((head)); \
+ (var); \
+ (var) = STAILQ_NEXT((var), field))
+
+
+#define STAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = STAILQ_FIRST((head)); \
+ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define STAILQ_INIT(head) do { \
+ STAILQ_FIRST((head)) = NULL; \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_NEXT((tqelm), field) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_HEAD(head, elm, field) do { \
+ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+ STAILQ_FIRST((head)) = (elm); \
+} while (0)
+
+#define STAILQ_INSERT_TAIL(head, elm, field) do { \
+ STAILQ_NEXT((elm), field) = NULL; \
+ *(head)->stqh_last = (elm); \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_LAST(head, type, field) \
+ (STAILQ_EMPTY((head)) ? \
+ _Q_TYPE_CAST(type)NULL : \
+ ((type *)(void *) \
+ ((char *)((head)->stqh_last) - offsetof(type, field))))
+
+#define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next)
+
+#define STAILQ_REMOVE(head, elm, type, field) do { \
+ if (STAILQ_FIRST((head)) == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ _Q_TYPE_FIELD(type, *curelm) = STAILQ_FIRST((head)); \
+ while (STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ } \
+ TRASHIT((elm)->field.stqe_next); \
+} while (0)
+
+#define STAILQ_REMOVE_SAFE(head, elm, type, field) ({ \
+ _Q_TYPE_FIELD(type, *curelm) = STAILQ_FIRST((head)); \
+ if (curelm == (elm)) { \
+ STAILQ_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ while (curelm && STAILQ_NEXT(curelm, field) != (elm)) \
+ curelm = STAILQ_NEXT(curelm, field); \
+ if (curelm) \
+ STAILQ_REMOVE_AFTER(head, curelm, field); \
+ }; \
+ TRASHIT((elm)->field.stqe_next); \
+ curelm; \
+})
+
+#define STAILQ_REMOVE_HEAD(head, field) do { \
+ if ((STAILQ_FIRST((head)) = \
+ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_FIRST((head)); \
+} while (0)
+
+#define STAILQ_REMOVE_AFTER(head, elm, field) do { \
+ if ((STAILQ_NEXT(elm, field) = \
+ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \
+ (head)->stqh_last = &STAILQ_NEXT((elm), field); \
+} while (0)
+
+#define STAILQ_SWAP(head1, head2, type) do { \
+ _Q_TYPE_FIELD(type, *swap_first) = STAILQ_FIRST(head1); \
+ _Q_TYPE_FIELD(type, **swap_last) = (head1)->stqh_last; \
+ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \
+ (head1)->stqh_last = (head2)->stqh_last; \
+ STAILQ_FIRST(head2) = swap_first; \
+ (head2)->stqh_last = swap_last; \
+ if (STAILQ_EMPTY(head1)) \
+ (head1)->stqh_last = &STAILQ_FIRST(head1); \
+ if (STAILQ_EMPTY(head2)) \
+ (head2)->stqh_last = &STAILQ_FIRST(head2); \
+} while (0)
+
+
+/*
+ * List declarations.
+ */
+#define DLIST_HEAD(name, type) \
+struct name { \
+ _Q_TYPE_FIELD(type, *lh_first); /* first element */ \
+}
+
+#define DLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define DLIST_ENTRY(type) \
+struct { \
+ _Q_TYPE_FIELD(type, *le_next); /* next element */ \
+ _Q_TYPE_FIELD(type, **le_prev); /* address of previous next element */ \
+}
+
+/*
+ * List functions.
+ */
+
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_DLIST_CHECK_HEAD(head, field) do { \
+ if (DLIST_FIRST((head)) != NULL && \
+ DLIST_FIRST((head))->field.le_prev != \
+ &DLIST_FIRST((head))) \
+ panic("Bad list head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_DLIST_CHECK_NEXT(elm, field) do { \
+ if (DLIST_NEXT((elm), field) != NULL && \
+ DLIST_NEXT((elm), field)->field.le_prev != \
+ &((elm)->field.le_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_DLIST_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.le_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_DLIST_CHECK_HEAD(head, field)
+#define QMD_DLIST_CHECK_NEXT(elm, field)
+#define QMD_DLIST_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define DLIST_EMPTY(head) ((head)->lh_first == NULL)
+
+#define DLIST_FIRST(head) ((head)->lh_first)
+
+#define DLIST_FOREACH(var, head, field) \
+ for ((var) = DLIST_FIRST((head)); \
+ (var); \
+ (var) = DLIST_NEXT((var), field))
+
+#define DLIST_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = DLIST_FIRST((head)); \
+ (var) && ((tvar) = DLIST_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define DLIST_INIT(head) do { \
+ DLIST_FIRST((head)) = NULL; \
+} while (0)
+
+#define DLIST_INSERT_AFTER(listelm, elm, field) do { \
+ QMD_DLIST_CHECK_NEXT(listelm, field); \
+ if ((DLIST_NEXT((elm), field) = DLIST_NEXT((listelm), field)) != NULL)\
+ DLIST_NEXT((listelm), field)->field.le_prev = \
+ &DLIST_NEXT((elm), field); \
+ DLIST_NEXT((listelm), field) = (elm); \
+ (elm)->field.le_prev = &DLIST_NEXT((listelm), field); \
+} while (0)
+
+#define DLIST_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_DLIST_CHECK_PREV(listelm, field); \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ DLIST_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &DLIST_NEXT((elm), field); \
+} while (0)
+
+#define DLIST_INSERT_HEAD(head, elm, field) do { \
+ QMD_DLIST_CHECK_HEAD((head), field); \
+ if ((DLIST_NEXT((elm), field) = DLIST_FIRST((head))) != NULL) \
+ DLIST_FIRST((head))->field.le_prev = &DLIST_NEXT((elm), field);\
+ DLIST_FIRST((head)) = (elm); \
+ (elm)->field.le_prev = &DLIST_FIRST((head)); \
+} while (0)
+
+#define DLIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define DLIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_prev) { \
+ QMD_DLIST_CHECK_NEXT(elm, field); \
+ QMD_DLIST_CHECK_PREV(elm, field); \
+ if (DLIST_NEXT((elm), field) != NULL) \
+ DLIST_NEXT((elm), field)->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = DLIST_NEXT((elm), field); \
+ TRASHIT((elm)->field.le_next); \
+ TRASHIT((elm)->field.le_prev); \
+ } \
+} while (0)
+
+#define DLIST_SWAP(head1, head2, type, field) do { \
+ _Q_TYPE_FIELD(type, *swap_tmp) = DLIST_FIRST((head1)); \
+ DLIST_FIRST((head1)) = DLIST_FIRST((head2)); \
+ DLIST_FIRST((head2)) = swap_tmp; \
+ if ((swap_tmp = DLIST_FIRST((head1))) != NULL) \
+ swap_tmp->field.le_prev = &DLIST_FIRST((head1)); \
+ if ((swap_tmp = DLIST_FIRST((head2))) != NULL) \
+ swap_tmp->field.le_prev = &DLIST_FIRST((head2)); \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ _Q_TYPE_FIELD(type, *tqh_first); /* first element */ \
+ _Q_TYPE_FIELD(type, **tqh_last); /* addr of last next element */ \
+ TRACEBUF \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ _Q_TYPE_FIELD(type, *tqe_next); /* next element */ \
+ _Q_TYPE_FIELD(type, **tqe_prev); /* address of previous next element */ \
+ TRACEBUF \
+}
+
+/*
+ * Tail queue functions.
+ */
+#if (defined(_KERNEL) && defined(INVARIANTS))
+#define QMD_TAILQ_CHECK_HEAD(head, field) do { \
+ if (!TAILQ_EMPTY(head) && \
+ TAILQ_FIRST((head))->field.tqe_prev != \
+ &TAILQ_FIRST((head))) \
+ panic("Bad tailq head %p first->prev != head", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_TAIL(head, field) do { \
+ if (*(head)->tqh_last != NULL) \
+ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_NEXT(elm, field) do { \
+ if (TAILQ_NEXT((elm), field) != NULL && \
+ TAILQ_NEXT((elm), field)->field.tqe_prev != \
+ &((elm)->field.tqe_next)) \
+ panic("Bad link elm %p next->prev != elm", (elm)); \
+} while (0)
+
+#define QMD_TAILQ_CHECK_PREV(elm, field) do { \
+ if (*(elm)->field.tqe_prev != (elm)) \
+ panic("Bad link elm %p prev->next != elm", (elm)); \
+} while (0)
+#else
+#define QMD_TAILQ_CHECK_HEAD(head, field)
+#define QMD_TAILQ_CHECK_TAIL(head, headname)
+#define QMD_TAILQ_CHECK_NEXT(elm, field)
+#define QMD_TAILQ_CHECK_PREV(elm, field)
+#endif /* (_KERNEL && INVARIANTS) */
+
+#define TAILQ_CONCAT(head1, head2, field) do { \
+ if (!TAILQ_EMPTY(head2)) { \
+ *(head1)->tqh_last = (head2)->tqh_first; \
+ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ TAILQ_INIT((head2)); \
+ QMD_TRACE_HEAD(head1); \
+ QMD_TRACE_HEAD(head2); \
+ } \
+} while (0)
+
+#define TAILQ_EMPTY(head) ((head)->tqh_first == NULL)
+
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+
+#define TAILQ_FOREACH(var, head, field) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var); \
+ (var) = TAILQ_NEXT((var), field))
+
+#define TAILQ_FOREACH_SAFE(var, head, field, tvar) \
+ for ((var) = TAILQ_FIRST((head)); \
+ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var); \
+ (var) = TAILQ_PREV((var), headname, field))
+
+#define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \
+ for ((var) = TAILQ_LAST((head), headname); \
+ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \
+ (var) = (tvar))
+
+#define TAILQ_INIT(head) do { \
+ TAILQ_FIRST((head)) = NULL; \
+ (head)->tqh_last = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_NEXT(listelm, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else { \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ } \
+ TAILQ_NEXT((listelm), field) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ QMD_TAILQ_CHECK_PREV(listelm, field); \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ TAILQ_NEXT((elm), field) = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+ QMD_TRACE_ELEM(&listelm->field); \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ QMD_TAILQ_CHECK_HEAD(head, field); \
+ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \
+ TAILQ_FIRST((head))->field.tqe_prev = \
+ &TAILQ_NEXT((elm), field); \
+ else \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ TAILQ_FIRST((head)) = (elm); \
+ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ QMD_TAILQ_CHECK_TAIL(head, field); \
+ TAILQ_NEXT((elm), field) = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &TAILQ_NEXT((elm), field); \
+ QMD_TRACE_HEAD(head); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ QMD_TAILQ_CHECK_NEXT(elm, field); \
+ QMD_TAILQ_CHECK_PREV(elm, field); \
+ if ((TAILQ_NEXT((elm), field)) != NULL) \
+ TAILQ_NEXT((elm), field)->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else { \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ QMD_TRACE_HEAD(head); \
+ } \
+ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \
+ TRASHIT((elm)->field.tqe_next); \
+ TRASHIT((elm)->field.tqe_prev); \
+ QMD_TRACE_ELEM(&(elm)->field); \
+} while (0)
+
+#define TAILQ_SWAP(head1, head2, type, field) do { \
+ _Q_TYPE_FIELD(type, *swap_first) = (head1)->tqh_first; \
+ _Q_TYPE_FIELD(type, **swap_last) = (head1)->tqh_last; \
+ (head1)->tqh_first = (head2)->tqh_first; \
+ (head1)->tqh_last = (head2)->tqh_last; \
+ (head2)->tqh_first = swap_first; \
+ (head2)->tqh_last = swap_last; \
+ if ((swap_first = (head1)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head1)->tqh_first; \
+ else \
+ (head1)->tqh_last = &(head1)->tqh_first; \
+ if ((swap_first = (head2)->tqh_first) != NULL) \
+ swap_first->field.tqe_prev = &(head2)->tqh_first; \
+ else \
+ (head2)->tqh_last = &(head2)->tqh_first; \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.c b/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.c
new file mode 100644
index 0000000..27eb5e0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.c
@@ -0,0 +1,124 @@
+/*
+<: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_rw_lock.h"
+
+struct bcmos_rw_lock
+{
+ /* the actual lock, held by the writer, used by the reader to safely obtain a read lock, but not held to allow
+ * multiple readers */
+ bcmos_mutex lock;
+ /* used by the writer to prevent new readers from obtaining read locks while a writer is waiting */
+ bcmos_mutex read_lock;
+ /* used by readers to signal waiting writers that they have finished reading */
+ bcmos_sem write_lock;
+ /* current number of readers */
+ uint32_t readers;
+};
+
+bcmos_errno bcmos_rw_lock_create(bcmos_rw_lock **lock)
+{
+ bcmos_errno err;
+ *lock = (bcmos_rw_lock*)bcmos_calloc(sizeof(bcmos_rw_lock));
+ if (*lock == NULL)
+ {
+ BUG();
+ return BCM_ERR_NOMEM;
+ }
+ if (BCM_ERR_OK != (err = bcmos_mutex_create(&(*lock)->lock, 0, "bcmos_rw_lock_create_lock")))
+ {
+ BUG();
+ return err;
+ }
+ if (BCM_ERR_OK != (err = bcmos_mutex_create(&(*lock)->read_lock, 0, "bcmos_rw_lock_create_rw_lock")))
+ {
+ BUG();
+ return err;
+ }
+ (*lock)->readers = 0;
+ if (BCM_ERR_OK != (err = bcmos_sem_create(&(*lock)->write_lock, 1, 0, "bcmos_rw_lock_create_write_lock")))
+ {
+ BUG();
+ return err;
+ }
+ return err;
+}
+
+/*lint -e{455} suppress "thread mutex has not been locked" */
+void bcmos_rw_write_lock(bcmos_rw_lock* lock)
+{
+ /* prevent any new readers from trying to obtain a read lock */
+ bcmos_mutex_lock(&lock->read_lock);
+ /* lock the actual lock */
+ bcmos_mutex_lock(&lock->lock);
+ while (lock->readers != 0)
+ {
+ /* there are still readers holding read locks, release the lock */
+ bcmos_mutex_unlock(&lock->lock);
+ /* wait for the signal from the last reader before trying again */
+ bcmos_sem_wait(&lock->write_lock, BCMOS_WAIT_FOREVER);
+ /* lock the actual lock and check for readers again */
+ bcmos_mutex_lock(&lock->lock);
+ }
+ /* no more readers, allow new readers to wait on the lock */
+ bcmos_mutex_unlock(&lock->read_lock);
+}
+/*lint +e{454} suppress "thread mutex has not been locked" */
+
+void bcmos_rw_write_release(bcmos_rw_lock* lock)
+{
+ /*lint --e{455} suppress "thread mutex has not been locked" */
+ bcmos_mutex_unlock(&lock->lock);
+}
+
+void bcmos_rw_read_lock(bcmos_rw_lock* lock)
+{
+ /* wait for anyone trying to get a write lock */
+ bcmos_mutex_lock(&lock->read_lock);
+ /* wait for the lock to be released */
+ bcmos_mutex_lock(&lock->lock);
+ lock->readers++;
+ /* reset the signal to the writers */
+ bcmos_sem_wait(&lock->write_lock, BCMOS_NO_WAIT);
+ /* all done, release everything so other readers can get a read lock */
+ bcmos_mutex_unlock(&lock->lock);
+ bcmos_mutex_unlock(&lock->read_lock);
+}
+
+void bcmos_rw_read_release(bcmos_rw_lock* lock)
+{
+ /* get a lock to prevent interruptions */
+ bcmos_mutex_lock(&lock->lock);
+ if (--lock->readers == 0)
+ {
+ /* if we're the last reader, signal that the lock is available for a writer */
+ bcmos_sem_post(&lock->write_lock);
+ }
+ bcmos_mutex_unlock(&lock->lock);
+}
+
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.h
new file mode 100644
index 0000000..b12d533
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_rw_lock.h
@@ -0,0 +1,66 @@
+/*
+<: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.
+
+:>
+ */
+
+/** A write-biased readers-writer lock
+ * NOTE: DO NOT attempt to obtain a write lock on a thread that is already holding a read lock or vice versa - this
+ * will result in a deadlock. Multiple read locks from the same thread are safe, multiple write locks are NOT.
+ */
+#ifndef BCMOS_RW_LOCK_H_
+#define BCMOS_RW_LOCK_H_
+#include "bcmos_system.h"
+
+typedef struct bcmos_rw_lock bcmos_rw_lock;
+
+/** Initialize a lock
+ * \param[out] lock the newly created lock
+ * \return error code
+ */
+bcmos_errno bcmos_rw_lock_create(bcmos_rw_lock **lock);
+
+/** Obtain a write lock
+ * \param[in] lock the lock to operate on
+ */
+void bcmos_rw_write_lock(bcmos_rw_lock* lock);
+
+/** Release a write lock
+ * \param[in] lock the lock to operate on
+ */
+void bcmos_rw_write_release(bcmos_rw_lock* lock);
+
+/** Obtain a read lock
+ * \param[in] lock the lock to operate on
+ */
+void bcmos_rw_read_lock(bcmos_rw_lock* lock);
+
+/** Release a read lock
+ * \param[in] lock the lock to operate on
+ */
+void bcmos_rw_read_release(bcmos_rw_lock* lock);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_sysif.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_sysif.h
new file mode 100644
index 0000000..43df6dc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_sysif.h
@@ -0,0 +1,93 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmos_sysif.h
+ *
+ * This internal header file includes OS-specific services
+ * that are referred in OS-independent OS abstraction implementation
+ *
+ */
+
+#ifndef BCMOS_SYSIF_H_
+#define BCMOS_SYSIF_H_
+
+/*
+ * OS-specific init
+ */
+
+/** Initialize system library
+ * Must be called before any other system function
+ * \returns 0=OK or error code <0
+ */
+bcmos_errno bcmos_sys_init(void);
+
+/** Clean-up system library
+ */
+void bcmos_sys_exit(void);
+
+
+/*
+ * Timer support
+ */
+
+/* OS abstraction must define struct bcmos_sys_timer
+ */
+typedef struct bcmos_sys_timer bcmos_sys_timer;
+
+/* System timer handler. Implemented in common OS abstraction services */
+typedef void (*bcmos_sys_timer_handler)(void *data);
+
+/* Create system timer
+ * It is expected that only one high-resolution system timer is needed.
+ * It is used to "kick" timer pool implemented in OS abstraction
+ * \param[in] timer System timer
+ * \param[in] handler Timer handler
+ * \param[in] data Data to be passed to the handler
+ * \returns 0 if OK or error < 0
+ */
+bcmos_errno bcmos_sys_timer_create(bcmos_sys_timer *timer, bcmos_sys_timer_handler handler, void *data);
+
+/* Destroy system timer
+ * \param[in] timer System timer
+ */
+void bcmos_sys_timer_destroy(bcmos_sys_timer *timer);
+
+/* Start system timer
+ * \param[in] timer System timer
+ * \param[in] interval Interval (us)
+ */
+void bcmos_sys_timer_start(bcmos_sys_timer *timer, uint32_t interval);
+
+/* Stop system timer
+ * \param[in] timer System timer
+ */
+void bcmos_sys_timer_stop(bcmos_sys_timer *timer);
+
+#endif /* BCMOS_SYSIF_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_tree.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_tree.h
new file mode 100755
index 0000000..82d9164
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_tree.h
@@ -0,0 +1,765 @@
+/* $NetBSD: tree.h,v 1.8 2004/03/28 19:38:30 provos Exp $ */
+/* $OpenBSD: tree.h,v 1.7 2002/10/17 21:51:54 art Exp $ */
+/* $FreeBSD$ */
+
+/*-
+ * Copyright 2002 Niels Provos <provos@citi.umich.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _BCMOS_TREE_H_
+#define _BCMOS_TREE_H_
+
+/*
+ * This file defines data structures for different types of trees:
+ * splay trees and red-black trees.
+ *
+ * A splay tree is a self-organizing data structure. Every operation
+ * on the tree causes a splay to happen. The splay moves the requested
+ * node to the root of the tree and partly rebalances it.
+ *
+ * This has the benefit that request locality causes faster lookups as
+ * the requested nodes move to the top of the tree. On the other hand,
+ * every lookup causes memory writes.
+ *
+ * The Balance Theorem bounds the total access time for m operations
+ * and n inserts on an initially empty tree as O((m + n)lg n). The
+ * amortized cost for a sequence of m accesses to a splay tree is O(lg n);
+ *
+ * A red-black tree is a binary search tree with the node color as an
+ * extra attribute. It fulfills a set of conditions:
+ * - every search path from the root to a leaf consists of the
+ * same number of black nodes,
+ * - each red node (except for the root) has a black parent,
+ * - each leaf node is black.
+ *
+ * Every operation on a red-black tree is bounded as O(lg n).
+ * The maximum height of a red-black tree is 2lg (n+1).
+ */
+
+#define SPLAY_HEAD(name, type) \
+struct name { \
+ type *sph_root; /* root of the tree */ \
+}
+
+#define SPLAY_INITIALIZER(root) \
+ { NULL }
+
+#define SPLAY_INIT(root) do { \
+ (root)->sph_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ENTRY(type) \
+struct { \
+ type *spe_left; /* left element */ \
+ type *spe_right; /* right element */ \
+}
+
+#define SPLAY_LEFT(elm, field) (elm)->field.spe_left
+#define SPLAY_RIGHT(elm, field) (elm)->field.spe_right
+#define SPLAY_ROOT(head) (head)->sph_root
+#define SPLAY_EMPTY(head) (SPLAY_ROOT(head) == NULL)
+
+/* SPLAY_ROTATE_{LEFT,RIGHT} expect that tmp hold SPLAY_{RIGHT,LEFT} */
+#define SPLAY_ROTATE_RIGHT(head, tmp, field) do { \
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(tmp, field); \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ROTATE_LEFT(head, tmp, field) do { \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(tmp, field); \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ (head)->sph_root = tmp; \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKLEFT(head, tmp, field) do { \
+ SPLAY_LEFT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_LINKRIGHT(head, tmp, field) do { \
+ SPLAY_RIGHT(tmp, field) = (head)->sph_root; \
+ tmp = (head)->sph_root; \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field); \
+} while (/*CONSTCOND*/ 0)
+
+#define SPLAY_ASSEMBLE(head, node, left, right, field) do { \
+ SPLAY_RIGHT(left, field) = SPLAY_LEFT((head)->sph_root, field); \
+ SPLAY_LEFT(right, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT((head)->sph_root, field) = SPLAY_RIGHT(node, field); \
+ SPLAY_RIGHT((head)->sph_root, field) = SPLAY_LEFT(node, field); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+
+#define SPLAY_PROTOTYPE(name, type, field, cmp) \
+void name##_SPLAY(struct name *, type *); \
+void name##_SPLAY_MINMAX(struct name *, int); \
+type *name##_SPLAY_INSERT(struct name *, type *); \
+type *name##_SPLAY_REMOVE(struct name *, type *); \
+ \
+/* Finds the node with the same key as elm */ \
+static __inline type * \
+name##_SPLAY_FIND(struct name *head, type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) \
+ return(NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) \
+ return (head->sph_root); \
+ return (NULL); \
+} \
+ \
+static __inline type * \
+name##_SPLAY_NEXT(struct name *head, type *elm) \
+{ \
+ name##_SPLAY(head, elm); \
+ if (SPLAY_RIGHT(elm, field) != NULL) { \
+ elm = SPLAY_RIGHT(elm, field); \
+ while (SPLAY_LEFT(elm, field) != NULL) { \
+ elm = SPLAY_LEFT(elm, field); \
+ } \
+ } else \
+ elm = NULL; \
+ return (elm); \
+} \
+ \
+static __inline type * \
+name##_SPLAY_MIN_MAX(struct name *head, int val) \
+{ \
+ name##_SPLAY_MINMAX(head, val); \
+ return (SPLAY_ROOT(head)); \
+}
+
+/* Main splay operation.
+ * Moves node close to the key of elm to top
+ */
+#define SPLAY_GENERATE(name, type, field, cmp) \
+type * \
+name##_SPLAY_INSERT(struct name *head, type *elm) \
+{ \
+ if (SPLAY_EMPTY(head)) { \
+ SPLAY_LEFT(elm, field) = SPLAY_RIGHT(elm, field) = NULL; \
+ } else { \
+ int __comp; \
+ name##_SPLAY(head, elm); \
+ __comp = (cmp)(elm, (head)->sph_root); \
+ if(__comp < 0) { \
+ SPLAY_LEFT(elm, field) = SPLAY_LEFT((head)->sph_root, field);\
+ SPLAY_RIGHT(elm, field) = (head)->sph_root; \
+ SPLAY_LEFT((head)->sph_root, field) = NULL; \
+ } else if (__comp > 0) { \
+ SPLAY_RIGHT(elm, field) = SPLAY_RIGHT((head)->sph_root, field);\
+ SPLAY_LEFT(elm, field) = (head)->sph_root; \
+ SPLAY_RIGHT((head)->sph_root, field) = NULL; \
+ } else \
+ return ((head)->sph_root); \
+ } \
+ (head)->sph_root = (elm); \
+ return (NULL); \
+} \
+ \
+type * \
+name##_SPLAY_REMOVE(struct name *head, type *elm) \
+{ \
+ type *__tmp; \
+ if (SPLAY_EMPTY(head)) \
+ return (NULL); \
+ name##_SPLAY(head, elm); \
+ if ((cmp)(elm, (head)->sph_root) == 0) { \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL) { \
+ (head)->sph_root = SPLAY_RIGHT((head)->sph_root, field);\
+ } else { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ (head)->sph_root = SPLAY_LEFT((head)->sph_root, field);\
+ name##_SPLAY(head, elm); \
+ SPLAY_RIGHT((head)->sph_root, field) = __tmp; \
+ } \
+ return (elm); \
+ } \
+ return (NULL); \
+} \
+ \
+void \
+name##_SPLAY(struct name *head, type *elm) \
+{ \
+ type __node, *__left, *__right, *__tmp; \
+ int __comp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while ((__comp = (cmp)(elm, (head)->sph_root)) != 0) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if ((cmp)(elm, __tmp) > 0){ \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+} \
+ \
+/* Splay with either the minimum or the maximum element \
+ * Used to find minimum or maximum element in tree. \
+ */ \
+void name##_SPLAY_MINMAX(struct name *head, int __comp) \
+{ \
+ type __node, *__left, *__right, *__tmp; \
+\
+ SPLAY_LEFT(&__node, field) = SPLAY_RIGHT(&__node, field) = NULL;\
+ __left = __right = &__node; \
+\
+ while (1) { \
+ if (__comp < 0) { \
+ __tmp = SPLAY_LEFT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp < 0){ \
+ SPLAY_ROTATE_RIGHT(head, __tmp, field); \
+ if (SPLAY_LEFT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKLEFT(head, __right, field); \
+ } else if (__comp > 0) { \
+ __tmp = SPLAY_RIGHT((head)->sph_root, field); \
+ if (__tmp == NULL) \
+ break; \
+ if (__comp > 0) { \
+ SPLAY_ROTATE_LEFT(head, __tmp, field); \
+ if (SPLAY_RIGHT((head)->sph_root, field) == NULL)\
+ break; \
+ } \
+ SPLAY_LINKRIGHT(head, __left, field); \
+ } \
+ } \
+ SPLAY_ASSEMBLE(head, &__node, __left, __right, field); \
+}
+
+#define SPLAY_NEGINF -1
+#define SPLAY_INF 1
+
+#define SPLAY_INSERT(name, x, y) name##_SPLAY_INSERT(x, y)
+#define SPLAY_REMOVE(name, x, y) name##_SPLAY_REMOVE(x, y)
+#define SPLAY_FIND(name, x, y) name##_SPLAY_FIND(x, y)
+#define SPLAY_NEXT(name, x, y) name##_SPLAY_NEXT(x, y)
+#define SPLAY_MIN(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_NEGINF))
+#define SPLAY_MAX(name, x) (SPLAY_EMPTY(x) ? NULL \
+ : name##_SPLAY_MIN_MAX(x, SPLAY_INF))
+
+#define SPLAY_FOREACH(x, name, head) \
+ for ((x) = SPLAY_MIN(name, head); \
+ (x) != NULL; \
+ (x) = SPLAY_NEXT(name, head, x))
+
+/* Macros that define a red-black tree */
+#define RB_HEAD(name, type) \
+struct name { \
+ type *rbh_root; /* root of the tree */ \
+}
+
+#define RB_INITIALIZER(root) \
+ { NULL }
+
+#define RB_INIT(root) do { \
+ (root)->rbh_root = NULL; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_BLACK 0
+#define RB_RED 1
+#define RB_ENTRY(type) \
+struct { \
+ type *rbe_left; /* left element */ \
+ type *rbe_right; /* right element */ \
+ type *rbe_parent; /* parent element */ \
+ int rbe_color; /* node color */ \
+}
+
+#define RB_LEFT(elm, field) (elm)->field.rbe_left
+#define RB_RIGHT(elm, field) (elm)->field.rbe_right
+#define RB_PARENT(elm, field) (elm)->field.rbe_parent
+#define RB_COLOR(elm, field) (elm)->field.rbe_color
+#define RB_ROOT_NODE(head) (head)->rbh_root
+#define RB_EMPTY(head) (RB_ROOT_NODE(head) == NULL)
+
+#define RB_SET(elm, parent, field) do { \
+ RB_PARENT(elm, field) = parent; \
+ RB_LEFT(elm, field) = RB_RIGHT(elm, field) = NULL; \
+ RB_COLOR(elm, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_SET_BLACKRED(black, red, field) do { \
+ RB_COLOR(black, field) = RB_BLACK; \
+ RB_COLOR(red, field) = RB_RED; \
+} while (/*CONSTCOND*/ 0)
+
+#ifndef RB_AUGMENT
+#define RB_AUGMENT(x) do {} while (0)
+#endif
+
+#define RB_ROTATE_LEFT(head, elm, tmp, field) do { \
+ (tmp) = RB_RIGHT(elm, field); \
+ if ((RB_RIGHT(elm, field) = RB_LEFT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_LEFT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_LEFT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+#define RB_ROTATE_RIGHT(head, elm, tmp, field) do { \
+ (tmp) = RB_LEFT(elm, field); \
+ if ((RB_LEFT(elm, field) = RB_RIGHT(tmp, field)) != NULL) { \
+ RB_PARENT(RB_RIGHT(tmp, field), field) = (elm); \
+ } \
+ RB_AUGMENT(elm); \
+ if ((RB_PARENT(tmp, field) = RB_PARENT(elm, field)) != NULL) { \
+ if ((elm) == RB_LEFT(RB_PARENT(elm, field), field)) \
+ RB_LEFT(RB_PARENT(elm, field), field) = (tmp); \
+ else \
+ RB_RIGHT(RB_PARENT(elm, field), field) = (tmp); \
+ } else \
+ (head)->rbh_root = (tmp); \
+ RB_RIGHT(tmp, field) = (elm); \
+ RB_PARENT(elm, field) = (tmp); \
+ RB_AUGMENT(tmp); \
+ if ((RB_PARENT(tmp, field))) \
+ RB_AUGMENT(RB_PARENT(tmp, field)); \
+} while (/*CONSTCOND*/ 0)
+
+/* Generates prototypes and inline functions */
+#define RB_PROTOTYPE(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp,)
+#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
+ RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
+attr void name##_RB_INSERT_COLOR(struct name *, type *); \
+attr void name##_RB_REMOVE_COLOR(struct name *, type *, type *); \
+attr type *name##_RB_REMOVE(struct name *, type *); \
+attr type *name##_RB_INSERT(struct name *, type *); \
+attr type *name##_RB_FIND(struct name *, type *); \
+attr type *name##_RB_NFIND(struct name *, type *); \
+attr type *name##_RB_NEXT(type *); \
+attr type *name##_RB_PREV(type *); \
+attr type *name##_RB_MINMAX(struct name *, int); \
+ \
+
+/* Main rb operation.
+ * Moves node close to the key of elm to top
+ */
+#define RB_GENERATE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp,)
+#define RB_GENERATE_STATIC(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
+#define RB_GENERATE_INLINE(name, type, field, cmp) \
+ RB_GENERATE_INTERNAL(name, type, field, cmp, static inline)
+#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
+attr void \
+name##_RB_INSERT_COLOR(struct name *head, type *elm) \
+{ \
+ type *parent, *gparent, *tmp; \
+ while ((parent = RB_PARENT(elm, field)) != NULL && \
+ RB_COLOR(parent, field) == RB_RED) { \
+ gparent = RB_PARENT(parent, field); \
+ if (parent == RB_LEFT(gparent, field)) { \
+ tmp = RB_RIGHT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_RIGHT(parent, field) == elm) { \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_RIGHT(head, gparent, tmp, field); \
+ } else { \
+ tmp = RB_LEFT(gparent, field); \
+ if (tmp && RB_COLOR(tmp, field) == RB_RED) { \
+ RB_COLOR(tmp, field) = RB_BLACK; \
+ RB_SET_BLACKRED(parent, gparent, field);\
+ elm = gparent; \
+ continue; \
+ } \
+ if (RB_LEFT(parent, field) == elm) { \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = parent; \
+ parent = elm; \
+ elm = tmp; \
+ } \
+ RB_SET_BLACKRED(parent, gparent, field); \
+ RB_ROTATE_LEFT(head, gparent, tmp, field); \
+ } \
+ } \
+ RB_COLOR(head->rbh_root, field) = RB_BLACK; \
+} \
+ \
+attr void \
+name##_RB_REMOVE_COLOR(struct name *head, type *parent, type *elm) \
+{ \
+ type *tmp; \
+ while ((elm == NULL || RB_COLOR(elm, field) == RB_BLACK) && \
+ elm != RB_ROOT_NODE(head)) { \
+ if (RB_LEFT(parent, field) == elm) { \
+ tmp = RB_RIGHT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK) {\
+ type *oleft; \
+ if ((oleft = RB_LEFT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oleft, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_RIGHT(head, tmp, oleft, field);\
+ tmp = RB_RIGHT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_RIGHT(tmp, field)) \
+ RB_COLOR(RB_RIGHT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_LEFT(head, parent, tmp, field);\
+ elm = RB_ROOT_NODE(head); \
+ break; \
+ } \
+ } else { \
+ tmp = RB_LEFT(parent, field); \
+ if (RB_COLOR(tmp, field) == RB_RED) { \
+ RB_SET_BLACKRED(tmp, parent, field); \
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ if ((RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) &&\
+ (RB_RIGHT(tmp, field) == NULL || \
+ RB_COLOR(RB_RIGHT(tmp, field), field) == RB_BLACK)) {\
+ RB_COLOR(tmp, field) = RB_RED; \
+ elm = parent; \
+ parent = RB_PARENT(elm, field); \
+ } else { \
+ if (RB_LEFT(tmp, field) == NULL || \
+ RB_COLOR(RB_LEFT(tmp, field), field) == RB_BLACK) {\
+ type *oright; \
+ if ((oright = RB_RIGHT(tmp, field)) \
+ != NULL) \
+ RB_COLOR(oright, field) = RB_BLACK;\
+ RB_COLOR(tmp, field) = RB_RED; \
+ RB_ROTATE_LEFT(head, tmp, oright, field);\
+ tmp = RB_LEFT(parent, field); \
+ } \
+ RB_COLOR(tmp, field) = RB_COLOR(parent, field);\
+ RB_COLOR(parent, field) = RB_BLACK; \
+ if (RB_LEFT(tmp, field)) \
+ RB_COLOR(RB_LEFT(tmp, field), field) = RB_BLACK;\
+ RB_ROTATE_RIGHT(head, parent, tmp, field);\
+ elm = RB_ROOT_NODE(head); \
+ break; \
+ } \
+ } \
+ } \
+ if (elm) \
+ RB_COLOR(elm, field) = RB_BLACK; \
+} \
+ \
+attr type * \
+name##_RB_REMOVE(struct name *head, type *elm) \
+{ \
+ type *child, *parent, *old = elm; \
+ int color; \
+ if (RB_LEFT(elm, field) == NULL) \
+ child = RB_RIGHT(elm, field); \
+ else if (RB_RIGHT(elm, field) == NULL) \
+ child = RB_LEFT(elm, field); \
+ else { \
+ type *left; \
+ elm = RB_RIGHT(elm, field); \
+ while ((left = RB_LEFT(elm, field)) != NULL) \
+ elm = left; \
+ child = RB_RIGHT(elm, field); \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT_NODE(head) = child; \
+ if (RB_PARENT(elm, field) == old) \
+ parent = elm; \
+ (elm)->field = (old)->field; \
+ if (RB_PARENT(old, field)) { \
+ if (RB_LEFT(RB_PARENT(old, field), field) == old)\
+ RB_LEFT(RB_PARENT(old, field), field) = elm;\
+ else \
+ RB_RIGHT(RB_PARENT(old, field), field) = elm;\
+ RB_AUGMENT(RB_PARENT(old, field)); \
+ } else \
+ RB_ROOT_NODE(head) = elm; \
+ RB_PARENT(RB_LEFT(old, field), field) = elm; \
+ if (RB_RIGHT(old, field)) \
+ RB_PARENT(RB_RIGHT(old, field), field) = elm; \
+ if (parent) { \
+ left = parent; \
+ do { \
+ RB_AUGMENT(left); \
+ } while ((left = RB_PARENT(left, field)) != NULL); \
+ } \
+ goto color; \
+ } \
+ parent = RB_PARENT(elm, field); \
+ color = RB_COLOR(elm, field); \
+ if (child) \
+ RB_PARENT(child, field) = parent; \
+ if (parent) { \
+ if (RB_LEFT(parent, field) == elm) \
+ RB_LEFT(parent, field) = child; \
+ else \
+ RB_RIGHT(parent, field) = child; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT_NODE(head) = child; \
+color: \
+ if (color == RB_BLACK) \
+ name##_RB_REMOVE_COLOR(head, parent, child); \
+ return (old); \
+} \
+ \
+/* Inserts a node into the RB tree */ \
+attr type * \
+name##_RB_INSERT(struct name *head, type *elm) \
+{ \
+ type *tmp; \
+ type *parent = NULL; \
+ int comp = 0; \
+ tmp = RB_ROOT_NODE(head); \
+ while (tmp) { \
+ parent = tmp; \
+ comp = (cmp)(elm, parent); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ RB_SET(elm, parent, field); \
+ if (parent != NULL) { \
+ if (comp < 0) \
+ RB_LEFT(parent, field) = elm; \
+ else \
+ RB_RIGHT(parent, field) = elm; \
+ RB_AUGMENT(parent); \
+ } else \
+ RB_ROOT_NODE(head) = elm; \
+ name##_RB_INSERT_COLOR(head, elm); \
+ return (NULL); \
+} \
+ \
+/* Finds the node with the same key as elm */ \
+attr type * \
+name##_RB_FIND(struct name *head, type *elm) \
+{ \
+ type *tmp = RB_ROOT_NODE(head); \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (NULL); \
+} \
+ \
+/* Finds the first node greater than or equal to the search key */ \
+attr type * \
+name##_RB_NFIND(struct name *head, type *elm) \
+{ \
+ type *tmp = RB_ROOT_NODE(head); \
+ type *res = NULL; \
+ int comp; \
+ while (tmp) { \
+ comp = cmp(elm, tmp); \
+ if (comp < 0) { \
+ res = tmp; \
+ tmp = RB_LEFT(tmp, field); \
+ } \
+ else if (comp > 0) \
+ tmp = RB_RIGHT(tmp, field); \
+ else \
+ return (tmp); \
+ } \
+ return (res); \
+} \
+ \
+/* ARGSUSED */ \
+attr type * \
+name##_RB_NEXT(type *elm) \
+{ \
+ if (RB_RIGHT(elm, field)) { \
+ elm = RB_RIGHT(elm, field); \
+ while (RB_LEFT(elm, field)) \
+ elm = RB_LEFT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+/* ARGSUSED */ \
+attr type * \
+name##_RB_PREV(type *elm) \
+{ \
+ if (RB_LEFT(elm, field)) { \
+ elm = RB_LEFT(elm, field); \
+ while (RB_RIGHT(elm, field)) \
+ elm = RB_RIGHT(elm, field); \
+ } else { \
+ if (RB_PARENT(elm, field) && \
+ (elm == RB_RIGHT(RB_PARENT(elm, field), field))) \
+ elm = RB_PARENT(elm, field); \
+ else { \
+ while (RB_PARENT(elm, field) && \
+ (elm == RB_LEFT(RB_PARENT(elm, field), field)))\
+ elm = RB_PARENT(elm, field); \
+ elm = RB_PARENT(elm, field); \
+ } \
+ } \
+ return (elm); \
+} \
+ \
+attr type * \
+name##_RB_MINMAX(struct name *head, int val) \
+{ \
+ type *tmp = RB_ROOT_NODE(head); \
+ type *parent = NULL; \
+ while (tmp) { \
+ parent = tmp; \
+ if (val < 0) \
+ tmp = RB_LEFT(tmp, field); \
+ else \
+ tmp = RB_RIGHT(tmp, field); \
+ } \
+ return (parent); \
+}
+
+#define RB_NEGINF -1
+#define RB_INF 1
+
+#define RB_INSERT(name, x, y) name##_RB_INSERT(x, y)
+#define RB_REMOVE(name, x, y) name##_RB_REMOVE(x, y)
+#define RB_FIND(name, x, y) name##_RB_FIND(x, y)
+#define RB_NFIND(name, x, y) name##_RB_NFIND(x, y)
+#define RB_NEXT(name, x, y) name##_RB_NEXT(y)
+#define RB_PREV(name, x, y) name##_RB_PREV(y)
+#define RB_MIN(name, x) name##_RB_MINMAX(x, RB_NEGINF)
+#define RB_MAX(name, x) name##_RB_MINMAX(x, RB_INF)
+
+#define RB_FOREACH(x, name, head) \
+ for ((x) = RB_MIN(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_NEXT(x))
+
+#define RB_FOREACH_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_SAFE(x, name, head, y) \
+ for ((x) = RB_MIN(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_NEXT(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE(x, name, head) \
+ for ((x) = RB_MAX(name, head); \
+ (x) != NULL; \
+ (x) = name##_RB_PREV(x))
+
+#define RB_FOREACH_REVERSE_FROM(x, name, y) \
+ for ((x) = (y); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#define RB_FOREACH_REVERSE_SAFE(x, name, head, y) \
+ for ((x) = RB_MAX(name, head); \
+ ((x) != NULL) && ((y) = name##_RB_PREV(x), (x) != NULL); \
+ (x) = (y))
+
+#endif /* _BCMOS_TREE_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/bcmos_types.h b/bcm68620_release/release/host_customized/os_abstraction/bcmos_types.h
new file mode 100644
index 0000000..21f0191
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/bcmos_types.h
@@ -0,0 +1,208 @@
+/*
+<: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 BCMOS_TYPES_H_
+#define BCMOS_TYPES_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_types.h directly. Include bcmos_system.h
+#endif
+
+#include "bcmos_pack.h"
+
+/** \defgroup system_types Generic types
+ * @{
+ */
+
+/*
+ * Limits of integer types.
+ */
+
+/* Minimum of signed integer types. */
+#ifndef INT8_MIN
+#define INT8_MIN (0x80)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (0x8000)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (0x80000000)
+#endif
+#ifndef INT64_MIN
+#define INT64_MIN (0x8000000000000000)
+#endif
+
+/* Maximum of signed integer types. */
+#ifndef INT8_MAX
+#define INT8_MAX (0x7F)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (0x7FFF)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (0x7FFFFFFF)
+#endif
+#ifndef INT64_MAX
+#define INT64_MAX (0x7FFFFFFFFFFFFFFF)
+#endif
+
+/* Maximum of unsigned integer types. */
+#ifndef UINT8_MAX
+#define UINT8_MAX (0xFF)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (0xFFFF)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (0xFFFFFFFF)
+#endif
+#ifndef UINT64_MAX
+#define UINT64_MAX (0xFFFFFFFFFFFFFFFF)
+#endif
+
+
+/** Endianness */
+#define BCMOS_ENDIAN_BIG 0
+#define BCMOS_ENDIAN_LITTLE 1
+
+typedef enum
+{
+ BCMOS_ENDIAN_BIG_E = BCMOS_ENDIAN_BIG,
+ BCMOS_ENDIAN_LITTLE_E = BCMOS_ENDIAN_LITTLE,
+} bcmos_endian;
+
+/* If endianness is not set explicitly, try to autodetect it.
+ * Modern gcc versions (over 4.8) define __BYTE_ORDER__
+ * see "gcc -E -dM - < /dev/null | grep ENDIAN"
+ */
+#ifndef BCM_CPU_ENDIAN
+
+#ifdef __BYTE_ORDER__
+
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
+#define BCM_CPU_ENDIAN BCMOS_ENDIAN_LITTLE
+#else
+#define BCM_CPU_ENDIAN BCMOS_ENDIAN_BIG
+#endif
+
+#else
+
+/* We are dealing with compiler that doesn't set __BYTE_ORDER__.
+ * If it is simulation build than it must be LE x86.
+ * Otherwise, no way to tell.
+ */
+#ifdef SIMULATION_BUILD
+#define BCM_CPU_ENDIAN BCMOS_ENDIAN_LITTLE
+#endif
+
+#endif /* #ifdef __BYTE_ORDER */
+
+#endif /* #ifndef BCM_CPU_ENDIAN */
+
+#include <bcm_config.h>
+
+/** 24-bit unsigned integer */
+typedef union
+{
+ uint8_t u8[3];
+ struct __PACKED_ATTR_START__
+ {
+#if (BCM_CPU_ENDIAN == BCMOS_ENDIAN_BIG)
+ uint8_t hi;
+ uint8_t mid;
+ uint8_t low;
+#elif (BCM_CPU_ENDIAN == BCMOS_ENDIAN_LITTLE)
+ uint8_t low;
+ uint8_t mid;
+ uint8_t hi;
+#else
+#error BCM_CPU_ENDIAN must be BCMOS_ENDIAN_BIG or _LITTLE
+#endif
+ } __PACKED_ATTR_END__ low_hi;
+} uint24_t;
+
+static inline uint32_t uint24_to_32(uint24_t u24)
+{
+ return (u24.low_hi.hi << 16) | (u24.low_hi.mid << 8) | u24.low_hi.low;
+}
+
+static inline uint24_t uint32_to_24(uint32_t u32)
+{
+ return (uint24_t){ .low_hi= { .hi = (u32 >> 16) & 0xff, .mid = (u32 >> 8) & 0xff, .low = u32 & 0xff } };
+}
+
+/** VLAN tag (CoS/CFI/VID) */
+typedef uint16_t bcmos_vlan_tag;
+
+#define BCMOS_ETH_ALEN 6
+
+/** MAC address */
+typedef struct
+{
+ uint8_t u8[BCMOS_ETH_ALEN];
+} bcmos_mac_address;
+
+/** IPv4 address. It is stored in network byte order. */
+typedef union
+{
+ uint32_t u32;
+ uint8_t u8[4];
+} bcmos_ipv4_address;
+
+/** IPv6 address */
+typedef uint8_t bcmos_ipv6_address[16];
+
+static inline void bcmos_mac_address_init(bcmos_mac_address *mac)
+{
+ memset(mac, 0, sizeof(*mac));
+}
+
+static inline void bcmos_ipv4_address_init(bcmos_ipv4_address *ip)
+{
+ memset(ip, 0, sizeof(*ip));
+}
+
+#ifndef CFE_BUILD
+static inline char *bcmos_inet_ntoa(bcmos_ipv4_address *ip, char *ip_str)
+{
+ snprintf(ip_str, 16, "%u.%u.%u.%u", ip->u8[0], ip->u8[1], ip->u8[2], ip->u8[3]);
+
+ return ip_str;
+}
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (long)__mptr - offsetof(type,member) );})
+#endif
+
+/** @} */
+
+#endif /* BCMOS_TYPES_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmolt_model_data_cfe_ext.h b/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmolt_model_data_cfe_ext.h
new file mode 100644
index 0000000..ddca9ce
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmolt_model_data_cfe_ext.h
@@ -0,0 +1,92 @@
+/*
+<:copyright-BRCM:2016:proprietary:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+This program is the proprietary software of Broadcom Corporation and/or its
+licensors, and may only be used, duplicated, modified or distributed pursuant
+to the terms and conditions of a separate, written license agreement executed
+between you and Broadcom (an "Authorized License"). Except as set forth in
+an Authorized License, Broadcom grants no license (express or implied), right
+to use, or waiver of any kind with respect to the Software, and Broadcom
+expressly reserves all rights in and to the Software and all intellectual
+property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE
+NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY
+BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
+
+Except as expressly set forth in the Authorized License,
+
+1. This program, including its structure, sequence and organization,
+ constitutes the valuable trade secrets of Broadcom, and you shall use
+ all reasonable efforts to protect the confidentiality thereof, and to
+ use this information only in connection with your use of Broadcom
+ integrated circuit products.
+
+2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
+ WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND
+ ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT,
+ FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
+ COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE
+ TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF USE OR
+ PERFORMANCE OF THE SOFTWARE.
+
+3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR
+ ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL,
+ INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY
+ WAY RELATING TO YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN
+ IF BROADCOM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES;
+ OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE
+ SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE LIMITATIONS
+ SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY
+ LIMITED REMEDY.
+:>
+*/
+
+#ifndef BCMOS_MODEL_DATA_CFE_EXT_H_
+#define BCMOS_MODEL_DATA_CFE_EXT_H_
+
+#include "bcmolt_model_data.h"
+
+typedef struct
+{
+ bcmolt_system_mode system_mode;
+ bcmolt_device_nni_speed nni_speed;
+ bcmos_bool use_prev_nni_serdes_firmware;
+} db_rec_device;
+
+/* System mode */
+static bcmolt_system_mode device_system_mode;
+
+/** Set system mode
+ * \param[in] dev Device id
+ * \param[in] system_mode System mode
+ * \returns BCM_ERR_OK, BCM_ERR_NOT_SUPPORTED
+ */
+static inline bcmos_errno bcmolt_system_mode_set(uint16_t dev, bcmolt_system_mode system_mode)
+{
+ device_system_mode = system_mode;
+ return BCM_ERR_OK;
+}
+
+/** Get system mode
+ * \param[in] dev Device id
+ * \param[in] system_mode System mode
+ * \returns BCM_ERR_OK
+ */
+static inline bcmos_errno bcmolt_system_mode_get(uint16_t dev, bcmolt_system_mode *system_mode)
+{
+ *system_mode = device_system_mode;
+ return BCM_ERR_OK;
+}
+
+
+static inline int is_issu_boot(void)
+{
+ return BCMOS_FALSE;
+}
+
+
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmos_system.h b/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmos_system.h
new file mode 100644
index 0000000..763cc79
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/cfe/bcmos_system.h
@@ -0,0 +1,138 @@
+/*
+<:copyright-BRCM:2016:proprietary:standard
+
+ Broadcom Proprietary and Confidential.(c) 2016 Broadcom
+ All Rights Reserved
+
+This program is the proprietary software of Broadcom Corporation and/or its
+licensors, and may only be used, duplicated, modified or distributed pursuant
+to the terms and conditions of a separate, written license agreement executed
+between you and Broadcom (an "Authorized License"). Except as set forth in
+an Authorized License, Broadcom grants no license (express or implied), right
+to use, or waiver of any kind with respect to the Software, and Broadcom
+expressly reserves all rights in and to the Software and all intellectual
+property rights therein. IF YOU HAVE NO AUTHORIZED LICENSE, THEN YOU HAVE
+NO RIGHT TO USE THIS SOFTWARE IN ANY WAY, AND SHOULD IMMEDIATELY NOTIFY
+BROADCOM AND DISCONTINUE ALL USE OF THE SOFTWARE.
+
+Except as expressly set forth in the Authorized License,
+
+1. This program, including its structure, sequence and organization,
+ constitutes the valuable trade secrets of Broadcom, and you shall use
+ all reasonable efforts to protect the confidentiality thereof, and to
+ use this information only in connection with your use of Broadcom
+ integrated circuit products.
+
+2. TO THE MAXIMUM EXTENT PERMITTED BY LAW, THE SOFTWARE IS PROVIDED "AS IS"
+ AND WITH ALL FAULTS AND BROADCOM MAKES NO PROMISES, REPRESENTATIONS OR
+ WARRANTIES, EITHER EXPRESS, IMPLIED, STATUTORY, OR OTHERWISE, WITH
+ RESPECT TO THE SOFTWARE. BROADCOM SPECIFICALLY DISCLAIMS ANY AND
+ ALL IMPLIED WARRANTIES OF TITLE, MERCHANTABILITY, NONINFRINGEMENT,
+ FITNESS FOR A PARTICULAR PURPOSE, LACK OF VIRUSES, ACCURACY OR
+ COMPLETENESS, QUIET ENJOYMENT, QUIET POSSESSION OR CORRESPONDENCE
+ TO DESCRIPTION. YOU ASSUME THE ENTIRE RISK ARISING OUT OF USE OR
+ PERFORMANCE OF THE SOFTWARE.
+
+3. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT SHALL BROADCOM OR
+ ITS LICENSORS BE LIABLE FOR (i) CONSEQUENTIAL, INCIDENTAL, SPECIAL,
+ INDIRECT, OR EXEMPLARY DAMAGES WHATSOEVER ARISING OUT OF OR IN ANY
+ WAY RELATING TO YOUR USE OF OR INABILITY TO USE THE SOFTWARE EVEN
+ IF BROADCOM HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES;
+ OR (ii) ANY AMOUNT IN EXCESS OF THE AMOUNT ACTUALLY PAID FOR THE
+ SOFTWARE ITSELF OR U.S. $1, WHICHEVER IS GREATER. THESE LIMITATIONS
+ SHALL APPLY NOTWITHSTANDING ANY FAILURE OF ESSENTIAL PURPOSE OF ANY
+ LIMITED REMEDY.
+:>
+*/
+#ifndef BCMOS_SYSTEM_H_
+#define BCMOS_SYSTEM_H_
+
+#include <limits.h>
+
+#include "lib_types.h"
+#include "lib_string.h"
+
+#include "../bcmos_errno.h"
+#include "../bcmos_types.h"
+#include "../bcmos_endian.h"
+#include "cfe_timer.h"
+#include "lib_printf.h"
+
+#define bcmos_printf printf
+
+#define bcmos_usleep(x) \
+ do { \
+ cfe_usleep (x); \
+ } \
+ while(0)
+/* Define bcmos_bool - the boolean type for bcmos - based on C99 standard boolean type */
+#ifndef BCMOS_BOOLEAN
+typedef _Bool bcmos_bool;
+#define BCMOS_FALSE 0
+#define BCMOS_TRUE 1
+#endif
+
+#define PERIPH_GENINT_REVID 0xffe00000
+#define CHIP_REV_MASK 0xFF
+static inline unsigned int get_chip_revision(void)
+{
+ return *(volatile unsigned int*)PERIPH_GENINT_REVID & CHIP_REV_MASK;
+}
+
+#define CHIP_REVISION_A0 0xA0
+#define CHIP_REVISION_B0 0xB0
+
+#ifdef SIMULATION_BUILD
+#define GET_CHIP_REVISION CHIP_REVISION_A0
+#else
+extern uint32_t chip_revision;
+#define GET_CHIP_REVISION (chip_revision != 0 ? chip_revision : (chip_revision = get_chip_revision()))
+#endif
+
+
+typedef uint16_t bcmos_fastlock;
+#define BCMOS_FASTLOCK_INITIALIZER 0
+#define bcmos_fastlock_lock(fastlock) (long)fastlock
+#define bcmos_fastlock_unlock(fastlock, flags) (void)flags
+
+typedef uint16_t bcmos_mutex;
+#define bcmos_mutex_create(mutex, flags, name)
+#define bcmos_mutex_lock(mutex)
+#define bcmos_mutex_unlock(mutex)
+
+
+#define BCM_SIZEOFARRAY(arr) (sizeof(arr)/sizeof(*arr))
+#define BCM_SIZEOFFIELD(s, f) (sizeof(((s*)NULL)->f))
+#define BCM_MEMZERO_STRUCT(ptr) memset(ptr, 0, sizeof(*(ptr)))
+#define BCM_MEMCPY_ARRAY(dst, src) memcpy(dst, src, sizeof(dst))
+
+
+#define BUG_ON_PRINT(condition, fmt, args...) \
+ do \
+ { \
+ if (condition) \
+ { \
+ printf(fmt, ##args); \
+ /* On one hand, don't let this task continue - it is likely to crash/create a system exception.
+ * On the other hand, it mustn't do a busy loop - otherwise it can cause lower priority tasks to stop responding. */ \
+ while (1) \
+ bcmos_usleep(10000000); \
+ } \
+ } while (0)
+
+#define BUG_ON(condition) BUG_ON_PRINT((condition), "BUG in %s %d!\n", __FUNCTION__, __LINE__)
+#define BUG() BUG_ON(1)
+#define BUG_UNLESS(condition) BUG_ON(!(condition))
+
+
+#define BCMOS_TRACE_ERR(fmt, args...) \
+ do \
+ { \
+ printf( fmt, ## args); \
+ } while (0)
+
+
+#define bcmos_vprintf printf
+#define bcmos_calloc(s) KMALLOC((s), 0)
+
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/linux/Makefile b/bcm68620_release/release/host_customized/os_abstraction/linux/Makefile
new file mode 100644
index 0000000..c66f726
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/linux/Makefile
@@ -0,0 +1,31 @@
+# Linux kernel OS abstraction
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = os_linux
+MOD_TYPE = linux_module
+MOD_SUPPRESS_OS_DEP = y
+MOD_DEPS = ll_pcie
+
+MOD_INC_DIRS = $(SRC_DIR) $(SRC_DIR)/..
+ifeq ("$(RELEASE_BUILD)", "y")
+ MOD_INC_DIRS += host_driver/config
+else
+ MOD_INC_DIRS += $(SUBSYSTEM)/os_abstraction/$(PLATFORM) $(SUBSYSTEM)/config
+endif
+
+EXTRA_CFLAGS += -DBCMOS_TRACE_PRINTF
+
+srcs = bcmos_system.c ../bcmos_errno.c ../bcmos_common.c
+
+ifeq ("$(DEBUG)", "y")
+ MOD_DEFS += -DBCMOS_MEM_DEBUG -DBCMOS_SYS_UNITTEST
+endif
+
+# If called by linux kernel builder - add include paths manually.
+# It is not elegant, but we'll not have many linux modules
+ifneq ("$(KBUILD_SRC)", "")
+ -include $(OUT_DIR_BASE)/Makefile.config.$(MOD_NAME)
+endif
+
+endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.c b/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.c
new file mode 100644
index 0000000..0b4a023
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.c
@@ -0,0 +1,536 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmos_system.c
+ *
+ * This file implements a subset of OS Abstraction services
+ * for linux kernel
+ */
+
+#include <bcmos_system.h>
+
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <asm-generic/pci-dma-compat.h>
+#include <linux/fs.h>
+#include <linux/fdtable.h>
+
+#include <bcmolt_llpcie.h>
+
+/* task control blocks */
+extern STAILQ_HEAD(task_list, bcmos_task) task_list;
+
+/* global OS lock */
+extern bcmos_mutex bcmos_res_lock;
+
+/* Initialize system library */
+bcmos_errno bcmos_sys_init(void)
+{
+ return BCM_ERR_OK;
+}
+/* Clean-up system library */
+void bcmos_sys_exit(void)
+{
+}
+
+/*
+ * Thread handler
+ */
+static int bcmos_task_handler(void *data)
+{
+ bcmos_task *task = (bcmos_task *)data;
+ F_bcmos_task_handler handler;
+ long handler_data;
+
+ task->sys_task.t = current;
+
+ if (task->parm.handler)
+ {
+ /* "traditional task */
+ handler = task->parm.handler;
+ handler_data = task->parm.data;
+ }
+ else
+ {
+ /* "integrated" task */
+ handler = bcmos_dft_task_handler;
+ handler_data = (long)task;
+ }
+ handler(handler_data);
+
+ return 0;
+}
+
+void _bcmos_backtrace(void)
+{
+ /*todo implement this*/
+}
+
+/* Create a new task.
+ * Attention! Priority is ignored.
+ */
+bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm)
+{
+ struct task_struct *t;
+ bcmos_errno rc;
+
+ if (!task || !parm)
+ return BCM_ERR_PARM;
+
+ memset(task, 0, sizeof(*task));
+ task->parm = *parm;
+ if (!parm->handler)
+ {
+ /* Initialize and lock mutex to wait on */
+ rc = bcmos_sem_create(&task->active_sem, 0, task->parm.flags, parm->name);
+ if (rc)
+ {
+ BCMOS_TRACE_ERR("Task %s: can't create active_sem. Error %s (%d)\n",
+ task->parm.name, bcmos_strerror(rc), rc);
+ return rc;
+ }
+ }
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (task->parm.name)
+ {
+ strncpy(task->name, task->parm.name, sizeof(task->name) - 1);
+ task->parm.name = task->name;
+ }
+ bcmos_fastlock_init(&task->active_lock, 0);
+ task->magic = BCMOS_TASK_MAGIC;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&task_list, task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+
+ t = kthread_run(bcmos_task_handler, task, parm->name);
+ if (t == ERR_PTR(-ENOMEM))
+ {
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = 0;
+ return BCM_ERR_NOMEM;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* Destroy task */
+bcmos_errno bcmos_task_destroy(bcmos_task *task)
+{
+ if (task->magic != BCMOS_TASK_MAGIC)
+ {
+ return BCM_ERR_PARM;
+ }
+ if (!task->sys_task.t)
+ {
+ return BCM_ERR_NOENT;
+ }
+ task->destroy_request = BCMOS_TRUE;
+ task->magic = BCMOS_TASK_MAGIC_DESTROYED;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ /* The task may be waiting on semaphore. Kick it */
+ if (!task->parm.handler)
+ {
+ bcmos_sem_post(&task->active_sem);
+ }
+
+ /* Sometimes by the time we get here the task has already been disposed of.
+ * TODO: investigate why */
+ if (task->sys_task.t->cred != NULL)
+ {
+ kthread_stop(task->sys_task.t);
+ }
+ return BCM_ERR_OK;
+}
+
+/** Get current task
+ * \returns task handle or NULL if not in task context
+ */
+bcmos_task *bcmos_task_current(void)
+{
+ struct task_struct *kt = current;
+ bcmos_task *t, *tmp;
+
+ STAILQ_FOREACH_SAFE(t, &task_list, list, tmp)
+ {
+ if (t->sys_task.t == kt)
+ break;
+ }
+ return t;
+}
+
+/* timer signal handler */
+static void sys_timer_handler(unsigned long data)
+{
+ bcmos_sys_timer *timer = (bcmos_sys_timer *)data;
+ timer->handler(timer->data);
+}
+
+/* Create timer */
+bcmos_errno bcmos_sys_timer_create(bcmos_sys_timer *timer, bcmos_sys_timer_handler handler, void *data)
+{
+ if (!timer || !handler)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "timer %p, handler %p\n", timer, handler);
+
+ timer->handler = handler;
+ timer->data = data;
+ init_timer(&timer->t);
+ timer->t.function = sys_timer_handler;
+ timer->t.data = (unsigned long)timer;
+
+ return BCM_ERR_OK;
+}
+
+/* Destroy timer */
+void bcmos_sys_timer_destroy(bcmos_sys_timer *timer)
+{
+ del_timer_sync(&timer->t);
+}
+
+/* (Re)start timer */
+void bcmos_sys_timer_start(bcmos_sys_timer *timer, uint32_t delay)
+{
+ /* Convert delay us --> ticks */
+ uint32_t ticks = usecs_to_jiffies(delay);
+ mod_timer(&timer->t, jiffies + ticks);
+}
+
+/* Stop timer if running */
+void bcmos_sys_timer_stop(bcmos_sys_timer *timer)
+{
+ /* No need to do anything. System timer isn't running */
+}
+
+void bcmos_usleep(uint32_t u)
+{
+ if (u >= 10000)
+ msleep((u + 999) / 1000);
+ else
+ udelay(u);
+}
+
+/*
+ * Semaphore
+ */
+
+/* Decrement semaphore counter. Wait if the counter is 0.
+ */
+bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout)
+{
+ if (timeout)
+ {
+ if (timeout != BCMOS_WAIT_FOREVER)
+ {
+ if (down_timeout(&sem->s, usecs_to_jiffies(timeout)))
+ return BCM_ERR_TIMEOUT;
+ }
+ else
+ {
+ if (down_interruptible(&sem->s))
+ return BCM_ERR_INTERNAL;
+ }
+ return BCM_ERR_OK;
+ }
+
+ /* 0 timeout */
+ if (down_trylock(&sem->s))
+ {
+ return BCM_ERR_NOENT;
+ }
+ return BCM_ERR_OK;
+}
+
+
+/*
+ * Byte memory pool
+ */
+
+/* Memory block header */
+typedef struct bcmos_byte_memblk
+{
+ bcmos_byte_pool *pool; /** pool that owns the block */
+ uint32_t size; /** block size (bytes) including bcmos_byte_memblk header */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /** magic number */
+#define BCMOS_MEM_MAGIC_ALLOC (('m'<<24) | ('b' << 16) | ('l' << 8) | 'k')
+#define BCMOS_MEM_MAGIC_FREE (('m'<<24) | ('b' << 16) | ('l' << 8) | '~')
+#endif
+} bcmos_byte_memblk;
+
+/* Create byte memory pool */
+bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm)
+{
+ if (!pool || !parm)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool %p, parm %p\n", pool, parm);
+ }
+
+ BCM_MEMZERO_STRUCT(pool);
+ pool->parm = *parm;
+ if (!pool->parm.size)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "size %u\n", parm->size);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_VALID;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Destroy memory pool */
+bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool)
+{
+ if (pool->allocated)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_STATE, "%u bytes of memory are still allocated from the pool %s\n",
+ pool->allocated, pool->parm.name);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_DELETED;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Allocate memory from memory pool */
+void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size)
+{
+ bcmos_byte_memblk *blk;
+ uint32_t byte_size;
+ void *ptr;
+
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+#endif
+
+ if (size + pool->allocated > pool->parm.size)
+ return NULL;
+
+ byte_size = size + sizeof(bcmos_byte_memblk);
+#ifdef BCMOS_MEM_DEBUG
+ byte_size += sizeof(uint32_t); /* block suffix */
+#endif
+ /* ToDo: Maintain LL of allocated blocks */
+ blk = (bcmos_byte_memblk *)bcmos_alloc(byte_size);
+ if (!blk)
+ return NULL;
+ ptr = (void *)(blk + 1);
+ blk->size = byte_size;
+ pool->allocated += byte_size;
+ blk->pool = pool;
+#ifdef BCMOS_MEM_DEBUG
+ blk->magic = BCMOS_MEM_MAGIC_ALLOC;
+ *(uint32_t *)((long)blk + byte_size - sizeof(uint32_t)) = BCMOS_MEM_MAGIC_ALLOC;
+#endif
+
+ return ptr;
+}
+
+/* Release memory allocated using bcmos_byte_pool_alloc() */
+void bcmos_byte_pool_free(void *ptr)
+{
+ bcmos_byte_memblk *blk;
+ bcmos_byte_pool *pool;
+
+ BUG_ON(!ptr);
+ blk = (bcmos_byte_memblk *)((long)ptr - sizeof(bcmos_byte_memblk));
+ pool = blk->pool;
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+ BUG_ON(blk->magic != BCMOS_MEM_MAGIC_ALLOC);
+ BUG_ON(*(uint32_t *)((long)blk + blk->size - sizeof(uint32_t)) != BCMOS_MEM_MAGIC_ALLOC);
+ blk->magic = BCMOS_MEM_MAGIC_FREE;
+#endif
+ pool->allocated -= blk->size;
+ bcmos_free(blk);
+}
+
+/*
+ * DMA-able memory management
+ */
+
+/* Dma-able block header */
+typedef struct
+{
+ struct pci_dev *pdev;
+ dma_addr_t dma_handle;
+ uint32_t size;
+} bcmos_dma_mem_hdr;
+
+/* Allocate DMA-able memory */
+void *bcmos_dma_alloc(uint8_t device, uint32_t size)
+{
+ bcmos_dma_mem_hdr hdr =
+ {
+ .pdev = (struct pci_dev *)bcm_ll_pcie_dev_get(device),
+ .size = size
+ };
+ void *ptr;
+
+ if (!hdr.pdev)
+ {
+ return NULL;
+ }
+
+ ptr = pci_alloc_consistent(hdr.pdev, size + sizeof(bcmos_dma_mem_hdr), &hdr.dma_handle);
+ if (ptr)
+ {
+ memcpy(ptr, &hdr, sizeof(hdr));
+ }
+ return (void *)((long)ptr + sizeof(hdr));
+}
+
+/* Release DMA-able memory */
+void bcmos_dma_free(uint8_t device, void *ptr)
+{
+ bcmos_dma_mem_hdr hdr;
+
+ /* Step back to prefix area */
+ ptr = (void *)((long)ptr - sizeof(hdr));
+ memcpy(&hdr, ptr, sizeof(hdr));
+
+ /* Sanity check */
+ if (!hdr.pdev || hdr.pdev != bcm_ll_pcie_dev_get(device))
+ {
+ BCMOS_TRACE_ERR("!!!Attempt to release insane DMA-able pointer. ptr=%p pdev=%p/%p\n",
+ ptr, hdr.pdev, bcm_ll_pcie_dev_get(device));
+ return;
+ }
+ pci_free_consistent(hdr.pdev, hdr.size, ptr, hdr.dma_handle);
+}
+
+/*
+ * Print to the current process' stdout
+ */
+
+#ifndef STDOUT_FILENO
+#define STDOUT_FILENO 1
+#endif
+
+static int _bcmos_write(struct file *fd, const unsigned char *buf, int len)
+{
+ mm_segment_t oldfs;
+ int len0 = len;
+ oldfs = get_fs();
+ set_fs(KERNEL_DS);
+ while(len)
+ {
+ int lw;
+ lw = vfs_write(fd, (char *)buf, len, &fd->f_pos);
+ if (lw < 0)
+ break;
+ len -= lw;
+ if (len)
+ {
+ if (msleep_interruptible(1))
+ break;
+ buf += lw;
+ }
+ }
+ set_fs(oldfs);
+ return (len0 - len);
+}
+
+int bcmos_sys_vprintf(const char *format, va_list args)
+{
+ struct file *f;
+ int rc=0;
+
+ /* Get stdout file handle if any */
+ if (in_interrupt() || !current || !current->files)
+ f = 0;
+ else
+ f = fcheck(STDOUT_FILENO);
+ if (!f)
+ {
+ rc = vprintk(format, args);
+ }
+ else
+ {
+ char printbuf[1024];
+ char *p1=printbuf, *p2;
+ vscnprintf(printbuf, sizeof(printbuf)-1, format, args);
+ printbuf[sizeof(printbuf)-1]=0;
+ do
+ {
+ p2 = strchr(p1, '\n');
+ if (p2)
+ {
+ rc += _bcmos_write(f, (unsigned char*) p1, p2-p1+1);
+ rc += _bcmos_write(f, (unsigned char*)"\r", 1);
+ }
+ else
+ {
+ rc += _bcmos_write(f, (unsigned char*)p1, strlen(p1));
+ }
+ p1 = p2 + 1;
+ } while(p2);
+ }
+ return rc;
+}
+
+static int os_linux_module_init(void)
+{
+ bcmos_errno rc;
+
+ rc = bcmos_init();
+
+ return rc ? -EINVAL : 0;
+}
+
+static void os_linux_module_exit(void)
+{
+ bcmos_exit();
+}
+
+module_init(os_linux_module_init);
+module_exit(os_linux_module_exit);
+
+MODULE_DESCRIPTION("OS Abstraction");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(bcmos_task_create);
+EXPORT_SYMBOL(bcmos_task_destroy);
+EXPORT_SYMBOL(bcmos_task_current);
+EXPORT_SYMBOL(bcmos_sem_wait);
+EXPORT_SYMBOL(bcmos_sys_trace_level);
+EXPORT_SYMBOL(bcmos_usleep);
+EXPORT_SYMBOL(bcmos_byte_pool_create);
+EXPORT_SYMBOL(bcmos_byte_pool_destroy);
+EXPORT_SYMBOL(bcmos_byte_pool_alloc);
+EXPORT_SYMBOL(bcmos_byte_pool_free);
+EXPORT_SYMBOL(bcmos_sys_vprintf);
+EXPORT_SYMBOL(bcmos_dma_alloc);
+EXPORT_SYMBOL(bcmos_dma_free);
+EXPORT_SYMBOL(_bcmos_backtrace);
+EXPORT_SYMBOL(sw_error_handler);
+EXPORT_SYMBOL(bcmos_exit);
diff --git a/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.h b/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.h
new file mode 100644
index 0000000..d6f36fe
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/linux/bcmos_system.h
@@ -0,0 +1,519 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmos_system.h
+ * Maple System Services
+ * posix port: simulation
+ */
+
+#ifndef BCMOS_SYSTEM_H_
+#define BCMOS_SYSTEM_H_
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/string.h>
+#include <linux/stddef.h>
+#include <linux/skbuff.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/semaphore.h>
+#include <linux/interrupt.h>
+#include <linux/kthread.h>
+#include <linux/compiler.h>
+#include <linux/random.h>
+#include <linux/ctype.h>
+#include <linux/time.h>
+#include <asm/io.h>
+
+#define BCMOS_IRQ_SINGLE 0
+#define BCMOS_IRQ_SHARED IRQF_SHARED
+
+/* Re-define GNU typeof as ISO __typeof__ */
+#define typeof __typeof__
+
+#define strtol(s,p,b) simple_strtol(s,p,b)
+
+/* Specify here which system functions are inlined */
+
+#define BCMOS_FASTLOCK_INLINE
+#define BCMOS_SEM_INLINE
+#define BCMOS_MUTEX_INLINE
+
+#ifdef ENABLE_LOG
+#define BCMOS_TRACE_IN_DEV_LOG
+#endif
+
+#if !defined(BCMOS_TRACE_IN_DEV_LOG) && !defined(BCMOS_TRACE_PRINTF)
+#define BCMOS_TRACE_PRINTF
+#endif
+
+/* #define BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */
+#define BCMOS_MALLOC_FREE_INLINE
+/* #define BCMOS_CALLOC_INLINE */
+#define BCMOS_BUF_OS_SPECIFIC
+#define BCMOS_BUF_INLINE
+#define BCMOS_INTERRUPT_INLINE
+#define BCMOS_TIMESTAMP_INLINE
+/* #define BCMOS_DMA_ALLOC_FREE_INLINE */
+#define BCMOS_VIRT_TO_PHYS_INLINE
+#define BCMOS_CACHE_INLINE
+/* Uncommentthe following line if h/w supports DMA cache coherency */
+/* #define BCMOS_DMA_CACHE_COHERENCY */
+
+/* getchar, putchar are not support. define as inline and proviude dummy targets */
+#define BCMOS_GETCHAR_INLINE
+#define BCMOS_PUTCHAR_INLINE
+
+#include "bcmos_common.h"
+
+static inline void bcm_pci_write32(volatile uint32_t *address, uint32_t value)
+{
+ writel(value, address);
+}
+
+static inline uint32_t bcm_pci_read32(const volatile uint32_t *address)
+{
+ return readl(address);
+}
+
+
+void _bcmos_backtrace(void);
+int bcmos_sys_vprintf(const char *format, va_list args);
+
+/*
+ * Memory allocation
+ */
+
+/* Allocate DMAable memory from the main heap */
+static inline void *bcmos_alloc(uint32_t size)
+{
+ return kmalloc(size, GFP_DMA);
+}
+
+/* Release memory to the main pool */
+static inline void bcmos_free(void *ptr)
+{
+ return kfree(ptr);
+}
+
+static inline void *bcmos_alloc_not_cache(int32_t size)
+{
+ return kmalloc(size, GFP_KERNEL);
+}
+static inline void bcmos_free_not_cache(void *dest)
+{
+ kfree(dest);
+}
+/*
+ * Synchronization
+ */
+
+/* Mutex control block */
+struct bcmos_mutex
+{
+ struct mutex m; /**< linux kernel mutex */
+};
+
+/* Create recursive mutex */
+static inline bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name)
+{
+ mutex_init(&mutex->m);
+ return BCM_ERR_OK;
+}
+
+/* Destroy mutex */
+static inline void bcmos_mutex_destroy(bcmos_mutex *mutex)
+{
+ mutex_destroy(&mutex->m);
+}
+
+/* Lock mutex */
+static inline void bcmos_mutex_lock(bcmos_mutex *mutex)
+{
+ mutex_lock(&mutex->m);
+}
+
+/* Release mutex */
+static inline void bcmos_mutex_unlock(bcmos_mutex *mutex)
+{
+ mutex_unlock(&mutex->m);
+}
+
+/** Fast lock control block */
+struct bcmos_fastlock
+{
+ spinlock_t m;
+};
+
+/** Fastlock initializer. Can be used instead of calling bcmos_fastlock_init() */
+#define BCMOS_FASTLOCK_INITIALIZER { SPINLOCK_UNLOCKED }
+
+/* Init fastlock */
+static inline void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags)
+{
+ spin_lock_init(&lock->m);
+}
+
+/* Take fast lock */
+static inline long bcmos_fastlock_lock(bcmos_fastlock *lock)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&lock->m, flags);
+ return (long)flags;
+}
+
+/* Release fast lock */
+static inline void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags)
+{
+ spin_unlock_irqrestore(&lock->m, (unsigned long)flags);
+}
+
+/** Semaphore control block */
+struct bcmos_sem
+{
+ struct semaphore s; /**< linux kernel semaphore */
+};
+
+/* Create semaphore */
+static inline bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name)
+{
+ sema_init(&sem->s, count);
+ return BCM_ERR_OK;
+}
+
+/* Destroy semaphore */
+static inline void bcmos_sem_destroy(bcmos_sem *sem)
+{
+}
+
+/* Wait for semaphore */
+bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout);
+
+/* Increment semaphore counter */
+static inline void bcmos_sem_post(bcmos_sem *sem)
+{
+ up(&sem->s);
+}
+
+/*
+ * Timers
+ */
+
+/** System timer */
+struct bcmos_sys_timer
+{
+ struct timer_list t; /**< linux timer */
+ bcmos_sys_timer_handler handler; /**< Timer handler */
+ void *data; /**< Parameter to be passed to the handler */
+};
+
+/* Get current timestamp (us) */
+static inline uint32_t bcmos_timestamp(void)
+{
+ struct timespec uptime;
+ do_posix_clock_monotonic_gettime(&uptime);
+ monotonic_to_bootbased(&uptime);
+ return uptime.tv_sec * USEC_PER_SEC + uptime.tv_nsec / NSEC_PER_USEC;
+}
+
+/* Get current timestamp (us) */
+static inline uint64_t bcmos_timestamp64(void)
+{
+ struct timespec uptime;
+ do_posix_clock_monotonic_gettime(&uptime);
+ monotonic_to_bootbased(&uptime);
+ return (uint64_t)uptime.tv_sec * USEC_PER_SEC + (uint64_t)uptime.tv_nsec / NSEC_PER_USEC;
+}
+
+/*
+ * Task control
+ */
+
+/** OS-specific task control block extension */
+typedef struct bcmos_sys_task
+{
+ struct task_struct *t;
+} bcmos_sys_task;
+
+/** Memory pool control block */
+struct bcmos_byte_pool
+{
+ bcmos_byte_pool_parm parm; /**< Pool parameters */
+ uint32_t allocated; /**< Number of bytes allocated */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /**< magic number */
+#define BCMOS_BYTE_POOL_VALID (('b'<<24) | ('y' << 16) | ('p' << 8) | 'o')
+#define BCMOS_BYTE_POOL_DELETED (('b'<<24) | ('y' << 16) | ('p' << 8) | '~')
+#endif
+};
+
+/* Transport / network buffer service */
+extern uint32_t bcmos_buf_default_headroom;
+
+/*
+ * Network / transport buffer
+ */
+
+/* Data alignment. Should be a max lf L1, L2 cache line size */
+#define BCMOS_BUF_DATA_ALIGNMENT 128
+
+/* Encapsulated skb */
+struct bcmos_buf
+{
+ struct sk_buff skb;
+};
+
+/* Buffer list */
+typedef struct sk_buff_head bcmos_buf_queue;
+
+/* Allocate buffer */
+static inline bcmos_buf *bcmos_buf_alloc(uint32_t size)
+{
+ /* Allocate extra 2 * BCMOS_BUF_DATA_ALIGNMENT to make sure that neither data start nor end
+ * end up in the middle of cache line
+ */
+ struct sk_buff *skb = dev_alloc_skb(size + BCMTR_BUF_EXTRA_HEADROOM + 2 * BCMOS_BUF_DATA_ALIGNMENT - 1);
+ if (!skb)
+ return NULL;
+#if BCMTR_BUF_EXTRA_HEADROOM
+ skb_reserve(skb, BCMTR_BUF_EXTRA_HEADROOM);
+#endif
+ if ((long)skb->data & (BCMOS_BUF_DATA_ALIGNMENT - 1))
+ {
+ skb_reserve(skb, BCMOS_BUF_DATA_ALIGNMENT - ((long)skb->data & (BCMOS_BUF_DATA_ALIGNMENT - 1)));
+ }
+ return (bcmos_buf *)skb;
+}
+
+/* Release buffer */
+static inline void bcmos_buf_free(bcmos_buf *buf)
+{
+ consume_skb(&buf->skb);
+}
+
+/* Get data length */
+static inline uint32_t bcmos_buf_length(bcmos_buf *buf)
+{
+ return buf->skb.len;
+}
+
+/* Set data length */
+static inline bcmos_errno bcmos_buf_length_set(bcmos_buf *buf, uint32_t length)
+{
+ if (unlikely(length > skb_tailroom(&buf->skb)))
+ {
+ BCMOS_TRACE_ERR("!!!%s: length=%u tailroom=%d\n",
+ __FUNCTION__, length, skb_tailroom(&buf->skb));
+ return BCM_ERR_OVERFLOW;
+ }
+ buf->skb.len = length;
+ return BCM_ERR_OK;
+}
+
+/* Get buffer data pointer. */
+static inline uint8_t *bcmos_buf_data(bcmos_buf *buf)
+{
+ return buf->skb.data;
+}
+
+/* Get buffer channel. */
+static inline uint8_t bcmos_buf_channel(bcmos_buf *buf)
+{
+ return buf->skb.cb[0];
+}
+
+/* Set buffer channel. */
+static inline void bcmos_buf_channel_set(bcmos_buf *buf, uint8_t channel)
+{
+ buf->skb.cb[0] = channel;
+}
+
+/** Initialize buffer queue
+ * \param[in] q Buffer queue
+ */
+static inline void bcmos_buf_queue_init(bcmos_buf_queue *q)
+{
+ skb_queue_head_init(q);
+}
+
+/** Enqueue buffer
+ *
+ * Must be called under lock, e.g., q->lock
+ *
+ * \param[in] q Buffer queue
+ * \param[in] buf Buffer
+ */
+static inline void bcmos_buf_queue_put(bcmos_buf_queue *q, bcmos_buf *buf)
+{
+ __skb_queue_tail(q, &buf->skb);
+}
+
+/* Check if buffer queue is empty
+ * \param[in] q Buffer queue
+ * \returns TRUE if the queue is empty
+ */
+static inline bcmos_bool bcmos_buf_queue_is_empty(bcmos_buf_queue *q)
+{
+ return (bcmos_bool)skb_queue_empty(q);
+}
+
+/* Dequeue buffer
+ *
+ * Must be called under lock, e.g., q->lock
+ *
+ * Remove and return the 1st queued buffer.
+ * \param[in] q Buffer queue
+ * \returns the buffer pointer
+ */
+static inline bcmos_buf *bcmos_buf_queue_get(bcmos_buf_queue *q)
+{
+ struct sk_buff *skb = __skb_dequeue(q);
+ return skb ? container_of(skb, bcmos_buf, skb) : NULL;
+}
+
+/* Peek into queue and return the 1st buffer without dequeing it
+ *
+ * Must be called under lock, e.g., q->lock
+ * \param[in] q Buffer queue
+ * \returns the buffer pointer
+ */
+static inline bcmos_buf *bcmos_buf_queue_peek(bcmos_buf_queue *q)
+{
+ struct sk_buff *skb = skb_peek(q);
+ return skb ? container_of(skb, bcmos_buf, skb) : NULL;
+}
+
+/*
+ * dcache utilities
+ */
+/* Invalidate address area in data cache. Dirty cache lines content is discarded */
+static inline void bcmos_dcache_inv(void *start, uint32_t size)
+{
+#if defined(CONFIG_MIPS)
+ dma_cache_inv((unsigned long)start, size);
+#elif defined(CONFIG_PPC)
+ if (((unsigned long)start & (L1_CACHE_BYTES - 1)) || (size & (L1_CACHE_BYTES - 1)))
+ flush_dcache_range((unsigned long)start, (unsigned long)start + size);
+ else
+ invalidate_dcache_range((unsigned long)start, (unsigned long)start + size);
+#elif defined(CONFIG_UML)
+ /* Nothing to do */
+#else
+#error Please implement bcmos_dcache_inv()
+#endif
+}
+
+/* Flush address area in data cache. Dirty cache lines are committed to memory */
+static inline void bcmos_dcache_flush(void *start, uint32_t size)
+{
+#if defined(CONFIG_MIPS)
+ dma_cache_wback((unsigned long)start, size);
+#elif defined(CONFIG_PPC)
+ clean_dcache_range((unsigned long)start, (unsigned long)start + size);
+#elif defined(CONFIG_UML)
+ /* Nothing to do */
+#else
+#error Please implement bcmos_dcache_flush()
+#endif
+}
+
+/*
+ * Interrupt service
+ */
+
+/* Connect system interrupt */
+static inline int bcmos_int_connect(int irq, int cpu, int flags,
+ int (*isr)(int irq, void *priv), const char *name, void *priv)
+{
+ return request_irq(irq, (irq_handler_t)isr, flags, name, priv);
+}
+
+/* Disconnect system interrupt */
+static inline void bcmos_int_disconnect(int irq, void *priv)
+{
+ free_irq(irq, priv);
+}
+
+/* Unmask IRQ */
+static inline void bcmos_int_enable(int irq)
+{
+ enable_irq(irq);
+}
+
+/* Mask IRQ */
+static inline void bcmos_int_disable(int irq)
+{
+ disable_irq(irq);
+}
+
+/* Check in-irq status */
+static inline int is_irq_mode(void)
+{
+ return in_interrupt();
+}
+
+/* Check if interrupts are disabled */
+static inline int is_irq_disabled(void)
+{
+ return irqs_disabled();
+}
+
+/* Convert virtual address to physical address */
+static inline unsigned long bcmos_virt_to_phys(void *va)
+{
+ return virt_to_phys(va);
+}
+
+/* write barrier */
+static inline void bcmos_barrier(void)
+{
+ smp_wmb();
+}
+static inline int bcmos_getchar(void)
+{
+ return -1;
+}
+
+static inline void bcmos_putchar(int c)
+{
+}
+
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+#undef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+#endif
+
+#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
+#undef BCMOS_MSG_QUEUE_UDP_SOCKET
+#endif
+
+/* 2nd part of OS-independent declarations */
+#include "bcmos_common2.h"
+
+#endif /* BCMOS_SYSTEM_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/os_cli/Makefile b/bcm68620_release/release/host_customized/os_abstraction/os_cli/Makefile
new file mode 100644
index 0000000..545a86a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/os_cli/Makefile
@@ -0,0 +1,7 @@
+# OS CLI commands
+#
+MOD_NAME = os_cli
+MOD_TYPE = lib
+MOD_DEPS = cli
+
+srcs = bcmos_cli.c
diff --git a/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.c b/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.c
new file mode 100644
index 0000000..3aef31a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.c
@@ -0,0 +1,335 @@
+/*
+<: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_cli.h>
+
+static bcmcli_entry *os_cli_dir;
+
+static bcmcli_enum_val trace_level_table[] =
+{
+ { .name="none", .val=BCMOS_TRACE_LEVEL_NONE },
+ { .name="error", .val=BCMOS_TRACE_LEVEL_ERROR },
+ { .name="info", .val=BCMOS_TRACE_LEVEL_INFO },
+ { .name="verbose_info", .val=BCMOS_TRACE_LEVEL_VERBOSE },
+ { .name="debug", .val=BCMOS_TRACE_LEVEL_DEBUG },
+ BCMCLI_ENUM_LAST
+};
+
+/*
+ * Command handlers
+ */
+
+static bcmos_errno _oscli_trace_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ bcmos_trace_level level = (bcmos_trace_level)parm[0].value.number;
+
+ if (bcmcli_parm_is_set(session, &parm[0]))
+ {
+ bcmos_trace_level old_level;
+
+ old_level = bcmos_trace_level_set(level);
+ bcmcli_session_print(session, "OS trace level: old=%s new=%s\n",
+ bcmcli_enum_stringval(trace_level_table, old_level),
+ bcmcli_enum_stringval(trace_level_table, level));
+ }
+ else
+ {
+ bcmcli_session_print(session, "OS trace level: %s\n",
+ bcmcli_enum_stringval(trace_level_table, bcmos_trace_level_get()));
+ }
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _oscli_task_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *name = bcmcli_parm_is_set(session, &parm[0]) ? (const char *)parm[0].value.string : NULL;
+ bcmos_task *task = NULL;
+ int nt = 0;
+
+ bcmcli_session_print(session, "%-20s %4s %4s %-10s %s\n", "task", "prio", "core", "timeout", "handler");
+ while (bcmos_task_get_next(&task) == BCM_ERR_OK)
+ {
+ bcmos_task_parm tp = {};
+ bcmos_task_query(task, &tp);
+ if (!name || (name && tp.name && strstr(tp.name, name)))
+ {
+ char core_name[10];
+ if (tp.core != BCMOS_CPU_CORE_ANY)
+ {
+ snprintf(core_name, sizeof(core_name), "%d", tp.core - 1);
+ }
+ else
+ {
+ strcpy(core_name, "any");
+ }
+ bcmcli_session_print(session, "%-20s %-4d %-4s %-10u %p\n",
+ tp.name, tp.priority, core_name,
+ (tp.msg_wait_timeout == BCMOS_WAIT_FOREVER) ? 0 : tp.msg_wait_timeout, tp.handler);
+ ++nt;
+ }
+ }
+ bcmcli_session_print(session, "%d tasks listed\n", nt);
+
+ return BCM_ERR_OK;
+}
+
+static void _oscli_print_qinfo_hdr(bcmcli_session *session, const char *prefix)
+{
+ bcmcli_session_print(session, "%-9s %-9s %-10s %-10s %-10s %-10s %-8s %-8s %-10s congested\n",
+ prefix ? prefix : "", "size", "in", "put", "get", "discard", "l_thresh", "h_thresh", "near-full");
+}
+
+static void _oscli_print_qinfo(bcmcli_session *session, bcmos_msg_queue_info *qi, const char *prefix)
+{
+ bcmcli_session_print(session, "%-s %-9d %-10u %-10u %-10u %-10u %-8d %-8d %-10u %s\n",
+ prefix ? prefix : "", (int)qi->parm.size, qi->stat.msg_in,
+ qi->stat.msg_sent, qi->stat.msg_received,
+ qi->stat.msg_discarded, (int)qi->parm.low_wm, (int)qi->parm.high_wm,
+ qi->stat.msg_almost_full, qi->stat.is_congested ? "yes" : "no");
+}
+
+static bcmos_errno _oscli_module_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ bcmos_module_id id = bcmcli_parm_is_set(session, &parm[0]) ?
+ (bcmos_module_id)parm[0].value.number : BCMOS_MODULE_ID_NONE;
+ bcmos_module_id i;
+ int nm = 0;
+
+ /* Heading */
+ _oscli_print_qinfo_hdr(session, "Module Task ");
+
+ for (i = BCMOS_MODULE_ID_NONE + 1; i < BCMOS_MODULE_ID__NUM_OF; i++)
+ {
+ bcmos_errno rc;
+ const bcmos_task *t = NULL;
+ bcmos_msg_queue_info qi = {};
+
+ rc = bcmos_module_query(i, &t, &qi);
+ if ((id == BCMOS_MODULE_ID_NONE || id == i) && rc == BCM_ERR_OK)
+ {
+ bcmos_task_parm tp = {};
+
+ bcmos_task_query(t, &tp);
+ bcmcli_session_print(session, "%-6d %-20s", i, (t && t->parm.name) ? t->parm.name : "*unknown*");
+ _oscli_print_qinfo(session, &qi, " ");
+ ++nm;
+ }
+ }
+ bcmcli_session_print(session, "%d modules listed\n", nm);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _oscli_blk_pool_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *name = bcmcli_parm_is_set(session, &parm[0]) ? (const char *)parm[0].value.string : NULL;
+ const bcmos_blk_pool *bp = NULL;
+ int nb = 0;
+
+ bcmcli_session_print(session, "%-24s %-9s %-9s %-9s %-10s %-10s %-10s %-10s\n",
+ "name", "pool_size", "blocks", "blk_size", "free", "allocated", "released", "failed");
+ while (bcmos_blk_pool_get_next(&bp) == BCM_ERR_OK)
+ {
+ bcmos_blk_pool_info pi = {};
+
+ bcmos_blk_pool_query(bp, &pi);
+ if (name == NULL || (pi.parm.name && strstr(pi.parm.name, name)))
+ {
+ bcmcli_session_print(session, "%-24s %-9u %-9u %-9u %-10u %-10u %-10u %-10u\n",
+ pi.parm.name ? pi.parm.name : "", pi.parm.pool_size, pi.parm.num_blks, pi.parm.blk_size,
+ pi.stat.free, pi.stat.allocated, pi.stat.released, pi.stat.alloc_failed);
+ ++nb;
+ }
+ }
+ bcmcli_session_print(session, "Total memory occupied by all block pools: %u bytes\n", bcmos_total_blk_pool_size);
+ bcmcli_session_print(session, "%d block pools listed\n", nb);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _oscli_msg_pool_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *name = bcmcli_parm_is_set(session, &parm[0]) ? (const char *)parm[0].value.string : NULL;
+ const bcmos_msg_pool *mp = NULL;
+ int np = 0;
+
+ bcmcli_session_print(session, "%-24s %-9s %-9s %-10s %-10s %-10s %-10s\n",
+ "name", "size", "data_size", "free", "allocated", "released", "failed");
+ while (bcmos_msg_pool_get_next(&mp) == BCM_ERR_OK)
+ {
+ bcmos_msg_pool_info pi = {};
+
+ bcmos_msg_pool_query(mp, &pi);
+ if (name == NULL || (pi.parm.name && strstr(pi.parm.name, name)))
+ {
+ bcmcli_session_print(session, "%-24s %-9u %-9u %-10u %-10u %-10u %-10u\n",
+ pi.parm.name ? pi.parm.name : "", pi.parm.size, pi.parm.data_size,
+ pi.stat.free, pi.stat.allocated, pi.stat.released, pi.stat.alloc_failed);
+ ++np;
+ }
+ }
+ bcmcli_session_print(session, "Total memory occupied by all message pools: %u bytes\n", bcmos_total_msg_pool_size);
+ bcmcli_session_print(session, "%d msg pools listed\n", np);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _oscli_msg_queue_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *name = bcmcli_parm_is_set(session, &parm[0]) ? (const char *)parm[0].value.string : NULL;
+ const bcmos_msg_queue *mq = NULL;
+ int nq = 0;
+
+ _oscli_print_qinfo_hdr(session, "name ");
+ while (bcmos_msg_queue_get_next(&mq) == BCM_ERR_OK)
+ {
+ bcmos_msg_queue_info qi = {};
+
+ bcmos_msg_queue_query(mq, &qi);
+ if (name == NULL || (qi.parm.name && strstr(qi.parm.name, name)))
+ {
+ bcmcli_session_print(session, "%-20s", qi.parm.name ? qi.parm.name : "");
+ _oscli_print_qinfo(session, &qi, " ");
+ ++nq;
+ }
+ }
+ bcmcli_session_print(session, "%d msg queues listed\n", nq);
+
+ return BCM_ERR_OK;
+}
+
+static void _oscli_print_qgroup_info_hdr(bcmcli_session *session)
+{
+ bcmcli_session_print(session, "%-12s %-6s %-9s %-10s %-10s %-10s %-10s %-8s %-8s %-10s congested\n",
+ "name", "queues", "size", "in", "put", "get", "discard", "l_thresh", "h_thresh", "near-full");
+}
+
+static void _oscli_print_qgroup_info(bcmcli_session *session, bcmos_msg_qgroup_info *qi)
+{
+ bcmcli_session_print(session, "%-12s %-6d %-9d %-10u %-10u %-10u %-10u %-8d %-8d %-10u %s\n",
+ qi->parm.name ? qi->parm.name : "", (int)qi->parm.nqueues, (int)qi->parm.size, qi->stat.msg_in,
+ qi->stat.msg_sent, qi->stat.msg_received,
+ qi->stat.msg_discarded, (int)qi->parm.low_wm, (int)qi->parm.high_wm,
+ qi->stat.msg_almost_full, qi->stat.is_congested ? "yes" : "no");
+}
+
+static bcmos_errno _oscli_msg_qgroup_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *name = bcmcli_parm_is_set(session, &parm[0]) ? (const char *)parm[0].value.string : NULL;
+ const bcmos_msg_qgroup *qgrp = NULL;
+ int ngroups = 0;
+
+ _oscli_print_qgroup_info_hdr(session);
+ while (bcmos_msg_qgroup_get_next(&qgrp) == BCM_ERR_OK)
+ {
+ bcmos_msg_qgroup_info qi = {};
+
+ bcmos_msg_qgroup_query(qgrp, &qi);
+ if (name == NULL || (qi.parm.name && strstr(qi.parm.name, name)))
+ {
+ _oscli_print_qgroup_info(session, &qi);
+ ++ngroups;
+ }
+ }
+ bcmcli_session_print(session, "%d msg queue groups listed\n", ngroups);
+
+ return BCM_ERR_OK;
+}
+
+#ifdef BCM_OS_THREADX
+
+extern TX_THREAD __sys_shell__;
+extern TX_THREAD *__usr_shell__;
+
+static bcmos_errno _oscli_sys_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ bcmcli_session_print(session, "Application CLI is suspended. Type \"suspend\" in system shell to resume\n");
+ tx_thread_resume(&__sys_shell__);
+ tx_thread_suspend(tx_thread_identify());
+ tx_thread_wait_abort(tx_thread_identify());
+ bcmcli_session_print(session, "Application CLI is resumed\n");
+ return BCM_ERR_OK;
+}
+#endif
+
+/*
+ * Init / exit interface
+ */
+
+
+bcmos_errno bcmos_cli_init(bcmcli_entry *top_dir)
+{
+ if (os_cli_dir)
+ {
+ return BCM_ERR_ALREADY;
+ }
+
+ /*
+ * rx directory
+ */
+ os_cli_dir = bcmcli_dir_add(top_dir, "os", "OS Abstraction", BCMCLI_ACCESS_GUEST, NULL);
+ BCMOS_CHECK_RETURN_ERROR(!os_cli_dir, BCM_ERR_INTERNAL);
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "trace", "Get/Set trace level", _oscli_trace_handler,
+ BCMCLI_MAKE_PARM_ENUM("level", "Trace level", trace_level_table, BCMCLI_PARM_FLAG_OPTIONAL));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "task", "Task info", _oscli_task_handler,
+ BCMCLI_MAKE_PARM("name", "Task name or partial name", BCMCLI_PARM_STRING, BCMCLI_PARM_FLAG_OPTIONAL));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "module", "Module(s)", _oscli_module_handler,
+ BCMCLI_MAKE_PARM_RANGE("id", "Module id", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_OPTIONAL,
+ BCMOS_MODULE_ID_NONE + 1, BCMOS_MODULE_ID__NUM_OF - 1));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "blk_pool", "Block pool(s)", _oscli_blk_pool_handler,
+ BCMCLI_MAKE_PARM("name", "Block pool name or partial name", BCMCLI_PARM_STRING, BCMCLI_PARM_FLAG_OPTIONAL));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "msg_pool", "Message pool(s)", _oscli_msg_pool_handler,
+ BCMCLI_MAKE_PARM("name", "Message pool name or partial name", BCMCLI_PARM_STRING, BCMCLI_PARM_FLAG_OPTIONAL));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "queue", "Message queue(s)", _oscli_msg_queue_handler,
+ BCMCLI_MAKE_PARM("name", "Message queue name or partial name", BCMCLI_PARM_STRING, BCMCLI_PARM_FLAG_OPTIONAL));
+
+ BCMCLI_MAKE_CMD(os_cli_dir, "qgroup", "Message queue group(s)", _oscli_msg_qgroup_handler,
+ BCMCLI_MAKE_PARM("name", "Message queue group name or partial name", BCMCLI_PARM_STRING, BCMCLI_PARM_FLAG_OPTIONAL));
+
+#ifdef BCM_OS_THREADX
+ BCMCLI_MAKE_CMD_NOPARM(os_cli_dir, "sys", "System shell", _oscli_sys_handler);
+#endif
+
+ return BCM_ERR_OK;
+}
+
+void bcmos_cli_exit(void)
+{
+ if (os_cli_dir)
+ {
+ bcmcli_token_destroy(os_cli_dir);
+ os_cli_dir = NULL;
+ }
+}
diff --git a/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.h b/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.h
new file mode 100644
index 0000000..487952c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/os_cli/bcmos_cli.h
@@ -0,0 +1,48 @@
+/*
+<: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 BCMOS_CLI_H_
+#define BCMOS_CLI_H_
+
+#include <bcmos_system.h>
+#include <bcmcli.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+bcmos_errno bcmos_cli_init(bcmcli_entry *top_dir);
+
+void bcmos_cli_exit(void);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* BCMOS_CLI_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.c b/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.c
new file mode 100644
index 0000000..d3cb902
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.c
@@ -0,0 +1,921 @@
+/*
+<: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"
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+#include <sys/un.h>
+#endif
+#include <sys/resource.h>
+
+/* task control blocks */
+extern STAILQ_HEAD(task_list, bcmos_task) task_list;
+
+/* global OS lock */
+extern bcmos_mutex bcmos_res_lock;
+
+/*
+ * Init
+ */
+
+#define TIMER_SIG SIGRTMIN
+
+/* Initialize system library */
+bcmos_errno bcmos_sys_init(void)
+{
+ return BCM_ERR_OK;
+}
+
+/* Clean-up system library */
+void bcmos_sys_exit(void)
+{
+}
+
+/*
+ * Task management
+ */
+
+/*
+ * Default task handler
+ */
+
+/* Create a new task */
+bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm)
+{
+ F_bcmos_task_handler handler;
+ pthread_attr_t pthread_attr;
+ struct sched_param pthread_sched_param = {};
+ int pthread_prio;
+ uint32_t stack_size;
+ void *data;
+ int rc;
+
+ if (!task || !parm)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "task %p, parm %p\n", task, parm);
+ memset(task, 0, sizeof(*task));
+ if (parm->handler)
+ {
+ /* "traditional task */
+ handler = parm->handler;
+ data = (void *)parm->data;
+ }
+ else
+ {
+ /* "integrated" task */
+ handler = bcmos_dft_task_handler;
+ data = task;
+
+ /* Initialize and lock mutex to wait on */
+ rc = bcmos_sem_create(&task->active_sem, 0, task->parm.flags, parm->name);
+ if (rc)
+ {
+ BCMOS_TRACE_ERR("Task %s: can't create active_sem. Error %s (%d)\n",
+ parm->name, bcmos_strerror(rc), rc);
+ return rc;
+ }
+ }
+
+ task->parm = *parm;
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (task->parm.name)
+ {
+ strncpy(task->name, task->parm.name, sizeof(task->name) - 1);
+ task->parm.name = task->name;
+ }
+ bcmos_fastlock_init(&task->active_lock, 0);
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&task_list, task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = BCMOS_TASK_MAGIC;
+ /* pthread priorities are 1..32, 32 being the highest */
+ pthread_prio = 32 - (int)parm->priority;
+ if (pthread_prio <= 0)
+ pthread_prio = 1;
+ stack_size = PTHREAD_STACK_MIN;
+ if (parm->stack_size && parm->stack_size > PTHREAD_STACK_MIN)
+ stack_size = parm->stack_size;
+ rc = pthread_attr_init(&pthread_attr);
+ pthread_sched_param.sched_priority = pthread_prio;
+ rc = rc ? rc : pthread_attr_setinheritsched(&pthread_attr, PTHREAD_EXPLICIT_SCHED);
+ rc = rc ? rc : pthread_attr_setschedpolicy(&pthread_attr, SCHED_RR);
+ rc = rc ? rc : pthread_attr_setschedparam(&pthread_attr, &pthread_sched_param);
+ rc = rc ? rc : pthread_attr_setstacksize(&pthread_attr, stack_size);
+ rc = rc ? rc : pthread_create(&task->sys_task.t, &pthread_attr, (void *(*)(void *))handler, data);
+ pthread_attr_destroy(&pthread_attr);
+ if (rc == EPERM)
+ {
+ BCMOS_TRACE_INFO("Thread %s: priority %d is ignored. Start as root to honor priorities\n",
+ parm->name, (int)parm->priority);
+ rc = pthread_create(&task->sys_task.t, NULL, (void *(*)(void *))handler, data);
+ }
+ if (rc)
+ {
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = 0;
+ if (!parm->handler)
+ {
+ bcmos_sem_destroy(&task->active_sem);
+ }
+ BCMOS_TRACE_RETURN(BCM_ERR_SYSCALL_ERR, "%s (%d)\n", strerror(rc), rc);
+ }
+ return BCM_ERR_OK;
+}
+
+/* Destroy task */
+bcmos_errno bcmos_task_destroy(bcmos_task *task)
+{
+ void *res;
+ int rc_cancel;
+ int rc;
+
+ if (task->magic != BCMOS_TASK_MAGIC)
+ {
+ return BCM_ERR_PARM;
+ }
+ task->destroy_request = BCMOS_TRUE;
+ task->magic = BCMOS_TASK_MAGIC_DESTROYED;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ /* The task may be waiting on semaphore. Kick it */
+ if (!task->parm.handler)
+ {
+ bcmos_sem_post(&task->active_sem);
+ }
+ rc_cancel = pthread_cancel(task->sys_task.t);
+ rc = pthread_join(task->sys_task.t, &res);
+ return (rc || ((!rc_cancel) && (res != PTHREAD_CANCELED))) ? BCM_ERR_SYSCALL_ERR : 0;
+}
+
+/** Get current task
+ * \returns task handle or NULL if not in task context
+ */
+bcmos_task *bcmos_task_current(void)
+{
+ pthread_t pt = pthread_self();
+ bcmos_task *t, *tmp;
+
+ STAILQ_FOREACH_SAFE(t, &task_list, list, tmp)
+ {
+ if (pthread_equal(pt, t->sys_task.t))
+ break;
+ }
+ return t;
+}
+
+/*
+ * Recursive mutex
+ */
+
+/* Create recursive mutex */
+bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name)
+{
+ int err;
+ err = pthread_mutexattr_init(&mutex->attr);
+ err = err ? err : pthread_mutexattr_settype(&mutex->attr, PTHREAD_MUTEX_RECURSIVE_NP);
+ err = err ? err : pthread_mutex_init(&mutex->m, &mutex->attr);
+ if (err)
+ BCMOS_TRACE_RETURN(BCM_ERR_SYSCALL_ERR, "errno=%s\n", strerror(err));
+ return BCM_ERR_OK;
+}
+
+/** Destroy mutex
+ * \param[in] mutex Mutex control block
+ */
+void bcmos_mutex_destroy(bcmos_mutex *mutex)
+{
+ pthread_mutex_destroy(&mutex->m);
+ pthread_mutexattr_destroy(&mutex->attr);
+}
+
+/* calculate absolute time equal to the current time + timeout */
+static inline void _bcmos_get_abs_time(struct timespec *ts, uint32_t timeout)
+{
+ int rc;
+ rc = clock_gettime(CLOCK_REALTIME, ts);
+ BUG_ON(rc);
+ ts->tv_sec += timeout / 1000000;
+ ts->tv_nsec += (timeout % 1000000) * 1000;
+ if (ts->tv_nsec > 1000000000)
+ {
+ ts->tv_sec += ts->tv_nsec / 1000000000;
+ ts->tv_nsec %= 1000000000;
+ }
+}
+
+/** Lock mutex
+ */
+void bcmos_mutex_lock(bcmos_mutex *mutex)
+{
+ int rc;
+ rc = pthread_mutex_lock(&mutex->m);
+ BUG_ON(rc);
+ return;
+}
+
+/** Release mutex
+ * \param[in] mutex Mutex control block
+ */
+void bcmos_mutex_unlock(bcmos_mutex *mutex)
+{
+ int rc;
+ rc = pthread_mutex_unlock(&mutex->m);
+ if (rc)
+ BCMOS_TRACE_ERR("pthread_mutex_unlock()->%d\n", rc);
+ BUG_ON(rc);
+}
+
+/*
+ * Semaphores
+ * Most of semaphore functions are inline
+ */
+
+/* Create semaphore */
+bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name)
+{
+ sem_init(&sem->s, 0, count);
+ return BCM_ERR_OK;
+}
+
+/* Destroy semaphore */
+void bcmos_sem_destroy(bcmos_sem *sem)
+{
+ sem_destroy(&sem->s);
+}
+
+/* Decrement semaphore counter. Wait if the counter is 0 */
+bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout)
+{
+ int rc;
+ struct timespec ts;
+
+ /* Init end time if necessary */
+ if (timeout && timeout != BCMOS_WAIT_FOREVER)
+ {
+ _bcmos_get_abs_time(&ts, timeout);
+ }
+
+ do
+ {
+ if (timeout == BCMOS_WAIT_FOREVER)
+ {
+ rc = sem_wait(&sem->s);
+ }
+ else if (timeout)
+ {
+ rc = sem_timedwait(&sem->s, &ts);
+ }
+ else
+ {
+ rc = sem_trywait(&sem->s);
+ }
+ } while (rc && errno == EINTR);
+
+ if (rc)
+ {
+ bcmos_errno err;
+
+ rc = errno;
+ if (rc == ETIMEDOUT)
+ {
+ err = BCM_ERR_TIMEOUT;
+ }
+ else
+ {
+ err = BCM_ERR_INTERNAL;
+ BCMOS_TRACE_ERR("sem_wait()->%d\n", rc);
+ }
+ return err;
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/*
+ * Timers
+ */
+
+/** Get current timestamp
+ * \returns the current system timestamp (us)
+ */
+uint32_t bcmos_timestamp(void)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ return (tp.tv_sec * 1000000 + tp.tv_nsec / 1000);
+}
+
+/** Get current timestamp - 64 bit
+ * \returns the current system timestamp (us)
+ */
+uint64_t bcmos_timestamp64(void)
+{
+ struct timespec tp;
+ clock_gettime(CLOCK_MONOTONIC, &tp);
+ return ((uint64_t)tp.tv_sec * 1000000LL + (uint64_t)tp.tv_nsec / 1000LL);
+}
+
+/*
+ * Timer handlers
+ */
+
+
+
+/* For posix we must create timer task, because there is no way
+ * to enforce protection between a signal handler and a thread
+ */
+static bcmos_task _bcmos_timer_task;
+static sem_t _bcmos_timer_lock;
+
+static int _bcmos_tmr_task_handler(long data)
+{
+ bcmos_sys_timer *timer = (bcmos_sys_timer *)data;
+ bcmos_task *this_task = bcmos_task_current();
+
+ while(!this_task->destroy_request)
+ {
+ sem_wait(&_bcmos_timer_lock);
+ timer->handler(timer->data);
+ }
+ this_task->destroyed = BCMOS_TRUE;
+
+ return 0;
+}
+
+/* timer signal handler */
+static void timer_sig_handler(int sig, siginfo_t *si, void *uc)
+{
+ BUG_ON(si->si_code != SI_TIMER);
+ sem_post(&_bcmos_timer_lock);
+}
+
+/* Create timer */
+bcmos_errno bcmos_sys_timer_create(bcmos_sys_timer *timer, bcmos_sys_timer_handler handler, void *data)
+{
+ static bcmos_task_parm tmr_task_parm = {
+ .name = "tmr_task",
+ .priority = BCMOS_TASK_PRIORITY_0,
+ .handler = _bcmos_tmr_task_handler
+ };
+ bcmos_errno rc;
+
+ struct sigaction sa;
+ struct sigevent sev = {};
+
+ if (!timer || !handler)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "timer %p, handler %p\n", timer, handler);
+
+ timer->handler = handler;
+ timer->data = data;
+
+ sem_init(&_bcmos_timer_lock, 0, 0);
+ tmr_task_parm.data = (long)timer;
+ rc = bcmos_task_create(&_bcmos_timer_task, &tmr_task_parm);
+ if (rc)
+ BCMOS_TRACE_RETURN(rc, "Can't create timer task\n");
+
+ sa.sa_flags = SA_SIGINFO;
+ sa.sa_sigaction = timer_sig_handler;
+ sigemptyset(&sa.sa_mask);
+ if (sigaction(TIMER_SIG, &sa, NULL) == -1)
+ perror("sigaction");
+ /* Prevent timer signal from interrupting system calls */
+ if (siginterrupt(TIMER_SIG, 0) == -1)
+ perror("siginterrupt");
+
+ /* Create librt timer */
+ sev.sigev_notify = SIGEV_SIGNAL;
+ sev.sigev_signo = TIMER_SIG;
+ sev.sigev_value.sival_ptr = timer;
+ if (timer_create(CLOCK_REALTIME, &sev, &timer->t) == -1)
+ BCMOS_TRACE_RETURN(BCM_ERR_SYSCALL_ERR, "errno %s\n", strerror(errno));
+
+ return BCM_ERR_OK;
+}
+
+/* Destroy timer */
+void bcmos_sys_timer_destroy(bcmos_sys_timer *timer)
+{
+ timer_delete(timer->t);
+ sem_destroy(&_bcmos_timer_lock);
+ bcmos_task_destroy(&_bcmos_timer_task);
+}
+
+/* (Re)start timer */
+void bcmos_sys_timer_start(bcmos_sys_timer *timer, uint32_t delay)
+{
+ struct itimerspec its;
+
+ its.it_value.tv_sec = delay / 1000000;
+ its.it_value.tv_nsec = (delay % 1000000) * 1000;
+ its.it_interval.tv_sec = 0;
+ its.it_interval.tv_nsec = 0;
+ if (timer_settime(timer->t, 0, &its, NULL) == -1)
+ {
+ BCMOS_TRACE_ERR("timer_settime errno %s\n", strerror(errno));
+ BUG();
+ }
+}
+
+/* Stop timer if running */
+void bcmos_sys_timer_stop(bcmos_sys_timer *timer)
+{
+ struct itimerspec its;
+
+ BUG_ON(!timer);
+ memset(&its, 0, sizeof(its));
+ timer_settime(timer->t, 0, &its, NULL);
+}
+
+
+/* Suspend current task for a time */
+void bcmos_usleep(uint32_t us)
+{
+ uint32_t ts = bcmos_timestamp();
+ uint32_t tse = ts + us;
+ int32_t d = (us > 1000000) ? 1000000 : us;
+
+ do
+ {
+ usleep(d);
+ d = tse - bcmos_timestamp();
+ if (d > 1000000) d = 1000000;
+ } while (d > 0);
+}
+
+/*
+ * Memory management
+ */
+
+/* Allocate memory from the main heap */
+void *bcmos_alloc(uint32_t size)
+{
+ return malloc(size);
+}
+
+/* Release memory to the main pool */
+void bcmos_free(void *ptr)
+{
+ free(ptr);
+}
+
+/*
+ * Byte memory pool
+ */
+
+/* Memory block header */
+typedef struct bcmos_byte_memblk
+{
+ bcmos_byte_pool *pool; /** pool that owns the block */
+ uint32_t size; /** block size (bytes) including bcmos_byte_memblk header */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /** magic number */
+#define BCMOS_MEM_MAGIC_ALLOC (('m'<<24) | ('b' << 16) | ('l' << 8) | 'k')
+#define BCMOS_MEM_MAGIC_FREE (('m'<<24) | ('b' << 16) | ('l' << 8) | '~')
+#endif
+} bcmos_byte_memblk;
+
+/* Create byte memory pool */
+bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm)
+{
+ if (!pool || !parm)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool %p, parm %p\n", pool, parm);
+ }
+
+ BCM_MEMZERO_STRUCT(pool);
+ pool->parm = *parm;
+ if (!pool->parm.size)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "size %u\n", parm->size);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_VALID;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Destroy memory pool */
+bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool)
+{
+ if (pool->allocated)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_STATE, "%u bytes of memory are still allocated from the pool %s\n",
+ pool->allocated, pool->parm.name);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_DELETED;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Allocate memory from memory pool */
+void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size)
+{
+ bcmos_byte_memblk *blk;
+ uint32_t byte_size;
+ void *ptr;
+
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+#endif
+
+ if (size + pool->allocated > pool->parm.size)
+ return NULL;
+
+ byte_size = size + sizeof(bcmos_byte_memblk);
+#ifdef BCMOS_MEM_DEBUG
+ byte_size += sizeof(uint32_t); /* block suffix */
+#endif
+ /* ToDo: Maintain LL of allocated blocks */
+ blk = (bcmos_byte_memblk *)malloc(byte_size);
+ if (!blk)
+ return NULL;
+ ptr = (void *)(blk + 1);
+ blk->size = byte_size;
+ pool->allocated += byte_size;
+ blk->pool = pool;
+#ifdef BCMOS_MEM_DEBUG
+ blk->magic = BCMOS_MEM_MAGIC_ALLOC;
+ *(uint32_t *)((long)blk + byte_size - sizeof(uint32_t)) = BCMOS_MEM_MAGIC_ALLOC;
+#endif
+
+ return ptr;
+}
+
+/* Release memory allocated using bcmos_byte_pool_alloc() */
+void bcmos_byte_pool_free(void *ptr)
+{
+ bcmos_byte_memblk *blk;
+ bcmos_byte_pool *pool;
+
+ BUG_ON(!ptr);
+ blk = (bcmos_byte_memblk *)((long)ptr - sizeof(bcmos_byte_memblk));
+ pool = blk->pool;
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+ BUG_ON(blk->magic != BCMOS_MEM_MAGIC_ALLOC);
+ BUG_ON(*(uint32_t *)((long)blk + blk->size - sizeof(uint32_t)) != BCMOS_MEM_MAGIC_ALLOC);
+ blk->magic = BCMOS_MEM_MAGIC_FREE;
+#endif
+ pool->allocated -= blk->size;
+ free(blk);
+}
+
+void _bcmos_backtrace(void)
+{
+ void *array[32];
+ size_t size;
+ char **strings;
+ size_t i;
+
+ size = backtrace(array, sizeof(array)/sizeof(array[0]));
+ strings = backtrace_symbols(array, size);
+
+ printf("Obtained %zd stack frames.\n", size);
+
+ for (i = 0; i < size; i++)
+ printf("%s\n", strings[i]);
+
+ free(strings);
+}
+
+/* stub for int enable */
+void bcmos_int_enable(int irq)
+{
+}
+
+void bcmos_int_disable(int irq)
+{
+}
+
+/* stub for int connect */
+int bcmos_int_connect(int irq, int cpu, int flags,
+ int (*isr)(int irq, void *priv), const char *name, void *priv)
+{
+ return 0;
+}
+
+/* Functions common for domain socket and UDP socket - based message queues */
+#if defined(BCMOS_MSG_QUEUE_DOMAIN_SOCKET) || defined(BCMOS_MSG_QUEUE_UDP_SOCKET)
+
+/** "send" to socket */
+static bcmos_errno _bcmos_socket_send(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length)
+{
+ int rc;
+ /* Message queue without remote endpoint address doesn't support transmit */
+ if (!queue->ep_extra_data_size)
+ return BCM_ERR_NOT_SUPPORTED;
+ rc = sendto(queue->ep, buf, buf_length, 0,
+ (struct sockaddr *)queue->ep_extra_data, queue->ep_extra_data_size);
+ return (rc == buf_length) ? BCM_ERR_OK : BCM_ERR_COMM_FAIL;
+}
+
+/** "recv" from socket */
+static bcmos_errno _bcmos_socket_recv(bcmos_msg_queue *queue, uint32_t timeout, uint8_t **buf, uint32_t *buf_length)
+{
+ int rc;
+ int wait = 0;
+
+ /* Message queue without local endpoint address doesn't support receive */
+ if (!queue->q.parm.local_ep_address)
+ return BCM_ERR_NOT_SUPPORTED;
+
+ if (timeout && timeout != BCMOS_WAIT_FOREVER)
+ {
+ fd_set read_fds;
+ struct timeval tv;
+
+ FD_ZERO(&read_fds);
+ FD_SET(queue->ep, &read_fds);
+ tv.tv_sec = timeout / 1000000;
+ tv.tv_usec = (timeout % 1000000) * 1000;
+ rc = select(queue->ep + 1, &read_fds, NULL, NULL, &tv);
+ if (rc < 0)
+ {
+ return BCM_ERR_COMM_FAIL;
+ }
+ if (!rc || !FD_ISSET(queue->ep, &read_fds))
+ return BCM_ERR_TIMEOUT;
+ wait = MSG_DONTWAIT;
+ }
+
+ rc = recv(queue->ep, queue->recv_buf, queue->q.parm.max_mtu, wait);
+ if (rc < 0)
+ {
+ return BCM_ERR_COMM_FAIL;
+ }
+ if (rc == 0)
+ return BCM_ERR_NOENT;
+
+ *buf = queue->recv_buf;
+ *buf_length = rc;
+ return BCM_ERR_OK;
+}
+
+
+static bcmos_errno _bcmos_socket_close(bcmos_msg_queue *queue)
+{
+ /* Close domain socket */
+ if (queue->ep > 0)
+ {
+ close(queue->ep);
+ }
+ if (queue->ep_extra_data)
+ {
+ bcmos_free(queue->ep_extra_data);
+ }
+ return BCM_ERR_OK;
+}
+
+
+/* Pack message for over-the-socket transmission.
+ * This function is good for case when both queue ends are on the same CPU
+ * and there is no need to do any translation.
+ */
+static bcmos_errno _bcmos_transparent_pack(bcmos_msg_queue *queue, bcmos_msg *msg, uint8_t **buf, uint32_t *buf_length)
+{
+ uint32_t size = BCMOS_MSG_HDR_SIZE + msg->size;
+
+ if (size > queue->q.parm.max_mtu)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_OVERFLOW, "Attempt to send message longer than configured max_mtu %u > %u\n",
+ size, queue->q.parm.max_mtu);
+ }
+ bcmos_msg_hdr_pack(msg, queue->send_buf, msg->size);
+ if (msg->size)
+ {
+ BUG_ON(msg->data == NULL);
+ memcpy(queue->send_buf + BCMOS_MSG_HDR_SIZE, msg->data, msg->size);
+ }
+ *buf = queue->send_buf;
+ *buf_length = size;
+ return BCM_ERR_OK;
+}
+
+/** "unpack" message. In case of domain socket both queue ends are in the same CPU.
+ * Message is sent as-is
+ */
+static bcmos_errno _bcmos_transparent_unpack(bcmos_msg_queue *queue, uint8_t *buf, uint32_t buf_length, bcmos_msg **msg)
+{
+ bcmos_msg *m;
+
+ if (buf_length < BCMOS_MSG_HDR_SIZE)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_INTERNAL, "Received message is too short (%u)\n", buf_length);
+ }
+
+ /* Adjust buf_length to account for difference in packed and unpacked message header sizes */
+ buf_length -= BCMOS_MSG_HDR_SIZE;
+ buf_length += sizeof(bcmos_msg);
+
+ m = bcmos_alloc(buf_length);
+ if (!m)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "Received message discarded: %u bytes\n", buf_length);
+ }
+
+ bcmos_msg_hdr_unpack(buf, m);
+ m->release = NULL;
+ m->data_release = NULL;
+ if (m->size != buf_length - sizeof(bcmos_msg))
+ {
+ BCMOS_TRACE_ERR("Received message is insane. Expected data length %u, got %u\n",
+ m->size, buf_length - sizeof(bcmos_msg));
+ bcmos_free(m);
+ return BCM_ERR_INTERNAL;
+ }
+ if (m->size)
+ {
+ m->data = m->start = (void *)(m + 1);
+ memcpy(m->data, &buf[BCMOS_MSG_HDR_SIZE], m->size);
+ }
+ else
+ {
+ m->data = m->start = NULL;
+ }
+ *msg = m;
+
+ return BCM_ERR_OK;
+}
+
+
+#endif
+
+/* Domain-socket-based inter-process communication */
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+
+bcmos_errno bcmos_sys_msg_queue_domain_socket_open(bcmos_msg_queue *queue)
+{
+ struct sockaddr_un sa;
+
+ /* Open domain socket */
+ queue->ep = socket(AF_UNIX, SOCK_DGRAM, 0);
+ if (queue->ep < 0)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't create domain socket. error %s\n", strerror(errno));
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sun_family = AF_UNIX;
+
+ /* If local_ep_address is set - the queue supports receive */
+ if (queue->q.parm.local_ep_address)
+ {
+ strncpy(sa.sun_path, queue->q.parm.local_ep_address, sizeof(sa.sun_path) - 1);
+ /* In linux path can start from 0 character */
+ if (!sa.sun_path[0])
+ {
+ strncpy(&sa.sun_path[1], &queue->q.parm.local_ep_address[1], sizeof(sa.sun_path) - 1);
+ }
+ if (bind(queue->ep, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ {
+ int err = errno;
+ close(queue->ep);
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't bind domain socket to %s. error %s\n",
+ queue->q.parm.local_ep_address, strerror(err));
+ }
+ }
+
+ /* If remote_ep_address is set - the queue supports transmit */
+ if (queue->q.parm.remote_ep_address)
+ {
+ queue->ep_extra_data = bcmos_calloc(sizeof(struct sockaddr_un));
+ if (!queue->ep_extra_data)
+ {
+ close(queue->ep);
+ return BCM_ERR_NOMEM;
+ }
+ strncpy(sa.sun_path, queue->q.parm.remote_ep_address, sizeof(sa.sun_path) - 1);
+ /* In linux path can start from 0 character */
+ if (!sa.sun_path[0])
+ {
+ strncpy(&sa.sun_path[1], &queue->q.parm.remote_ep_address[1], sizeof(sa.sun_path) - 1);
+ }
+ memcpy(queue->ep_extra_data, &sa, sizeof(sa));
+ queue->ep_extra_data_size = sizeof(sa);
+ }
+
+ /* Set callbacks */
+ queue->q.parm.close = _bcmos_socket_close;
+ queue->q.parm.send = _bcmos_socket_send;
+ queue->q.parm.recv = _bcmos_socket_recv;
+ if (!queue->q.parm.pack)
+ queue->q.parm.pack = _bcmos_transparent_pack;
+ if (!queue->q.parm.unpack)
+ queue->q.parm.unpack = _bcmos_transparent_unpack;
+
+ return BCM_ERR_OK;
+}
+
+#endif
+
+/* UDP-socket-based inter-process communication */
+#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
+
+static bcmos_errno _bcmos_parse_ip_port(const char *s, struct sockaddr_in *sa)
+{
+ uint32_t ip;
+ int n;
+ uint32_t ip1, ip2, ip3, ip4, port;
+
+ n = sscanf(s, "%u.%u.%u.%u:%u", &ip1, &ip2, &ip3, &ip4, &port);
+ if (n != 5 || ip1 > 0xff || ip2 > 0xff || ip3 > 0xff || ip4 > 0xff || port > 0xffff)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't parse %s. Must be ip_address:port\n", s);
+ }
+ ip = (ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4;
+ sa->sin_port = htons(port);
+ sa->sin_addr.s_addr = htonl(ip);
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmos_sys_msg_queue_udp_socket_open(bcmos_msg_queue *queue)
+{
+ struct sockaddr_in sa;
+ bcmos_errno rc;
+
+ /* Open UDP socket */
+ queue->ep = socket(AF_INET, SOCK_DGRAM, 0);
+ if (queue->ep < 0)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't create UDP socket. error %s\n", strerror(errno));
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+
+ /* If local_ep_address is set - the queue supports receive */
+ if (queue->q.parm.local_ep_address)
+ {
+ rc = _bcmos_parse_ip_port(queue->q.parm.local_ep_address, &sa);
+ if (rc)
+ return rc;
+ if (!sa.sin_addr.s_addr)
+ sa.sin_addr.s_addr = INADDR_ANY;
+ if (bind(queue->ep, (struct sockaddr *)&sa, sizeof(sa)) < 0)
+ {
+ int err = errno;
+ close(queue->ep);
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't bind UDP socket to %s. error %s\n",
+ queue->q.parm.local_ep_address, strerror(err));
+ }
+ }
+
+ /* If remote_ep_address is set - the queue supports transmit */
+ if (queue->q.parm.remote_ep_address)
+ {
+ rc = _bcmos_parse_ip_port(queue->q.parm.remote_ep_address, &sa);
+ if (rc)
+ return rc;
+ queue->ep_extra_data = bcmos_calloc(sizeof(sa));
+ if (!queue->ep_extra_data)
+ {
+ close(queue->ep);
+ return BCM_ERR_NOMEM;
+ }
+ memcpy(queue->ep_extra_data, &sa, sizeof(sa));
+ queue->ep_extra_data_size = sizeof(sa);
+ }
+
+ /* Set callbacks */
+ queue->q.parm.close = _bcmos_socket_close;
+ queue->q.parm.send = _bcmos_socket_send;
+ queue->q.parm.recv = _bcmos_socket_recv;
+ if (!queue->q.parm.pack)
+ queue->q.parm.pack = _bcmos_transparent_pack;
+ if (!queue->q.parm.unpack)
+ queue->q.parm.unpack = _bcmos_transparent_unpack;
+
+ return BCM_ERR_OK;
+}
+#endif
diff --git a/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.h b/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.h
new file mode 100644
index 0000000..9dc902e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/posix/bcmos_system.h
@@ -0,0 +1,301 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmos_system.h
+ * Maple System Services
+ * posix port: simulation
+ */
+
+#ifndef BCMOS_SYSTEM_H_
+#define BCMOS_SYSTEM_H_
+
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <stdio.h>
+#include <assert.h>
+#include <stdint.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* posix port has only been tested in linux user space */
+#define LINUX_USER_SPACE
+
+/* Re-define GNU typeof as ISO __typeof__ */
+#define typeof __typeof__
+
+void _bcmos_backtrace(void);
+
+#define BUG_ON_PRINT(condition, fmt, args...) \
+ do \
+ { \
+ if (condition) \
+ { \
+ BCMOS_TRACE_ERR(fmt, ##args); \
+ assert(!(condition)); \
+ } \
+ } while (0)
+
+#define BUG_ON(condition) BUG_ON_PRINT((condition), "BUG in %s %d!\n", __FUNCTION__, __LINE__)
+#define BUG() BUG_ON(1)
+#define BUG_UNLESS(condition) BUG_ON(!(condition))
+
+/* If 'err' is not BCM_ERR_OK, there is a bug in the software - halt and print the specified message */
+#define BUG_ON_ERROR(err, fmt, args...) \
+ BUG_ON_PRINT((err) != BCM_ERR_OK, \
+ "%s:%d: err=%s (%d): " fmt, \
+ __FUNCTION__, __LINE__, bcmos_strerror(err), (err), ##args)
+
+/* Specify here which system functions are inlined */
+
+#define BCMOS_FASTLOCK_INLINE
+/* #define BCMOS_SEM_WAIT_INLINE */
+#define BCMOS_SEM_POST_INLINE
+#define BCMOS_TRACE_PRINTF
+/* #define BCMOS_BYTE_POOL_ALLOC_FREE_INLINE */
+/* #define BCMOS_MALLOC_FREE_INLINE */
+/* #define BCMOS_CALLOC_INLINE */
+#define BCMOS_DMA_ALLOC_FREE_INLINE
+#define BCMOS_VIRT_TO_PHYS_INLINE
+#define BCMOS_CACHE_INLINE
+
+#include "bcmos_common.h"
+
+/* posix-specific stuff */
+
+/*
+ * Synchronization
+ */
+
+/** \addtogroup system_mutex
+ * @{
+ */
+
+/** Mutex control block */
+struct bcmos_mutex
+{
+ pthread_mutex_t m; /**< pthread mutex */
+ pthread_mutexattr_t attr; /**< pthread mutex attribute */
+};
+
+/** @} system_mutex */
+
+/** \addtogroup system_fastlock
+ * @{
+ */
+
+/** Fast lock control block */
+struct bcmos_fastlock
+{
+ bcmos_mutex m;
+};
+
+/** Fastlock initializer. Can be used instead of calling bcmos_fastlock_init() */
+#define BCMOS_FASTLOCK_INITIALIZER { { PTHREAD_MUTEX_INITIALIZER } }
+
+/* Init fastlock */
+static inline void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags)
+{
+ bcmos_mutex_create(&lock->m, 0, NULL);
+}
+
+/* Take fast lock */
+static inline long bcmos_fastlock_lock(bcmos_fastlock *lock)
+{
+ bcmos_mutex_lock(&lock->m);
+ return 0;
+}
+
+/* Release fast lock */
+static inline void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags)
+{
+ bcmos_mutex_unlock(&lock->m);
+}
+
+/** @} system_fastlock */
+
+/** \addtogroup system_sem
+ * @{
+ */
+
+/** Semaphore control block */
+struct bcmos_sem
+{
+ sem_t s; /**< pthread semaphore */
+};
+
+/* Increment semaphore counter */
+static inline void bcmos_sem_post(bcmos_sem *sem)
+{
+ sem_post(&sem->s);
+}
+
+/** @} system_sem */
+
+/** \addtogroup system_timer
+ * @{
+ */
+
+/** System timer */
+struct bcmos_sys_timer
+{
+ timer_t t; /**< librt timer */
+ bcmos_sys_timer_handler handler; /**< Timer handler */
+ void *data; /**< Parameter to be passed to the handler */
+};
+
+/** @} system_timer */
+
+/** \addtogroup system_task
+ * @{
+ */
+
+/** OS-specific task control block extension */
+typedef struct bcmos_sys_task
+{
+ pthread_t t; /**< posix pthread */
+} bcmos_sys_task;
+
+/** @} system_task */
+
+/** \addtogroup byte_pool
+ * @{
+ */
+
+/** Memory pool control block */
+struct bcmos_byte_pool
+{
+ bcmos_byte_pool_parm parm; /**< Pool parameters */
+ uint32_t allocated; /**< Number of bytes allocated */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /**< magic number */
+#define BCMOS_BYTE_POOL_VALID (('b'<<24) | ('y' << 16) | ('p' << 8) | 'o')
+#define BCMOS_BYTE_POOL_DELETED (('b'<<24) | ('y' << 16) | ('p' << 8) | '~')
+#endif
+};
+
+/** @} */
+
+/* Print */
+#define bcmos_sys_vprintf(fmt, args) vprintf(fmt, args)
+
+/* A few macros to enable linux kernel space compilation */
+#define EXPORT_SYMBOL(_sym)
+
+/*
+ * The following low-level functions are mostly for simulation
+ */
+
+/*
+ * DMA-able memory allocation
+ */
+
+/* Allocate DMA-able memory */
+static inline void *bcmos_dma_alloc(uint8_t device, uint32_t size)
+{
+ return bcmos_alloc(size);
+}
+
+/* Release DMA-able memory */
+static inline void bcmos_dma_free(uint8_t device, void *ptr)
+{
+ bcmos_free(ptr);
+}
+
+/* Convert virtual address to physical address */
+static inline unsigned long bcmos_virt_to_phys(void *va)
+{
+ return (unsigned long)(va);
+}
+
+/* Invalidate address area in data cache. Dirty cache lines content is discarded. */
+static inline void bcmos_dcache_inv(void *start, uint32_t size)
+{
+}
+
+/* Flush address area in data cache. Dirty cache lines are committed to memory. */
+static inline void bcmos_dcache_flush(void *start, uint32_t size)
+{
+}
+
+/* write barrier */
+static inline void bcmos_barrier(void)
+{
+}
+
+static inline void bcm_pci_write32(volatile uint32_t *address, uint32_t value)
+{
+}
+
+static inline uint32_t bcm_pci_read32(const volatile uint32_t *address)
+{
+ return -1;
+}
+
+/* Check in-irq status */
+static inline bcmos_bool is_irq_mode(void)
+{
+ return BCMOS_FALSE;
+}
+
+/* Check if interrupts are disabled */
+static inline bcmos_bool is_irq_disabled(void)
+{
+ return BCMOS_FALSE;
+}
+
+/*
+ * Internal (to OS abstraction) functions for messaging over domain and UDP sockets
+ */
+#ifdef BCMOS_MSG_QUEUE_DOMAIN_SOCKET
+bcmos_errno bcmos_sys_msg_queue_domain_socket_open(bcmos_msg_queue *queue);
+#endif
+
+#ifdef BCMOS_MSG_QUEUE_UDP_SOCKET
+bcmos_errno bcmos_sys_msg_queue_udp_socket_open(bcmos_msg_queue *queue);
+#endif
+
+/* 2nd part of OS-independent declarations */
+#include "bcmos_common2.h"
+
+#endif /* BCMOS_SYSTEM_H_ */
diff --git a/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.c b/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.c
new file mode 100644
index 0000000..645c8d0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.c
@@ -0,0 +1,742 @@
+/*
+<: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 <vxWorks.h>
+#include <unistd.h>
+#include <taskLib.h>
+#include <wdLib.h>
+#include <sysLib.h>
+#include <errnoLib.h>
+#include <time.h>
+#include <intLib.h>
+#include <cacheLib.h>
+#include "memPartLib.h"
+
+#ifdef HOST_CPU_IS_MIPS
+#include "arch/mips/archMips.h"
+#endif
+
+#include <iv.h>
+
+#define BCMOS_DEFAULT_STACK_SIZE (100*1024)/*0x4000*/
+#define BCMOS_MICROSECONDS_TO_TICKS(u) (u)/1000000*bcmos_timer_get_frequency() + BCMOS_DIVIDE_ROUND_UP(((u)%1000000)*bcmos_timer_get_frequency(),1000000)
+
+/* task control blocks */
+extern STAILQ_HEAD(task_list, bcmos_task) task_list;
+
+/* global OS lock */
+extern bcmos_mutex bcmos_res_lock;
+
+/*
+ * Default task handler
+ */
+extern int bcmos_dft_task_handler(long data);
+
+bcmos_errno bcmos_sys_init(void)
+{
+ return BCM_ERR_OK;
+}
+
+/* Clean-up system library */
+void bcmos_sys_exit(void)
+{
+}
+
+static uint32_t bcmos_timer_get_frequency()
+{
+ static uint32_t frequency = 0;
+ if (!frequency)
+ frequency = sysClkRateGet();
+ return frequency;
+}
+
+bcmos_errno bcmos_task_create(bcmos_task *task, const bcmos_task_parm *parm)
+{
+ F_bcmos_task_handler handler;
+ void *data;
+
+ if (!task || !parm)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "task %p, parm %p\n", (void* )task, (void* )parm);
+ memset(task, 0, sizeof ( *task ));
+
+ if (parm->handler)
+ {
+ /* "traditional task */
+ handler = parm->handler;
+ data = (void *)parm->data;
+ }
+ else
+ {
+ bcmos_errno rc;
+ /* "integrated" task */
+ handler = bcmos_dft_task_handler;
+ data = task;
+
+ /* Initialize and lock mutex to wait on */
+ rc = bcmos_sem_create(&task->active_sem, 0, task->parm.flags, parm->name);
+ if (rc)
+ {
+ BCMOS_TRACE_ERR("Task %s: can't create active_sem. Error %s (%d)\n",
+ parm->name, bcmos_strerror(rc), rc);
+ return rc;
+ }
+ }
+
+ task->parm = *parm;
+ /* Copy name to make sure that it is not released - in case it was on the stack */
+ if (task->parm.name)
+ {
+ strncpy(task->name, task->parm.name, sizeof(task->name) - 1);
+ task->parm.name = task->name;
+ }
+ bcmos_fastlock_init(&task->active_lock, 0);
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_INSERT_TAIL(&task_list, task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = BCMOS_TASK_MAGIC;
+ task->sys_task.t = taskSpawn((char*)parm->name,
+ 10 + parm->priority * 2,
+ 0,
+ parm->stack_size ? parm->stack_size : BCMOS_DEFAULT_STACK_SIZE,
+ (FUNCPTR)handler,
+ (int32_t)data,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0);
+
+ if (task->sys_task.t == ERROR)
+ {
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = 0;
+ if (!parm->handler)
+ {
+ bcmos_sem_destroy(&task->active_sem);
+ }
+ BCMOS_TRACE_ERR("(%s) Error: taskSpawn, errnoGet()=%d\n", __FUNCTION__, errnoGet());
+ BUG();
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmos_task_destroy(bcmos_task *task)
+{
+ if (task->magic != BCMOS_TASK_MAGIC)
+ {
+ return BCM_ERR_PARM;
+ }
+ task->destroy_request = BCMOS_TRUE;
+ bcmos_mutex_lock(&bcmos_res_lock);
+ STAILQ_REMOVE(&task_list, task, bcmos_task, list);
+ bcmos_mutex_unlock(&bcmos_res_lock);
+ task->magic = BCMOS_TASK_MAGIC_DESTROYED;
+ /* The task may be waiting on semaphore. Kick it */
+ if (!task->parm.handler)
+ {
+ bcmos_sem_post(&task->active_sem);
+ }
+ if (taskDelete(task->sys_task.t) != OK)
+ {
+ BCMOS_TRACE_ERR("(%s) Error: taskDelete, errnoGet()=%d\n", __FUNCTION__, errnoGet());
+ BUG();
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_task *bcmos_task_current(void)
+{
+ uint32_t pt = taskIdSelf();
+ bcmos_task *t, *tmp;
+
+ STAILQ_FOREACH_SAFE(t, &task_list, list, tmp)
+ {
+ if (pt == t->sys_task.t)
+ break;
+ }
+ return t;
+}
+
+void *bcmos_alloc(uint32_t size)
+{
+ return malloc(size);
+}
+
+void bcmos_free(void *ptr)
+{
+ free(ptr);
+}
+
+inline static void bcmos_sem_mutex_destroy(uint32_t sm)
+{
+ if (semDelete((SEM_ID)sm) != OK)
+ {
+ BCMOS_TRACE_ERR("(%s) Error: semDelete, errnoGet()=%d\n", __FUNCTION__, errnoGet());
+ BUG();
+ }
+}
+
+inline static bcmos_errno bcmos_sem_mutex_wait(uint32_t sm, uint32_t timeout)
+{
+ int errno;
+ STATUS status;
+
+ timeout = ((timeout == BCMOS_WAIT_FOREVER )? WAIT_FOREVER : BCMOS_MICROSECONDS_TO_TICKS(timeout));
+ status = semTake((SEM_ID)sm, timeout);
+ if (status != OK)
+ {
+ errno = errnoGet();
+ if (errno == S_objLib_OBJ_TIMEOUT)
+ {
+ return BCM_ERR_TIMEOUT;
+ }
+ BUG();
+ return BCM_ERR_INTERNAL;
+ }
+ return BCM_ERR_OK;
+}
+
+inline static void bcmos_sem_mutex_post(uint32_t sm)
+{
+ STATUS status;
+
+ status = semGive((SEM_ID)sm);
+ if (status != OK)
+ {
+ BCMOS_TRACE_ERR("(%s) Error: semGive, status=%d\n", __FUNCTION__, status);
+ BUG();
+ }
+}
+
+bcmos_errno bcmos_sem_create(bcmos_sem *sem, uint32_t count, uint32_t flags, const char *name)
+{
+ SEM_ID semaphore;
+
+ semaphore = semCCreate(SEM_Q_PRIORITY, (SEM_B_STATE)count);
+ if (semaphore == NULL)
+ {
+ BCMOS_TRACE_ERR("(%s) Error: semCCreate, errnoGet()=%d\n", __FUNCTION__, errnoGet());
+ BUG();
+ }
+ sem->s = (uint32_t)semaphore;
+
+ return BCM_ERR_OK;
+}
+
+void bcmos_sem_destroy(bcmos_sem *sem)
+{
+ bcmos_sem_mutex_destroy(sem->s);
+}
+
+bcmos_errno bcmos_sem_wait(bcmos_sem *sem, uint32_t timeout)
+{
+ return bcmos_sem_mutex_wait(sem->s, timeout);
+}
+
+void bcmos_sem_post(bcmos_sem *sem)
+{
+ bcmos_sem_mutex_post(sem->s);
+}
+
+bcmos_errno bcmos_mutex_create(bcmos_mutex *mutex, uint32_t flags, const char *name)
+{
+ SEM_ID semaphore;
+ int options;
+
+ /* SEM_INVERSION_SAFE: Enable (by default) the prevention of priority inversion problem */
+ options = SEM_Q_PRIORITY | SEM_INVERSION_SAFE;
+
+ semaphore = semMCreate(options);
+ if (semaphore == NULL)
+ {
+ BCMOS_TRACE_ERR("(%s) Error: semCCreate, errnoGet()=%d\n", __FUNCTION__, errnoGet());
+ BUG();
+ }
+
+ mutex->m = (uint32_t)semaphore;
+
+ return BCM_ERR_OK;
+}
+
+void bcmos_mutex_destroy(bcmos_mutex *mutex)
+{
+ bcmos_sem_mutex_destroy(mutex->m);
+}
+
+void bcmos_mutex_lock(bcmos_mutex *mutex)
+{
+ bcmos_sem_mutex_wait(mutex->m, BCMOS_WAIT_FOREVER);
+}
+
+void bcmos_mutex_unlock(bcmos_mutex *mutex)
+{
+ bcmos_sem_mutex_post(mutex->m);
+}
+
+void bcmos_fastlock_init(bcmos_fastlock *lock, uint32_t flags)
+{
+}
+
+long bcmos_fastlock_lock(bcmos_fastlock *lock)
+{
+ return (long)intLock();
+}
+
+void bcmos_fastlock_unlock(bcmos_fastlock *lock, long flags)
+{
+ intUnlock(flags);
+}
+
+bcmos_errno bcmos_sys_timer_create(bcmos_sys_timer *timer, bcmos_sys_timer_handler handler, void *data)
+{
+ WDOG_ID watchdog;
+
+ if (!timer || !handler)
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "timer %p, handler %p\n", timer, handler);
+
+ /* Call the underlying OS */
+ watchdog = wdCreate();
+ if (watchdog == NULL)
+ BCMOS_TRACE_RETURN(BCM_ERR_SYSCALL_ERR, "errno %s\n", strerror(errno));
+
+ timer->t = (uint32_t)watchdog;
+ timer->handler = handler;
+ timer->data = data;
+
+ return BCM_ERR_OK;
+}
+
+void bcmos_sys_timer_destroy(bcmos_sys_timer *timer)
+{
+ STATUS status;
+ status = wdDelete((WDOG_ID)timer->t);
+ BCMOS_TRACE_DEBUG("wdDelete: status=%d\n", status);
+}
+
+static void _bcmos_time_handler_wrapper(long data)
+{
+ bcmos_sys_timer * timer = (bcmos_sys_timer*)data ;
+ timer->handler(timer->data);
+}
+
+void bcmos_sys_timer_start(bcmos_sys_timer *timer, uint32_t delay)
+{
+ STATUS status;
+ status = wdStart((WDOG_ID)timer->t, BCMOS_MICROSECONDS_TO_TICKS(delay), (FUNCPTR)_bcmos_time_handler_wrapper, (long)timer);
+ if (status == ERROR)
+ {
+ BCMOS_TRACE_ERR("wdStart status %d\n", status);
+ BUG();
+ }
+}
+
+void bcmos_sys_timer_stop(bcmos_sys_timer *timer)
+{
+ STATUS status;
+ status = wdCancel((WDOG_ID)timer->t);
+ if (status == ERROR)
+ {
+ BCMOS_TRACE_ERR("wdCancel status=%d\n", status);
+ BUG();
+ }
+}
+
+void bcmos_usleep(uint32_t us)
+{
+ struct timespec ts;
+
+ ts.tv_sec = us / 1000000;
+ ts.tv_nsec = ( us % 1000000 ) * 1000;
+
+ nanosleep(&ts, 0);
+}
+
+uint32_t bcmos_timestamp(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return (ts.tv_sec * 1000000 + ts.tv_nsec / 1000);
+}
+
+/** Get current timestamp - 64 bit
+ * \returns the current system timestamp (us)
+ */
+uint64_t bcmos_timestamp64(void)
+{
+ struct timespec ts;
+ clock_gettime(CLOCK_REALTIME, &ts);
+ return ((uint64_t)ts.tv_sec * 1000000LL + (uint64_t)ts.tv_nsec / 1000LL);
+}
+
+/*
+ * Byte memory pool
+ */
+
+/* Memory block header */
+typedef struct bcmos_byte_memblk
+{
+ bcmos_byte_pool *pool; /** pool that owns the block */
+ uint32_t size; /** block size (bytes) including bcmos_byte_memblk header */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /** magic number */
+#define BCMOS_MEM_MAGIC_ALLOC (('m'<<24) | ('b' << 16) | ('l' << 8) | 'k')
+#define BCMOS_MEM_MAGIC_FREE (('m'<<24) | ('b' << 16) | ('l' << 8) | '~')
+#endif
+} bcmos_byte_memblk;
+
+/* Create byte memory pool */
+bcmos_errno bcmos_byte_pool_create(bcmos_byte_pool *pool, const bcmos_byte_pool_parm *parm)
+{
+ if (!pool || !parm)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "pool %p, parm %p\n", pool, parm);
+ }
+
+ BCM_MEMZERO_STRUCT(pool);
+ pool->parm = *parm;
+ if (!pool->parm.size)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "size %u\n", parm->size);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_VALID;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Destroy memory pool */
+bcmos_errno bcmos_byte_pool_destroy(bcmos_byte_pool *pool)
+{
+ if (pool->allocated)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_STATE, "%u bytes of memory are still allocated from the pool %s\n",
+ pool->allocated, pool->parm.name);
+ }
+#ifdef BCMOS_MEM_DEBUG
+ pool->magic = BCMOS_BYTE_POOL_DELETED;
+#endif
+ return BCM_ERR_OK;
+}
+
+/* Allocate memory from memory pool */
+void *bcmos_byte_pool_alloc(bcmos_byte_pool *pool, uint32_t size)
+{
+ bcmos_byte_memblk *blk;
+ uint32_t byte_size;
+ void *ptr;
+
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+#endif
+
+ if (size + pool->allocated > pool->parm.size)
+ return NULL;
+
+ byte_size = size + sizeof(bcmos_byte_memblk);
+#ifdef BCMOS_MEM_DEBUG
+ byte_size += sizeof(uint32_t); /* block suffix */
+#endif
+ /* ToDo: Maintain LL of allocated blocks */
+ blk = (bcmos_byte_memblk *)malloc(byte_size);
+ if (!blk)
+ return NULL;
+ ptr = (void *)(blk + 1);
+ blk->size = byte_size;
+ pool->allocated += byte_size;
+ blk->pool = pool;
+#ifdef BCMOS_MEM_DEBUG
+ blk->magic = BCMOS_MEM_MAGIC_ALLOC;
+ *(uint32_t *)((long)blk + byte_size - sizeof(uint32_t)) = BCMOS_MEM_MAGIC_ALLOC;
+#endif
+
+ return ptr;
+}
+
+/* Release memory allocated using bcmos_byte_pool_alloc() */
+void bcmos_byte_pool_free(void *ptr)
+{
+ bcmos_byte_memblk *blk;
+ bcmos_byte_pool *pool;
+
+ BUG_ON(!ptr);
+ blk = (bcmos_byte_memblk *)((long)ptr - sizeof(bcmos_byte_memblk));
+ pool = blk->pool;
+#ifdef BCMOS_MEM_DEBUG
+ BUG_ON(pool->magic != BCMOS_BYTE_POOL_VALID);
+ BUG_ON(blk->magic != BCMOS_MEM_MAGIC_ALLOC);
+ BUG_ON(*(uint32_t *)((long)blk + blk->size - sizeof(uint32_t)) != BCMOS_MEM_MAGIC_ALLOC);
+ blk->magic = BCMOS_MEM_MAGIC_FREE;
+#endif
+ pool->allocated -= blk->size;
+ free(blk);
+}
+
+void _bcmos_backtrace(void)
+{
+ /*todo implement this*/
+}
+
+int ffsll(long long int i)
+{
+ int l = ffs(i & 0xFFFFFFFF);
+ int h = ffs((i >> 32) & 0xFFFFFFFF);
+
+ if (l)
+ return l;
+
+ if (h)
+ return h + 32;
+
+ return 0;
+}
+
+/* stub for int enable */
+void bcmos_int_enable(int irq)
+{
+}
+
+typedef struct bcmos_int_data
+{
+ int (*isr)(int irq, void *priv);
+ int irq;
+ void *priv;
+} bcmos_int_data;
+
+static void _bcmos_int_handler(long priv)
+{
+ bcmos_int_data *data = (bcmos_int_data *)priv;
+ data->isr(data->irq, data->priv);
+}
+
+int bcmos_int_connect(int irq, int cpu, int flags, int (*isr)(int irq, void *priv), const char *name, void *priv)
+{
+ bcmos_int_data *data = bcmos_calloc(sizeof(bcmos_int_data));
+ if (!data)
+ return (int)BCM_ERR_NOMEM;
+ data->isr = isr;
+ data->irq = irq;
+ data->priv = priv;
+ return pciIntConnect(INUM_TO_IVEC(irq), _bcmos_int_handler, (long)data);
+}
+
+/* Disconnect system interrupt */
+void bcmos_int_disconnect(int irq, void *priv)
+{
+ pciIntDisconnect(INUM_TO_IVEC(irq), _bcmos_int_handler);
+}
+
+/**************************************************************
+ * Check in-irq status *
+ * related header file: "intLib.h" *
+ * param[in] none *
+ * param[out] none *
+ * return BCMOS_TRUE (1) - in interrupt context; *
+ * BCMOS_FALSE (0) - in task context; *
+ **************************************************************/
+
+bcmos_bool is_irq_mode(void)
+{
+ return intContext();
+}
+
+// from bsp
+extern int isIntDisabled();
+/**************************************************************
+ * Check if interrupts are disabled *
+ * related header file: "mipsinc.h" *
+ * param[in] none *
+ * param[out] none *
+ * return BCMOS_TRUE (1) - Gloal interrupt disable *
+ BCMOS_FALSE (0) - Gloal interrupt enable; *
+ * comment if BSP team can provide similar function, *
+ we will call it; *
+ * Another option is share this macro used on switch product *
+ *************************************************************/
+bcmos_bool is_irq_disabled(void)
+{
+ return isIntDisabled();
+}
+
+/**************************************************************
+ * write barrier *
+ * related header file: none *
+ * param[in] none *
+ * param[out] none *
+ * return none *
+ * comment:use "sync" base on MIPS (GNU style) *
+ *************************************************************/
+
+void bcmos_barrier(void)
+{
+ #if defined(HOST_CPU_IS_MIPS) || defined(HOST_CPU_IS_PPC)
+ {__asm__ __volatile__("sync");}
+ #else
+ #error HOST CPU MUST BE MIPS OR POWERPC
+ #endif
+}
+
+/**************************************************************
+ * Allocate DMA-able memory *
+ * related header file:memPartLib.h *
+ * param[in] device Device id *
+ * param[in] size Block size (bytes) *
+ * param[out] none *
+ * returns memory block pointer(uncached memory) or NULL *
+ * comment: BSP need to allocate uncached memory pool first *
+ * if BSP team can provide such function,call it directly; *
+ * suggestion: memPartCreate()create uncached memory and *
+ * return memory ID:uncachePoolMemPartId *
+ * memPartAlloc()/memPartFree():allocate/free memory via *
+ * memory ID:uncachePoolMemPartId and size *
+ * if BSP can gurantee the Memory allocated by cacheDmaMalloc *
+ * cacheDmaFree() is noncached memory,we can call them directly*
+ *************************************************************/
+
+void *bcmos_dma_alloc(uint8_t device, uint32_t size)
+{
+ void * pBuffer;
+#ifdef NON_CACHED_MEMORY_CREATED_BY_CACHEDMAMALLOC
+ pBuffer = cacheDmaMalloc(size);
+ return (pBuffer);
+#else
+ pBuffer = (void *)memPartAlloc(uncachePoolMemPartId, size));
+ return (pBuffer);
+#endif
+}
+
+/**************************************************************
+ * Release DMA-able memory *
+ * related header file: memPartLib.h *
+ * param[in] device Device id *
+ * param[in] ptr Block pointer *
+ * param[out] none *
+ * return none *
+ * comment: see above *
+ *************************************************************/
+void bcmos_dma_free(uint8_t device, void *ptr)
+{
+#ifdef NON_CACHED_MEMORY_CREATED_BY_CACHEDMAMALLOC
+ cacheDmaFree((void *)(ptr));
+#else
+ memPartFree(uncachePoolMemPartId,ptr);
+#endif
+ return;
+}
+
+/**************************************************************
+ * Convert virtual address to physical address *
+ * related header file:for MIPS CPU archMips.h *
+ * param[in] va Virtual address *
+ * return - physical address va is mapped to *
+**************************************************************/
+unsigned long bcmos_virt_to_phys(void *va)
+{
+#ifdef HOST_CPU_IS_MIPS
+ return (unsigned long)(K0_TO_PHYS(va));
+
+#else
+ /* this is an just an example,
+ if you are not working with mips make sure you define the correct mapping for your system */
+ return (unsigned long)(va);
+#endif
+}
+
+/**************************************************************
+ * Invalidate address area in data cache. *
+ * related header file: cacheLib.h *
+ * param[in] start Address area start *
+ * param[in] size Address area size *
+ * return none *
+ **************************************************************/
+void bcmos_dcache_inv(void *start, uint32_t size)
+{
+ cacheInvalidate(DATA_CACHE,start, size);
+ return;
+}
+
+/**************************************************************
+ * Flush address area in data cache. *
+ * related header file: cacheLib.h *
+ * param[in] start Address area start *
+ * param[in] size Address area size *
+ * return none *
+**************************************************************/
+void bcmos_dcache_flush(void *start, uint32_t size)
+{
+ cacheFlush(DATA_CACHE,start, size);
+ return;
+}
+
+/**************************************************************
+ * write value to PCI memory *
+ * related header file: bcmos_common2.h *
+ * param[in] address pointer to Address *
+ * param[in] value value *
+ * return none *
+ * Comment re-use BCMOS_ENDIAN_CPU_TO_LITTLE_U32 which is from*
+ * bcmos_common2.h,by this macro,can support both big endian *
+ * host and little endian host.move PCI access functions after*
+ * bcmos_common2.h *
+ **************************************************************/
+void bcm_pci_write32(volatile uint32_t *address, uint32_t value)
+{
+#ifdef HOST_PCIE_SWAP_NEEDED
+ value = BCMOS_ENDIAN_CPU_TO_LITTLE_U32(value);
+#endif
+ *address = value;
+}
+
+/**************************************************************
+ * read value to PCI memory *
+ * related header file: bcmos_common2.h *
+ * param[in] address pointer to Address *
+ * return value *
+ * Comment see above *
+**************************************************************/
+uint32_t bcm_pci_read32(const volatile uint32_t *address)
+{
+ uint32_t value;
+ value = *address;
+#ifdef HOST_PCIE_SWAP_NEEDED
+ value = BCMOS_ENDIAN_LITTLE_TO_CPU_U32(value);
+#endif
+ return value;
+
+}
+
+
diff --git a/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.h b/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.h
new file mode 100644
index 0000000..5633e28
--- /dev/null
+++ b/bcm68620_release/release/host_customized/os_abstraction/vxworks55/bcmos_system.h
@@ -0,0 +1,184 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmos_system.h
+ * Maple System Services
+ * vxWorks 5.5 port
+ */
+
+#ifndef BCMOS_SYSTEM_H_
+#define BCMOS_SYSTEM_H_
+
+#define BCMOS_IRQ_SINGLE 0
+#define BCMOS_IRQ_SHARED 1
+
+#define inline __inline
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <ctype.h>
+#include <time.h>
+#include <limits.h>
+#include <unistd.h>
+#include <sockLib.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+/* Re-define GNU typeof as ISO __typeof__ */
+#define typeof __typeof__
+
+/* Specify here which system functions are inlined */
+
+/* #define BCMOS_FASTLOCK_INLINE */
+/* #define BCMOS_SEM_WAIT_INLINE */
+/* #define BCMOS_SEM_POST_INLINE */
+/* #define BCMOS_USLEEP_INLINE */
+#define BCMOS_TRACE_PRINTF
+#define BCMOS_BYTE_POOL_ALLOC_FREE_INLINE
+/* #define BCMOS_MALLOC_FREE_INLINE */
+/* #define BCMOS_CALLOC_INLINE */
+/* if Host cpu is MIPS cpu,enable this macro */
+/* Host cpu type will be determined during compile*/
+//#define HOST_CPU_IS_MIPS
+//#define HOST_CPU_IS_PPC
+/*if the Memory allocated by cacheDmaMalloc/acheDmaFree() is non-cached memory,enable this macro*/
+#define NON_CACHED_MEMORY_CREATED_BY_CACHEDMAMALLOC
+/* Uncommentthe following line if h/w supports DMA cache coherency */
+/* #define BCMOS_DMA_CACHE_COHERENCY */
+
+static inline void bcmos_int_disable(int irq)
+{}
+
+void _bcmos_backtrace(void);
+
+#define BUG_ON(_f) do { if (_f) { _bcmos_backtrace(); } } while (0)
+#define BUG() BUG_ON(1)
+#define BUG_UNLESS(_f) BUG_ON(!(_f))
+
+/** Boolean */
+#define BCMOS_BOOLEAN
+typedef enum
+{
+ BCMOS_FALSE = 0,
+ BCMOS_TRUE = 1,
+} bcmos_bool;
+
+#include "bcmos_common.h"
+
+#define ffs(n) ffsLsb(n)
+
+/** Semaphore control block */
+struct bcmos_sem
+{
+ uint32_t s;
+};
+
+
+/** Mutex control block */
+struct bcmos_mutex
+{
+ uint32_t m;
+};
+
+/** Fast lock control block */
+struct bcmos_fastlock
+{
+ uint32_t l;
+};
+
+/** Fastlock initializer. Can be used instead of calling bcmos_fastlock_init() */
+#define BCMOS_FASTLOCK_INITIALIZER { 0 }
+
+/** OS-specific task control block extension */
+typedef struct bcmos_sys_task
+{
+ uint32_t t; /**< vxWorks task ID */
+} bcmos_sys_task;
+
+
+/** System timer */
+struct bcmos_sys_timer
+{
+ uint32_t t; /**< VxW timer */
+ bcmos_sys_timer_handler handler; /**< Timer handler */
+ void *data; /**< Parameter to be passed to the handler */
+};
+
+/** Byte memory pool control block */
+struct bcmos_byte_pool
+{
+ bcmos_byte_pool_parm parm; /**< Pool parameters */
+ uint32_t allocated; /**< Number of bytes allocated */
+#ifdef BCMOS_MEM_DEBUG
+ uint32_t magic; /**< magic number */
+#define BCMOS_BYTE_POOL_VALID (('b'<<24) | ('y' << 16) | ('p' << 8) | 'o')
+#define BCMOS_BYTE_POOL_DELETED (('b'<<24) | ('y' << 16) | ('p' << 8) | '~')
+#endif
+};
+
+#define bcmos_sys_vprintf(fmt, args) vprintf(fmt, args)
+
+#define EXPORT_SYMBOL(_sym)
+
+/* 2nd part of OS-independent declarations */
+#include "bcmos_common2.h"
+
+void bcm_pci_write32(volatile uint32_t *address, uint32_t value);
+uint32_t bcm_pci_read32(const volatile uint32_t *address);
+
+
+/*todo must check validity that the string is numeric, sscanf cannot detect errors,
+ * if not valid, put (*tailptr) in the first non valid char in string,
+ if valid, point tailptr in the last char in string (*tailptr=string+strlen(string))*/
+#define strtoull(string,tailptr,base) ({\
+ unsigned long long int __a;\
+ *(tailptr)=(char*)((string)+strlen(string));\
+ sscanf(string, base == 10 ? "%llu" : "%llx", &__a );\
+ __a;\
+ })
+#define strtoll(string,tailptr,base) ({\
+ long long int __a;\
+ *(tailptr)=(char*)((string)+strlen(string));\
+ sscanf(string,"%lld", &__a );\
+ __a;\
+ })
+
+#define snprintf(s1,n,s2,args...) sprintf(s1, s2,## args)
+#define vsnprintf(s1,n,s2,args...) vsprintf(s1, s2,## args)
+
+
+int ffsLsb (UINT32 i);
+int ffsll(long long int i);
+
+
+#endif /* BCMOS_SYSTEM_H_ */