BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_customized/api_linux/Makefile b/bcm68620_release/release/host_customized/api_linux/Makefile
new file mode 100644
index 0000000..da617b5
--- /dev/null
+++ b/bcm68620_release/release/host_customized/api_linux/Makefile
@@ -0,0 +1,16 @@
+# Makefile for building utilities as linux module
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = api_linux
+MOD_TYPE = linux_lib
+MOD_DEPS = utils_linux sysmodel
+srcs = bcmolt_msg.c
+
+# 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/api_linux/bcmolt_api.c b/bcm68620_release/release/host_customized/api_linux/bcmolt_api.c
new file mode 120000
index 0000000..4aea218
--- /dev/null
+++ b/bcm68620_release/release/host_customized/api_linux/bcmolt_api.c
@@ -0,0 +1 @@
+../../host_driver/api/bcmolt_api.c
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/api_linux/bcmolt_api.h b/bcm68620_release/release/host_customized/api_linux/bcmolt_api.h
new file mode 120000
index 0000000..fe53e25
--- /dev/null
+++ b/bcm68620_release/release/host_customized/api_linux/bcmolt_api.h
@@ -0,0 +1 @@
+../../host_driver/api/bcmolt_api.h
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.c b/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.c
new file mode 120000
index 0000000..c3875f3
--- /dev/null
+++ b/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.c
@@ -0,0 +1 @@
+../../host_driver/api/bcmolt_msg.c
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.h b/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.h
new file mode 120000
index 0000000..546a74e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/api_linux/bcmolt_msg.h
@@ -0,0 +1 @@
+../../host_driver/api/bcmolt_msg.h
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/board/wrx/Makefile b/bcm68620_release/release/host_customized/board/wrx/Makefile
new file mode 100644
index 0000000..67d1e07
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/Makefile
@@ -0,0 +1,14 @@
+# Maple board specific configurations. Relevant only if working in Linux
+#
+MOD_TYPE = lib
+MOD_NAME = bcm_board
+
+ifeq ("$(OS_KERNEL)", "linux")
+ifeq ("$(ENABLE_CLI)", "y")
+
+MOD_DEPS = cli i2c_devs api_cli bcm_dev_ctrl_linux
+
+srcs = bcmolt_board.c bcmolt_board_cli.c
+endif
+endif
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.c b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.c
new file mode 100644
index 0000000..479c5f9
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.c
@@ -0,0 +1,702 @@
+/*
+<: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 <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <bcmcli.h>
+#include <bcmolt_i2c_devs_ioctl.h>
+#include <bcmolt_dev_ctrl_ioctl.h>
+#include <bcmolt_api.h>
+#include <bcmolt_model_types.h>
+#include <bcmolt_fld.h>
+#include "bcmolt_board.h"
+#include "bcmolt_dpll_table.h"
+
+#define BCM_I2C_DEV_ADDR_START typedef enum {
+#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
+#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
+
+#define BCM_FPGA_REG_FPGA_VERSION 0x0
+#define BCM_FPGA_REG_BOARD_CONF 0x1
+#define BCM_FPGA_REG_RESETS 0x2
+/* Enable/disable transceiver */
+#define BCM_FPGA_REG_TRX_ENABLE 0x3
+#define BCM_FPGA_REG_TRX_FAIL 0x4
+/* Is transceiver present ? */
+#define BCM_FPGA_REG_TRX_IS_PRESENT 0x5
+#define BCM_FPGA_REG_CXP_CONTROLS 0x6
+#define BCM_FPGA_REG_SHIFT_REGISTER_DATA 0x7
+#define BCM_FPGA_REG_SHIFT_REGISTER_CONTROL 0x8
+#define BCM_FPGA_REG_LEDS 0x9
+#define BCM_FPGA_REG_DEBUG_LEDS 0xA
+#define BCM_FPGA_REG_GPIO_DIR 0xB
+#define BCM_FPGA_REG_GPIO_INPUT 0xC
+#define BCM_FPGA_REG_GPIO_OUTPUT 0xD
+#define BCM_FPGA_REG_GPIO_IRQ 0xE
+
+#define BCM_FPGA_REG_LOW BCM_FPGA_REG_FPGA_VERSION
+#define BCM_FPGA_REG_HIGH BCM_FPGA_REG_GPIO_IRQ
+
+#define BCM_RST_BIT_DEVICE 0x0
+#define BCM_RST_BIT_PON_DPLL 0x1
+#define BCM_RST_BIT_PM_DPLL 0x2
+#define BCM_RST_BIT_KT2 0x4
+
+#define SVK4_IDENT_FILE                 "/etc/svk4"
+
+#include <bcmolt_i2c_devs_addr.h>
+
+#define MAX_CMD_STR_LEN 1024
+
+/* Since the board driver configuration is specific for Linux, there is no point using OS abstraction layer to perform operations like ioctl(). */
+
+static int maple_i2c_fd;
+static int maple_dev_ctrl_fd;
+
+static bcmos_bool bcm_board_is_svk4(void)
+{
+    bcmos_bool is_svk4 = BCMOS_FALSE;
+    FILE *f = fopen(SVK4_IDENT_FILE, "r");
+    if (f)
+    {
+        is_svk4 = BCMOS_TRUE;
+        fclose(f);
+    }
+    return is_svk4;
+}
+
+static bcmos_errno bcm_access_fpga(void)
+{
+    bcmos_errno rc;
+    if (bcm_board_is_svk4())
+    {
+        rc = bcm_board_dev_change(I2C_SW1_I2C_ADDR);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(I2C_SW1_I2C_ADDR) failed\n");
+        rc = bcm_board_switch_write(0x4);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_switch_write(1) failed\n");
+    }
+    else
+    {
+        rc = bcm_board_dev_change(I2C_SW0_I2C_ADDR);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(I2C_SW0_I2C_ADDR) failed\n");
+        rc = bcm_board_switch_write(1);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_switch_write(1) failed\n");
+    }
+    rc = bcm_board_dev_change(FPGA_I2C_ADDR);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(FPGA_I2C_ADDR) failed \n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_dev_change(uint32_t addr)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .addr = addr,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_CHANGE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for maple_i2c_fd\n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_dev_write(uint32_t count, uint32_t addr, uint32_t val)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .count = count,
+        .addr = addr,
+        .val = val,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for maple_i2c_fd\n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_dev_read(uint32_t count, uint32_t addr, uint32_t *val)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .count = count,
+        .addr = addr,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_READ, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for maple_i2c_fd\n");
+    *val = params.val;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_switch_write(uint32_t val)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .val = val,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_SWITCH_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for maple_i2c_fd\n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_switch_read(uint32_t *val)
+{
+    int rc;
+    maple_i2c_ioctl_param params = {};
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_SWITCH_READ, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for maple_i2c_fd\n");
+    *val = params.val;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_fpga_write(uint32_t addr, uint32_t val)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .addr = addr,
+        .val = val,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_FPGA_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for fpga_write\n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_host_event_write(uint32_t val)
+{
+    int rc;
+    dev_ctrl_ioctl_param params =
+    {
+        .event = val,
+    };
+
+    rc = ioctl(maple_dev_ctrl_fd, MAPLE_DEV_CTRL_IOCTL_OP_HOST_EVENT_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for host_event_write\n");
+
+#ifdef CONFIG_ONU_SIM
+    /* Raise an interrupt on ext_irq1 for the embedded side. */
+    rc = bcm_board_fpga_gen_gpio_irq(BCMOLT_EXT_IRQ_EXT_IRQ1);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for bcm_board_fpga_gen_gpio_irq\n");
+#endif
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_pci_debug(uint32_t device, uint32_t command, int32_t start, int32_t howmany, uint32_t *dumpptr)
+{
+    int rc;
+    dev_ctrl_ioctl_param params =
+    {
+        .device = device,
+        .dumpptr = dumpptr,
+        .start_index = start,
+        .howmany = howmany
+    };
+
+    rc = ioctl(maple_dev_ctrl_fd, command, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for dev_ctrl\n");
+
+    return BCM_ERR_OK;
+}
+bcmos_errno bcm_board_fpga_read(uint32_t addr, uint32_t *val)
+{
+    int rc;
+    maple_i2c_ioctl_param params =
+    {
+        .addr = addr,
+    };
+
+    rc = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_FPGA_READ, &params);
+    BCMOS_TRACE_CHECK_RETURN(rc, BCM_ERR_INTERNAL, "ioctl failed for fpga_read\n");
+    *val = params.val;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_fpga_reg_read(uint32_t reg, uint32_t *val)
+{
+    bcmos_errno rc;
+
+    if (reg > BCM_FPGA_REG_HIGH)
+        return BCM_ERR_RANGE;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    return bcm_board_fpga_read(reg, val);
+}
+
+bcmos_errno bcm_board_fpga_reg_write(uint32_t reg, uint32_t val)
+{
+    bcmos_errno rc;
+
+    if (reg > BCM_FPGA_REG_HIGH)
+        return BCM_ERR_RANGE;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    return bcm_board_fpga_write(reg, val);
+}
+
+bcmos_errno bcm_board_fpga_version_get(uint32_t *version)
+{
+    bcmos_errno rc;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    return bcm_board_fpga_read(BCM_FPGA_REG_FPGA_VERSION, version);
+}
+
+bcmos_errno bcm_board_fpga_set_gpio_dir(bcmolt_gpio_pin gpio_pin, bcm_fpga_gpio_dir dir)
+{
+    bcmos_errno rc;
+    uint32_t gpio_dir_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Read-modify-write direction register (we don't want to affect other GPIO's). */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_GPIO_DIR, &gpio_dir_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    if (dir == BCM_FPGA_GPIO_DIR_INPUT)
+        gpio_dir_mask &= ~(1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4));
+    else
+        gpio_dir_mask |= (1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4));
+
+    return bcm_board_fpga_write(BCM_FPGA_REG_GPIO_DIR, gpio_dir_mask);
+}
+
+bcmos_errno bcm_board_fpga_get_gpio_dir(bcmolt_gpio_pin gpio_pin, bcm_fpga_gpio_dir *dir)
+{
+    bcmos_errno rc;
+    uint32_t gpio_dir_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_GPIO_DIR, &gpio_dir_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    *dir = (gpio_dir_mask & (1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4))) ? BCM_FPGA_GPIO_DIR_OUTPUT : BCM_FPGA_GPIO_DIR_INPUT;
+
+    return rc;
+}
+
+bcmos_errno bcm_board_fpga_write_gpio(bcmolt_gpio_pin gpio_pin, uint32_t val)
+{
+    bcmos_errno rc;
+    uint32_t gpio_write_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Read-modify-write direction register (we don't want to affect other GPIO's). */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_GPIO_OUTPUT, &gpio_write_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    if (!val)
+        gpio_write_mask &= ~(1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4));
+    else
+        gpio_write_mask |= (1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4));
+
+    return bcm_board_fpga_write(BCM_FPGA_REG_GPIO_OUTPUT, gpio_write_mask);
+}
+
+bcmos_errno bcm_board_fpga_read_gpio(bcmolt_gpio_pin gpio_pin, uint32_t *val)
+{
+    bcmos_errno rc;
+    uint32_t gpio_read_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_GPIO_INPUT, &gpio_read_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    *val = (gpio_read_mask & (1 << (gpio_pin - BCMOLT_GPIO_PIN_PIN4)));
+
+    return rc;
+}
+
+bcmos_errno bcm_board_fpga_gen_gpio_irq(bcmolt_ext_irq ext_irq)
+{
+    bcmos_errno rc;
+    uint32_t gpio_irq_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Read-modify-write direction register (we don't want to affect other GPIO's). */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_GPIO_IRQ, &gpio_irq_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    gpio_irq_mask |= (1 << ext_irq);
+    rc = bcm_board_fpga_write(BCM_FPGA_REG_GPIO_IRQ, gpio_irq_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    bcmos_usleep(1000);
+
+    gpio_irq_mask &= ~(1 << ext_irq);
+    rc = bcm_board_fpga_write(BCM_FPGA_REG_GPIO_IRQ, gpio_irq_mask);
+
+    return rc;
+}
+
+bcmos_errno bcm_board_trx_present(uint8_t pon)
+{
+    bcmos_errno rc;
+    uint32_t trx_absence_mask;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Check that the transceiver is present (plugged in). For ONU simulator, we allow working without transceivers. */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_TRX_IS_PRESENT, &trx_absence_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    if (trx_absence_mask & (1 << pon))
+    {
+        /* The transceiver is absent. */
+        return BCM_ERR_NODEV;
+    }
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_trx_enable(uint8_t pon, bcmos_bool is_enabled)
+{
+#ifdef CONFIG_ONU_SIM
+    static uint32_t trx_disable_mask = 0xFFFFFFFF;
+
+    /* Keep track of which TRXs are logically enabled. */
+    if (is_enabled)
+        trx_disable_mask &= ~(1 << pon);
+    else
+        trx_disable_mask |= (1 << pon);
+
+    return bcm_board_host_event_write(trx_disable_mask);
+#else
+    uint32_t trx_disable_mask;
+    uint32_t trx_absence_mask;
+
+    bcmos_errno rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Check that the transceiver is present (plugged in). */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_TRX_IS_PRESENT, &trx_absence_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    if (trx_absence_mask & (1 << pon))
+    {
+        /* The transceiver is absent. */
+        return BCM_ERR_NODEV;
+    }
+
+    /* Read-modify-write transceiver disable mask (we don't want to affect other PON's). */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_TRX_ENABLE, &trx_disable_mask);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    if (is_enabled == BCMOS_TRUE)
+        trx_disable_mask &= ~(1 << pon);
+    else
+        trx_disable_mask |= (1 << pon);
+
+    rc = bcm_board_fpga_write(BCM_FPGA_REG_TRX_ENABLE, trx_disable_mask);
+    if (rc != BCM_ERR_OK)
+        return BCM_ERR_INTERNAL;
+    return bcm_board_host_event_write(trx_disable_mask);
+#endif
+}
+
+static bcmos_errno bcm_board_config_reset_value(uint32_t rst_bit, bcmos_bool is_on)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    /* Read-modify-write so we can set only the relevant bit to 0 */
+    rc = bcm_board_fpga_read(BCM_FPGA_REG_RESETS, &reset_values);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    if (is_on == BCMOS_TRUE)
+        reset_values |= 1 << rst_bit;
+    else
+        reset_values &= ~(1 << rst_bit);
+
+    return bcm_board_fpga_write(BCM_FPGA_REG_RESETS, reset_values);
+}
+
+static bcmos_errno device_disconnect(void)
+{
+    bcmolt_device_key key = {};
+    bcmolt_device_cfg dev_cfg;
+    bcmolt_device_disconnect dev_disconnect;
+    bcmos_errno rc;
+
+    BCMOLT_CFG_INIT(&dev_cfg, device, key);
+    BCMOLT_CFG_PROP_GET(&dev_cfg, device, state);
+    rc = bcmolt_cfg_get(0, &dev_cfg.hdr);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    if (dev_cfg.data.state != BCMOLT_DEVICE_STATE_DISCONNECTED)
+    {
+        BCMOLT_OPER_INIT(&dev_disconnect, device, disconnect, key);
+        return bcmolt_oper_submit(0, &dev_disconnect.hdr);
+    }
+    else
+        return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_device_reset(void)
+{
+    bcmos_errno rc;
+
+    rc = device_disconnect();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    rc = bcm_board_config_reset_value(BCM_RST_BIT_DEVICE, BCMOS_FALSE);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    return bcm_board_config_reset_value(BCM_RST_BIT_DEVICE, BCMOS_TRUE);
+}
+
+/* Device on keeps the reset bit on active high */
+bcmos_errno bcm_board_device_on(void)
+{
+    return bcm_board_config_reset_value(BCM_RST_BIT_DEVICE, BCMOS_TRUE);
+}
+
+/* Device off keeps the reset bit on active low */
+bcmos_errno bcm_board_device_off(void)
+{
+    bcmos_errno rc;
+
+    rc = device_disconnect();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    return bcm_board_config_reset_value(BCM_RST_BIT_DEVICE, BCMOS_FALSE);
+}
+
+/* Katana2 Device on keeps the reset bit on active high */
+bcmos_errno bcm_board_kt2_device_on(void)
+{
+    /* take the KT2 out of reset */
+    return bcm_board_config_reset_value(BCM_RST_BIT_KT2, BCMOS_TRUE);
+}
+
+/* Device off keeps the reset bit on active low */
+bcmos_errno bcm_board_kt2_device_off(void)
+{
+    return bcm_board_config_reset_value(BCM_RST_BIT_KT2, BCMOS_FALSE);
+}
+
+static bcmos_errno bcm_access_dpll(void)
+{
+    bcmos_errno rc;
+
+    if (bcm_board_is_svk4())
+    {
+        rc = bcm_board_dev_change(I2C_SW1_I2C_ADDR);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(I2C_SW1_I2C_ADDR) failed\n");
+        rc = bcm_board_switch_write(0x20);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_switch_write(0x20) failed\n");
+    }
+    else
+    {
+        rc = bcm_board_dev_change(I2C_SW0_I2C_ADDR);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(I2C_SW0_I2C_ADDR) failed\n");
+        rc = bcm_board_switch_write(2);
+        BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_switch_write(2) failed\n");
+    }
+
+    rc = bcm_board_dev_change(PON_DPLL_I2C_ADDR);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_change(PON_DPLL_I2C_ADDR) failed \n");
+
+    return rc;
+}
+
+static int bcm_board_set_page_dpll(uint32_t page)
+{
+    int rcioctl;
+    maple_i2c_ioctl_param params =
+    {
+        .count = 8,
+        .addr = 1,
+        .val = page,
+    };
+
+    rcioctl = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rcioctl, BCM_ERR_INTERNAL, "ioctl write change page failed\n");
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_read_dpll(uint32_t page, uint32_t reg, uint32_t *val)
+{
+    bcmos_errno rc;
+    int rcioctl;
+    maple_i2c_ioctl_param params =
+    {
+        .count = 8,
+        .addr = reg,
+        .val = 0,
+    };
+
+    rc = bcm_access_dpll();
+    bcm_board_set_page_dpll(page);
+    rcioctl = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_READ, &params);
+    BCMOS_TRACE_CHECK_RETURN(rcioctl, BCM_ERR_INTERNAL, "ioctl read failed for maple_i2c_fd\n");
+    *val = params.val;
+
+    return rc;
+}
+
+bcmos_errno bcm_board_write_dpll(uint32_t page, uint32_t reg, uint32_t val)
+{
+    bcmos_errno rc;
+    int rcioctl;
+    maple_i2c_ioctl_param params =
+    {
+        .count = 8,
+        .addr = reg,
+        .val = val,
+    };
+
+    rc = bcm_access_dpll();
+    bcm_board_set_page_dpll(page);
+    rcioctl = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_WRITE, &params);
+    BCMOS_TRACE_CHECK_RETURN(rcioctl, BCM_ERR_INTERNAL, "ioctl write failed for maple_i2c_fd\n");
+
+    return rc;
+}
+
+static bcmos_errno bcm_board_load_dpll(dpll_command *commands, int cmdlen)
+{
+    int rcioctl,i;
+    bcmos_errno rc;
+    uint8_t previous_page = 0;
+
+    maple_i2c_ioctl_param params =
+    {
+        .count = 8,
+        .addr = 0,
+        .val = 0,
+    };
+
+    rc = bcm_access_dpll();
+    for (i=0; i < cmdlen; i++)
+    {
+        if (commands[i].page != previous_page)
+        {
+            bcm_board_set_page_dpll(commands[i].page);
+            previous_page = commands[i].page;
+        }
+        params.addr = commands[i].reg;
+        params.val = commands[i].data;
+        rcioctl = ioctl(maple_i2c_fd, MAPLE_I2C_IOCTL_OP_DEV_WRITE, &params);
+        BCMOS_TRACE_CHECK_RETURN(rcioctl, BCM_ERR_INTERNAL, "ioctl write data page failed\n");
+    }
+    return rc;
+}
+bcmos_errno bcm_board_burn_pon_dpll(bcm_dpll_users dpll_dev)
+{
+    switch(dpll_dev)
+    {
+        case GPON_DPLL:
+            return bcm_board_load_dpll(gpon_dpll_table,sizeof(gpon_dpll_table)/sizeof(dpll_command));
+            break;
+        case EPON_DPLL:
+            return bcm_board_load_dpll(epon_dpll_table,sizeof(epon_dpll_table)/sizeof(dpll_command));
+            break;
+        case GPON_SYNCE:
+            return bcm_board_load_dpll(gpon_synce_dpll_table,sizeof(gpon_synce_dpll_table)/sizeof(dpll_command));
+            break;
+        default:
+            break;
+    }
+
+    return BCM_ERR_PARM;
+}
+
+bcmos_errno bcm_board_init(void)
+{
+    maple_dev_ctrl_fd = open("/dev/maple_dev_ctrl", O_RDWR);
+    BCMOS_TRACE_CHECK_RETURN(maple_dev_ctrl_fd < 0, errno, "maple_dev_ctrl_fd open failed\n");
+
+    maple_i2c_fd = open("/dev/maple_i2c", O_RDWR);
+    BCMOS_TRACE_CHECK_RETURN(maple_i2c_fd < 0, errno, "maple_i2c_fd open failed\n");
+
+#ifdef CONFIG_ONU_SIM
+    /* If the ONU sim is running, always leave all transceivers physically disabled. */
+    bcmos_errno rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    rc = bcm_board_fpga_write(BCM_FPGA_REG_TRX_ENABLE, 0xFFFFFFFF);
+    if (rc != BCM_ERR_OK)
+        return BCM_ERR_INTERNAL;
+#endif
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_get_board_id(bcm_board_svk_board_id * board_id)
+{
+    bcmos_errno rc;
+    uint32_t val;
+
+    rc = bcm_access_fpga();
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    rc = bcm_board_fpga_read(0x1, &val);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+
+    *board_id = val & 0x7;
+    return BCM_ERR_OK;
+}
+
+void bcm_board_uninit(void)
+{
+    close(maple_i2c_fd);
+    maple_i2c_fd = 0;
+
+    close(maple_dev_ctrl_fd);
+    maple_dev_ctrl_fd = -1;
+}
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.h b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.h
new file mode 100644
index 0000000..3a58eba
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board.h
@@ -0,0 +1,100 @@
+/*
+<: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 _BCMOLT_BOARD_H_
+#define _BCMOLT_BOARD_H_
+
+#include <bcmos_system.h>
+#include <bcmolt_model_types.h>
+
+typedef enum
+{
+    SVK_1    = 0x7, /* SVK #1 - BCM968620S: all PON flavors supported, SFP+ */
+    SVK_2_XG = 0x6, /* SVK #2 - BCM968620XG: XGPON */
+    SVK_2_XE = 0x5, /* SVK #2 - BCM968620XE: 10G EPON */
+    SVK_3    = 0x4, /* SVK #3 - BCM968620K: all PON flavors supported, XFP */
+} bcm_board_svk_board_id;
+
+bcmos_errno bcm_board_dev_change(uint32_t addr);
+bcmos_errno bcm_board_dev_write(uint32_t count, uint32_t addr, uint32_t val);
+bcmos_errno bcm_board_dev_read(uint32_t count, uint32_t addr, uint32_t *val);
+bcmos_errno bcm_board_switch_write(uint32_t val);
+bcmos_errno bcm_board_switch_read(uint32_t *val);
+bcmos_errno bcm_board_fpga_write(uint32_t addr, uint32_t val);
+bcmos_errno bcm_board_fpga_read(uint32_t addr, uint32_t *val);
+bcmos_errno bcm_board_host_event_write(uint32_t val);
+
+bcmos_errno bcm_board_fpga_version_get(uint32_t *version);
+
+/* FPGA GPIO access */
+typedef enum
+{
+    BCM_FPGA_GPIO_DIR_INPUT,
+    BCM_FPGA_GPIO_DIR_OUTPUT,
+} bcm_fpga_gpio_dir;
+
+typedef enum
+{
+    GPON_DPLL,
+    EPON_DPLL,
+    GPON_SYNCE
+} bcm_dpll_users;
+
+typedef struct
+{
+    uint8_t  page;
+    uint8_t  reg;
+    uint8_t  data;
+} dpll_command;
+
+bcmos_errno bcm_board_fpga_set_gpio_dir(bcmolt_gpio_pin gpio_pin, bcm_fpga_gpio_dir dir);
+bcmos_errno bcm_board_fpga_get_gpio_dir(bcmolt_gpio_pin gpio_pin, bcm_fpga_gpio_dir *dir);
+bcmos_errno bcm_board_fpga_write_gpio(bcmolt_gpio_pin gpio_pin, uint32_t val);
+bcmos_errno bcm_board_fpga_read_gpio(bcmolt_gpio_pin gpio_pin, uint32_t *val);
+bcmos_errno bcm_board_fpga_gen_gpio_irq(bcmolt_ext_irq ext_irq);
+
+bcmos_errno bcm_board_trx_enable(uint8_t pon, bcmos_bool is_enabled);
+bcmos_errno bcm_board_trx_present(uint8_t pon);
+bcmos_errno bcm_board_device_reset(void);
+bcmos_errno bcm_board_device_on(void);
+bcmos_errno bcm_board_device_off(void);
+bcmos_errno bcm_board_kt2_device_on(void);
+bcmos_errno bcm_board_kt2_device_off(void);
+bcmos_errno bcm_board_get_board_id(bcm_board_svk_board_id * board_id);
+bcmos_errno bcm_board_fpga_reg_read(uint32_t reg, uint32_t *val);
+bcmos_errno bcm_board_fpga_reg_write(uint32_t reg, uint32_t val);
+bcmos_errno bcm_board_pci_debug(uint32_t device, uint32_t command, int32_t start, int32_t howmany, uint32_t *dumpptr);
+bcmos_errno bcm_board_burn_pon_dpll(bcm_dpll_users dpll_dev);
+bcmos_errno bcm_board_write_dpll(uint32_t page, uint32_t reg, uint32_t val);
+bcmos_errno bcm_board_read_dpll(uint32_t page, uint32_t reg, uint32_t *val);
+
+bcmos_errno bcm_board_init(void);
+void bcm_board_uninit(void);
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.c b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.c
new file mode 100644
index 0000000..e7b59fa
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.c
@@ -0,0 +1,581 @@
+/*
+<: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 <bcmcli.h>
+#include "bcmolt_board.h"
+#include "bcmolt_board_cli.h"
+#include <arpa/inet.h>
+
+#define BCM_I2C_DEV_ADDR_START static bcmcli_enum_val bcm_i2c_dev_addr_table[] = {
+#define BCM_I2C_DEV_ADDR(name, desc, val) {desc, val},
+#define BCM_I2C_DEV_ADDR_END BCMCLI_ENUM_LAST};
+#include <bcmolt_i2c_devs_addr.h>
+
+static bcmos_errno bcm_board_cli_dev_change(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t addr = bcmcli_find_named_parm(session, "dev")->value.unumber;
+
+    return bcm_board_dev_change(addr);
+}
+
+static bcmos_errno bcm_board_cli_dev_write(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t count = bcmcli_find_named_parm(session, "width")->value.unumber;
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+
+    switch (count)
+    {
+    case 8:
+    case 16:
+    case 32:
+        break;
+    default:
+        bcmcli_session_print(session, "Count can be 8|16|32\n");
+        return BCM_ERR_PARM;
+    }
+    return bcm_board_dev_write(count, addr, val);
+}
+
+static bcmos_errno bcm_board_cli_dev_read(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t count = bcmcli_find_named_parm(session, "width")->value.unumber;
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val;
+    bcmos_errno rc;
+    
+    switch (count)
+    {
+    case 8:
+    case 16:
+    case 32:
+        break;
+    default:
+        bcmcli_session_print(session, "Count can be 8|16|32\n");
+        return BCM_ERR_PARM;
+    }
+    rc = bcm_board_dev_read(count, addr, &val);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dev_read() failed\n");
+    bcmcli_session_print(session, "0x%x\n", val);
+    
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_board_cli_switch_write(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+
+    return bcm_board_switch_write(val);
+}
+
+static bcmos_errno bcm_board_cli_switch_read(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t val;
+    bcmos_errno rc;
+
+    rc = bcm_board_switch_read(&val);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_switch_read() failed\n");
+    bcmcli_session_print(session, "0x%x\n", val);
+    
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_board_cli_fpga_write(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+    
+    return bcm_board_fpga_write(addr, val);
+}
+
+static bcmos_errno bcm_board_cli_fpga_read(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val;
+    bcmos_errno rc;
+    
+    rc = bcm_board_fpga_read(addr, &val);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_fpga_read() failed\n");
+    bcmcli_session_print(session, "0x%x\n", val);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_board_cli_fpga_version(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t version;
+    bcmos_errno rc;
+
+    rc = bcm_board_fpga_version_get(&version);
+    bcmcli_session_print(session, "0x%x\n", version);
+    return rc;
+}
+
+static bcmos_errno bcm_board_cli_fpga_set_gpio_dir(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmolt_gpio_pin gpio_pin = bcmcli_find_named_parm(session, "gpio_pin")->value.unumber;
+    bcm_fpga_gpio_dir dir = bcmcli_find_named_parm(session, "dir")->value.unumber;
+
+    return bcm_board_fpga_set_gpio_dir(gpio_pin, dir);
+}
+
+static bcmos_errno bcm_board_cli_fpga_get_gpio_dir(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmolt_gpio_pin gpio_pin = bcmcli_find_named_parm(session, "gpio_pin")->value.unumber;
+    bcm_fpga_gpio_dir dir;
+    bcmos_errno rc;
+  
+    rc = bcm_board_fpga_get_gpio_dir(gpio_pin, &dir);
+    bcmcli_session_print(session, "%s\n", dir == BCM_FPGA_GPIO_DIR_INPUT ? "input" : "output");
+    return rc;
+}
+
+static bcmos_errno bcm_board_cli_fpga_write_gpio(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmolt_gpio_pin gpio_pin = bcmcli_find_named_parm(session, "gpio_pin")->value.unumber;
+    uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+
+    return bcm_board_fpga_write_gpio(gpio_pin, val);
+}
+
+static bcmos_errno bcm_board_cli_fpga_read_gpio(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmolt_gpio_pin gpio_pin = bcmcli_find_named_parm(session, "gpio_pin")->value.unumber;
+    uint32_t val;
+    bcmos_errno rc;
+  
+    rc = bcm_board_fpga_read_gpio(gpio_pin, &val);
+    bcmcli_session_print(session, "0x%x\n", val);
+    return rc;
+}
+
+static bcmos_errno bcm_board_cli_fpga_gen_gpio_irq(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    bcmolt_ext_irq ext_irq = bcmcli_find_named_parm(session, "irq")->value.unumber;
+  
+    return bcm_board_fpga_gen_gpio_irq(ext_irq);
+}
+
+static bcmos_errno bcm_board_cli_trx_enable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint8_t pon_id = bcmcli_find_named_parm(session, "pon_id")->value.unumber;
+
+    return bcm_board_trx_enable(pon_id, BCMOS_TRUE);
+}
+
+static bcmos_errno bcm_board_cli_trx_disable(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint8_t pon_id = bcmcli_find_named_parm(session, "pon_id")->value.unumber;
+
+    return bcm_board_trx_enable(pon_id, BCMOS_FALSE);
+}
+
+static bcmos_errno bcm_board_cli_device_reset(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return bcm_board_device_reset();
+}
+
+static bcmos_errno bcm_board_cli_device_on(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return bcm_board_device_on();
+}
+
+static bcmos_errno bcm_board_cli_device_off(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return bcm_board_device_off();
+}
+
+static bcmos_errno bcm_board_cli_kt2_on(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return bcm_board_kt2_device_on();
+}
+
+static bcmos_errno bcm_board_cli_kt2_off(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    return bcm_board_kt2_device_off();
+}
+
+static bcmos_errno bcm_board_cli_fpga_reg_read(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+	uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+	uint32_t val;
+	bcmos_errno rc;
+
+	rc = bcm_board_fpga_reg_read(addr, &val);
+	BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_fpga_reg_read() failed\n");
+	bcmcli_session_print(session, "0x%x\n", val);
+
+	return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_board_cli_fpga_reg_write(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+	uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+	uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+
+    return bcm_board_fpga_reg_write(addr, val);
+}
+
+static bcmos_errno bcm_board_cli_burn_dpll(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+	bcmos_errno rc;
+
+    uint32_t dev = bcmcli_find_named_parm(session, "device")->value.unumber;
+    rc = bcm_board_burn_pon_dpll(dev);
+	BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_burn_pon_dpll() failed\n");
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_board_cli_dpll_write(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t page = bcmcli_find_named_parm(session, "page")->value.unumber;
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val = bcmcli_find_named_parm(session, "val")->value.unumber;
+    
+    return bcm_board_write_dpll(page, addr, val);
+}
+
+static bcmos_errno bcm_board_cli_dpll_read(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t n_parms)
+{
+    uint32_t page = bcmcli_find_named_parm(session, "page")->value.unumber;
+    uint32_t addr = bcmcli_find_named_parm(session, "addr")->value.unumber;
+    uint32_t val;
+    bcmos_errno rc;
+    
+    rc = bcm_board_read_dpll(page, addr, &val);
+    BCMOS_TRACE_CHECK_RETURN(rc, rc, "bcm_board_dpll_read() failed\n");
+    bcmcli_session_print(session, "0x%x\n", val);
+
+    return BCM_ERR_OK;
+}
+
+/* LUK_MAX_DATA_SIZE (2*1024) */
+#define SWITCH_RECEIVE_BUFFER_LENGTH   (2*1024)
+static int switch_socket = -1;
+static char *switch_buffer = NULL;
+static bcmos_bool switch_first_connection = BCMOS_TRUE;
+
+static void switch_response(bcmcli_session *session)
+{
+    int len;
+    char *prompt = NULL;
+
+    while (1)
+    {
+        len = read(switch_socket, switch_buffer, SWITCH_RECEIVE_BUFFER_LENGTH-1);
+        if (len > 0)
+        {
+            switch_buffer[len] = '\0';
+            bcmcli_print(session, "%s", switch_buffer);
+            prompt = strstr(switch_buffer, "BCM");
+            while (prompt)
+            {
+                len = strlen(prompt);
+                if (len >= 6)
+                {
+                    if ((prompt[3] == '>') || ((prompt[3] == '.') && (prompt[5] == '>')))
+                        return;
+                }
+                else if (len >= 4)
+                {
+                    if (prompt[3] == '>')
+                        return;
+                }
+                prompt = strstr(&prompt[2], "BCM");
+            }
+        }
+        else
+            break;
+    }
+}
+
+static bcmos_errno kt2_conn(bcmcli_session *session, const bcmcli_cmd_parm parm[],  uint16_t n_parms)
+{
+    struct sockaddr_in server;
+
+    if (switch_socket != -1)
+    {
+        bcmcli_print(session, "A connection already exists\n");
+        return BCM_ERR_ALREADY;
+    }
+
+    switch_buffer = bcmos_alloc(SWITCH_RECEIVE_BUFFER_LENGTH);
+    if (!switch_buffer)
+    {
+        bcmcli_print(session, "Failed to allocate buffer\n");
+        return BCM_ERR_NOMEM;
+    }
+    memset((void *)&server, 0, sizeof(server));
+    server.sin_family = AF_INET;
+    server.sin_port = htons(parm[0].value.number);
+    server.sin_addr.s_addr = inet_addr("127.0.0.1");
+    switch_socket = socket(AF_INET, SOCK_STREAM, 0);
+    if (switch_socket < 0)
+    {
+        bcmcli_print(session, "Can't open client socket\n");
+        goto exit;
+    }
+    if (connect(switch_socket, (struct sockaddr *)&server, sizeof(server)) == -1)
+    {
+        close(switch_socket);
+        bcmcli_print(session, "Failed to connect\n");
+        goto exit;
+    }
+    if (switch_first_connection)
+    {
+        switch_first_connection = BCMOS_FALSE;
+        switch_response(session);
+    }
+
+    return BCM_ERR_OK;
+
+exit:
+    bcmos_free(switch_buffer);
+    return BCM_ERR_COMM_FAIL;
+}
+
+static bcmos_errno kt2_disconn(bcmcli_session *session, const bcmcli_cmd_parm parm[],  uint16_t n_parms)
+{
+    if (switch_socket != -1)
+    {
+        bcmcli_print(session, "Send 'exit'\n");
+        if (write(switch_socket, "exit\r", strlen("exit\r")) < 0)
+            bcmcli_print(session, "Send 'exit' to switch failed\n");
+        fsync(switch_socket);
+    }
+    bcmos_usleep(1000);
+    if (switch_socket != -1)
+        close(switch_socket);
+    if (switch_buffer)
+        bcmos_free(switch_buffer);
+    /* set socket and buffer with initial values */
+    switch_socket = -1;
+    switch_buffer = NULL;
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno kt2_cmd(bcmcli_session *session, const bcmcli_cmd_parm parm[],  uint16_t n_parms)
+{
+    int len, sent_len;
+    char *str;
+
+    if ((switch_socket == -1) || (!switch_buffer))
+    {
+        bcmcli_print(session, "Connection or buffer do not exist\n");
+        return BCM_ERR_NORES;
+    }
+    /* switch user space application receives thru _fd_input_cb and
+       send to kernel thru _kernel_proxy_output_cb */
+    len = (int)strlen(parm[0].value.string);
+    {
+        /* dirty - just to avoid error : cast discards '__attribute__((const))' qualifier if useing strcat */
+        unsigned long strp = (unsigned long)&parm[0].value.string;
+        str = *(char **)strp;
+    }
+    str[len++] = '\r';
+    str[len] = '\0';
+    sent_len = 0;
+    do
+    {
+        sent_len = write(switch_socket, str + sent_len , len - sent_len);
+        if (sent_len == -1 || ((sent_len == 0) && errno))
+        {
+            bcmcli_print(session, "Send command to switch failed (write to socket error: %d)\n", errno);
+            return BCM_ERR_COMM_FAIL;
+        }
+        fsync(switch_socket);
+    } while(len - sent_len);
+    /* switch kernel send thru _kernel_proxy_input_cb
+       to switch user space application thru _fd_outout_cb */
+    switch_response(session);
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_board_cli_init(bcmcli_entry *top_dir)
+{
+    bcmcli_entry *board_dir, *i2c_dir;
+    bcmos_errno rc;
+    bcm_board_svk_board_id board_id;
+    bcmcli_entry *dir;
+    static bcmcli_enum_val fpga_gpio_pin_table[] =
+    {
+        {"pin4", BCMOLT_GPIO_PIN_PIN4},
+        {"pin5", BCMOLT_GPIO_PIN_PIN5},
+        {"pin6", BCMOLT_GPIO_PIN_PIN6},
+        {"pin7", BCMOLT_GPIO_PIN_PIN7},
+        {"pin8", BCMOLT_GPIO_PIN_PIN8},
+        {"pin9", BCMOLT_GPIO_PIN_PIN9},
+        {"pin10", BCMOLT_GPIO_PIN_PIN10},
+        {"pin11", BCMOLT_GPIO_PIN_PIN11},
+        {"pin12", BCMOLT_GPIO_PIN_PIN12},
+        {"pin13", BCMOLT_GPIO_PIN_PIN13},
+        {"pin14", BCMOLT_GPIO_PIN_PIN14},
+        {"pin15", BCMOLT_GPIO_PIN_PIN15},
+        {"pin16", BCMOLT_GPIO_PIN_PIN16},
+        {"pin17", BCMOLT_GPIO_PIN_PIN17},
+        {"pin18", BCMOLT_GPIO_PIN_PIN18},
+        {"pin19", BCMOLT_GPIO_PIN_PIN19},
+        {"pin20", BCMOLT_GPIO_PIN_PIN20},
+        {"pin21", BCMOLT_GPIO_PIN_PIN21},
+        {"pin22", BCMOLT_GPIO_PIN_PIN22},
+        {"pin23", BCMOLT_GPIO_PIN_PIN23},
+        {"pin24", BCMOLT_GPIO_PIN_PIN24},
+        {"pin25", BCMOLT_GPIO_PIN_PIN25},
+        {"pin26", BCMOLT_GPIO_PIN_PIN26},
+        {"pin27", BCMOLT_GPIO_PIN_PIN27},
+        {"pin28", BCMOLT_GPIO_PIN_PIN28},
+        {"pin29", BCMOLT_GPIO_PIN_PIN29},
+        {"pin30", BCMOLT_GPIO_PIN_PIN30},
+        {"pin31", BCMOLT_GPIO_PIN_PIN31},
+        BCMCLI_ENUM_LAST
+    };
+    static bcmcli_enum_val fpga_ext_irq_table[] =
+    {
+        {"ext_irq0", BCMOLT_EXT_IRQ_EXT_IRQ0},
+        {"ext_irq1", BCMOLT_EXT_IRQ_EXT_IRQ1},
+        {"ext_irq2", BCMOLT_EXT_IRQ_EXT_IRQ2},
+        {"ext_irq3", BCMOLT_EXT_IRQ_EXT_IRQ3},
+        {"ext_irq4", BCMOLT_EXT_IRQ_EXT_IRQ4},
+        {"ext_irq5", BCMOLT_EXT_IRQ_EXT_IRQ5},
+        BCMCLI_ENUM_LAST
+    };
+
+    static bcmcli_enum_val fpga_gpio_dir_table[] =
+    {
+        {"input", BCM_FPGA_GPIO_DIR_INPUT},
+        {"output", BCM_FPGA_GPIO_DIR_OUTPUT},
+        BCMCLI_ENUM_LAST
+    };
+
+    static bcmcli_enum_val dpll_devices[] = {
+        { .name="gpon", .val=GPON_DPLL},
+        { .name="epon", .val=EPON_DPLL},
+        { .name="synce", .val=GPON_SYNCE},
+        BCMCLI_ENUM_LAST
+    };
+    
+    board_dir = bcmcli_dir_add(top_dir, "board", "Board", BCMCLI_ACCESS_GUEST, NULL);
+    BCMOS_CHECK_RETURN_ERROR(!board_dir, BCM_ERR_INTERNAL);
+
+    i2c_dir = bcmcli_dir_add(board_dir, "i2c", "i2c", BCMCLI_ACCESS_GUEST, NULL);
+    BCMOS_CHECK_RETURN_ERROR(!i2c_dir, BCM_ERR_INTERNAL);
+
+    BCMCLI_MAKE_CMD(i2c_dir, "dev_change", "Change current device", bcm_board_cli_dev_change,
+        BCMCLI_MAKE_PARM_ENUM("dev", "device", bcm_i2c_dev_addr_table, 0));
+
+    BCMCLI_MAKE_CMD(i2c_dir, "dev_write", "Write to current i2c device", bcm_board_cli_dev_write,
+        BCMCLI_MAKE_PARM("width", "Width of register in bits (8|16|32)", BCMCLI_PARM_NUMBER, 0),
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("val", "value", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(i2c_dir, "dev_read", "Read from current i2c device", bcm_board_cli_dev_read,
+        BCMCLI_MAKE_PARM("width", "Width of register in bits (8|16|32)", BCMCLI_PARM_NUMBER, 0),
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(i2c_dir, "switch_write", "Write to switch", bcm_board_cli_switch_write,
+        BCMCLI_MAKE_PARM_RANGE("val", "value", BCMCLI_PARM_HEX, 0, 0, UCHAR_MAX));
+
+    BCMCLI_MAKE_CMD_NOPARM(i2c_dir, "switch_read", "Read from switch", bcm_board_cli_switch_read);
+
+    BCMCLI_MAKE_CMD(i2c_dir, "fpga_write", "Write to FPGA", bcm_board_cli_fpga_write,
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("val", "value", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(i2c_dir, "fpga_read", "Read from FPGA", bcm_board_cli_fpga_read,
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD_NOPARM(board_dir, "fpga_version", "FPGA version", bcm_board_cli_fpga_version);
+    
+    BCMCLI_MAKE_CMD(board_dir, "fpga_set_gpio_dir", "Set GPIO direction", bcm_board_cli_fpga_set_gpio_dir,
+        BCMCLI_MAKE_PARM_ENUM("gpio_pin", "GPIO pin", fpga_gpio_pin_table, 0),
+        BCMCLI_MAKE_PARM_ENUM("dir", "Direction", fpga_gpio_dir_table, 0));
+    BCMCLI_MAKE_CMD(board_dir, "fpga_get_gpio_dir", "Get GPIO direction", bcm_board_cli_fpga_get_gpio_dir,
+        BCMCLI_MAKE_PARM_ENUM("gpio_pin", "GPIO pin", fpga_gpio_pin_table, 0));
+    BCMCLI_MAKE_CMD(board_dir, "fpga_write_gpio", "Write to GPIO pin", bcm_board_cli_fpga_write_gpio,
+        BCMCLI_MAKE_PARM_ENUM("gpio_pin", "GPIO pin", fpga_gpio_pin_table, 0),
+        BCMCLI_MAKE_PARM("val", "Value", BCMCLI_PARM_HEX, 0));
+    BCMCLI_MAKE_CMD(board_dir, "fpga_read_gpio", "Read from GPIO pin", bcm_board_cli_fpga_read_gpio,
+        BCMCLI_MAKE_PARM_ENUM("gpio_pin", "GPIO pin", fpga_gpio_pin_table, 0));
+    BCMCLI_MAKE_CMD(board_dir, "fpga_gen_irq", "Generate GPIO IRQ", bcm_board_cli_fpga_gen_gpio_irq,
+        BCMCLI_MAKE_PARM_ENUM("irq", "IRQ", fpga_ext_irq_table, 0));
+
+    BCMCLI_MAKE_CMD(board_dir, "trx_enable", "Enable transceiver", bcm_board_cli_trx_enable,
+        BCMCLI_MAKE_PARM("pon_id", "pon_id", BCMCLI_PARM_UDECIMAL, 0));
+
+    BCMCLI_MAKE_CMD(board_dir, "trx_disable", "Disable transceiver", bcm_board_cli_trx_disable,
+        BCMCLI_MAKE_PARM("pon_id", "pon_id", BCMCLI_PARM_UDECIMAL, 0));
+
+    BCMCLI_MAKE_CMD_NOPARM(board_dir, "device_reset", "Reset the device - clears the reset bit and then set it on", bcm_board_cli_device_reset);
+
+    BCMCLI_MAKE_CMD_NOPARM(board_dir, "device_on", "Keeps the device with reset bit on", bcm_board_cli_device_on);
+
+    BCMCLI_MAKE_CMD_NOPARM(board_dir, "device_off", "Keeps the device with reset bit off", bcm_board_cli_device_off);
+
+    BCMCLI_MAKE_CMD(board_dir, "fpga_reg_read", "Read data from an FPGA register", bcm_board_cli_fpga_reg_read,
+    	BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(board_dir, "fpga_reg_write", "Write data to an FPGA register", bcm_board_cli_fpga_reg_write,
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("val", "value", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(board_dir, "dpll", "Burn DPLL", bcm_board_cli_burn_dpll,
+        BCMCLI_MAKE_PARM_ENUM("device", "Device", dpll_devices, 0));
+    
+    BCMCLI_MAKE_CMD(board_dir, "dpll_write", "Write to DPLL", bcm_board_cli_dpll_write,
+        BCMCLI_MAKE_PARM("page", "page", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("val", "value", BCMCLI_PARM_HEX, 0));
+
+    BCMCLI_MAKE_CMD(board_dir, "dpll_read", "Read from DPLL", bcm_board_cli_dpll_read,
+        BCMCLI_MAKE_PARM("page", "page", BCMCLI_PARM_HEX, 0),
+        BCMCLI_MAKE_PARM("addr", "address", BCMCLI_PARM_HEX, 0));
+
+    rc = bcm_board_get_board_id(&board_id);
+    BCMOS_CHECK_RETURN(rc, rc, rc);
+    /* check if the board is SVK#3 */
+    if (board_id == SVK_3)
+    {
+        BCMCLI_MAKE_CMD_NOPARM(board_dir, "kt2_on", "Keeps the Katana2 with reset bit on", bcm_board_cli_kt2_on);
+
+        BCMCLI_MAKE_CMD_NOPARM(board_dir, "kt2_off", "Keeps the Katana2 with reset bit off", bcm_board_cli_kt2_off);
+
+        dir = bcmcli_dir_add(board_dir, "switch", "Switch", BCMCLI_ACCESS_ADMIN, NULL);
+        BCMOS_CHECK_RETURN_ERROR(!dir, BCM_ERR_NOMEM);
+        BCMCLI_MAKE_CMD(dir, "conn", "connect to switch daemon", kt2_conn,
+            BCMCLI_MAKE_PARM("port", "connection port on localhost", BCMCLI_PARM_NUMBER, 0));
+        BCMCLI_MAKE_CMD_NOPARM(dir, "disconn", "disconnect from switch daemon", kt2_disconn);
+        BCMCLI_MAKE_CMD(dir, "cmd", "command to switch - string between quotes", kt2_cmd,
+            BCMCLI_MAKE_PARM("", "", BCMCLI_PARM_STRING, 0));
+    }
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.h b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.h
new file mode 100644
index 0000000..91a904a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/bcmolt_board_cli.h
@@ -0,0 +1,39 @@
+/*
+<: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 _BCMOLT_BOARD_CLI_H_
+#define _BCMOLT_BOARD_CLI_H_
+
+#include <bcmos_system.h>
+#include <bcmcli.h>
+
+bcmos_errno bcm_board_cli_init(bcmcli_entry *top_dir);
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/bcmolt_dpll_table.h b/bcm68620_release/release/host_customized/board/wrx/bcmolt_dpll_table.h
new file mode 100755
index 0000000..a7d610e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/bcmolt_dpll_table.h
@@ -0,0 +1,1144 @@
+#ifndef _BCMOLT_DPLL_TABLE_H_
+#define _BCMOLT_DPLL_TABLE_H_
+
+/* auto generated loading files */
+
+static dpll_command gpon_dpll_table[] =
+{
+    {0x0B,0x24,0xD8},
+    {0x0B,0x25,0x00},
+    {0x00,0x0B,0x68},
+    {0x00,0x16,0x02},
+    {0x00,0x17,0x1C},
+    {0x00,0x18,0xEE},
+    {0x00,0x19,0xDD},
+    {0x00,0x1A,0xDF},
+    {0x00,0x2B,0x02},
+    {0x00,0x2C,0x01},
+    {0x00,0x2D,0x01},
+    {0x00,0x2E,0x6F},
+    {0x00,0x2F,0x00},
+    {0x00,0x30,0x00},
+    {0x00,0x31,0x00},
+    {0x00,0x32,0x00},
+    {0x00,0x33,0x00},
+    {0x00,0x34,0x00},
+    {0x00,0x35,0x00},
+    {0x00,0x36,0x6F},
+    {0x00,0x37,0x00},
+    {0x00,0x38,0x00},
+    {0x00,0x39,0x00},
+    {0x00,0x3A,0x00},
+    {0x00,0x3B,0x00},
+    {0x00,0x3C,0x00},
+    {0x00,0x3D,0x00},
+    {0x00,0x3F,0x11},
+    {0x00,0x40,0x04},
+    {0x00,0x41,0x0E},
+    {0x00,0x42,0x00},
+    {0x00,0x43,0x00},
+    {0x00,0x44,0x00},
+    {0x00,0x45,0x0C},
+    {0x00,0x46,0x32},
+    {0x00,0x47,0x00},
+    {0x00,0x48,0x00},
+    {0x00,0x49,0x00},
+    {0x00,0x4A,0x32},
+    {0x00,0x4B,0x00},
+    {0x00,0x4C,0x00},
+    {0x00,0x4D,0x00},
+    {0x00,0x4E,0x05},
+    {0x00,0x4F,0x00},
+    {0x00,0x51,0x03},
+    {0x00,0x52,0x00},
+    {0x00,0x53,0x00},
+    {0x00,0x54,0x00},
+    {0x00,0x55,0x03},
+    {0x00,0x56,0x00},
+    {0x00,0x57,0x00},
+    {0x00,0x58,0x00},
+    {0x00,0x59,0x03},
+    {0x00,0x5A,0x55},
+    {0x00,0x5B,0x55},
+    {0x00,0x5C,0xD0},
+    {0x00,0x5D,0x00},
+    {0x00,0x5E,0x00},
+    {0x00,0x5F,0x00},
+    {0x00,0x60,0x00},
+    {0x00,0x61,0x00},
+    {0x00,0x62,0x00},
+    {0x00,0x63,0x00},
+    {0x00,0x64,0x00},
+    {0x00,0x65,0x00},
+    {0x00,0x66,0x00},
+    {0x00,0x67,0x00},
+    {0x00,0x68,0x00},
+    {0x00,0x69,0x00},
+    {0x00,0x92,0x00},
+    {0x00,0x93,0x00},
+    {0x00,0x95,0x00},
+    {0x00,0x96,0x00},
+    {0x00,0x98,0x00},
+    {0x00,0x9A,0x02},
+    {0x00,0x9B,0x10},
+    {0x00,0x9D,0x00},
+    {0x00,0x9E,0x20},
+    {0x00,0xA0,0x00},
+    {0x00,0xA2,0x02},
+    {0x00,0xA8,0xC9},
+    {0x00,0xA9,0x62},
+    {0x00,0xAA,0x10},
+    {0x00,0xAB,0x00},
+    {0x00,0xAC,0x00},
+    {0x01,0x02,0x01},
+    {0x01,0x08,0x06},
+    {0x01,0x09,0x09},
+    {0x01,0x0A,0x6B},
+    {0x01,0x0B,0x00},
+    {0x01,0x0D,0x01},
+    {0x01,0x0E,0x09},
+    {0x01,0x0F,0x3B},
+    {0x01,0x10,0x00},
+    {0x01,0x12,0x06},
+    {0x01,0x13,0x09},
+    {0x01,0x14,0x6B},
+    {0x01,0x15,0x00},
+    {0x01,0x17,0x01},
+    {0x01,0x18,0x09},
+    {0x01,0x19,0x3B},
+    {0x01,0x1A,0x00},
+    {0x01,0x1C,0x06},
+    {0x01,0x1D,0x09},
+    {0x01,0x1E,0x6B},
+    {0x01,0x1F,0x00},
+    {0x01,0x21,0x01},
+    {0x01,0x22,0x09},
+    {0x01,0x23,0x3B},
+    {0x01,0x24,0x00},
+    {0x01,0x26,0x06},
+    {0x01,0x27,0x09},
+    {0x01,0x28,0x6B},
+    {0x01,0x29,0x00},
+    {0x01,0x2B,0x01},
+    {0x01,0x2C,0x09},
+    {0x01,0x2D,0x3B},
+    {0x01,0x2E,0x00},
+    {0x01,0x30,0x06},
+    {0x01,0x31,0x09},
+    {0x01,0x32,0x6B},
+    {0x01,0x33,0x00},
+    {0x01,0x3A,0x06},
+    {0x01,0x3B,0xCC},
+    {0x01,0x3C,0x00},
+    {0x01,0x3D,0x00},
+    {0x01,0x3F,0x00},
+    {0x01,0x40,0x00},
+    {0x01,0x41,0x40},
+    {0x01,0x42,0xFF},
+    {0x02,0x02,0x00},
+    {0x02,0x03,0x00},
+    {0x02,0x04,0x00},
+    {0x02,0x05,0x00},
+    {0x02,0x06,0x00},
+    {0x02,0x08,0x4F},
+    {0x02,0x09,0x00},
+    {0x02,0x0A,0x00},
+    {0x02,0x0B,0x00},
+    {0x02,0x0C,0x00},
+    {0x02,0x0D,0x00},
+    {0x02,0x0E,0x01},
+    {0x02,0x0F,0x00},
+    {0x02,0x10,0x00},
+    {0x02,0x11,0x00},
+    {0x02,0x12,0x00},
+    {0x02,0x13,0x00},
+    {0x02,0x14,0x00},
+    {0x02,0x15,0x00},
+    {0x02,0x16,0x00},
+    {0x02,0x17,0x00},
+    {0x02,0x18,0x00},
+    {0x02,0x19,0x00},
+    {0x02,0x1A,0x00},
+    {0x02,0x1B,0x00},
+    {0x02,0x1C,0x00},
+    {0x02,0x1D,0x00},
+    {0x02,0x1E,0x00},
+    {0x02,0x1F,0x00},
+    {0x02,0x20,0x00},
+    {0x02,0x21,0x00},
+    {0x02,0x22,0x00},
+    {0x02,0x23,0x00},
+    {0x02,0x24,0x00},
+    {0x02,0x25,0x00},
+    {0x02,0x26,0x00},
+    {0x02,0x27,0x00},
+    {0x02,0x28,0x00},
+    {0x02,0x29,0x00},
+    {0x02,0x2A,0x00},
+    {0x02,0x2B,0x00},
+    {0x02,0x2C,0x00},
+    {0x02,0x2D,0x00},
+    {0x02,0x2E,0x00},
+    {0x02,0x2F,0x00},
+    {0x02,0x31,0x03},
+    {0x02,0x32,0x03},
+    {0x02,0x33,0x03},
+    {0x02,0x34,0x03},
+    {0x02,0x35,0x00},
+    {0x02,0x36,0x00},
+    {0x02,0x37,0x00},
+    {0x02,0x38,0xC0},
+    {0x02,0x39,0xDE},
+    {0x02,0x3A,0x00},
+    {0x02,0x3B,0x00},
+    {0x02,0x3C,0x00},
+    {0x02,0x3D,0x00},
+    {0x02,0x3E,0xC8},
+    {0x02,0x4A,0x00},
+    {0x02,0x4B,0x00},
+    {0x02,0x4C,0x00},
+    {0x02,0x4D,0x00},
+    {0x02,0x4E,0x00},
+    {0x02,0x4F,0x00},
+    {0x02,0x50,0x00},
+    {0x02,0x51,0x00},
+    {0x02,0x52,0x00},
+    {0x02,0x53,0x00},
+    {0x02,0x54,0x00},
+    {0x02,0x55,0x00},
+    {0x02,0x56,0x00},
+    {0x02,0x57,0x00},
+    {0x02,0x58,0x00},
+    {0x02,0x59,0x00},
+    {0x02,0x5A,0x00},
+    {0x02,0x5B,0x00},
+    {0x02,0x5C,0x00},
+    {0x02,0x5D,0x00},
+    {0x02,0x5E,0x00},
+    {0x02,0x5F,0x00},
+    {0x02,0x60,0x00},
+    {0x02,0x61,0x00},
+    {0x02,0x62,0x00},
+    {0x02,0x63,0x00},
+    {0x02,0x64,0x00},
+    {0x02,0x68,0x00},
+    {0x02,0x69,0x00},
+    {0x02,0x6A,0x00},
+    {0x02,0x6B,0x47},
+    {0x02,0x6C,0x50},
+    {0x02,0x6D,0x4F},
+    {0x02,0x6E,0x4E},
+    {0x02,0x6F,0x5F},
+    {0x02,0x70,0x43},
+    {0x02,0x71,0x4C},
+    {0x02,0x72,0x4B},
+    {0x03,0x02,0x00},
+    {0x03,0x03,0x00},
+    {0x03,0x04,0x00},
+    {0x03,0x05,0x00},
+    {0x03,0x06,0x16},
+    {0x03,0x07,0x00},
+    {0x03,0x08,0x00},
+    {0x03,0x09,0x00},
+    {0x03,0x0A,0x00},
+    {0x03,0x0B,0x80},
+    {0x03,0x0D,0x00},
+    {0x03,0x0E,0x00},
+    {0x03,0x0F,0x00},
+    {0x03,0x10,0x00},
+    {0x03,0x11,0x00},
+    {0x03,0x12,0x00},
+    {0x03,0x13,0x00},
+    {0x03,0x14,0x00},
+    {0x03,0x15,0x00},
+    {0x03,0x16,0x00},
+    {0x03,0x18,0x00},
+    {0x03,0x19,0x00},
+    {0x03,0x1A,0x00},
+    {0x03,0x1B,0x00},
+    {0x03,0x1C,0x00},
+    {0x03,0x1D,0x00},
+    {0x03,0x1E,0x00},
+    {0x03,0x1F,0x00},
+    {0x03,0x20,0x00},
+    {0x03,0x21,0x00},
+    {0x03,0x23,0x00},
+    {0x03,0x24,0x00},
+    {0x03,0x25,0x00},
+    {0x03,0x26,0x00},
+    {0x03,0x27,0x00},
+    {0x03,0x28,0x00},
+    {0x03,0x29,0x00},
+    {0x03,0x2A,0x00},
+    {0x03,0x2B,0x00},
+    {0x03,0x2C,0x00},
+    {0x03,0x2E,0x00},
+    {0x03,0x2F,0x00},
+    {0x03,0x30,0x00},
+    {0x03,0x31,0x00},
+    {0x03,0x32,0x00},
+    {0x03,0x33,0x00},
+    {0x03,0x34,0x00},
+    {0x03,0x35,0x00},
+    {0x03,0x36,0x00},
+    {0x03,0x37,0x00},
+    {0x03,0x39,0x1F},
+    {0x03,0x3B,0x00},
+    {0x03,0x3C,0x00},
+    {0x03,0x3D,0x00},
+    {0x03,0x3E,0x00},
+    {0x03,0x3F,0x00},
+    {0x03,0x40,0x00},
+    {0x03,0x41,0x00},
+    {0x03,0x42,0x00},
+    {0x03,0x43,0x00},
+    {0x03,0x44,0x00},
+    {0x03,0x45,0x00},
+    {0x03,0x46,0x00},
+    {0x03,0x47,0x00},
+    {0x03,0x48,0x00},
+    {0x03,0x49,0x00},
+    {0x03,0x4A,0x00},
+    {0x03,0x4B,0x00},
+    {0x03,0x4C,0x00},
+    {0x03,0x4D,0x00},
+    {0x03,0x4E,0x00},
+    {0x03,0x4F,0x00},
+    {0x03,0x50,0x00},
+    {0x03,0x51,0x00},
+    {0x03,0x52,0x00},
+    {0x03,0x53,0x00},
+    {0x03,0x54,0x00},
+    {0x03,0x55,0x00},
+    {0x03,0x56,0x00},
+    {0x03,0x57,0x00},
+    {0x03,0x58,0x00},
+    {0x03,0x59,0x00},
+    {0x03,0x5A,0x00},
+    {0x03,0x5B,0x00},
+    {0x03,0x5C,0x00},
+    {0x03,0x5D,0x00},
+    {0x03,0x5E,0x00},
+    {0x03,0x5F,0x00},
+    {0x03,0x60,0x00},
+    {0x03,0x61,0x00},
+    {0x03,0x62,0x00},
+    {0x04,0x87,0x00},
+    {0x05,0x02,0x01},
+    {0x05,0x08,0x14},
+    {0x05,0x09,0x22},
+    {0x05,0x0A,0x0D},
+    {0x05,0x0B,0x0C},
+    {0x05,0x0C,0x01},
+    {0x05,0x0D,0x3F},
+    {0x05,0x0E,0x15},
+    {0x05,0x0F,0x26},
+    {0x05,0x10,0x0C},
+    {0x05,0x11,0x0B},
+    {0x05,0x12,0x01},
+    {0x05,0x13,0x3F},
+    {0x05,0x15,0x00},
+    {0x05,0x16,0x00},
+    {0x05,0x17,0x00},
+    {0x05,0x18,0xDF},
+    {0x05,0x19,0x38},
+    {0x05,0x1A,0x03},
+    {0x05,0x1B,0x00},
+    {0x05,0x1C,0x00},
+    {0x05,0x1D,0x80},
+    {0x05,0x1E,0x96},
+    {0x05,0x1F,0x98},
+    {0x05,0x21,0x33},
+    {0x05,0x2A,0x01},
+    {0x05,0x2B,0x01},
+    {0x05,0x2C,0x0F},
+    {0x05,0x2D,0x03},
+    {0x05,0x2E,0x19},
+    {0x05,0x2F,0x19},
+    {0x05,0x31,0x00},
+    {0x05,0x32,0x4B},
+    {0x05,0x33,0x03},
+    {0x05,0x34,0x00},
+    {0x05,0x36,0x0C},
+    {0x05,0x37,0x00},
+    {0x05,0x38,0x01},
+    {0x05,0x39,0x00},
+    {0x09,0x0E,0x02},
+    {0x09,0x43,0x01},
+    {0x09,0x49,0x01},
+    {0x09,0x4A,0x01},
+    {0x0A,0x02,0x00},
+    {0x0A,0x03,0x01},
+    {0x0A,0x04,0x01},
+    {0x0A,0x05,0x01},
+    {0x0B,0x44,0x0F},
+    {0x0B,0x46,0x00},
+    {0x0B,0x47,0x00},
+    {0x0B,0x48,0x0E},
+    {0x0B,0x4A,0x1E},
+    {0x05,0x14,0x01},
+    {0x00,0x1C,0x01},
+    {0x0B,0x24,0xDB},
+    {0x0B,0x25,0x02}
+};
+
+static dpll_command epon_dpll_table[] =
+{
+    {0x0B,0x24,0xD8},
+    {0x0B,0x25,0x00},
+    {0x00,0x0B,0x68},
+    {0x00,0x16,0x02},
+    {0x00,0x17,0x1C},
+    {0x00,0x18,0xEE},
+    {0x00,0x19,0xDD},
+    {0x00,0x1A,0xDF},
+    {0x00,0x2B,0x02},
+    {0x00,0x2C,0x01},
+    {0x00,0x2D,0x01},
+    {0x00,0x2E,0x70},
+    {0x00,0x2F,0x00},
+    {0x00,0x30,0x00},
+    {0x00,0x31,0x00},
+    {0x00,0x32,0x00},
+    {0x00,0x33,0x00},
+    {0x00,0x34,0x00},
+    {0x00,0x35,0x00},
+    {0x00,0x36,0x70},
+    {0x00,0x37,0x00},
+    {0x00,0x38,0x00},
+    {0x00,0x39,0x00},
+    {0x00,0x3A,0x00},
+    {0x00,0x3B,0x00},
+    {0x00,0x3C,0x00},
+    {0x00,0x3D,0x00},
+    {0x00,0x3F,0x11},
+    {0x00,0x40,0x04},
+    {0x00,0x41,0x0E},
+    {0x00,0x42,0x00},
+    {0x00,0x43,0x00},
+    {0x00,0x44,0x00},
+    {0x00,0x45,0x0C},
+    {0x00,0x46,0x32},
+    {0x00,0x47,0x00},
+    {0x00,0x48,0x00},
+    {0x00,0x49,0x00},
+    {0x00,0x4A,0x32},
+    {0x00,0x4B,0x00},
+    {0x00,0x4C,0x00},
+    {0x00,0x4D,0x00},
+    {0x00,0x4E,0x05},
+    {0x00,0x4F,0x00},
+    {0x00,0x51,0x03},
+    {0x00,0x52,0x00},
+    {0x00,0x53,0x00},
+    {0x00,0x54,0x00},
+    {0x00,0x55,0x03},
+    {0x00,0x56,0x00},
+    {0x00,0x57,0x00},
+    {0x00,0x58,0x00},
+    {0x00,0x59,0x03},
+    {0x00,0x5A,0x55},
+    {0x00,0x5B,0x55},
+    {0x00,0x5C,0xD0},
+    {0x00,0x5D,0x00},
+    {0x00,0x5E,0x00},
+    {0x00,0x5F,0x00},
+    {0x00,0x60,0x00},
+    {0x00,0x61,0x00},
+    {0x00,0x62,0x00},
+    {0x00,0x63,0x00},
+    {0x00,0x64,0x00},
+    {0x00,0x65,0x00},
+    {0x00,0x66,0x00},
+    {0x00,0x67,0x00},
+    {0x00,0x68,0x00},
+    {0x00,0x69,0x00},
+    {0x00,0x92,0x00},
+    {0x00,0x93,0x00},
+    {0x00,0x95,0x00},
+    {0x00,0x96,0x00},
+    {0x00,0x98,0x00},
+    {0x00,0x9A,0x02},
+    {0x00,0x9B,0x10},
+    {0x00,0x9D,0x00},
+    {0x00,0x9E,0x20},
+    {0x00,0xA0,0x00},
+    {0x00,0xA2,0x02},
+    {0x00,0xA8,0x1E},
+    {0x00,0xA9,0x94},
+    {0x00,0xAA,0x10},
+    {0x00,0xAB,0x00},
+    {0x00,0xAC,0x00},
+    {0x01,0x02,0x01},
+    {0x01,0x08,0x06},
+    {0x01,0x09,0x09},
+    {0x01,0x0A,0x6B},
+    {0x01,0x0B,0x00},
+    {0x01,0x0D,0x01},
+    {0x01,0x0E,0x09},
+    {0x01,0x0F,0x3B},
+    {0x01,0x10,0x00},
+    {0x01,0x12,0x06},
+    {0x01,0x13,0x09},
+    {0x01,0x14,0x6B},
+    {0x01,0x15,0x00},
+    {0x01,0x17,0x01},
+    {0x01,0x18,0x09},
+    {0x01,0x19,0x3B},
+    {0x01,0x1A,0x00},
+    {0x01,0x1C,0x06},
+    {0x01,0x1D,0x09},
+    {0x01,0x1E,0x6B},
+    {0x01,0x1F,0x00},
+    {0x01,0x21,0x01},
+    {0x01,0x22,0x09},
+    {0x01,0x23,0x3B},
+    {0x01,0x24,0x00},
+    {0x01,0x26,0x06},
+    {0x01,0x27,0x09},
+    {0x01,0x28,0x6B},
+    {0x01,0x29,0x00},
+    {0x01,0x2B,0x01},
+    {0x01,0x2C,0x09},
+    {0x01,0x2D,0x3B},
+    {0x01,0x2E,0x00},
+    {0x01,0x30,0x06},
+    {0x01,0x31,0x09},
+    {0x01,0x32,0x6B},
+    {0x01,0x33,0x00},
+    {0x01,0x3A,0x06},
+    {0x01,0x3B,0xCC},
+    {0x01,0x3C,0x00},
+    {0x01,0x3D,0x00},
+    {0x01,0x3F,0x00},
+    {0x01,0x40,0x00},
+    {0x01,0x41,0x40},
+    {0x01,0x42,0xFF},
+    {0x02,0x02,0x00},
+    {0x02,0x03,0x00},
+    {0x02,0x04,0x00},
+    {0x02,0x05,0x00},
+    {0x02,0x06,0x00},
+    {0x02,0x08,0x4F},
+    {0x02,0x09,0x00},
+    {0x02,0x0A,0x00},
+    {0x02,0x0B,0x00},
+    {0x02,0x0C,0x00},
+    {0x02,0x0D,0x00},
+    {0x02,0x0E,0x01},
+    {0x02,0x0F,0x00},
+    {0x02,0x10,0x00},
+    {0x02,0x11,0x00},
+    {0x02,0x12,0x00},
+    {0x02,0x13,0x00},
+    {0x02,0x14,0x00},
+    {0x02,0x15,0x00},
+    {0x02,0x16,0x00},
+    {0x02,0x17,0x00},
+    {0x02,0x18,0x00},
+    {0x02,0x19,0x00},
+    {0x02,0x1A,0x00},
+    {0x02,0x1B,0x00},
+    {0x02,0x1C,0x00},
+    {0x02,0x1D,0x00},
+    {0x02,0x1E,0x00},
+    {0x02,0x1F,0x00},
+    {0x02,0x20,0x00},
+    {0x02,0x21,0x00},
+    {0x02,0x22,0x00},
+    {0x02,0x23,0x00},
+    {0x02,0x24,0x00},
+    {0x02,0x25,0x00},
+    {0x02,0x26,0x00},
+    {0x02,0x27,0x00},
+    {0x02,0x28,0x00},
+    {0x02,0x29,0x00},
+    {0x02,0x2A,0x00},
+    {0x02,0x2B,0x00},
+    {0x02,0x2C,0x00},
+    {0x02,0x2D,0x00},
+    {0x02,0x2E,0x00},
+    {0x02,0x2F,0x00},
+    {0x02,0x31,0x03},
+    {0x02,0x32,0x03},
+    {0x02,0x33,0x03},
+    {0x02,0x34,0x03},
+    {0x02,0x35,0x00},
+    {0x02,0x36,0x00},
+    {0x02,0x37,0x00},
+    {0x02,0x38,0xD8},
+    {0x02,0x39,0xD6},
+    {0x02,0x3A,0x00},
+    {0x02,0x3B,0x00},
+    {0x02,0x3C,0x00},
+    {0x02,0x3D,0x00},
+    {0x02,0x3E,0xC0},
+    {0x02,0x4A,0x00},
+    {0x02,0x4B,0x00},
+    {0x02,0x4C,0x00},
+    {0x02,0x4D,0x00},
+    {0x02,0x4E,0x00},
+    {0x02,0x4F,0x00},
+    {0x02,0x50,0x00},
+    {0x02,0x51,0x00},
+    {0x02,0x52,0x00},
+    {0x02,0x53,0x00},
+    {0x02,0x54,0x00},
+    {0x02,0x55,0x00},
+    {0x02,0x56,0x00},
+    {0x02,0x57,0x00},
+    {0x02,0x58,0x00},
+    {0x02,0x59,0x00},
+    {0x02,0x5A,0x00},
+    {0x02,0x5B,0x00},
+    {0x02,0x5C,0x00},
+    {0x02,0x5D,0x00},
+    {0x02,0x5E,0x00},
+    {0x02,0x5F,0x00},
+    {0x02,0x60,0x00},
+    {0x02,0x61,0x00},
+    {0x02,0x62,0x00},
+    {0x02,0x63,0x00},
+    {0x02,0x64,0x00},
+    {0x02,0x68,0x00},
+    {0x02,0x69,0x00},
+    {0x02,0x6A,0x00},
+    {0x02,0x6B,0x45},
+    {0x02,0x6C,0x50},
+    {0x02,0x6D,0x4F},
+    {0x02,0x6E,0x4E},
+    {0x02,0x6F,0x5F},
+    {0x02,0x70,0x43},
+    {0x02,0x71,0x4C},
+    {0x02,0x72,0x4B},
+    {0x03,0x02,0x00},
+    {0x03,0x03,0x00},
+    {0x03,0x04,0x00},
+    {0x03,0x05,0x00},
+    {0x03,0x06,0x16},
+    {0x03,0x07,0x00},
+    {0x03,0x08,0x00},
+    {0x03,0x09,0x00},
+    {0x03,0x0A,0x00},
+    {0x03,0x0B,0x80},
+    {0x03,0x0D,0x00},
+    {0x03,0x0E,0x00},
+    {0x03,0x0F,0x00},
+    {0x03,0x10,0x00},
+    {0x03,0x11,0x00},
+    {0x03,0x12,0x00},
+    {0x03,0x13,0x00},
+    {0x03,0x14,0x00},
+    {0x03,0x15,0x00},
+    {0x03,0x16,0x00},
+    {0x03,0x18,0x00},
+    {0x03,0x19,0x00},
+    {0x03,0x1A,0x00},
+    {0x03,0x1B,0x00},
+    {0x03,0x1C,0x00},
+    {0x03,0x1D,0x00},
+    {0x03,0x1E,0x00},
+    {0x03,0x1F,0x00},
+    {0x03,0x20,0x00},
+    {0x03,0x21,0x00},
+    {0x03,0x23,0x00},
+    {0x03,0x24,0x00},
+    {0x03,0x25,0x00},
+    {0x03,0x26,0x00},
+    {0x03,0x27,0x00},
+    {0x03,0x28,0x00},
+    {0x03,0x29,0x00},
+    {0x03,0x2A,0x00},
+    {0x03,0x2B,0x00},
+    {0x03,0x2C,0x00},
+    {0x03,0x2E,0x00},
+    {0x03,0x2F,0x00},
+    {0x03,0x30,0x00},
+    {0x03,0x31,0x00},
+    {0x03,0x32,0x00},
+    {0x03,0x33,0x00},
+    {0x03,0x34,0x00},
+    {0x03,0x35,0x00},
+    {0x03,0x36,0x00},
+    {0x03,0x37,0x00},
+    {0x03,0x39,0x1F},
+    {0x03,0x3B,0x00},
+    {0x03,0x3C,0x00},
+    {0x03,0x3D,0x00},
+    {0x03,0x3E,0x00},
+    {0x03,0x3F,0x00},
+    {0x03,0x40,0x00},
+    {0x03,0x41,0x00},
+    {0x03,0x42,0x00},
+    {0x03,0x43,0x00},
+    {0x03,0x44,0x00},
+    {0x03,0x45,0x00},
+    {0x03,0x46,0x00},
+    {0x03,0x47,0x00},
+    {0x03,0x48,0x00},
+    {0x03,0x49,0x00},
+    {0x03,0x4A,0x00},
+    {0x03,0x4B,0x00},
+    {0x03,0x4C,0x00},
+    {0x03,0x4D,0x00},
+    {0x03,0x4E,0x00},
+    {0x03,0x4F,0x00},
+    {0x03,0x50,0x00},
+    {0x03,0x51,0x00},
+    {0x03,0x52,0x00},
+    {0x03,0x53,0x00},
+    {0x03,0x54,0x00},
+    {0x03,0x55,0x00},
+    {0x03,0x56,0x00},
+    {0x03,0x57,0x00},
+    {0x03,0x58,0x00},
+    {0x03,0x59,0x00},
+    {0x03,0x5A,0x00},
+    {0x03,0x5B,0x00},
+    {0x03,0x5C,0x00},
+    {0x03,0x5D,0x00},
+    {0x03,0x5E,0x00},
+    {0x03,0x5F,0x00},
+    {0x03,0x60,0x00},
+    {0x03,0x61,0x00},
+    {0x03,0x62,0x00},
+    {0x04,0x87,0x00},
+    {0x05,0x02,0x01},
+    {0x05,0x08,0x14},
+    {0x05,0x09,0x22},
+    {0x05,0x0A,0x0D},
+    {0x05,0x0B,0x0C},
+    {0x05,0x0C,0x01},
+    {0x05,0x0D,0x3F},
+    {0x05,0x0E,0x15},
+    {0x05,0x0F,0x26},
+    {0x05,0x10,0x0C},
+    {0x05,0x11,0x0B},
+    {0x05,0x12,0x01},
+    {0x05,0x13,0x3F},
+    {0x05,0x15,0x00},
+    {0x05,0x16,0x00},
+    {0x05,0x17,0x00},
+    {0x05,0x18,0x00},
+    {0x05,0x19,0x65},
+    {0x05,0x1A,0x03},
+    {0x05,0x1B,0x00},
+    {0x05,0x1C,0x00},
+    {0x05,0x1D,0x00},
+    {0x05,0x1E,0x00},
+    {0x05,0x1F,0xA0},
+    {0x05,0x21,0x33},
+    {0x05,0x2A,0x01},
+    {0x05,0x2B,0x01},
+    {0x05,0x2C,0x0F},
+    {0x05,0x2D,0x03},
+    {0x05,0x2E,0x19},
+    {0x05,0x2F,0x19},
+    {0x05,0x31,0x00},
+    {0x05,0x32,0x4B},
+    {0x05,0x33,0x03},
+    {0x05,0x34,0x00},
+    {0x05,0x36,0x0C},
+    {0x05,0x37,0x00},
+    {0x05,0x38,0x01},
+    {0x05,0x39,0x00},
+    {0x09,0x0E,0x02},
+    {0x09,0x43,0x01},
+    {0x09,0x49,0x01},
+    {0x09,0x4A,0x01},
+    {0x0A,0x02,0x00},
+    {0x0A,0x03,0x01},
+    {0x0A,0x04,0x01},
+    {0x0A,0x05,0x01},
+    {0x0B,0x44,0x0F},
+    {0x0B,0x46,0x00},
+    {0x0B,0x47,0x00},
+    {0x0B,0x48,0x0E},
+    {0x0B,0x4A,0x1E},
+    {0x05,0x14,0x01},
+    {0x00,0x1C,0x01},
+    {0x0B,0x24,0xDB},
+    {0x0B,0x25,0x02}
+};
+
+static dpll_command gpon_synce_dpll_table[] =
+{
+    {0x0B,0x24,0xD8},
+    {0x0B,0x25,0x00},
+    {0x00,0x0B,0x68},
+    {0x00,0x16,0x02},
+    {0x00,0x17,0x1C},
+    {0x00,0x18,0xCC},
+    {0x00,0x19,0xDD},
+    {0x00,0x1A,0xDF},
+    {0x00,0x2B,0x02},
+    {0x00,0x2C,0x03},
+    {0x00,0x2D,0x05},
+    {0x00,0x2E,0x6E},
+    {0x00,0x2F,0x00},
+    {0x00,0x30,0x37},
+    {0x00,0x31,0x00},
+    {0x00,0x32,0x00},
+    {0x00,0x33,0x00},
+    {0x00,0x34,0x00},
+    {0x00,0x35,0x00},
+    {0x00,0x36,0x6E},
+    {0x00,0x37,0x00},
+    {0x00,0x38,0x37},
+    {0x00,0x39,0x00},
+    {0x00,0x3A,0x00},
+    {0x00,0x3B,0x00},
+    {0x00,0x3C,0x00},
+    {0x00,0x3D,0x00},
+    {0x00,0x3F,0x33},
+    {0x00,0x40,0x04},
+    {0x00,0x41,0x0E},
+    {0x00,0x42,0x0A},
+    {0x00,0x43,0x00},
+    {0x00,0x44,0x00},
+    {0x00,0x45,0x0C},
+    {0x00,0x46,0x32},
+    {0x00,0x47,0x32},
+    {0x00,0x48,0x00},
+    {0x00,0x49,0x00},
+    {0x00,0x4A,0x32},
+    {0x00,0x4B,0x32},
+    {0x00,0x4C,0x00},
+    {0x00,0x4D,0x00},
+    {0x00,0x4E,0x55},
+    {0x00,0x4F,0x00},
+    {0x00,0x51,0x03},
+    {0x00,0x52,0x03},
+    {0x00,0x53,0x00},
+    {0x00,0x54,0x00},
+    {0x00,0x55,0x03},
+    {0x00,0x56,0x03},
+    {0x00,0x57,0x00},
+    {0x00,0x58,0x00},
+    {0x00,0x59,0x0F},
+    {0x00,0x5A,0x55},
+    {0x00,0x5B,0x55},
+    {0x00,0x5C,0xD0},
+    {0x00,0x5D,0x00},
+    {0x00,0x5E,0x55},
+    {0x00,0x5F,0x55},
+    {0x00,0x60,0xD5},
+    {0x00,0x61,0x00},
+    {0x00,0x62,0x00},
+    {0x00,0x63,0x00},
+    {0x00,0x64,0x00},
+    {0x00,0x65,0x00},
+    {0x00,0x66,0x00},
+    {0x00,0x67,0x00},
+    {0x00,0x68,0x00},
+    {0x00,0x69,0x00},
+    {0x00,0x92,0x00},
+    {0x00,0x93,0x00},
+    {0x00,0x95,0x00},
+    {0x00,0x96,0x00},
+    {0x00,0x98,0x00},
+    {0x00,0x9A,0x02},
+    {0x00,0x9B,0x00},
+    {0x00,0x9D,0x00},
+    {0x00,0x9E,0x60},
+    {0x00,0xA0,0x40},
+    {0x00,0xA2,0x02},
+    {0x00,0xA8,0xB7},
+    {0x00,0xA9,0x28},
+    {0x00,0xAA,0x10},
+    {0x00,0xAB,0x00},
+    {0x00,0xAC,0x00},
+    {0x01,0x02,0x01},
+    {0x01,0x08,0x06},
+    {0x01,0x09,0x09},
+    {0x01,0x0A,0x6B},
+    {0x01,0x0B,0x00},
+    {0x01,0x0D,0x01},
+    {0x01,0x0E,0x09},
+    {0x01,0x0F,0x3B},
+    {0x01,0x10,0x00},
+    {0x01,0x12,0x06},
+    {0x01,0x13,0x09},
+    {0x01,0x14,0x6B},
+    {0x01,0x15,0x00},
+    {0x01,0x17,0x01},
+    {0x01,0x18,0x09},
+    {0x01,0x19,0x3B},
+    {0x01,0x1A,0x00},
+    {0x01,0x1C,0x06},
+    {0x01,0x1D,0x09},
+    {0x01,0x1E,0x6B},
+    {0x01,0x1F,0x00},
+    {0x01,0x21,0x01},
+    {0x01,0x22,0x09},
+    {0x01,0x23,0x3B},
+    {0x01,0x24,0x00},
+    {0x01,0x26,0x06},
+    {0x01,0x27,0x09},
+    {0x01,0x28,0x6B},
+    {0x01,0x29,0x00},
+    {0x01,0x2B,0x01},
+    {0x01,0x2C,0x09},
+    {0x01,0x2D,0x3B},
+    {0x01,0x2E,0x00},
+    {0x01,0x30,0x06},
+    {0x01,0x31,0x09},
+    {0x01,0x32,0x6B},
+    {0x01,0x33,0x00},
+    {0x01,0x3A,0x06},
+    {0x01,0x3B,0xCC},
+    {0x01,0x3C,0x00},
+    {0x01,0x3D,0x00},
+    {0x01,0x3F,0x00},
+    {0x01,0x40,0x00},
+    {0x01,0x41,0x40},
+    {0x01,0x42,0xFF},
+    {0x02,0x02,0x00},
+    {0x02,0x03,0x00},
+    {0x02,0x04,0x00},
+    {0x02,0x05,0x00},
+    {0x02,0x06,0x00},
+    {0x02,0x08,0xDB},
+    {0x02,0x09,0x1A},
+    {0x02,0x0A,0x00},
+    {0x02,0x0B,0xC4},
+    {0x02,0x0C,0x09},
+    {0x02,0x0D,0x00},
+    {0x02,0x0E,0x00},
+    {0x02,0x0F,0x00},
+    {0x02,0x10,0x00},
+    {0x02,0x11,0x20},
+    {0x02,0x12,0x37},
+    {0x02,0x13,0x00},
+    {0x02,0x14,0x00},
+    {0x02,0x15,0x14},
+    {0x02,0x16,0x00},
+    {0x02,0x17,0x00},
+    {0x02,0x18,0x00},
+    {0x02,0x19,0x00},
+    {0x02,0x1A,0x00},
+    {0x02,0x1B,0x04},
+    {0x02,0x1C,0x00},
+    {0x02,0x1D,0x00},
+    {0x02,0x1E,0x00},
+    {0x02,0x1F,0x00},
+    {0x02,0x20,0x00},
+    {0x02,0x21,0x00},
+    {0x02,0x22,0x00},
+    {0x02,0x23,0x00},
+    {0x02,0x24,0x00},
+    {0x02,0x25,0x00},
+    {0x02,0x26,0x00},
+    {0x02,0x27,0x00},
+    {0x02,0x28,0x00},
+    {0x02,0x29,0x00},
+    {0x02,0x2A,0x00},
+    {0x02,0x2B,0x00},
+    {0x02,0x2C,0x00},
+    {0x02,0x2D,0x00},
+    {0x02,0x2E,0x00},
+    {0x02,0x2F,0x00},
+    {0x02,0x31,0x11},
+    {0x02,0x32,0x11},
+    {0x02,0x33,0x01},
+    {0x02,0x34,0x01},
+    {0x02,0x35,0x00},
+    {0x02,0x36,0x00},
+    {0x02,0x37,0x00},
+    {0x02,0x38,0xC0},
+    {0x02,0x39,0xDE},
+    {0x02,0x3A,0x00},
+    {0x02,0x3B,0x00},
+    {0x02,0x3C,0x00},
+    {0x02,0x3D,0x00},
+    {0x02,0x3E,0xC8},
+    {0x02,0x4A,0x00},
+    {0x02,0x4B,0x00},
+    {0x02,0x4C,0x00},
+    {0x02,0x4D,0x00},
+    {0x02,0x4E,0x00},
+    {0x02,0x4F,0x00},
+    {0x02,0x50,0x00},
+    {0x02,0x51,0x00},
+    {0x02,0x52,0x00},
+    {0x02,0x53,0x00},
+    {0x02,0x54,0x00},
+    {0x02,0x55,0x00},
+    {0x02,0x56,0x00},
+    {0x02,0x57,0x00},
+    {0x02,0x58,0x00},
+    {0x02,0x59,0x00},
+    {0x02,0x5A,0x00},
+    {0x02,0x5B,0x00},
+    {0x02,0x5C,0x00},
+    {0x02,0x5D,0x00},
+    {0x02,0x5E,0x00},
+    {0x02,0x5F,0x00},
+    {0x02,0x60,0x00},
+    {0x02,0x61,0x00},
+    {0x02,0x62,0x00},
+    {0x02,0x63,0x00},
+    {0x02,0x64,0x00},
+    {0x02,0x68,0x00},
+    {0x02,0x69,0x00},
+    {0x02,0x6A,0x00},
+    {0x02,0x6B,0x47},
+    {0x02,0x6C,0x50},
+    {0x02,0x6D,0x4F},
+    {0x02,0x6E,0x4E},
+    {0x02,0x6F,0x5F},
+    {0x02,0x70,0x43},
+    {0x02,0x71,0x4C},
+    {0x02,0x72,0x4B},
+    {0x03,0x02,0x00},
+    {0x03,0x03,0x00},
+    {0x03,0x04,0x00},
+    {0x03,0x05,0x00},
+    {0x03,0x06,0x16},
+    {0x03,0x07,0x00},
+    {0x03,0x08,0x00},
+    {0x03,0x09,0x00},
+    {0x03,0x0A,0x00},
+    {0x03,0x0B,0x80},
+    {0x03,0x0D,0x00},
+    {0x03,0x0E,0x00},
+    {0x03,0x0F,0x00},
+    {0x03,0x10,0x00},
+    {0x03,0x11,0x00},
+    {0x03,0x12,0x00},
+    {0x03,0x13,0x00},
+    {0x03,0x14,0x00},
+    {0x03,0x15,0x00},
+    {0x03,0x16,0x00},
+    {0x03,0x18,0x00},
+    {0x03,0x19,0x00},
+    {0x03,0x1A,0x00},
+    {0x03,0x1B,0x00},
+    {0x03,0x1C,0x00},
+    {0x03,0x1D,0x00},
+    {0x03,0x1E,0x00},
+    {0x03,0x1F,0x00},
+    {0x03,0x20,0x00},
+    {0x03,0x21,0x00},
+    {0x03,0x23,0x00},
+    {0x03,0x24,0x00},
+    {0x03,0x25,0x00},
+    {0x03,0x26,0x00},
+    {0x03,0x27,0x00},
+    {0x03,0x28,0x00},
+    {0x03,0x29,0x00},
+    {0x03,0x2A,0x00},
+    {0x03,0x2B,0x00},
+    {0x03,0x2C,0x00},
+    {0x03,0x2E,0x00},
+    {0x03,0x2F,0x00},
+    {0x03,0x30,0x00},
+    {0x03,0x31,0x00},
+    {0x03,0x32,0x00},
+    {0x03,0x33,0x00},
+    {0x03,0x34,0x00},
+    {0x03,0x35,0x00},
+    {0x03,0x36,0x00},
+    {0x03,0x37,0x00},
+    {0x03,0x39,0x1F},
+    {0x03,0x3B,0x00},
+    {0x03,0x3C,0x00},
+    {0x03,0x3D,0x00},
+    {0x03,0x3E,0x00},
+    {0x03,0x3F,0x00},
+    {0x03,0x40,0x00},
+    {0x03,0x41,0x00},
+    {0x03,0x42,0x00},
+    {0x03,0x43,0x00},
+    {0x03,0x44,0x00},
+    {0x03,0x45,0x00},
+    {0x03,0x46,0x00},
+    {0x03,0x47,0x00},
+    {0x03,0x48,0x00},
+    {0x03,0x49,0x00},
+    {0x03,0x4A,0x00},
+    {0x03,0x4B,0x00},
+    {0x03,0x4C,0x00},
+    {0x03,0x4D,0x00},
+    {0x03,0x4E,0x00},
+    {0x03,0x4F,0x00},
+    {0x03,0x50,0x00},
+    {0x03,0x51,0x00},
+    {0x03,0x52,0x00},
+    {0x03,0x53,0x00},
+    {0x03,0x54,0x00},
+    {0x03,0x55,0x00},
+    {0x03,0x56,0x00},
+    {0x03,0x57,0x00},
+    {0x03,0x58,0x00},
+    {0x03,0x59,0x00},
+    {0x03,0x5A,0x00},
+    {0x03,0x5B,0x00},
+    {0x03,0x5C,0x00},
+    {0x03,0x5D,0x00},
+    {0x03,0x5E,0x00},
+    {0x03,0x5F,0x00},
+    {0x03,0x60,0x00},
+    {0x03,0x61,0x00},
+    {0x03,0x62,0x00},
+    {0x04,0x87,0x00},
+    {0x05,0x02,0x01},
+    {0x05,0x08,0x14},
+    {0x05,0x09,0x22},
+    {0x05,0x0A,0x0D},
+    {0x05,0x0B,0x0C},
+    {0x05,0x0C,0x01},
+    {0x05,0x0D,0x3F},
+    {0x05,0x0E,0x15},
+    {0x05,0x0F,0x26},
+    {0x05,0x10,0x0C},
+    {0x05,0x11,0x0B},
+    {0x05,0x12,0x01},
+    {0x05,0x13,0x3F},
+    {0x05,0x15,0x00},
+    {0x05,0x16,0xB8},
+    {0x05,0x17,0xC1},
+    {0x05,0x18,0x49},
+    {0x05,0x19,0xAC},
+    {0x05,0x1A,0x02},
+    {0x05,0x1B,0x00},
+    {0x05,0x1C,0x00},
+    {0x05,0x1D,0x00},
+    {0x05,0x1E,0x00},
+    {0x05,0x1F,0x80},
+    {0x05,0x21,0x31},
+    {0x05,0x2A,0x00},
+    {0x05,0x2B,0x01},
+    {0x05,0x2C,0x0F},
+    {0x05,0x2D,0x03},
+    {0x05,0x2E,0x19},
+    {0x05,0x2F,0x19},
+    {0x05,0x31,0x00},
+    {0x05,0x32,0x42},
+    {0x05,0x33,0x03},
+    {0x05,0x34,0x00},
+    {0x05,0x36,0x0C},
+    {0x05,0x37,0x00},
+    {0x05,0x38,0x21},
+    {0x05,0x39,0x00},
+    {0x09,0x0E,0x02},
+    {0x09,0x43,0x01},
+    {0x09,0x49,0x03},
+    {0x09,0x4A,0x03},
+    {0x0A,0x02,0x00},
+    {0x0A,0x03,0x01},
+    {0x0A,0x04,0x01},
+    {0x0A,0x05,0x01},
+    {0x0B,0x44,0x0C},
+    {0x0B,0x46,0x00},
+    {0x0B,0x47,0x00},
+    {0x0B,0x48,0x0C},
+    {0x0B,0x4A,0x1E},
+    {0x05,0x14,0x01},
+    {0x00,0x1C,0x01},
+    {0x0B,0x24,0xDB},
+    {0x0B,0x25,0x02}
+}; 
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/fs/i2c_addrs.sh b/bcm68620_release/release/host_customized/board/wrx/fs/i2c_addrs.sh
new file mode 100755
index 0000000..643fd4c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/fs/i2c_addrs.sh
@@ -0,0 +1,4 @@
+#! /bin/bash
+
+# Body will be inserted here by copy_host_fs target in project's main Makefile
+
diff --git a/bcm68620_release/release/host_customized/board/wrx/fs/svk_init.sh b/bcm68620_release/release/host_customized/board/wrx/fs/svk_init.sh
new file mode 100755
index 0000000..c1eece0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/board/wrx/fs/svk_init.sh
@@ -0,0 +1,156 @@
+#! /bin/bash
+cd /opt/bcm68620
+
+# These files are mounted using tmpfs, so they will be deleted upon reboot
+LOCK_DIR_INIT=/tmp/bcm68620_svk_init
+FILE_INIT_DONE="$LOCK_DIR_INIT/done"
+LOCK_DIR_KERNEL_LOG_OWNED=/tmp/bcm68620_kernel_log_owned
+
+USER_APPL_ARGS=""
+KT2_PORT=""
+SWKT2_PORT=""
+KERNEL_LOG="y"
+COOP_DBA="n"
+
+while (($#)); do
+    case "$1" in
+    --kt2)
+        shift
+        KT2_PORT="$1"
+        ;;
+    --swkt2)
+        shift
+        SWKT2_PORT="$1"
+        ;;
+    --proxy) # for backward compatibility (could just use '-proxy')
+        shift
+        USER_APPL_ARGS="$USER_APPL_ARGS -proxy $1"
+        ;;
+    -nl)
+        KERNEL_LOG="n"
+        USER_APPL_ARGS="$USER_APPL_ARGS $1"
+        ;;
+    -coop_dba)
+        COOP_DBA="y"
+        ;;
+    *)
+        USER_APPL_ARGS="$USER_APPL_ARGS $1"
+        ;;
+    esac
+    shift
+done
+
+# Check if the initialization steps (installing kernel modules, etc) have already been done.
+# If not, start the initialization process.
+if mkdir "$LOCK_DIR_INIT" 2>/dev/null; then
+    trap "rmdir \"$LOCK_DIR_INIT\"" EXIT
+    echo "Initializing BCM68620 SVK..."
+
+    insmod ll_pcie.ko
+    sleep 1
+
+    insmod os_linux.ko
+    sleep 1
+
+    source ./i2c_addrs.sh
+    insmod i2c_devs.ko
+    sleep 1
+
+    function probe_dev
+    {
+        2>/dev/null echo maple_i2c 0x$1 > /sys/bus/i2c/devices/i2c-0/new_device
+    }
+
+    # Suppress error warnings in case device cannot be probed because it is inexistent.
+    dmesg -n 1
+    probe_dev $I2C_SW0_I2C_ADDR
+    probe_dev $I2C_SW1_I2C_ADDR
+    probe_dev $I2C_SW2_I2C_ADDR
+    probe_dev $I2C_SW3_I2C_ADDR
+    probe_dev $I2C_SW4_I2C_ADDR
+    probe_dev $SFP_I2C_ADDR1
+    probe_dev $SFP_I2C_ADDR2
+    probe_dev $FPGA_I2C_ADDR
+    probe_dev $PON_DPLL_I2C_ADDR
+    probe_dev $PM_DPLL_I2C_ADDR
+    probe_dev $CXP_T_I2C_ADDR
+    probe_dev $CXP_R_I2C_ADDR
+    probe_dev $PCIE_SW_I2C_ADDR
+    dmesg -n 8
+
+    rm -f /dev/maple_i2c
+    mknod /dev/maple_i2c c `cat /sys/module/i2c_devs/parameters/maple_i2c_chrdev_major` 0
+
+    if [ "$KT2_PORT" != "" ]; then
+        echo k 1 > /proc/maple_i2c/i2c
+        insmod linux-kernel-bde.ko
+        sleep 1
+        cat /proc/linux-kernel-bde
+        sleep 1
+        insmod linux-uk-proxy.ko
+        sleep 1
+        mknod /dev/linux-uk-proxy c 125 0
+        sleep 1
+        insmod linux-bcm-diag-full.ko
+        sleep 1
+        echo "KT2 will wait on port $KT2_PORT"
+        ./bcm.user.proxy -d $KT2_PORT &
+    fi
+
+    if [ "$SWKT2_PORT" != "" ]; then
+        echo "SW KT2 init"
+        insmod linux-kernel-bde.ko
+        sleep 1
+        cat /proc/linux-kernel-bde
+        sleep 1
+        insmod linux-uk-proxy.ko
+        sleep 1
+        mknod /dev/linux-uk-proxy c 125 0
+        sleep 1
+        insmod linux-bcm-diag-full.ko
+        sleep 1
+        echo "KT2 will wait on port $SWKT2_PORT"
+        ./bcm.user.proxy -d $SWKT2_PORT &
+    fi
+
+    insmod bcm_dev_ctrl_linux.ko
+    sleep 1
+    
+    if [ "$COOP_DBA" != "n" ]; then
+        insmod coop_dba_linux.ko
+        sleep 1
+    fi
+    
+    rm -f /dev/bcm_log
+    mknod /dev/bcm_log c `cat /sys/module/bcm_dev_ctrl_linux/parameters/dev_log_chrdev_major` 0
+    mknod /dev/maple_dev_ctrl c `cat /sys/module/bcm_dev_ctrl_linux/parameters/maple_dev_ctrl_chrdev_major` 0
+
+    touch "$FILE_INIT_DONE"
+    trap - EXIT
+else
+    if [ -f "$FILE_INIT_DONE" ]; then
+        echo "Skipped BCM68620 SVK initialization since it has already been done"
+    else
+        echo "Waiting for SVK initialization to complete..."
+        while [ ! -f "$FILE_INIT_DONE" ]; do
+            sleep 1
+        done
+    fi
+fi
+
+# Only one application can have the kernel logger enabled at once.
+# If someone else already owns the kernel logger, run without it.
+if [ "$KERNEL_LOG" == "y" ]; then
+    if mkdir "$LOCK_DIR_KERNEL_LOG_OWNED" 2>/dev/null; then
+        trap "rmdir \"$LOCK_DIR_KERNEL_LOG_OWNED\"" EXIT
+    else
+        USER_APPL_ARGS="$USER_APPL_ARGS -nl"
+        echo "Running without kernel logger since someone else owns it"
+    fi
+fi
+
+#echo "In Band: Launching BCM68620 user space device control application "
+#./bcm_dev_ctrl_user > /dev/null 2>&1 &
+
+echo "Launching BCM68620 user application with options \"$USER_APPL_ARGS\""
+./bcm_user_appl $USER_APPL_ARGS
diff --git a/bcm68620_release/release/host_customized/coop_dba_linux/Makefile b/bcm68620_release/release/host_customized/coop_dba_linux/Makefile
new file mode 100644
index 0000000..9e2043e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/coop_dba_linux/Makefile
@@ -0,0 +1,38 @@
+# Cooperative DBA
+
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = coop_dba_linux
+MOD_TYPE = linux_module
+MOD_DEPS = coop_dba
+
+srcs = bcmolt_coop_dba_linux.c
+
+MOD_INC_DIRS = $(SRC_DIR) $(MODEL_OUT_DIR)
+
+# 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
+    ifeq ("$(RELEASE_BUILD)", "y")
+	    KBUILD_EXTRA_SYMBOLS += $(TOP_DIR)/host_driver/dev_ctrl/linux/Module.symvers
+    	EXTRA_CFLAGS += -I$(TOP_DIR)/host_driver/common_gpon \
+-I$(TOP_DIR)/host_driver/transport/pcie_sw_queue \
+-I$(TOP_DIR)/host_driver/pcie \
+-I$(TOP_DIR)/host_driver/api \
+-I$(TOP_DIR)/host_driver/utils \
+-I$(TOP_DIR)/host_reference/dev_log \
+-I$(TOP_DIR)/host_driver/transport/mux 
+    else
+	    KBUILD_EXTRA_SYMBOLS += $(TOP_DIR)/host/dev_ctrl/linux/Module.symvers
+	    EXTRA_CFLAGS += -I$(TOP_DIR)/common/gpon \
+-I$(TOP_DIR)/common/model/maple \
+-I$(TOP_DIR)/common/transport/driver/maple/pcie_sw_queue \
+-I$(TOP_DIR)/common/drivers/maple/pcie \
+-I$(TOP_DIR)/common/api \
+-I$(TOP_DIR)/common/utils \
+-I$(TOP_DIR)/common/dev_log \
+-I$(TOP_DIR)/host/transport/driver/maple/mux
+    endif
+endif
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/coop_dba_linux/bcmolt_coop_dba_linux.c b/bcm68620_release/release/host_customized/coop_dba_linux/bcmolt_coop_dba_linux.c
new file mode 100644
index 0000000..70fc52c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/coop_dba_linux/bcmolt_coop_dba_linux.c
@@ -0,0 +1,81 @@
+/*
+<: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 "bcmolt_coop_dba.h"
+
+module_param(bcmos_sys_trace_level, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(bcmos_sys_trace_level, "trace_level");
+
+static void bcmolt_coop_dba_unregister_registered_devices(bcmolt_devid max_devid, bcmtrmux_channel channel)
+{
+	bcmolt_devid devid;
+
+	for (devid = 0; devid < max_devid; devid++)
+	{
+		bcmolt_coop_dba_exit(devid, channel);
+	}
+}
+static void bcmolt_coop_dba_module_exit(void)
+{
+	bcmolt_coop_dba_unregister_registered_devices(BCMTR_MAX_OLTS, URGENT_CHANNEL);
+
+    printk("%s\n", __FUNCTION__);
+}
+
+static int bcmolt_coop_dba_module_init(void)
+{
+    bcmos_errno rc;
+    bcmolt_devid devid;
+    bcmtrmux_channel channel = URGENT_CHANNEL;
+
+    printk("%s\n", __FUNCTION__);
+
+#if 0
+    bcmos_trace_level_set(BCMOS_TRACE_LEVEL_DEBUG);
+#endif
+
+	for (devid = 0; devid < BCMTR_MAX_OLTS; devid++)
+	{
+		rc = bcmolt_coop_dba_init(devid, &channel, bcmolt_coop_dba_rx, NULL);
+		if (rc != BCM_ERR_OK)
+		{
+			printk("error in bcmolt_coop_dba_init rc=%d\n", rc);
+			bcmolt_coop_dba_unregister_registered_devices(devid, channel);
+			break;
+		}
+	}
+
+    return rc ? -EINVAL : 0;
+}
+
+module_init(bcmolt_coop_dba_module_init);
+module_exit(bcmolt_coop_dba_module_exit);
+
+MODULE_DESCRIPTION("Cooperative DBA");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/bcm68620_release/release/host_customized/dev_ctrl_linux/Makefile b/bcm68620_release/release/host_customized/dev_ctrl_linux/Makefile
new file mode 100644
index 0000000..39a56ff
--- /dev/null
+++ b/bcm68620_release/release/host_customized/dev_ctrl_linux/Makefile
@@ -0,0 +1,17 @@
+# device_control Linux wrapper
+
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = bcm_dev_ctrl_linux
+MOD_TYPE = linux_module
+MOD_DEPS = dev_ctrl nltr dev_log_kernel user_config host_api_linux api_linux pcie pcie_mod
+
+srcs = bcmolt_dev_ctrl_linux.c
+
+# 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/dev_ctrl_linux/bcmolt_dev_ctrl_ioctl.h b/bcm68620_release/release/host_customized/dev_ctrl_linux/bcmolt_dev_ctrl_ioctl.h
new file mode 100755
index 0000000..037c467
--- /dev/null
+++ b/bcm68620_release/release/host_customized/dev_ctrl_linux/bcmolt_dev_ctrl_ioctl.h
@@ -0,0 +1,30 @@
+/*
+ * bcmolt_dev_ctrl_ioctl.h
+ *
+ *  Created on: 7 ???? 2015
+ *      Author: milya
+ */
+
+#ifndef HOST_DEV_CTRL_LINUX_BCMOLT_DEV_CTRL_IOCTL_H_
+#define HOST_DEV_CTRL_LINUX_BCMOLT_DEV_CTRL_IOCTL_H_
+
+
+#include <linux/ioctl.h>
+
+typedef struct
+{
+    uint32_t *dumpptr;
+    int32_t start_index;
+    int32_t howmany;
+    uint8_t device;
+    uint32_t event; /* For MAPLE_DEV_CTRL_IOCTL_OP_HOST_EVENT_WRITE only */
+} dev_ctrl_ioctl_param;
+
+#define MAPLE_DEV_CTRL_IOCTL_MAGIC 'J'
+
+#define MAPLE_DEV_CTRL_IOCTL_OP_PCI_STAT    _IOW(MAPLE_DEV_CTRL_IOCTL_MAGIC, 1, dev_ctrl_ioctl_param)
+#define MAPLE_DEV_CTRL_IOCTL_OP_PCI_DUMP_TX _IOW(MAPLE_DEV_CTRL_IOCTL_MAGIC, 2, dev_ctrl_ioctl_param)
+#define MAPLE_DEV_CTRL_IOCTL_OP_PCI_DUMP_RX _IOWR(MAPLE_DEV_CTRL_IOCTL_MAGIC, 3, dev_ctrl_ioctl_param)
+#define MAPLE_DEV_CTRL_IOCTL_OP_HOST_EVENT_WRITE _IOW(MAPLE_DEV_CTRL_IOCTL_MAGIC, 4, dev_ctrl_ioctl_param)
+
+#endif /* HOST_DEV_CTRL_LINUX_BCMOLT_DEV_CTRL_IOCTL_H_ */
diff --git a/bcm68620_release/release/host_customized/dev_ctrl_linux/bcmolt_dev_ctrl_linux.c b/bcm68620_release/release/host_customized/dev_ctrl_linux/bcmolt_dev_ctrl_linux.c
new file mode 100644
index 0000000..5f48de4
--- /dev/null
+++ b/bcm68620_release/release/host_customized/dev_ctrl_linux/bcmolt_dev_ctrl_linux.c
@@ -0,0 +1,370 @@
+#include <linux/proc_fs.h>
+#include <bcmolt_tr_nl_driver.h>
+#include <bcmolt_dev_log_kernel.h>
+#include <bcm_dev_log.h>
+#include <bcmolt_dev_ctrl.h>
+#include <bcmolt_tr_mux.h>
+#include <bcmos_system.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h> /*copy_from_user*/
+#include <linux/proc_fs.h>
+#include <bcmolt_dev_ctrl_ioctl.h>
+#include <bcmolt_user_utils.h>
+#include <bcmolt_host_api.h>
+#include <bcmolt_fld.h>
+#include <bcmtr_pcie.h>
+
+module_param(bcmos_sys_trace_level, uint, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+MODULE_PARM_DESC(bcmos_sys_trace_level, "trace_level");
+
+
+int maple_dev_ctrl_chrdev_major = 237;
+module_param(maple_dev_ctrl_chrdev_major, int, S_IRUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(maple_dev_ctrl_chrdev_major, "maple_dev_ctrl_major");
+static char is_chrdev_reg;
+static char is_cdev_add;
+
+extern struct proc_dir_entry *bcmolt_dir;
+
+bcmos_errno bcmtr_init(void)
+{
+    return BCM_ERR_OK;
+}
+
+/* /proc/bcmolt/trmux read operation */
+static int trmux_stats_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    static bcmtrmux_stat prev_stat;
+    int len;
+    bcmtrmux_stat stat;
+    bcmos_errno rc;
+    bcmolt_devid *device_id = data;
+
+    rc = bcmtrmux_stat_get(*device_id, &stat);
+    if (rc)
+    {
+        len = snprintf(page, count, "Can't read trmux statistics rc=%s\n", bcmos_strerror(rc));
+        return len;
+    }
+
+    len = snprintf(page, count, "trmux statistics\n\n");
+    len += sprintf(page + len, "tx_remote      : %u\n", stat.tx_remote - prev_stat.tx_remote);
+    len += sprintf(page + len, "tx_local       : %u\n", stat.tx_local - prev_stat.tx_local);
+    len += sprintf(page + len, "tx_disc_remote : %u\n", stat.tx_disc_remote - prev_stat.tx_disc_remote);
+    len += sprintf(page + len, "tx_disc_local  : %u\n", stat.tx_disc_local - prev_stat.tx_disc_local);
+    len += sprintf(page + len, "rx_remote      : %u\n", stat.rx_remote - prev_stat.rx_remote);
+    len += sprintf(page + len, "rx_local       : %u\n", stat.rx_local - prev_stat.rx_local);
+    len += sprintf(page + len, "rx_auto        : %u\n", stat.rx_auto - prev_stat.rx_auto);
+    len += sprintf(page + len, "rx_disc_remote : %u\n", stat.rx_disc_remote - prev_stat.rx_disc_remote);
+    len += sprintf(page + len, "rx_disc_local  : %u\n", stat.rx_disc_local - prev_stat.rx_disc_local);
+    len += sprintf(page + len, "rx_disc_auto   : %u\n", stat.rx_disc_auto - prev_stat.rx_disc_auto);
+    len += sprintf(page + len, "ctl_to_host    : %u\n", stat.control_to_host - prev_stat.control_to_host);
+    len += sprintf(page + len, "ctl_to_line    : %u\n", stat.control_to_line - prev_stat.control_to_line);
+    len += sprintf(page + len, "rx_disc_inv_ch : %u\n", stat.rx_disc_inv_ch - prev_stat.rx_disc_inv_ch);
+    len += sprintf(page + len, "rx_poll_urgent : %u\n", stat.rx_poll_urgent - prev_stat.rx_poll_urgent);
+    len += sprintf(page + len, "rx_poll_normal : %u\n", stat.rx_poll_normal - prev_stat.rx_poll_normal);
+    prev_stat = stat;
+
+    return len;
+}
+
+/* /proc/bcmolt/devctrl read operation */
+static int devctrl_debug_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    int len;
+    dev_ctrl_database db;
+    bcmolt_devid *device_id = data;
+
+    dev_ctrl_read_db(*device_id, &db);
+
+    /* db contains the entire copy of dev_ctrl_database. add whatever you want to print. */
+    len = snprintf(page, count, "dev_ctrl debug information\n\n");
+    len += sprintf(page + len, "task name                 : %s\n", db.task_info.name);
+    len += sprintf(page + len, "module name               : %s\n", db.module_info.name);
+    len += sprintf(page + len, "connection state          : %s\n",
+        bcm_str_host_connecting_state(db.connection_info.state));
+    len += sprintf(page + len, "tod                       : %s\n",
+        (db.enable_tod == BCMOLT_CONTROL_STATE_DISABLE) ? "DISABLE" : "ENABLE");
+    len += sprintf(page + len, "last event                : %s\n", bcm_str_device_event(db.last_event));
+    if (db.conn_fail_reason < BCMOLT_HOST_CONNECTION_FAIL_REASON__NUM_OF)
+        len += sprintf(page + len, "connection failure reason : %s\n",
+            bcm_str_host_connection_fail_reason(db.conn_fail_reason));
+    return len;
+}
+
+#ifdef ENABLE_LOG
+static bcmos_errno dev_ctrl_logger_init_cb(void)
+{
+    bcmos_errno rc;
+
+    /* Create kernel logger */
+    rc = bcm_dev_log_linux_init();
+    BUG_ON(rc);
+
+    /* For now just map BCMOS_TRACE_XX to dev_log. Later on dev_control
+     * can define its own log ids
+     */
+    rc = bcm_dev_log_os_trace_init();
+    BUG_ON(rc);
+
+    return rc;
+}
+#endif
+
+static struct cdev maple_dev_ctrl_chrdev_cdev;
+static int maple_dev_ctrl_chrdev_open(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static int maple_dev_ctrl_chrdev_release(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static long maple_dev_ctrl_chrdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    bcmos_errno bcmrc;
+    int linux_rc = 0;
+    int rc = 0;
+    dev_ctrl_ioctl_param params;
+
+    /* don't even decode wrong cmds: better returning  ENOTTY than EFAULT */
+    if (_IOC_TYPE(cmd) != MAPLE_DEV_CTRL_IOCTL_MAGIC)
+        return -ENOTTY;
+
+    rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+    if (rc < 0)
+        return rc;
+
+    switch (cmd)
+    {
+    case MAPLE_DEV_CTRL_IOCTL_OP_PCI_STAT:
+        {
+            bcm_pcied_stat stat;
+
+            memset(params.dumpptr, 0, sizeof(bcm_pcied_stat));
+            bcmrc = bcmtr_pcie_get_statistics(params.device, params.start_index, &stat);
+            if (bcmrc == BCM_ERR_OK)
+                memcpy(params.dumpptr, &stat, sizeof(bcm_pcied_stat));
+            else
+                linux_rc = (int)bcmrc;
+        }
+        break;
+    case MAPLE_DEV_CTRL_IOCTL_OP_PCI_DUMP_TX:
+        linux_rc = (int)bcmtr_pcie_tx_dump((char *)params.dumpptr, params.device, params.start_index, params.howmany);
+        break;
+    case MAPLE_DEV_CTRL_IOCTL_OP_PCI_DUMP_RX:
+        linux_rc = (int)bcmtr_pcie_rx_dump((char *)params.dumpptr, params.device, params.start_index, params.howmany);
+        break;
+    case MAPLE_DEV_CTRL_IOCTL_OP_HOST_EVENT_WRITE:
+        linux_rc = (int)bcmolt_dev_ctrl_host_event_write(params.device, params.event);
+        break;
+    default:
+        rc = -ENOTTY;
+        break;
+    }
+
+    return linux_rc;
+}
+static ssize_t maple_dev_ctrl_chrdev_write(struct file *filp, const char __user *buf,
+    size_t count, loff_t *f_pos)
+{
+    return 0;
+}
+
+static struct file_operations maple_dev_ctrl_chrdev_fops =
+{
+    .owner = THIS_MODULE,
+    .open = maple_dev_ctrl_chrdev_open,
+    .release = maple_dev_ctrl_chrdev_release,
+    .write = maple_dev_ctrl_chrdev_write,
+    .unlocked_ioctl = maple_dev_ctrl_chrdev_ioctl
+};
+
+static int maple_dev_ctrl_dev_create_chrdev(void)
+{
+    dev_t dev = MKDEV(maple_dev_ctrl_chrdev_major, 0);
+    int linux_rc;
+    is_chrdev_reg = 0;
+    is_cdev_add = 0;
+    /*
+     * Register your major, and accept a dynamic number.
+     */
+    if (!maple_dev_ctrl_chrdev_major)
+        return -1;
+    linux_rc = register_chrdev_region(dev, 0, "maple_dev_ctrl");
+    if (linux_rc < 0)
+    {
+        printk("register_chrdev_region()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_chrdev_reg = 1;
+
+    cdev_init(&maple_dev_ctrl_chrdev_cdev, &maple_dev_ctrl_chrdev_fops);
+    linux_rc = cdev_add(&maple_dev_ctrl_chrdev_cdev, dev, 1);
+    if (linux_rc < 0)
+    {
+        printk("cdev_add()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_cdev_add = 1;
+    return 0;
+}
+
+
+#define BCMOLT_PROCFS_NAME_LEN  4       /* device_id is 1-byte, which can be 3 digit in decimal. */
+#define PROC_TRMUX_NAME         "trmux"
+#define PROC_DEVCTRL_NAME       "devctrl"
+#define PROC_ENTRY_MODE         (S_IFREG | S_IWUSR | S_IRUGO)
+
+typedef struct
+{
+    bcmolt_devid device_id;
+    char name[BCMOLT_PROCFS_NAME_LEN];
+} bcmolt_proc_ctx_t;
+
+static bcmolt_proc_ctx_t bcmolt_proc_ctx[BCMTR_MAX_OLTS];
+static bcmos_bool bcmdev_bcmolt_proc_initialized;
+struct proc_dir_entry *trmux_dir = NULL;
+struct proc_dir_entry *devctrl_dir = NULL;
+
+static void bcmdev_bcmolt_proc_init(void)
+{
+    bcmolt_devid devid;
+    if (!bcmdev_bcmolt_proc_initialized)
+    {
+        for (devid = 0; devid < BCMTR_MAX_OLTS; devid++)
+        {
+            bcmolt_proc_ctx[devid].device_id = devid;
+            sprintf(bcmolt_proc_ctx[devid].name, "%d", devid);
+        }
+        bcmdev_bcmolt_proc_initialized = BCMOS_TRUE;
+    }
+}
+
+static void bcmdev_module_exit(void)
+{
+    int devid;
+
+    if (trmux_dir)
+    {
+        for (devid = 0; devid < BCMTR_MAX_OLTS; devid++)
+        {
+            remove_proc_entry(bcmolt_proc_ctx[devid].name, trmux_dir);
+        }
+        remove_proc_entry(PROC_TRMUX_NAME, bcmolt_dir);
+    }
+    if (devctrl_dir)
+    {
+        for (devid = 0; devid < BCMTR_MAX_OLTS; devid++)
+        {
+            remove_proc_entry(bcmolt_proc_ctx[devid].name, devctrl_dir);
+        }
+        remove_proc_entry(PROC_DEVCTRL_NAME, bcmolt_dir);
+    }
+
+    bcmolt_dev_ctrl_exit();
+    bcmtr_nl_exit();
+    if (is_cdev_add)
+       cdev_del(&maple_dev_ctrl_chrdev_cdev);
+    if (is_chrdev_reg)
+       unregister_chrdev_region(MKDEV(maple_dev_ctrl_chrdev_major, 0), 1);
+#if defined(ENABLE_LOG)
+    bcm_dev_log_linux_exit();
+    bcm_dev_log_destroy();
+#endif
+    printk("%s\n", __FUNCTION__);
+}
+
+static int bcmdev_module_init(void)
+{
+    bcmos_errno rc;
+    struct proc_dir_entry *trmux_file;
+    struct proc_dir_entry *devctrl_file;
+    bcmolt_devid devid;
+    bcmolt_host_init_params params =
+    {
+#ifdef ENABLE_LOG
+        .logger_init_cb = dev_ctrl_logger_init_cb,
+#endif
+        .dev_ctrl_params =
+        {
+            .image_read_cb = bcmuser_image_read,
+            .system_mode_validate_cb = bcmuser_system_mode_validate,
+            .device_off_cb = bcmuser_device_off,
+            .device_on_cb = bcmuser_device_on,
+            .device_is_running_cb = bcmuser_device_is_running,
+            .host_reset_cb = bcmuser_host_reset,
+            .pcie_channel_prepare_cb = bcmuser_pcie_channel_prepare,
+            .pcie_channel_remove_cb = bcmuser_pcie_channel_remove,
+        }
+    };
+
+    if (!is_cdev_add)
+    {
+        if (maple_dev_ctrl_dev_create_chrdev() < 0)
+            printk("%s error to create dev ctrl cdev \n", __FUNCTION__);
+    }
+
+    printk("%s\n", __FUNCTION__);
+
+    rc = bcmolt_host_init(&params);
+    BUG_ON(rc);
+
+    bcmos_trace_level_set(BCMOS_TRACE_LEVEL_DEBUG);
+
+    bcmdev_bcmolt_proc_init();
+
+    rc = bcmtr_nl_init();
+    BUG_ON(rc);
+
+    rc = bcmuser_pcie_prepare();
+
+    if (rc == BCM_ERR_OK)
+    {
+        if ((trmux_dir = create_proc_entry(PROC_TRMUX_NAME, S_IFDIR, bcmolt_dir)) == NULL)
+        {
+            printk("Unable to create /proc/bcmolt/trmux directory\n");
+            return -1;
+        }
+
+        if ((devctrl_dir = create_proc_entry(PROC_DEVCTRL_NAME, S_IFDIR, bcmolt_dir)) == NULL)
+        {
+            printk("Unable to create /proc/bcmolt/devctrl directory\n");
+            return -1;
+        }
+
+        for (devid = 0; devid < BCMTR_MAX_OLTS; devid++)
+        {
+            if ((trmux_file = create_proc_entry(bcmolt_proc_ctx[devid].name, PROC_ENTRY_MODE, trmux_dir)) == NULL)
+            {
+                printk("Unable to create /proc/bcmolt/%s/%s\n", PROC_TRMUX_NAME, bcmolt_proc_ctx[devid].name);
+                return -1;
+            }
+            trmux_file->read_proc = (read_proc_t *)trmux_stats_read;
+            trmux_file->data = &bcmolt_proc_ctx[devid].device_id;
+
+            if ((devctrl_file = create_proc_entry(bcmolt_proc_ctx[devid].name, PROC_ENTRY_MODE, devctrl_dir)) == NULL)
+            {
+                printk("Unable to create /proc/bcmolt/%s/%s\n", PROC_DEVCTRL_NAME, bcmolt_proc_ctx[devid].name);
+                return -1;
+            }
+            devctrl_file->read_proc = (read_proc_t *)devctrl_debug_read;
+            devctrl_file->data = &bcmolt_proc_ctx[devid].device_id;
+        }
+    }
+    else
+    {
+    	bcmos_usleep(2000000);
+    	bcmdev_module_exit();
+    }
+
+    return rc ? -EINVAL : 0;
+}
+
+module_init(bcmdev_module_init);
+module_exit(bcmdev_module_exit);
+
+MODULE_DESCRIPTION("device_control");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/bcm68620_release/release/host_customized/embedded_cli/Makefile b/bcm68620_release/release/host_customized/embedded_cli/Makefile
new file mode 100644
index 0000000..3867ac3
--- /dev/null
+++ b/bcm68620_release/release/host_customized/embedded_cli/Makefile
@@ -0,0 +1,13 @@
+# Host API
+#
+ifeq ("$(ENABLE_CLI)", "y")
+    MOD_NAME = embedded_cli
+    MOD_TYPE = lib
+    MOD_DEPS = transport model cli
+ifeq ("$(RELEASE_BUILD)", "y")
+    MOD_DEPS += common_api
+else
+    MOD_DEPS += api
+endif
+    srcs = bcmolt_embedded_cli.c
+endif
diff --git a/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.c b/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.c
new file mode 100644
index 0000000..0c5a8f7
--- /dev/null
+++ b/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.c
@@ -0,0 +1,268 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcm_embedded_cli.c - embedded CLI access from the host
+ */
+
+#include <bcmos_system.h>
+#include <bcmolt_embedded_cli.h>
+#include <bcmolt_model_types.h>
+#include <bcmolt_api.h>
+#include <bcmtr_interface.h>
+#include <bcmcli.h>
+
+#define EMBEDDED_CLI_BUFFER_SIZE        2048
+#define EMBEDDED_CLI_TIMER_DELAY_US     100000
+
+/* Embedded CLI client context */
+typedef struct
+{
+    bcmolt_devid device;
+    bcmos_task task;
+    bcmos_timer timer;
+    bcmcli_session *session;
+    uint8_t inbuf[EMBEDDED_CLI_BUFFER_SIZE];
+    uint32_t inbuf_length;
+} embedded_cli_context;
+
+static embedded_cli_context *cli_context;
+
+static bcmos_timer_rc embedded_cli_timer_handler(bcmos_timer *timer, long data)
+{
+    /* FFU: this timer is for future line editing support */
+    return BCMOS_TIMER_OK;
+}
+
+static void embedded_cli_output_msg_handler(bcmolt_devid olt, bcmolt_msg *msg)
+{
+    bcmolt_debug_cli_input *cli_msg = (bcmolt_debug_cli_input *)msg;
+
+    if (cli_context && cli_msg->data.data.val)
+    {
+        /* print directly because output can contain ESC sequences */
+        uint8_t *val = cli_msg->data.data.val;
+        while (*val)
+        {
+            bcmos_putchar(*(val++));
+        }
+    }
+    bcmolt_msg_free(msg);
+}
+
+static void embedded_cli_send_input(embedded_cli_context *context)
+{
+    bcmolt_debug_key key = {};
+    bcmolt_debug_cli_input msg;
+    bcmolt_u8_list_u32 data = { context->inbuf_length, context->inbuf };
+
+    if (!context->inbuf_length)
+    {
+        return;
+    }
+    BCMOLT_OPER_INIT(&msg, debug, cli_input, key);
+    BCMOLT_OPER_PROP_SET(&msg, debug, cli_input, data, data);
+    bcmolt_oper_submit(context->device, &msg.hdr);
+    context->inbuf_length = 0;
+}
+
+/* Initialize embedded CLI module */
+bcmos_errno bcm_embedded_cli_enter(bcmcli_session *session, bcmolt_devid device)
+{
+    static char *embedded_cli_task_name = "embedded_cli";
+    bcmos_task_parm taskp =
+    {
+        .name = embedded_cli_task_name,
+        .priority = TASK_PRIORITY_CLI,
+        .data = device
+    };
+    bcmos_module_parm modulep = {};
+    bcmos_timer_parm timerp =
+    {
+        .owner = BCMOS_MODULE_ID_CLI_OVER_PCIE,
+        .handler = embedded_cli_timer_handler,
+        .data = device
+    };
+    bcmtr_handler_parm msgp =
+    {
+        .object = BCMOLT_OBJ_ID_DEBUG,
+        .group = BCMOLT_MGT_GROUP_AUTO,
+        .subgroup = BCMOLT_DEBUG_AUTO_ID_CLI_OUTPUT,
+        .module = BCMOS_MODULE_ID_CLI_OVER_PCIE,
+        .app_cb = embedded_cli_output_msg_handler,
+        .flags = BCMOLT_AUTO_FLAGS_DISPATCH
+    };
+    bcmtr_handler_parm old_msgp =
+    {
+        .object = BCMOLT_OBJ_ID_DEBUG,
+        .group = BCMOLT_MGT_GROUP_AUTO,
+        .subgroup = BCMOLT_DEBUG_AUTO_ID_CLI_OUTPUT,
+    };
+
+    int c;
+    bcmos_errno rc;
+    bcmos_bool raw_mode = BCMOS_FALSE;
+
+    /* Only 1 instance is supported */
+    if (cli_context)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "embedded_cli client is already active for device %u\n",
+            cli_context->device);
+    }
+    cli_context = bcmos_calloc(sizeof(*cli_context));
+    if (!cli_context)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "can't allocate embedded CLI context\n");
+    }
+    cli_context->session = session;
+    cli_context->device = device;
+
+    /* Create input/output task & module */
+    rc = bcmos_task_create(&cli_context->task, &taskp);
+    if (rc)
+    {
+        BCMOS_TRACE_ERR("Can't create embedded cli task: %s\n", bcmos_strerror(rc));
+        goto cleanup1;
+    }
+
+    modulep.data = (long)cli_context;
+    rc = bcmos_module_create(BCMOS_MODULE_ID_CLI_OVER_PCIE, &cli_context->task, &modulep);
+    if (rc)
+    {
+        BCMOS_TRACE_ERR("Can't create embedded cli module: %s\n", bcmos_strerror(rc));
+        goto cleanup2;
+    }
+
+    timerp.data = (long)cli_context;
+    rc = bcmos_timer_create(&cli_context->timer, &timerp);
+    if (rc)
+    {
+        BCMOS_TRACE_ERR("Can't create embedded cli timer: %s\n", bcmos_strerror(rc));
+        goto cleanup3;
+    }
+
+    /* Query existing indication in order to be able to restore it */
+    bcmtr_msg_handler_register_get(device, &old_msgp);
+
+    /* Unregister old handler */
+    bcmtr_msg_handler_unregister(device, &old_msgp);
+
+    /* Register for cli_output indication */
+    rc = bcmtr_msg_handler_register(device, &msgp);
+    if (rc)
+    {
+        BCMOS_TRACE_ERR("Can't register for cli_output indication: %s\n", bcmos_strerror(rc));
+        goto cleanup4;
+    }
+
+    bcmcli_session_print(session, "Device %u: Entering embedded CLI. Type %c to terminate\n",
+        device, BCM_EMBEDDED_CONSOLE_EXIT_CHAR);
+
+    /* Try to enter raw mode if line editing is requested */
+    rc = bcmcli_session_raw_mode_set(session, BCMOS_TRUE);
+    if (rc)
+    {
+        bcmcli_session_print(session, "Can't enable RAW input mode. Line editing is disabled\n");
+    }
+    else
+    {
+        raw_mode = BCMOS_TRUE;
+    }
+    /* No we read input and push it into input buffer */
+    if (raw_mode)
+    {
+        c = bcmos_getchar();
+        while (c >= 0 && c != BCM_EMBEDDED_CONSOLE_EXIT_CHAR)
+        {
+            cli_context->inbuf[cli_context->inbuf_length++] = c;
+            embedded_cli_send_input(cli_context);
+            c = bcmos_getchar();
+        }
+        bcmcli_session_raw_mode_set(session, BCMOS_FALSE);
+    }
+    else
+    {
+        /* Line mode */
+        char *buf;
+
+        buf = bcmcli_session_gets(session, (char *)cli_context->inbuf, sizeof(cli_context->inbuf));
+        while (buf && buf[0] != BCM_EMBEDDED_CONSOLE_EXIT_CHAR)
+        {
+            cli_context->inbuf_length = strlen(buf);
+            if (!cli_context->inbuf_length)
+                continue;
+            if (buf[cli_context->inbuf_length-1] != '\n' && buf[cli_context->inbuf_length-1] != '\r' &&
+                cli_context->inbuf_length < sizeof(cli_context->inbuf) - 1)
+            {
+                buf[cli_context->inbuf_length++] = '\n';
+            }
+            embedded_cli_send_input(cli_context);
+            buf = bcmcli_session_gets(session, (char *)cli_context->inbuf, sizeof(cli_context->inbuf));
+        }
+    }
+
+    bcmos_timer_stop(&cli_context->timer);
+    bcmcli_session_print(session, "Device %u: Embedded CLI terminated\n", device);
+    bcmtr_msg_handler_unregister(device, &msgp);
+    if (old_msgp.app_cb)
+        rc = bcmtr_msg_handler_register(device, &old_msgp);
+
+cleanup4:
+    bcmos_timer_destroy(&cli_context->timer);
+cleanup3:
+    bcmos_module_destroy(BCMOS_MODULE_ID_CLI_OVER_PCIE);
+cleanup2:
+    bcmos_task_destroy(&cli_context->task);
+cleanup1:
+    bcmos_free(cli_context);
+    cli_context = NULL;
+
+    return rc;
+}
+
+static bcmos_errno bcm_embedded_cli_command(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+    bcmolt_devid device = parm[0].value.number;
+    return bcm_embedded_cli_enter(session, device);
+}
+
+/* Initialize embedded CLI module */
+bcmos_errno bcm_embedded_cli_init(void)
+{
+    BCMCLI_MAKE_CMD(NULL, "embedded", "Embedded CLI", bcm_embedded_cli_command,
+        BCMCLI_MAKE_PARM_RANGE("device", "Device index", BCMCLI_PARM_DECIMAL, 0, 0, BCMTR_MAX_OLTS-1));
+
+    return BCM_ERR_OK;
+}
+
+/* Cleanup embedded CVLI module */
+bcmos_errno bcm_embedded_cli_exit(void)
+{
+    return BCM_ERR_OK;
+}
diff --git a/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.h b/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.h
new file mode 100644
index 0000000..4a1e519
--- /dev/null
+++ b/bcm68620_release/release/host_customized/embedded_cli/bcmolt_embedded_cli.h
@@ -0,0 +1,64 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcm_embedded_cli.h - embedded CLI access from the host
+ */
+
+#ifndef BCMOLT_EMBEDDED_CLI_H_
+#define BCMOLT_EMBEDDED_CLI_H_
+
+#include <bcmcli_session.h>
+#include <bcmolt_msg.h>
+
+/* Character used to exit from embedded console */
+#define BCM_EMBEDDED_CONSOLE_EXIT_CHAR  '!'
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Initialize embedded CLI module */
+bcmos_errno bcm_embedded_cli_init(void);
+
+/* Cleanup embedded CLI module */
+bcmos_errno bcm_embedded_cli_exit(void);
+
+/* Connect to embedded CLI console.
+ * The function waits for user input and
+ * returns when encounters BCM_EMBEDDED_CONSOLE_EXIT_CHAR
+ */
+bcmos_errno bcm_embedded_cli_enter(bcmcli_session *session, bcmolt_devid device);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
diff --git a/bcm68620_release/release/host_customized/embedded_cli/main/Makefile b/bcm68620_release/release/host_customized/embedded_cli/main/Makefile
new file mode 100644
index 0000000..c6f7c95
--- /dev/null
+++ b/bcm68620_release/release/host_customized/embedded_cli/main/Makefile
@@ -0,0 +1,9 @@
+# Embedded CLI console application
+#
+ifeq ("$(ENABLE_CLI)", "y")
+    MOD_NAME = embedded_console
+    MOD_TYPE = app
+    MOD_DEPS = embedded_cli
+    
+    srcs = bcmolt_embedded_console.c
+endif
diff --git a/bcm68620_release/release/host_customized/embedded_cli/main/bcmolt_embedded_console.c b/bcm68620_release/release/host_customized/embedded_cli/main/bcmolt_embedded_console.c
new file mode 100644
index 0000000..5ce767b
--- /dev/null
+++ b/bcm68620_release/release/host_customized/embedded_cli/main/bcmolt_embedded_console.c
@@ -0,0 +1,79 @@
+/*
+<: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 <bcmolt_embedded_cli.h>
+
+static int _cli_help(void)
+{
+    fprintf(stderr, "embedded_console [-d device_index]");
+    return -1;
+}
+
+int main(int argc, char *argv[])
+{
+    bcmcli_session_parm mon_session_parm;
+    bcmcli_session *session;
+    int device = 0;
+    int i;
+
+    /* argc must be odd because all options except for argv[0] go in pairs */
+    if (!(argc % 2))
+    {
+        return _cli_help();
+    }
+
+    memset(&mon_session_parm, 0, sizeof(mon_session_parm));
+    mon_session_parm.access_right = BCMCLI_ACCESS_ADMIN;
+    for(i=1; i<argc; i++)
+    {
+        if (!strcmp(argv[i], "-d"))
+        {
+            char *pend;
+            ++i;
+            device = strtoul(argv[i], &pend, 0);
+            if (pend && *pend)
+                return _cli_help();
+        }
+    }
+
+    if (bcmcli_session_open(&mon_session_parm, &session))
+    {
+        printf("Can't open CLI session\n");
+        return -EINVAL;
+    }
+
+    /* Process user input until EOF or ! command */
+    bcm_embedded_cli_enter(session, device);
+
+    bcmcli_session_close(session);
+
+    return 0;
+}
+
diff --git a/bcm68620_release/release/host_customized/host_api_linux/Makefile b/bcm68620_release/release/host_customized/host_api_linux/Makefile
new file mode 100644
index 0000000..6ab83b5
--- /dev/null
+++ b/bcm68620_release/release/host_customized/host_api_linux/Makefile
@@ -0,0 +1,17 @@
+# Makefile for building host/host_api as linux library to be called from kernel modules
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = host_api_linux
+MOD_TYPE = linux_lib
+MOD_DEPS = common_gpon
+
+srcs = bcmolt_host_api.c
+
+# 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/host_api_linux/bcmolt_host_api.c b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api.c
new file mode 120000
index 0000000..420887e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api.c
@@ -0,0 +1 @@
+../../host_driver/host_api/bcmolt_host_api.c
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api.h b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api.h
new file mode 120000
index 0000000..0ebbe28
--- /dev/null
+++ b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api.h
@@ -0,0 +1 @@
+../../host_driver/host_api/bcmolt_host_api.h
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api_gpon_utils.h b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api_gpon_utils.h
new file mode 120000
index 0000000..66be99e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/host_api_linux/bcmolt_host_api_gpon_utils.h
@@ -0,0 +1 @@
+../../host_driver/host_api/bcmolt_host_api_gpon_utils.h
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/i2c/Makefile b/bcm68620_release/release/host_customized/i2c/Makefile
new file mode 100644
index 0000000..333c2db
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/Makefile
@@ -0,0 +1,19 @@
+# I2C devices driver
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = i2c_devs
+MOD_TYPE = linux_module
+
+srcs = bcmolt_i2c_devs.c
+
+# 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
+
+USE_LINT = yes
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c
new file mode 100644
index 0000000..48e9ec4
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.c
@@ -0,0 +1,1038 @@
+/*
+<: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 <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/cdev.h>
+#include <asm/uaccess.h> /*copy_from_user*/
+#include <linux/proc_fs.h>
+#include "bcmos_system.h"
+#include "bcmolt_i2c_devs.h"
+#include "bcmolt_i2c_devs_ioctl.h"
+
+#define BCM_I2C_DEV_ADDR_START typedef enum {
+#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
+#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
+
+#include "bcmolt_i2c_devs_addr.h"
+
+#define PROC_DIR_NAME       "maple_i2c"
+#define PROC_ENTRY_NAME     "i2c"
+#define MAX_EAGAIN_ITERS    200 /* 10ms per iter */
+
+/* uncomment the next line to enable debug output to the kernel CLI */
+/* #define I2C_DEBUG_PRINTS 1 */
+#ifdef I2C_DEBUG_PRINTS
+#define i2c_debug_print(fmt, args...) printk("%s#%d: " fmt, __FUNCTION__, __LINE__, ## args)
+#else
+#define i2c_debug_print(...)
+#endif
+
+int maple_i2c_chrdev_major = 216;
+module_param(maple_i2c_chrdev_major, int, S_IRUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(maple_i2c_chrdev_major, "maple_i2c_major");
+
+static struct proc_dir_entry *i2c_proc_dir;
+static struct proc_dir_entry *i2c_proc_entry;
+static char is_chrdev_reg;
+static char is_cdev_add;
+static int i2c_client_num;
+static int i2c_num_clients;
+
+const unsigned short normal_i2c[] = {
+    I2C_SW0_I2C_ADDR,
+    I2C_SW1_I2C_ADDR,
+    I2C_SW2_I2C_ADDR,
+    I2C_SW3_I2C_ADDR,
+    I2C_SW4_I2C_ADDR,
+    SFP_I2C_ADDR1,
+    SFP_I2C_ADDR2,
+    FPGA_I2C_ADDR,
+    PON_DPLL_I2C_ADDR,
+    PM_DPLL_I2C_ADDR,
+    CXP_R_I2C_ADDR,
+    PCIE_SW_I2C_ADDR,
+    I2C_CLIENT_END
+};
+
+static unsigned char slave_valid[SLAVE_NUM_OF_SLAVES] = {0};
+
+/*
+ * Driver data (common to all clients)
+ */
+
+static const struct i2c_device_id maple_i2c_id_table[] = {
+    { "maple_i2c", 0 },
+    { }
+};
+MODULE_DEVICE_TABLE(i2c, maple_i2c_id_table);
+
+static void bcm_access_fpga(void);
+
+/*
+ * Client data (each client gets its own)
+ */
+struct maple_i2c_data {
+    struct i2c_client client;
+};
+
+static struct maple_i2c_data *pclient_data_ar[SLAVE_NUM_OF_SLAVES];
+
+static int get_client(unsigned char client_num, struct i2c_client **client)
+{
+    if ((client_num >= SLAVE_NUM_OF_SLAVES) || !slave_valid[client_num])
+    {
+        i2c_debug_print("I2C error: Wrong client number 0x%x\n", client_num);
+        return -1;
+    }
+    *client = &pclient_data_ar[client_num]->client;
+
+    return 0;
+}
+
+
+/*
+ * Helper functions which attempt I2C transfer until successful, or error code is other than -EAGAIN
+ */
+
+static int maple_i2c_send(unsigned char client_num, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    do {
+        rc = i2c_master_send(client, buf, count);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+    rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+static int maple_i2c_recv(unsigned char client_num, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    do {
+        rc = i2c_master_recv(client, buf, count);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+    rc = (rc == count) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+
+static int maple_i2c_read_with_offset(unsigned char client_num, u8 *offset, size_t offset_size, u8 *buf, size_t count)
+{
+    struct i2c_client *client;
+    struct i2c_msg msg[2];
+    int rc;
+    int niter = 0;
+
+    if (get_client(client_num, &client))
+        return -1;
+
+    msg[0].addr = msg[1].addr = client->addr;
+    msg[0].flags = msg[1].flags = client->flags & I2C_M_TEN;
+
+    msg[0].len = offset_size;
+    msg[0].buf = offset;
+
+    msg[1].flags |= I2C_M_RD;
+    msg[1].len = count;
+    msg[1].buf = buf;
+
+    do {
+        rc = i2c_transfer(client->adapter, msg, 2);
+        if (rc == -EAGAIN)
+            msleep(10);
+    } while (rc == -EAGAIN && ++niter < MAX_EAGAIN_ITERS);
+
+    rc = (rc == 2) ? 0 : (rc < 0 ) ? rc : -1;
+
+    return rc;
+}
+
+ssize_t maple_i2c_write(unsigned char client_num, char *buf, size_t count)
+{
+    int rc;
+
+    i2c_debug_print("Write to switch: client=0x%x val = 0x%x\n", normal_i2c[client_num], *buf);
+    rc = maple_i2c_send(client_num, (u8 *)buf, count);
+
+    if (rc < 0)
+        i2c_debug_print("Write Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Successful client=%u[%u]\n",
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write);
+
+ssize_t maple_i2c_read(unsigned char client_num, char *buf, size_t count)
+{
+    int rc;
+
+    i2c_debug_print("Read from switch: client 0x%x\n", normal_i2c[client_num]);
+    rc = maple_i2c_recv(client_num, (u8 *)buf, count);
+
+    if (rc < 0)
+        i2c_debug_print("Read Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Read Successful: count=%u val = 0x%x\n", (unsigned)count, *buf);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read);
+
+int maple_i2c_write_byte(unsigned char client_num, unsigned char offset, unsigned char val)
+{
+    u8 buf[2];
+    int rc;
+
+    i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
+
+    buf[0] = offset;
+    buf[1] = val;
+    rc = maple_i2c_send(client_num, buf, 2);
+
+    if (rc < 0)
+        i2c_debug_print("Write Byte Failed. rc=%d  offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Byte: offset=0x%x val=0x%x client=%u/%u\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_byte);
+
+int maple_i2c_read_byte(unsigned char client_num, unsigned char offset, unsigned char *data)
+{
+    u8 o = offset;
+    u8 val;
+    int rc;
+
+    i2c_debug_print("Write Byte: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, val);
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, &val, 1);
+
+    if (rc < 0)
+        i2c_debug_print("Read Byte Failed. rc=%d  client=%u[%u]\n", rc,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = val;
+        i2c_debug_print("Read Byte: client=0x%x offset = 0x%x, val = 0x%x\n",
+            normal_i2c[client_num], offset, *data);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_byte);
+
+
+int maple_i2c_write_word(unsigned char client_num, unsigned char offset, unsigned short val)
+{
+    u8 buf[3];
+    int rc;
+
+    i2c_debug_print("Write Word: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* The offset to be written should be the first byte in the I2C write */
+    buf[0] = offset;
+    buf[1] = (char)(val&0xFF);
+    buf[2] = (char)(val>>8);
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write Word Failed. rc=%d  offset=0x%x val=0x%x, client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Word: offset=0x%x val=0x%x, client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_word);
+
+int maple_i2c_read_word(unsigned char client_num, unsigned char offset, unsigned short *data)
+{
+    u8 o = offset;
+    u8 buf[2];
+    int rc;
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read Word Failed. rc=%d  offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = (buf[1]<<8) | buf[0]; /* I2C data is LE */
+        i2c_debug_print("Read Word: offset = 0x%x, val = 0x%x client=%u[%u]\n",
+            offset, *data,
+            normal_i2c[client_num], client_num);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_word);
+
+
+int maple_i2c_write_reg(unsigned char client_num, unsigned char offset, int val)
+{
+    u8 buf[5];
+    int rc;
+
+    i2c_debug_print("Write Register: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* Set the buf[0] to be the offset for write operation */
+    buf[0] = offset;
+
+    /* On the I2C bus, LS Byte should go first */
+    buf[1] = val & 0xff;
+    buf[2] = (val >> 8) & 0xff;
+    buf[3] = (val >> 16) & 0xff;
+    buf[4] = (val >> 24) & 0xff;
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write Reg Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write Reg Successful. offset=0x%x val=0x%x client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_reg);
+
+
+int maple_i2c_read_reg(unsigned char client_num, unsigned char offset, unsigned int *data)
+{
+    u8 o = offset;
+    u8 buf[4];
+    int rc;
+
+    rc = maple_i2c_read_with_offset(client_num, &o, 1, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read Reg Failed. rc=%d offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24); /* LS byte is transferred first */
+        i2c_debug_print("Read Register: client=0x%x offset = 0x%x, val = 0x%x\n", normal_i2c[client_num], offset, *data);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_reg);
+
+
+int maple_i2c_write_fpga(unsigned char client_num, unsigned int offset, unsigned int val)
+{
+    u8 buf[8];
+    int rc;
+
+    bcm_access_fpga();
+
+    i2c_debug_print("Write fpga: offset = 0x%x, val = 0x%x\n", offset, val);
+
+    /* Set the offset for write operation */
+    //    offset = swab32(offset);
+    memcpy(&buf[0], (char*)&offset, 4);
+
+    /* On the I2C bus, LS Byte should go first */
+    //    val = swab32(val);
+    memcpy(&buf[4], (char*)&val, 4);
+
+    rc = maple_i2c_send(client_num, buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Write FPGA Failed. rc=%d offset=0x%x val=0x%x client=%u[%u]\n",
+            rc, offset, val,
+            normal_i2c[client_num], client_num);
+    else
+        i2c_debug_print("Write FPGA: offset=0x%x val=0x%x client=%u[%u]\n",
+            offset, val,
+            normal_i2c[client_num], client_num);
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_write_fpga);
+
+int maple_i2c_read_fpga(unsigned char client_num, unsigned int offset, unsigned int *data)
+{
+    u8 obuf[4];
+    u8 buf[4];
+    int rc;
+
+    bcm_access_fpga();
+
+    /* FPGA expects 4 byte offset in BIG ENDIAN format */
+    obuf[0] = (offset >> 24) & 0xff;
+    obuf[1] = (offset >> 16) & 0xff;
+    obuf[2] = (offset >> 8) & 0xff;
+    obuf[3] = offset & 0xff;
+    rc = maple_i2c_read_with_offset(client_num, obuf, sizeof(obuf), buf, sizeof(buf));
+
+    if (rc < 0)
+        i2c_debug_print("Read FPGA Failed. rc=%d offset=0x%x client=%u[%u]\n",
+            rc, offset,
+            normal_i2c[client_num], client_num);
+    else
+    {
+        *data = buf[3] | (buf[2] << 8) | (buf[1] << 16) | (buf[0] << 24); /* MS byte is transferred first */
+        i2c_debug_print("Read FPGA: offset = 0x%x, val = 0x%x %02x %02x %02x %02x  client=%u[%u]\n",
+            offset, *data, buf[0], buf[1], buf[2], buf[3],
+            normal_i2c[client_num], client_num);
+    }
+    return rc;
+}
+EXPORT_SYMBOL(maple_i2c_read_fpga);
+
+enum client_num maple_i2c_get_client(u32 addr)
+{
+    enum client_num i = 0;
+    while (i < SLAVE_NUM_OF_SLAVES)
+    {
+        if (pclient_data_ar[i])
+        {
+            if (slave_valid[i] && pclient_data_ar[i]->client.addr == addr)
+            {
+                break;
+            }
+        }
+        i++;
+    }
+    return i;
+}
+EXPORT_SYMBOL(maple_i2c_get_client);
+
+static int dev_change(u32 addr)
+{
+    enum client_num i = maple_i2c_get_client(addr);
+
+    if (i < SLAVE_NUM_OF_SLAVES)
+    {
+        i2c_client_num = i;
+        i2c_debug_print("Slave was set successfully i %d, addr 0x%x\n", i, addr);
+    }
+    else
+    {
+        i2c_debug_print("Failed to set slave i %d, addr 0x%x\n", i, addr);
+    }
+
+    return 0;
+}
+
+static void bcm_access_fpga(void)
+{
+    static int access_enabled;
+    int fpga_client_num  = maple_i2c_get_client(I2C_SW1_I2C_ADDR);
+    uint8_t  b;
+
+    if (access_enabled)
+    	return;
+    b = 4;
+    maple_i2c_write(fpga_client_num, &b, 1);
+    access_enabled = 1;
+}
+#define BCM_FPGA_REG_RESETS 0x2
+#define BCM_FPGA_REG_FPGA_VERSION 0x0
+/* 1 = out of reset bcm_board_config_reset_value */
+void reset_maple(int bit,int param)
+{
+    int fpga_client_num  = maple_i2c_get_client(FPGA_I2C_ADDR);
+    int sw_client_num  = maple_i2c_get_client(I2C_SW0_I2C_ADDR);
+    uint8_t  b = 1;
+    uint32_t reset_values;
+
+    maple_i2c_write(sw_client_num, &b, 1);
+
+    /* Read-modify-write so we can set only the relevant bit */
+    maple_i2c_read_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, &reset_values);
+
+    if (param)
+        reset_values |= 1 << bit;
+    else
+        reset_values &= ~(1 << bit);
+    maple_i2c_write_fpga(fpga_client_num, BCM_FPGA_REG_RESETS, reset_values);
+}
+EXPORT_SYMBOL(reset_maple);
+
+/* Calls the appropriate function based on user command */
+static int exec_command(const char *buf, size_t count)
+{
+#define MAX_ARGS 4
+#define MAX_ARG_SIZE 32
+    int i, argc = 0, val = 0;
+    char cmd;
+    u32 offset = 0;
+    char arg[MAX_ARGS][MAX_ARG_SIZE];
+#define LOG_WR_KBUF_SIZE 128
+    char kbuf[LOG_WR_KBUF_SIZE];
+
+    if ((count > LOG_WR_KBUF_SIZE-1) || (copy_from_user(kbuf, buf, count) != 0))
+        return -EFAULT;
+    kbuf[count]=0;
+    argc = sscanf(kbuf, "%c %s %s %s %s", &cmd, arg[0], arg[1], arg[2], arg[3]);
+
+    if (argc < 1)
+    {
+        printk("Need at-least 2 arguments\n");
+        return -EFAULT;
+    }
+
+    for (i=0; i<MAX_ARGS; ++i) {
+        arg[i][MAX_ARG_SIZE-1] = '\0';
+    }
+    offset = (u32)simple_strtoul(arg[0], NULL, 0);
+    if (argc == 3)
+        val = (int)simple_strtoul(arg[1], NULL, 0);
+
+    switch (cmd)
+    {
+    case 'm':
+        reset_maple(0,offset); // maple out of reset(1) | reset (0)
+        break;
+    case 'k':
+        reset_maple(4,offset); // katana2 out of reset(1) | reset (0)
+        break;
+    case 'b':
+        if (argc == 3)
+            maple_i2c_write_byte(i2c_client_num, (u8)offset, (u8)val);
+        else
+        {
+            u8 data;
+            maple_i2c_read_byte(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 's':
+        if (argc == 2)
+        {
+            u8 data = (u8)offset;
+            maple_i2c_write(i2c_client_num, &data, 1);
+        }
+        else
+        {
+            u8 data = offset;
+            maple_i2c_read(i2c_client_num, &data, 1);
+            printk("client 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], data);
+        }
+        break;
+
+    case 'w':
+        if (argc == 3)
+            maple_i2c_write_word(i2c_client_num, (u8)offset, (u16)val);
+        else
+        {
+            u16 data;
+            maple_i2c_read_word(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'd':
+        if (argc == 3)
+            maple_i2c_write_reg(i2c_client_num, (u8)offset, val);
+        else
+        {
+            u32 data;
+            maple_i2c_read_reg(i2c_client_num, (u8)offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'f':
+        if (argc == 3)
+            maple_i2c_write_fpga(i2c_client_num, offset, val);
+        else
+        {
+            u32 data;
+            maple_i2c_read_fpga(i2c_client_num, offset, &data);
+            printk("client 0x%x, offset 0x%x, data=0x%x\n", normal_i2c[i2c_client_num], offset, data);
+        }
+        break;
+
+    case 'c':
+        dev_change(offset);
+        break;
+
+    default:
+        printk("Invalid command.\n Valid commands:\n"
+            "  Change I2C Addr: c addr\n"
+            "  Write Reg:       d offset val\n"
+            "  Read Reg:        d offset\n"
+            "  Write Word:      w offset val\n"
+            "  Read Word:       w offset\n"
+            "  Write Byte:      b offset val\n"
+            "  Read Byte:       b offset\n"
+            "  Write fpga:      f offset val\n"
+            "  Read fpga:       f offset\n"
+            "  Write to switch: s val (one byte)\n"
+            "  Read from switch:s\n"
+            "  Maple:           m <0|1>\n"
+            "  Katana2:         k <0|1>\n"
+            );
+        break;
+    }
+    return count;
+}
+
+
+
+/* Read Function of PROCFS attribute "maple_i2c/test" */
+static ssize_t maple_i2c_proc_test_read(struct file *f, char *buf, size_t count,
+    loff_t *pos)
+{
+    printk(" Usage: echo command > "
+        " /proc/maple_i2c/test\n");
+    printk(" supported commands:\n"
+        "  Change I2C Addr: c addr\n"
+        "  Write Reg:       d offset val\n"
+        "  Read Reg:        d offset\n"
+        "  Write Word:      w offset val\n"
+        "  Read Word:       w offset\n"
+        "  Write Byte:      b offset val\n"
+        "  Read Byte:       b offset\n"
+        "  Write fpga:      f offset val\n"
+        "  Read fpga:       f offset\n"
+        "  Write to switch: s val (one byte)\n"
+        "  Read from switch:s\n"
+        );
+    return 0;
+}
+
+/* Write Function of PROCFS attribute "maple_i2c/test" */
+static ssize_t maple_i2c_proc_test_write(struct file *f, const char *buf,
+    size_t count, loff_t *pos)
+{
+    return exec_command(buf, count);
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int maple_i2c_dev_detect(struct i2c_client *client, struct i2c_board_info *info)
+{
+    i2c_debug_print("detecting i2c device 0x%x\n", client->addr);
+
+    /* TODO: detection and identification */
+
+    strcpy(info->type, "maple_i2c");
+    info->flags = 0;
+    return 0;
+}
+
+static struct file_operations maple_i2c_fops =
+{
+    read: maple_i2c_proc_test_read,
+    write: maple_i2c_proc_test_write
+};
+
+static int maple_i2c_dev_create_proc(void)
+{
+    i2c_proc_dir = proc_mkdir(PROC_DIR_NAME, NULL);
+    if (!i2c_proc_dir)
+    {
+        i2c_debug_print("fail to create proc dir\n");
+        return -ENOMEM;
+    }
+
+    i2c_proc_entry = create_proc_entry(PROC_ENTRY_NAME, 0, i2c_proc_dir);
+    if (!i2c_proc_entry)
+    {
+        remove_proc_entry(PROC_DIR_NAME, NULL);
+        return -ENOMEM;
+    }
+
+    i2c_proc_entry->proc_fops = &maple_i2c_fops;
+
+    return 0;
+}
+
+static int maple_i2c_chrdev_open(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static int maple_i2c_chrdev_release(struct inode *inode, struct file *filp)
+{
+    return 0;
+}
+
+static long maple_i2c_chrdev_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+    int linux_rc = 0;
+    int rc;
+    maple_i2c_ioctl_param params;
+
+    /* don't even decode wrong cmds: better returning  ENOTTY than EFAULT */
+    if (_IOC_TYPE(cmd) != MAPLE_I2C_IOCTL_MAGIC)
+        return -ENOTTY;
+
+    /*
+     * the type is a bitmask, and VERIFY_WRITE catches R/W
+     * transfers. Note that the type is user-oriented, while
+     * verify_area is kernel-oriented, so the concept of "read" and
+     * "write" is reversed
+     */
+    if (_IOC_DIR(cmd) & _IOC_READ)
+        linux_rc = !access_ok(VERIFY_WRITE, (void __user *)arg, _IOC_SIZE(cmd));
+    else if (_IOC_DIR(cmd) & _IOC_WRITE)
+        linux_rc =  !access_ok(VERIFY_READ, (void __user *)arg, _IOC_SIZE(cmd));
+    if (linux_rc)
+        return -EFAULT;
+
+    switch (cmd)
+    {
+    case MAPLE_I2C_IOCTL_OP_DEV_CHANGE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            return dev_change(params.addr);
+        }
+        break;
+    case MAPLE_I2C_IOCTL_OP_DEV_WRITE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            switch (params.count)
+            {
+            case 8:
+                return maple_i2c_write_byte(i2c_client_num, params.addr, params.val);
+            case 16:
+                return maple_i2c_write_word(i2c_client_num, params.addr, params.val);
+            case 32:
+                return maple_i2c_write_reg(i2c_client_num, params.addr, params.val);
+            default:
+                return -EINVAL;
+            }
+        }
+        break;
+    case MAPLE_I2C_IOCTL_OP_DEV_READ:
+        {
+            unsigned char b;
+            unsigned short w;
+            unsigned int r;
+
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            switch (params.count)
+            {
+            case 8:
+                linux_rc = maple_i2c_read_byte(i2c_client_num, params.addr, &b);
+                if (linux_rc < 0)
+                    break;
+                params.val = b;
+                break;
+            case 16:
+                linux_rc = maple_i2c_read_word(i2c_client_num, params.addr, &w);
+                if (linux_rc < 0)
+                    break;
+                params.val = w;
+                break;
+            case 32:
+                linux_rc = maple_i2c_read_reg(i2c_client_num, params.addr, &r);
+                if (linux_rc < 0)
+                    break;
+                params.val = r;
+                break;
+            default:
+                return -EINVAL;
+            }
+            if (linux_rc < 0)
+                break;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    case MAPLE_I2C_IOCTL_OP_SWITCH_WRITE:
+        {
+            char b;
+
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            b = params.val;
+            return maple_i2c_write(i2c_client_num, &b, 1);
+        }
+    case MAPLE_I2C_IOCTL_OP_SWITCH_READ:
+        {
+            char b;
+
+            linux_rc = maple_i2c_read(i2c_client_num, &b, 1);
+            if (linux_rc < 0)
+                break;
+            params.val = b;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    case MAPLE_I2C_IOCTL_OP_FPGA_WRITE:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            return maple_i2c_write_fpga(i2c_client_num, params.addr, params.val);
+        }
+    case MAPLE_I2C_IOCTL_OP_FPGA_READ:
+        {
+            linux_rc = copy_from_user((char *)&params, (char *)arg, sizeof(params));
+            if (linux_rc < 0)
+                break;
+            linux_rc = maple_i2c_read_fpga(i2c_client_num, params.addr, &params.val);
+            if (linux_rc < 0)
+                break;
+            return copy_to_user((char *)arg, (char *)&params, sizeof(params));
+        }
+    default:
+        rc = -ENOTTY;
+        break;
+    }
+
+    return linux_rc;
+}
+
+static ssize_t maple_i2c_chrdev_write(struct file *filp, const char __user *buf,
+    size_t count, loff_t *f_pos)
+{
+    return 0;
+}
+
+static struct file_operations maple_i2c_chrdev_fops =
+{
+    .owner = THIS_MODULE,
+    .open = maple_i2c_chrdev_open,
+    .release = maple_i2c_chrdev_release,
+    .write = maple_i2c_chrdev_write,
+    .unlocked_ioctl = maple_i2c_chrdev_ioctl
+};
+
+static struct cdev maple_i2c_chrdev_cdev;
+
+static int maple_i2c_dev_create_chrdev(void)
+{
+    dev_t dev = MKDEV(maple_i2c_chrdev_major, 0);
+    int linux_rc;
+
+    is_chrdev_reg = 0;
+    is_cdev_add = 0;
+    /*
+     * Register your major, and accept a dynamic number.
+     */
+    if (!maple_i2c_chrdev_major)
+        return -1;
+    linux_rc = register_chrdev_region(dev, 0, "maple_i2c");
+    if (linux_rc < 0)
+    {
+        i2c_debug_print("register_chrdev_region()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_chrdev_reg = 1;
+
+    cdev_init(&maple_i2c_chrdev_cdev, &maple_i2c_chrdev_fops);
+    linux_rc = cdev_add(&maple_i2c_chrdev_cdev, dev, 1);
+    if (linux_rc < 0)
+    {
+        i2c_debug_print("cdev_add()->%d\n", linux_rc);
+        return -EIO;
+    }
+    is_cdev_add = 1;
+
+    return 0;
+}
+
+static int maple_i2c_dev_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+    int err = 0;
+    struct maple_i2c_data *pclient_data;
+
+    i2c_debug_print("!!!! i2c device 0x%x probe\n", client->addr);
+
+    if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+        goto exit;
+
+    if (!(pclient_data = kzalloc(sizeof(struct maple_i2c_data), GFP_KERNEL)))
+    {
+        err = -ENOMEM;
+        goto exit;
+    }
+
+    pclient_data->client.addr = client->addr;
+    pclient_data->client.adapter = client->adapter;
+    pclient_data->client.driver = client->driver;
+    pclient_data->client.flags = client->flags;
+
+    i2c_set_clientdata(client, pclient_data);
+
+    switch(client->addr)
+    {
+    case I2C_SW0_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_70] = pclient_data;
+        slave_valid[SLAVE_SWITCH_70] = 1;
+        break;
+    case I2C_SW1_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_71] = pclient_data;
+        slave_valid[SLAVE_SWITCH_71] = 1;
+        break;
+    case I2C_SW2_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_72] = pclient_data;
+        slave_valid[SLAVE_SWITCH_72] = 1;
+        break;
+    case I2C_SW3_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_73] = pclient_data;
+        slave_valid[SLAVE_SWITCH_73] = 1;
+        break;
+    case I2C_SW4_I2C_ADDR:
+        pclient_data_ar[SLAVE_SWITCH_74] = pclient_data;
+        slave_valid[SLAVE_SWITCH_74] = 1;
+        break;
+    case SFP_I2C_ADDR1:
+        pclient_data_ar[SLAVE_SFP_50] = pclient_data;
+        slave_valid[SLAVE_SFP_50] = 1;
+        break;
+    case SFP_I2C_ADDR2:
+        pclient_data_ar[SLAVE_SFP_51] = pclient_data;
+        slave_valid[SLAVE_SFP_51] = 1;
+        break;
+    case FPGA_I2C_ADDR:
+        pclient_data_ar[SLAVE_FPGA_40] = pclient_data;
+        slave_valid[SLAVE_FPGA_40] = 1;
+        break;
+    case PON_DPLL_I2C_ADDR:
+        pclient_data_ar[SLAVE_PON_DPLL_68] = pclient_data;
+        slave_valid[SLAVE_PON_DPLL_68] = 1;
+        break;
+    case PM_DPLL_I2C_ADDR:
+        pclient_data_ar[SLAVE_PM_DPLL_6A] = pclient_data;
+        slave_valid[SLAVE_PM_DPLL_6A] = 1;
+        break;
+    case CXP_R_I2C_ADDR:
+        pclient_data_ar[SLAVE_CXP_R_54] = pclient_data;
+        slave_valid[SLAVE_CXP_R_54] = 1;
+        break;
+    case PCIE_SW_I2C_ADDR:
+        pclient_data_ar[SLAVE_PCIE_SW_3C] = pclient_data;
+        slave_valid[SLAVE_PCIE_SW_3C] = 1;
+        break;
+    default:
+        i2c_debug_print("%s client addr out of range 0x%x\n", __FUNCTION__, client->addr);
+        goto exit_kfree;
+    }
+
+    /* Create only once */
+    if (i2c_proc_entry == NULL)
+    {
+        if (maple_i2c_dev_create_proc() < 0)
+            goto exit_kfree;
+    }
+    if (!is_cdev_add)
+    {
+        if (maple_i2c_dev_create_chrdev() < 0)
+            goto exit_kfree;
+    }
+    ++i2c_num_clients;
+
+    return 0;
+
+exit_kfree:
+    kfree(pclient_data);
+exit:
+    return err;
+}
+
+static int maple_i2c_dev_remove(struct i2c_client *client)
+{
+    kfree(i2c_get_clientdata(client));
+    --i2c_num_clients;
+    if (!i2c_num_clients)
+    {
+        if (i2c_proc_entry != NULL)
+        {
+            remove_proc_entry(PROC_ENTRY_NAME, i2c_proc_dir);
+            i2c_proc_entry = NULL;
+        }
+        if (i2c_proc_dir != NULL)
+        {
+            remove_proc_entry(PROC_DIR_NAME, NULL);
+            i2c_proc_dir = NULL;
+        }
+        if (is_cdev_add)
+        {
+            cdev_del(&maple_i2c_chrdev_cdev);
+            is_cdev_add = 0;
+        }
+        if (is_chrdev_reg)
+        {
+            unregister_chrdev_region(MKDEV(maple_i2c_chrdev_major, 0), 1);
+            is_chrdev_reg = 0;
+        }
+    }
+
+    return 0;
+}
+
+static struct i2c_driver maple_i2c_dev_driver = {
+    .class		= ~0,
+    .driver = {
+        .name	= "maple_i2c",
+    },
+    .probe		= maple_i2c_dev_probe,
+    .remove		= maple_i2c_dev_remove,
+    .id_table	= maple_i2c_id_table,
+    .detect		= maple_i2c_dev_detect,
+    .address_list	= normal_i2c,
+};
+
+module_i2c_driver(maple_i2c_dev_driver);
+
+MODULE_DESCRIPTION("maple i2c devices");
+MODULE_LICENSE("GPL");
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h
new file mode 100644
index 0000000..ad0edaa
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs.h
@@ -0,0 +1,226 @@
+/*
+<: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 _BCMOLT_I2C_DEVS_H_
+#define _BCMOLT_I2C_DEVS_H_
+
+/* When inserting the module (with insmod) onlt the I2C switch devices (I2C_SWX_I2C_ADDR) 
+   will be automatically detected, and therefore will be probed.
+   Probing all other devices can be done after inerting the module via sysfs.
+   for example, in order to probe FPGA device, the following line should be applied:
+   -- echo maple_i2c FPGA_I2C_ADDR > /sys/bus/i2c/devices/i2c-0/new_device --
+*/ 
+enum client_num
+{
+    SLAVE_SWITCH_70    = 0,
+    SLAVE_SWITCH_71    = 1,
+    SLAVE_SWITCH_72    = 2,
+    SLAVE_SWITCH_73    = 3,
+    SLAVE_SWITCH_74    = 4,
+    SLAVE_SFP_50       = 5,
+    SLAVE_SFP_51       = 6,
+    SLAVE_FPGA_40      = 7,
+    SLAVE_PON_DPLL_68  = 8,
+    SLAVE_PM_DPLL_6A   = 9,
+    SLAVE_CXP_R_54     = 10,
+    SLAVE_PCIE_SW_3C   = 11,
+    SLAVE_NUM_OF_SLAVES
+};
+
+
+/*****************************************************************
+   maple_i2c_write
+
+   DESCRIPTION:
+       Writes serially data to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       buf        - The buffer to write.
+       count      - Number of bytes to write
+
+   OUTPUT:
+       The number of bytes that were written, when fails return negative number
+********************************************************************/
+ssize_t maple_i2c_write(unsigned char client_num, char *buf, size_t count);
+
+/*****************************************************************
+   maple_i2c_read
+
+   DESCRIPTION:
+       Read serially data from I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       buf        - The buffer to read to.
+       count      - Number of bytes to read
+
+   OUTPUT:
+       The number of bytes that were read, when fails return negative number
+********************************************************************/
+ssize_t maple_i2c_read(unsigned char client_num, char *buf, size_t count);
+
+/*****************************************************************
+   maple_i2c_write_byte
+
+   DESCRIPTION:
+       Write byte to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_byte(unsigned char client_num, unsigned char offset, unsigned char val);
+
+/*****************************************************************
+   maple_i2c_read_byte
+
+   DESCRIPTION:
+       Read byte from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_byte(unsigned char client_num, unsigned char offset, unsigned char* data);
+
+/*****************************************************************
+   maple_i2c_write_word
+
+   DESCRIPTION:
+       Write 16 bit word to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_word(unsigned char client_num, unsigned char offset, unsigned short val);
+
+/*****************************************************************
+   maple_i2c_read_word
+
+   DESCRIPTION:
+       Read 16 bit word from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_word(unsigned char client_num, unsigned char offset, unsigned short* data);
+
+/*****************************************************************
+   maple_i2c_write_reg
+
+   DESCRIPTION:
+       Write 32 bit register to I2C device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_reg(unsigned char client_num, unsigned char offset, int val);
+
+/*****************************************************************
+   maple_i2c_read_reg
+
+   DESCRIPTION:
+       Read 32 bit word from I2C device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_reg(unsigned char client_num, unsigned char offset, unsigned int* data);
+
+/*****************************************************************
+   maple_i2c_write_fpga
+
+   DESCRIPTION:
+       Write 32 bit register to I2C fpga device
+
+   PARAMETERS:
+       client num - The client to write to.
+       offset     - The offset to write to.
+       val        - Tha data to write.
+
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_write_fpga(unsigned char client_num, unsigned int offset, unsigned int val);
+
+/*****************************************************************
+   maple_i2c_read_fpga
+
+   DESCRIPTION:
+       Read 32 bit word from I2C fpga device
+
+   PARAMETERS:
+       client num - The client to read from.
+       offset     - The offset to read from.
+       data       - the read value is written to this pointer.
+   OUTPUT:
+       0 on success, -1 on failure.
+********************************************************************/
+int maple_i2c_read_fpga(unsigned char client_num, unsigned int offset, unsigned int* data);
+
+/*****************************************************************
+   maple_i2c_get_client
+
+   DESCRIPTION:
+       Gets an I2C client number from an address
+
+   PARAMETERS:
+       addr       - The address of the client.
+   OUTPUT:
+       The client number for this client, or SLAVE_NUM_OF_SLAVES on failure.
+********************************************************************/
+enum client_num maple_i2c_get_client(unsigned int addr);
+
+#endif   /* _MAPLE_I2C_DEVS_H_ */
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h
new file mode 100644
index 0000000..f1a9a2c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_addr.h
@@ -0,0 +1,50 @@
+/*
+<: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 _BCMOLT_I2C_DEVS_ADDR_H_
+#define _BCMOLT_I2C_DEVS_ADDR_H_
+
+BCM_I2C_DEV_ADDR_START
+BCM_I2C_DEV_ADDR(I2C_SW0_I2C_ADDR, "sw0", 0x70)
+BCM_I2C_DEV_ADDR(I2C_SW1_I2C_ADDR, "sw1", 0x71)
+BCM_I2C_DEV_ADDR(I2C_SW2_I2C_ADDR, "sw2", 0x72)
+BCM_I2C_DEV_ADDR(I2C_SW3_I2C_ADDR, "sw3", 0x73)
+BCM_I2C_DEV_ADDR(I2C_SW4_I2C_ADDR, "sw4", 0x74)
+BCM_I2C_DEV_ADDR(SFP_I2C_ADDR1, "sfp1", 0x50)
+BCM_I2C_DEV_ADDR(SFP_I2C_ADDR2, "sfp2", 0x51)
+BCM_I2C_DEV_ADDR(FPGA_I2C_ADDR, "fpga", 0x40)
+BCM_I2C_DEV_ADDR(PON_DPLL_I2C_ADDR, "pon_dpll", 0x68)
+BCM_I2C_DEV_ADDR(PM_DPLL_I2C_ADDR, "pm_dpll", 0x6a)
+BCM_I2C_DEV_ADDR(CXP_T_I2C_ADDR, "cxp_t", 0x50)
+BCM_I2C_DEV_ADDR(CXP_R_I2C_ADDR, "cxp_r", 0x54)
+BCM_I2C_DEV_ADDR(PCIE_SW_I2C_ADDR, "pcie_sw", 0x3c)
+BCM_I2C_DEV_ADDR_END
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h
new file mode 100644
index 0000000..e15f71a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/i2c/bcmolt_i2c_devs_ioctl.h
@@ -0,0 +1,24 @@
+#ifndef _BCMOLT_I2C_DEVS_IOCTL_H_
+#define _BCMOLT_I2C_DEVS_IOCTL_H_
+
+#include <linux/ioctl.h>
+
+typedef struct
+{
+    uint32_t count;
+    uint32_t addr;
+    uint32_t val;
+} maple_i2c_ioctl_param;
+
+#define MAPLE_I2C_IOCTL_MAGIC 'I'
+
+#define MAPLE_I2C_IOCTL_OP_DEV_CHANGE _IOW(MAPLE_I2C_IOCTL_MAGIC, 1, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_DEV_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 2, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_DEV_READ _IOWR(MAPLE_I2C_IOCTL_MAGIC, 3, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_SWITCH_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 4, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_SWITCH_READ _IOR(MAPLE_I2C_IOCTL_MAGIC, 5, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_FPGA_WRITE _IOW(MAPLE_I2C_IOCTL_MAGIC, 6, maple_i2c_ioctl_param)
+#define MAPLE_I2C_IOCTL_OP_FPGA_READ _IOWR(MAPLE_I2C_IOCTL_MAGIC, 7, maple_i2c_ioctl_param)
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/Makefile b/bcm68620_release/release/host_customized/ll_pcie/Makefile
new file mode 100755
index 0000000..db7aa7d
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/Makefile
@@ -0,0 +1,36 @@
+MOD_NAME = ll_pcie
+MOD_SUPPRESS_OS_DEP = y
+MOD_DEPS = board_selector
+
+ifeq ("$(RELEASE_BUILD)", "y")
+	EXTRA_CFLAGS += -I$(SRC_DIR) -I$(TOP_DIR)/host_customized/os_abstraction 
+	EXTRA_CFLAGS += -I$(TOP_DIR)/host_customized/os_abstraction/linux -I$(TOP_DIR)/host_driver/config
+else
+	EXTRA_CFLAGS += -I$(SRC_DIR) -I$(TOP_DIR)/common/os_abstraction -I$(TOP_DIR)/host/config
+	EXTRA_CFLAGS += -I$(TOP_DIR)/common/os_abstraction/linux -I$(TOP_DIR)/host/os_abstraction/$(PLATFORM)
+endif
+
+ifeq ("$(ENABLE_TRACE)", "y")
+	MOD_DEFS += -DTX_ENABLE_EVENT_TRACE
+	EXTRA_CFLAGS += -I$(TOP_DIR)/common/drivers/maple/fld
+    ifeq ("$(DEBUG_TRACE_INIT)", "y")
+       MOD_DEFS += -DDEBUG_TRACE_INIT
+    endif
+endif
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_module
+    srcs = bcmolt_llpcie.c 
+else
+    MOD_TYPE = lib
+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
+
+USE_LINT = yes
+
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c
new file mode 100755
index 0000000..4bb1507
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.c
@@ -0,0 +1,1010 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+    might use readl or ioread32
+*/
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/compiler.h>
+#include <linux/pci.h>
+#include <linux/pci_regs.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/proc_fs.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/gfp.h>
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/spinlock.h>
+
+#ifdef TX_ENABLE_EVENT_TRACE
+#include <linux/ctype.h>
+#include <linux/file.h>
+#include <linux/fs.h>
+#include "bcm_fld_common.h"
+#endif
+#include <bcmolt_board_selector.h>
+#include "bcmolt_llpcie.h"
+
+#define DRV_NAME	"maple"
+#define DRV_VERSION	"1.0.3"
+
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+/*
+bar 1 = 8  Mbyte register space
+bar 2 = 16 Mbyte DDR space
+bar 3 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406CU /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400U /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940CU /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300U /* Interrupt Status Register */
+
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+#define MAPLE_DRIVER_NAME   DRV_NAME " BCM68620 (Maple) PCI driver " DRV_VERSION
+
+struct proc_dir_entry *bcmolt_dir = NULL;
+static DEFINE_PCI_DEVICE_TABLE(maple_pci_tbl) =
+{ /* vendor_id,                  device_id,       any,       any */
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_DEVICE_ID)},
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_6863_SKU_DEVICE_ID)},
+    {PCI_DEVICE(PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_EPON_DEVICE_ID)},
+    {0}
+};
+MODULE_DEVICE_TABLE (pci, maple_pci_tbl);
+
+typedef struct
+{
+    bcm_ll_dev_info  device;
+    spinlock_t       lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;
+    unsigned int    *traceaddr;
+    struct pci_dev  *pdev;
+    int              enabled;
+} maple_device_info;
+
+static int crt_device = 0;
+static bcm_ll_pcie_status_change callback;
+static bcmos_bool is_initialized = BCMOS_FALSE;
+
+static maple_device_info devices[MAPLE_MAX_DEVICES];
+//static irqreturn_t maple_interrupt (int irq, void *dev_instance);
+static maple_device_info *get_maple_pci_info(int crt);
+
+static int maple_write(struct file *file,const char *buffer,size_t count, void *data);
+static int maple_read(char *page, char **start, off_t off, int count, int *eof, void *data);
+
+/* Map bus/device to device_id */
+static int _pcie_bus_devfv_to_devid(int bus, int devfn)
+{
+    const bus_devfn_devid *map;
+    for (map = bcmolt_board_pci_map_table_get(); map && map->bus > 0; map++)
+    {
+        if (map->bus == bus && map->devfn == devfn)
+        {
+            return map->device;
+        }
+    }
+    /* Not found - use incremental mapping */
+    return crt_device;
+}
+
+/* procedure used by OS to connect Maple PCI to allocated memory */
+
+static int __devinit maple_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+    int rc;
+    volatile unsigned int readval;
+    maple_device_info *device_info = NULL;
+    int dev_id;
+    u32 val;
+
+    if (!pdev)
+        return 1;
+
+    dev_info(&pdev->dev,
+        "Bus = %d Slot = %d Vendor:device = 0x%04x:0x%04x revision = 0x%02x\n",
+        pdev->bus->number, pdev->devfn,
+        pdev->vendor, pdev->device, pdev->revision);
+
+    if (crt_device == MAPLE_MAX_DEVICES)
+    {
+        printk(" Maximum Maple devices already defined (%d)\n", MAPLE_MAX_DEVICES);
+        return -ENODEV;
+    }
+
+    dev_id = _pcie_bus_devfv_to_devid(pdev->bus->number, pdev->devfn);
+    ++crt_device;
+    device_info = &devices[dev_id];
+    memset(device_info, 0, sizeof(maple_device_info));
+
+    spin_lock_init(&device_info->lock);
+    device_info->deviceid = dev_id;
+    device_info->pdev = pdev;
+
+    /* Enable maple device on PCIe bus and fixup BARs.
+     * Without fixup, module unload/reload crashes with WRX host
+     * because PCI hotplug doesn't work and after unload/re-load
+     * linux believes that BARs are already set.
+     */
+    rc = bcm_ll_pcie_dev_enable(dev_id);
+    if (rc)
+    {
+        printk("Error pci_enable_device_mem = %d\n",rc);
+        goto err_out;
+    }
+
+    rc = pci_request_selected_regions(pdev, pci_select_bars(pdev, IORESOURCE_MEM), DRV_NAME);
+    if (rc)
+        goto err_out;
+
+    pci_set_master(pdev);
+    pci_save_state(pdev);
+
+    device_info->device.soc_regs_base = (unsigned long)pci_ioremap_bar(pdev, BAR_REGS);
+    device_info->device.soc_sram_base = (unsigned long)pci_ioremap_bar(pdev, BAR_SRAM);
+    device_info->device.soc_ddr_base = (unsigned long)pci_ioremap_bar(pdev, BAR_DDR);
+    device_info->device.soc_ddr_length = (uint32_t)pci_resource_len(pdev, BAR_DDR);
+    device_info->device.irq = pdev->irq;
+    pci_set_drvdata(pdev, device_info);
+
+    //rc = request_irq(device_info->device.irq, maple_interrupt, IRQF_SHARED, "maple-pcie", device_info);
+    if (!rc && device_info->device.soc_sram_base)
+    {
+        device_info->device.irq_connected = 1;
+        readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+        printk("Card %d version major=%02x minor=%02x\n",device_info->deviceid,
+               ((readval & 0x0000ff00) >> 8),(readval & 0x000000ff));
+        printk("regs_start = 0x%lx\nddr_start  = 0x%lx\nsram_start = 0x%lx\nddr_length  = %d\n",
+                 device_info->device.soc_regs_base,device_info->device.soc_ddr_base,
+                 device_info->device.soc_sram_base, (int)device_info->device.soc_ddr_length);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_0,&val);
+        printk("BAR REGS = 0x%x\n",(unsigned int)val);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_2,&val);
+        printk("BAR DDR = 0x%x\n",(unsigned int)val);
+        pci_read_config_dword(pdev,PCI_BASE_ADDRESS_4,&val);
+        printk("BAR SRAM = 0x%x\n",(unsigned int)val);
+        readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+        device_info->err_status = readval & 0x0000000f;
+        device_info->phylink    = (readval >> 4) & 0x1;
+        device_info->datalink   = (readval >> 5) & 0x1;
+        device_info->prev_datalink  = device_info->datalink;
+    }
+    else
+        goto err_out;
+
+    return rc;
+
+err_out:
+    pci_disable_device (pdev);
+    memset(device_info, 0, sizeof(*device_info));
+    --crt_device;
+
+    return rc;
+}
+
+static void __devexit maple_pci_remove(struct pci_dev *pdev)
+{
+    int i;
+    maple_device_info *dev = pci_get_drvdata(pdev);
+
+    if (!dev)
+        return;
+
+    if (dev->device.irq_connected)
+    {
+        //free_irq(dev->device.irq, dev);
+        dev->device.irq_connected = 0;
+    }
+    if (callback)
+    {
+        for (i = 0; i < crt_device; i++)
+        {
+            if (devices[i].pdev == pdev)
+            {
+                callback(i, BCM_LL_PCIE_LINK_DOWN);
+                break;
+            }
+        }
+    }
+    pci_disable_device(pdev);
+    pci_release_regions(pdev);
+    pci_set_drvdata(pdev, NULL);
+    dev->device.soc_sram_base = 0;
+    dev->device.soc_regs_base = 0;
+    dev->pdev = NULL;
+}
+
+static struct pci_driver maple_pci_driver = {
+    .name       = DRV_NAME,
+    .id_table   = maple_pci_tbl,
+    .probe      = maple_pci_probe,
+    .remove     = __devexit_p(maple_pci_remove),
+};
+
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    unsigned int readval=0;
+    maple_device_info *device;
+
+    if (crt >= BCMTR_MAX_OLTS)
+        return NULL;
+
+    device = &devices[crt];
+    if (device->device.soc_regs_base)
+    {
+        if (device->enabled)
+        {
+            readval = bcm_pci_read32((uint32_t *)(device->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+            device->err_status = readval & 0x0000000f;
+            device->phylink    = (readval >> 4) & 0x1;
+            device->datalink   = (readval >> 5) & 0x1;
+        }
+        else
+        {
+            device->err_status = 0;
+            device->phylink    = 0;
+            device->datalink   = 0;
+        }
+    }
+    else
+        device = NULL;
+
+    return device;
+}
+
+#if 0
+static irqreturn_t maple_interrupt (int irq, void *dev_instance)
+{
+    volatile unsigned int value;
+    maple_device_info *device_info;
+    unsigned long flags;
+    int handled = IRQ_NONE;
+    uint32_t device;
+
+    spin_lock_irqsave(&device_info->lock, flags);
+    value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    if (value)
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printk("Device=%d : Link is up !!!\n", device);
+            else
+            {
+                printk("Device=%d : Link is down !!!\n", device);
+                printk("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (callback)
+                callback(device, device_info->datalink);
+        }
+        value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        if (!value)
+            handled = IRQ_HANDLED;
+    }
+    spin_unlock_irqrestore(&device_info->lock, flags);
+
+    return IRQ_RETVAL(handled);
+}
+#endif
+
+/* Returns BAR register address */
+static int _pci_bar_reg_addr(int res)
+{
+    return 0x10 + res*4;
+}
+
+static void _pci_update_resource(struct pci_dev *dev, int resno)
+{
+        struct pci_bus_region region;
+        u16 cmd;
+        u32 new, check, mask;
+        int reg;
+        struct resource *res = dev->resource + resno;
+
+        /*
+         * Ignore resources for unimplemented BARs and unused resource slots
+         * for 64 bit BARs.
+         */
+        if (!res->flags)
+                return;
+
+        /*
+         * Ignore non-moveable resources.  This might be legacy resources for
+         * which no functional BAR register exists or another important
+         * system resource we shouldn't move around.
+         */
+        if (res->flags & IORESOURCE_PCI_FIXED)
+                return;
+
+        pcibios_resource_to_bus(dev, &region, res);
+
+        new = region.start | (res->flags & PCI_REGION_FLAG_MASK);
+        if (res->flags & IORESOURCE_IO)
+                mask = (u32)PCI_BASE_ADDRESS_IO_MASK;
+        else
+                mask = (u32)PCI_BASE_ADDRESS_MEM_MASK;
+
+        reg = _pci_bar_reg_addr(resno);
+
+        pci_write_config_dword(dev, reg, new);
+        pci_read_config_dword(dev, reg, &check);
+
+        if ((new ^ check) & mask) {
+                dev_err(&dev->dev, "BAR %d: error updating (%#08x != %#08x)\n",
+                        resno, new, check);
+        }
+
+        if (res->flags & IORESOURCE_MEM_64) {
+                new = region.start >> 16 >> 16;
+                pci_write_config_dword(dev, reg + 4, new);
+                pci_read_config_dword(dev, reg + 4, &check);
+                if (check != new) {
+                        dev_err(&dev->dev, "BAR %d: error updating "
+                               "(high %#08x != %#08x)\n", resno, new, check);
+                }
+        }
+
+        pci_read_config_word(dev, PCI_COMMAND, &cmd);
+        pci_write_config_word(dev, PCI_COMMAND, cmd | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+
+        res->flags &= ~IORESOURCE_UNSET;
+        dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
+                resno, res, (unsigned long long)region.start,
+                (unsigned long long)region.end);
+}
+
+/* Enable PCI access to device */
+bcmos_errno bcm_ll_pcie_dev_enable(int dev_id)
+{
+    maple_device_info *device;
+    int rc;
+
+    if (dev_id >= MAPLE_MAX_DEVICES)
+        return BCM_ERR_PARM;
+
+    device = &devices[dev_id];
+    if (!device->pdev)
+        return BCM_ERR_IO;
+
+    rc = pci_enable_device_mem(device->pdev);
+    if (rc)
+    {
+        printk("Error pci_enable_device_mem for device %d = %d\n", dev_id, rc);\
+        goto out;
+    }
+
+    /* Refresh devices's PCIe header */
+    _pci_update_resource(device->pdev, BAR_REGS);
+    _pci_update_resource(device->pdev, BAR_SRAM);
+    _pci_update_resource(device->pdev, BAR_DDR);
+    device->enabled = 1;
+
+out:
+    return rc ? BCM_ERR_IO : BCM_ERR_OK;
+}
+
+/* Disable PCI access to device */
+bcmos_errno bcm_ll_pcie_dev_disable(int dev_id)
+{
+    maple_device_info *device;
+
+    printk("%s: device %d\n", __FUNCTION__, dev_id);
+
+    if (dev_id >= MAPLE_MAX_DEVICES)
+        return BCM_ERR_PARM;
+
+    device = &devices[dev_id];
+    if (!device->pdev || !device->enabled)
+        return BCM_ERR_OK;
+    pci_disable_device(device->pdev);
+    device->enabled = 0;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_init(void)
+{
+    int rc;
+    if (is_initialized)
+        return BCM_ERR_OK;
+    is_initialized = BCMOS_TRUE;
+    rc = pci_register_driver(&maple_pci_driver);
+    printk(KERN_INFO "Maple PCI driver registered with PCI subsystem. rc=%d\n", rc);
+    return rc ? BCM_ERR_INTERNAL : BCM_ERR_OK;
+}
+
+void bcm_ll_pcie_cleanup(void)
+{
+    if (!is_initialized)
+        return;
+    is_initialized = BCMOS_FALSE;
+
+    pci_unregister_driver(&maple_pci_driver);
+    crt_device = 0;
+    memset(devices, 0, sizeof(devices));
+}
+
+/*******************************************/
+/* procedures executed on insmod and rmmod */
+/*******************************************/
+static int __init bcm_ll_init_module(void)
+{
+    struct proc_dir_entry *bcmolt_file = NULL;
+
+    if ((bcmolt_dir = create_proc_entry("bcmolt", S_IFDIR, NULL)) == NULL)
+    {
+        printk("Unable to create /proc/bcmolt entry\n");
+        return -1;
+    }
+    if ((bcmolt_file = create_proc_entry("card", S_IFREG | S_IWUSR | S_IRUGO, bcmolt_dir)) == NULL)
+    {
+        printk("Unable to create /proc/bcmolt/card entry\n");
+        remove_proc_entry("bcmolt", bcmolt_dir);
+        return -1;
+    }
+    bcmolt_file->write_proc = (write_proc_t *)maple_write;
+    bcmolt_file->read_proc = (read_proc_t *)maple_read;
+
+    return 0;
+}
+
+static void __exit bcm_ll_cleanup_module(void)
+{
+    bcm_ll_pcie_cleanup();
+    remove_proc_entry("card", bcmolt_dir);
+    remove_proc_entry("bcmolt", NULL);
+    printk("Unregister done\n");
+}
+
+/*****************************/
+/* APIs used by Host drivers */
+/*****************************/
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *device_info;
+
+    callback = cb;
+    if(callback)
+    {
+        for (i = 0; i < crt_device; i++)
+        {
+            device_info = get_maple_pci_info(i);
+            if (device_info)
+                callback(i, device_info->datalink);
+            else
+                callback(i, BCM_LL_PCIE_LINK_DOWN);
+        }
+    }
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    callback = NULL;
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *device_info;
+
+    if (!info)
+        return BCM_ERR_PARM;
+
+    if (dev_id < MAPLE_MAX_DEVICES)
+    {
+        device_info = get_maple_pci_info(dev_id);
+        if (device_info && device_info->pdev)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+                return BCM_ERR_IO;
+            *info = device_info->device;
+            return BCM_ERR_OK;
+        }
+        return BCM_ERR_IO;
+    }
+    return BCM_ERR_RANGE;
+}
+
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+
+    if (dev_id < crt_device)
+    {
+        device_info = get_maple_pci_info(dev_id);
+        return (device_info ? device_info->pdev : NULL);
+    }
+
+    return NULL;
+}
+
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(devices[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET), val);
+
+    return BCM_ERR_OK;
+}
+
+#ifdef TX_ENABLE_EVENT_TRACE
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+    uint32_t val,lim,base,size;
+    uint32_t reglo,reghi,baselim;
+    unsigned long addr;
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+            return BCM_ERR_IO;
+        size = EVENT_BUFFER_SIZE;
+        device_info->traceaddr = (unsigned int *)bcmos_alloc_not_cache(size);
+        memset(device_info->traceaddr,0,size);
+        addr = bcmos_virt_to_phys(device_info->traceaddr); /* | 0x02 = reverse byte order = swap */
+        printk("trace window : alloc=0x%lx size=0x%x\n",(unsigned long)device_info->traceaddr, (unsigned int)size);
+        reglo = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO;
+        reghi = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI;
+        baselim = PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT;
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + reglo),addr & 0xffffffff);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + reghi)),((addr >> 32) & 0xffffffff);
+        /* base */
+        base = CPU_2_PCIE_MEM_WIN1_BASE;
+        /* limit */
+        lim = base + size;
+        val = lim  | (base >> 16);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_regs_base + baselim),val);
+        //bcm_fld_set_event_trace(dev_id);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_sram_base + BCM_FLD_EVENT_TRACE_OFFSET),0x1);
+
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id)
+{
+    maple_device_info *device_info;
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+            return BCM_ERR_IO;
+        //bcm_fld_clear_event_trace(dev_id);
+        bcm_pci_write32((uint32_t *)(device_info->device.soc_sram_base + BCM_FLD_EVENT_TRACE_OFFSET),0x0);
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename)
+{
+    maple_device_info *device_info;
+    struct file         *fp;
+    unsigned long seg   = 0;
+    mm_segment_t memseg;
+
+    if (!tracefilename)
+        return BCM_ERR_PARM;
+
+    printk("device=%d from=%d, Go to write to file %s\n",dev_id , crt_device, tracefilename);
+
+    if (dev_id < crt_device)
+    {
+        device_info = &devices[dev_id];
+        if (!device_info)
+        {
+            printk("Error: device_info is null\n");
+            goto exit;
+        }
+        fp = filp_open(tracefilename, O_WRONLY | O_CREAT, 0666);
+        if ((fp == NULL) || (fp == (void *)-ENOENT))
+        {
+            printk("Error: Can't open file %s\n",tracefilename);
+            goto exit;
+        }
+        // Get current segment descriptor
+        seg = get_fs().seg;
+
+        // Set segment descriptor associated to kernel space
+        set_fs(get_ds());
+        fp->f_op->write(fp, (char *)device_info->traceaddr,EVENT_BUFFER_SIZE, &fp->f_pos);
+
+        memseg.seg = seg;
+        set_fs(memseg);
+        filp_close(fp, NULL);
+        printk("Wrote file %s\n",tracefilename);
+exit:
+        bcmos_free_not_cache(device_info->traceaddr);
+
+        return BCM_ERR_OK;
+    }
+    return BCM_ERR_RANGE;
+}
+#endif
+
+/*************************************************************/
+/* User interface functions : implement echo/cat to proc file*/
+/*************************************************************/
+
+typedef struct
+{
+    char *name;
+	void (*callback)(int cmdid, char *cmd);
+    char *description;
+} maple_card_command;
+
+static char *find_command(char *cmd);
+static void command_reg(int cmdid, char *line);
+static void command_mem(int cmdid, char *line);
+static void command_cfg(int cmdid, char *line);
+#ifdef TX_ENABLE_EVENT_TRACE
+static void command_trace(int cmdid, char *line);
+#endif
+
+#define READCMD     0
+#define WRITECMD    1
+
+static maple_card_command commands[] =
+{
+    {"readreg",     command_reg, "read register <index> <register offset - hex>"},
+    {"writereg",    command_reg, "write register <index> <register offset - hex> <value - hex>"},
+    {"read",        command_mem, "read <address - hex> <number of words - dec>"},
+    {"write",       command_mem, "write <address - hex> <value - hex>"},
+    {"rcfg",        command_cfg, "read dev <address - hex> <number of words - dec>"},
+    {"wcfg",        command_cfg, "write dev <address - hex> <value - hex>"},
+#ifdef TX_ENABLE_EVENT_TRACE
+    {"trace",       command_trace, "trace <index> on/off/save tx trace"},
+#endif
+    {NULL, NULL, NULL}
+};
+
+static char *find_command(char *cmd)
+{
+    char *rest;
+    int i = 0;
+    maple_card_command *cmdptr = &commands[0];
+
+    cmd = skip_spaces(cmd);
+    if (!strncmp(cmd,"help",strlen("help")))
+    {
+        while (cmdptr->name)
+        {
+            printk("%s\t: %s\n",cmdptr->name, cmdptr->description);
+            cmdptr = &commands[++i];
+        }
+        return NULL;
+    }
+    while (cmdptr->name)
+    {
+        if (!strncmp(cmdptr->name, cmd, strlen(cmdptr->name)))
+        {
+            rest = cmd + strlen(cmdptr->name);
+            rest = skip_spaces(rest);
+            cmdptr->callback(i%2, rest);
+            return NULL;
+        }
+        cmdptr = &commands[++i];
+    }
+
+    return "Wrong command name";
+}
+/**********************************************************************
+  answers to cat /proc/bcmolt command
+**********************************************************************/
+static int maple_read(char *page, char **start, off_t off, int count, int *eof, void *data)
+{
+    int i;
+    int len;
+    maple_device_info *dev = NULL;
+
+    len = sprintf(page, "Maple Device Info\n\n");
+    for (i = 0; i < MAPLE_MAX_DEVICES; i++)
+    {
+        dev = get_maple_pci_info(i);
+        if (dev)
+        {
+            len += sprintf(page + len, "id=%d regs_start=0x%lx ddr_start=0x%lx sram_start=0x%lx ddr_length=%d\n",
+                dev->deviceid,
+                dev->device.soc_regs_base,dev->device.soc_ddr_base,
+                dev->device.soc_sram_base, (int)dev->device.soc_ddr_length);
+            len += sprintf(page + len, "Phy Link is %s Data Link is %s Error status = %d\n\n",
+                dev->phylink == 1 ? "UP" : "DOWN", dev->datalink == 1 ? "UP" : "DOWN", (int)dev->err_status);
+        }
+    }
+
+    return len;
+}
+#ifdef TX_ENABLE_EVENT_TRACE
+static void command_trace(int cmdid, char *line)
+{
+    char token[5];
+    int  index;
+
+    if (sscanf(line, "%d %s", &index, token) != 2)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    printk("TRACE commands : %s\n",token);
+    if (!strncmp(token,"on",2))
+    {
+        //on
+        bcm_ll_pcie_setrace(index);
+        return;
+    }
+    if (!strncmp(token,"off",3))
+    {
+        // off
+        bcm_ll_pcie_cleartrace(index);
+        return;
+    }
+    if (!strncmp(token,"save",4))
+    {
+        //get
+        char filename[20];
+        sprintf(filename,"./tt_trace_%d.trx",index);
+        bcm_ll_pcie_savetrace(index,filename);
+        return;
+    }
+    printk("Wrong command\n");
+}
+#endif
+
+
+static void command_reg(int cmdindex, char *line)
+{
+    char *rest;
+    char *token;
+    int  index;
+    unsigned long address;
+    unsigned int reg;
+
+    if (sscanf(line, "%d %lx", &index, &address) != 2)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    address += (unsigned long)devices[index].device.soc_regs_base;
+    switch (cmdindex)
+    {
+    case READCMD:
+        reg = bcm_pci_read32((uint32_t *)address);
+        printk("0x%lx : %08x\n", address, reg);
+        break;
+    case WRITECMD:
+        rest = line;
+        token = strsep(&rest, " "); /* skip index */
+        token = strsep(&rest, " "); /* skip address */
+        token = strsep(&rest, " ");
+        if (!token)
+        {
+            printk("Wrong parameter\n");
+            return;
+        }
+        sscanf(token, "%x", &reg);
+        printk("write 0x%x to 0x%lx\n", reg, address);
+        bcm_pci_write32((uint32_t *)address,reg);
+        break;
+    }
+}
+
+static void command_mem(int cmdindex, char *line)
+{
+    char *token;
+    char *rest;
+    unsigned long address;
+    unsigned int reg;
+    int i, number_of_words;
+    int in_line=0, max_in_line;
+
+    if (sscanf(line, "%lx", &address) != 1)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+    rest = line;
+    token = strsep(&rest, " "); /* skip address */
+    switch (cmdindex)
+    {
+    case READCMD:
+        token = strsep(&rest, " ");
+        if (!token)
+            number_of_words = 1;
+        else
+            sscanf(token, "%d", &number_of_words);
+
+        max_in_line = 4;
+        for (i = 0; i < number_of_words; i++, address += 4)
+        {
+            if (!in_line)
+                printk("%08lx: ", address);
+            reg = bcm_pci_read32((uint32_t *)address);
+            printk("%08x", reg);
+            if (++in_line < max_in_line)
+                printk(" ");
+            else
+            {
+                printk("\n");
+                in_line = 0;
+            }
+        }
+        if (in_line)
+            printk("\n");
+        break;
+    case WRITECMD:
+        token = strsep(&rest, " ");
+        if (!token)
+        {
+            printk("Wrong parameter\n");
+            return;
+        }
+        sscanf(token, "%x", &reg);
+        bcm_pci_write32((uint32_t *)address,reg);
+        break;
+    }
+}
+
+static void command_cfg(int cmdindex, char *line)
+{
+    unsigned long address;
+    unsigned int reg;
+    unsigned int val_or_num;
+    int crt;
+    int i;
+    int in_line=0, max_in_line;
+    maple_device_info *device;
+
+    if (sscanf(line, "%d %lx %x", &crt, &address, &val_or_num) != 3)
+    {
+        printk("Wrong parameter\n");
+        return;
+    }
+
+    if (crt >= crt_device || !devices[crt].pdev)
+    {
+        printk("Invalid device %d\n", crt);
+        return;
+    }
+
+    device = &devices[crt];
+
+    switch (cmdindex)
+    {
+    case READCMD:
+        max_in_line = 4;
+        for (i = 0; i < val_or_num; i++, address += 4)
+        {
+            if (!in_line)
+                printk("%08lx: ", address);
+            pci_read_config_dword(device->pdev, address, &reg);
+            printk("%08x", reg);
+            if (++in_line < max_in_line)
+                printk(" ");
+            else
+            {
+                printk("\n");
+                in_line = 0;
+            }
+        }
+        if (in_line)
+            printk("\n");
+        break;
+
+    case WRITECMD:
+        pci_write_config_dword(device->pdev, address, val_or_num);
+        break;
+    }
+}
+
+/**********************************************************************
+  answers to echo [...] > /proc/bcmolt command
+**********************************************************************/
+static int maple_write(struct file *file,const char *buffer,size_t count, void *data)
+{
+    char *internal;
+
+    if (buffer == NULL)
+        return -EFAULT;
+
+    internal = kmalloc(count, GFP_KERNEL);
+    if (!internal)
+    {
+        printk("Not enough memmory\n");
+        return count;
+    }
+
+    memset(internal, 0, count);
+    if (copy_from_user(internal, buffer, count))
+    {
+        printk("Not enough memmory\n");
+        goto error;
+    }
+    find_command(internal);
+
+error:
+    kfree(internal);
+
+    return count;
+}
+
+EXPORT_SYMBOL(bcmolt_dir);
+EXPORT_SYMBOL(bcm_ll_pcie_init);
+EXPORT_SYMBOL(bcm_ll_pcie_cleanup);
+EXPORT_SYMBOL(bcm_ll_pcie_status_change_register);
+EXPORT_SYMBOL(bcm_ll_pcie_status_change_unregister);
+EXPORT_SYMBOL(bcm_ll_pcie_query);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_get);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_enable);
+EXPORT_SYMBOL(bcm_ll_pcie_dev_disable);
+EXPORT_SYMBOL(bcm_ll_pcie_host_reset_enable);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+EXPORT_SYMBOL(bcm_ll_pcie_setrace);
+EXPORT_SYMBOL(bcm_ll_pcie_cleartrace);
+EXPORT_SYMBOL(bcm_ll_pcie_savetrace);
+#endif
+module_init(bcm_ll_init_module);
+module_exit(bcm_ll_cleanup_module);
+
+MODULE_DESCRIPTION("maple line card");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h
new file mode 100755
index 0000000..bd1a60e
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/bcmolt_llpcie.h
@@ -0,0 +1,134 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define MAPLE_MAX_DEVICES               BCMTR_MAX_OLTS
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+    int             irq_connected;      /**< Device irq number connected */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/* Initialize low-level PCIe driver
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_INTERNAL - failed to register with PCI subsystem
+ */
+bcmos_errno bcm_ll_pcie_init(void);
+
+/* Cleanup low-level PCIe driver */
+void bcm_ll_pcie_cleanup(void);
+
+/** Enable PCI access to device
+ * \param[in]   dev_id  Device id
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_PARM-dev_id is invalid
+ *   - BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_dev_enable(int dev_id);
+
+/** Disable PCI access to device
+ * \param[in]   dev_id  Device id
+ * \return
+ *   - 0=OK
+ *   - BCM_ERR_PARM-dev_id is invalid
+ */
+bcmos_errno bcm_ll_pcie_dev_disable(int dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+
+#endif
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c
new file mode 100644
index 0000000..df6d3c0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.c
@@ -0,0 +1,410 @@
+/*
+<: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 <vxWorks.h>
+#include <drv/pci/pciConfigLib.h>
+#include "bcmolt_llpcie.h"
+
+/* Define PCIE device BAR registers */
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+
+/* 
+Define PCIE device BAR space length:
+    bar 1 = 8  Mbyte register space 
+    bar 2 = 16 Mbyte DDR space 
+    bar 3 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+/* Define special registers address */
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U	
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U	
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406C /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400 /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940C /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300 /* Interrupt Status Register */       	
+
+/* Maple device ID */
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862 
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+/* Define interrupt vector number according BCM53003 BSP */
+#define PCIE1_IV_0 86
+#define PCIE1_IV_1 87
+#define PCIE1_INT_LINE 4
+
+/* Maple device object struct */
+typedef struct  
+{
+    bcm_ll_dev_info  device;
+    bcmos_fastlock   lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;  // start from 0
+    unsigned int    *traceaddr;
+    void  *pdev;
+    int pciBusNo;       /* PCI bus number */
+    int pciDevNo;       /* PCI device number */
+    int pciFuncNo;      /* PCI function number */
+    uint32_t dev_status_irq;
+} maple_device_info;
+
+/* Maple device objects */
+static maple_device_info devices[MAPLE_MAX_DEVICES];
+int crt_device = 0;
+
+/* Device PCIE interface status change callback */
+static bcm_ll_pcie_status_change callback;
+
+/** Device status change ISR
+ * \irq          IRQ number
+ * \dev_instance device object 
+ */
+int dev_status_interrupt (int irq, void *dev_instance)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t reg_value = 0;
+    maple_device_info *device_info = NULL;   
+    long flags = 0;
+    int handled = 0;
+    uint32_t dev_id = 0;
+    
+    device_info = (maple_device_info *)dev_instance;
+    dev_id = device_info->deviceid;
+    
+    flags = bcmos_fastlock_lock(&device_info->lock);
+
+    reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printf("Device=%d : Link is up !!!\n", dev_id);
+            else
+            {
+                printf("Device=%d : Link is down !!!\n", dev_id);
+                printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (callback)
+            {
+                callback(dev_id, device_info->datalink); 
+            }
+        }
+        reg_value = bcm_pci_read32(
+                        (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        {
+            handled = 1;
+        }
+    }
+    
+    bcmos_fastlock_unlock(&device_info->lock, flags);
+    
+    return handled;
+}
+
+/** Maple device detection and initialization
+ */
+bcmos_errno bcm_ll_pcie_interface_init()
+{
+    STATUS ret_status;
+    maple_device_info *dev_info = NULL; 
+    uint32_t readval = 0;
+    uint8_t readvalb = 0;
+    bcmos_errno err = BCM_ERR_OK;
+    uint8_t irq = 0;
+    uint16_t device_id;
+
+    printf("%s()\r\n", __FUNCTION__);
+
+    // check maple device number
+    if (crt_device == MAPLE_MAX_DEVICES)
+    {
+        printf(" Maximum Maple devices already defined (%d)\n", MAPLE_MAX_DEVICES);
+        return BCM_ERR_ALREADY;
+    } 
+    // Init device object struct
+    dev_info = &devices[crt_device++];
+    memset(dev_info, 0, sizeof(maple_device_info));
+    
+    // find maple 6862 device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    // find maple 6863 device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_6863_SKU_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    // find maple epon device
+    ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+        PCIE_MAPLE_EPON_DEVICE_ID,
+        0,
+        &dev_info->pciBusNo,
+        &dev_info->pciDevNo,
+        &dev_info->pciFuncNo);
+
+    if (OK == ret_status)
+    {
+        device_id = PCIE_MAPLE_EPON_DEVICE_ID;
+        goto found_device_id;
+    }
+
+    printf("Can't find any device[%d]\n", PCIE_MAPLE_VENDOR_ID);
+    return BCM_ERR_NODEV;
+
+found_device_id:
+    printf("Found maple device[%x - %x]\n", PCIE_MAPLE_VENDOR_ID, device_id);
+
+    // init    
+    dev_info->deviceid = (crt_device - 1);
+    dev_info->pdev = NULL;
+
+
+    // Enable PCI address map
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8 *)&readvalb);
+    printf("CMD reg = 0x%x\n", readvalb);
+
+    readvalb |= 0x6;
+    pciConfigOutByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8)readvalb);
+
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_COMMAND,
+                    (UINT8 *)&readvalb);
+    printf("Adjusted CMD reg = 0x%x\n", readvalb);
+
+    // Init base addresses
+    dev_info->device.soc_regs_base = 0xe0000000;
+    dev_info->device.soc_sram_base = 0xe2000000;
+    dev_info->device.soc_ddr_base  = 0xe1000000;
+    dev_info->device.soc_ddr_length = 0x1000000; // 16M
+
+    // init interrupt line
+    readvalb = PCIE1_INT_LINE;
+    pciConfigOutByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_DEV_INT_LINE,
+                    (UINT8)readvalb);
+    pciConfigInByte(dev_info->pciBusNo,
+                    dev_info->pciDevNo,
+                    dev_info->pciFuncNo,
+                    PCI_CFG_DEV_INT_LINE,
+                    (UINT8 *)&readvalb);
+    printf("Adjusted INT Line reg = 0x%x\n", readvalb);
+
+    // init interrupt
+    dev_info->device.irq = PCIE1_IV_0;
+    dev_info->dev_status_irq = PCIE1_IV_1;
+
+    // read revision register
+    readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+    printf("readval = 0x%x\n", readval);
+    printf("Card %d version major=%02x minor=%02x\n",
+                dev_info->deviceid, 
+                ((readval & 0x0000ff00) >> 8),
+                (readval & 0x000000ff)); 
+    
+    // read status register
+    readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    printf("readval = 0x%x\n", readval);
+    dev_info->err_status = (readval & 0x0000000f);
+    dev_info->phylink    = ((readval >> 4) & 0x1);
+    dev_info->datalink   = ((readval >> 5) & 0x1);
+    dev_info->prev_datalink  = dev_info->datalink;
+
+    // connect INT for device status
+    bcmos_fastlock_init(&dev_info->lock, 0);
+    bcmos_int_connect((int)dev_info->dev_status_irq, 
+                        0, 
+                        BCMOS_IRQ_SHARED, 
+                        dev_status_interrupt, 
+                        "status_isr", 
+                        dev_info);
+
+    return BCM_ERR_OK;
+}
+
+/** Get Maple device object struct
+ * \crt devie index,start from 0
+ */
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t readval = 0;
+    maple_device_info *device_info = NULL;
+
+    /* check input parameter */
+    if (MAPLE_MAX_DEVICES <= crt)
+    {
+        return NULL;
+    }
+    device_info = &devices[crt];
+
+    /* read status register */
+    readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    device_info->err_status = (readval & 0x0000000f);
+    device_info->phylink    = ((readval >> 4) & 0x1);
+    device_info->datalink   = ((readval >> 5) & 0x1);
+
+    /* return device */
+    return device_info;
+}
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0 
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *dev_info; 
+    
+    callback = cb;
+    for (i = 0; i < crt_device; i++)
+    {
+        dev_info = get_maple_pci_info(i);
+        callback(i, dev_info->datalink);
+    }
+    
+    return BCM_ERR_OK;
+}
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    callback = NULL;
+    
+    return BCM_ERR_OK;
+}
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *dev_info; 
+    
+    if (NULL == info)
+    {
+        return BCM_ERR_PARM;
+    }
+    
+    if (dev_id < crt_device)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+        {
+            return BCM_ERR_IO;
+        }
+
+        *info = dev_info->device;
+        return BCM_ERR_OK;
+    }
+    
+    return BCM_ERR_RANGE;   
+}
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *dev_info; 
+    
+    if (dev_id < MAPLE_MAX_DEVICES)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        return dev_info->pdev;
+    } 
+    
+    return NULL;
+}
+
+/** Host reset enable 
+ * \enabled 
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(devices[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET) , val);
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h
new file mode 100644
index 0000000..d484976
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/bcmolt_llpcie.h
@@ -0,0 +1,105 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define MAPLE_MAX_DEVICES               1 /* 5 */
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+#endif
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c
new file mode 100755
index 0000000..1de7475
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.c
@@ -0,0 +1,505 @@
+/*
+<: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 <vxWorks.h>
+#include <drv/pci/pciConfigLib.h>
+#include "bcmolt_llpcie.h"
+
+/* Define PCIE device BAR registers */
+#define BAR_REGS                        0
+#define BAR_DDR                         2
+#define BAR_SRAM                        4
+
+/* 
+Define PCIE device BAR space length:
+    bar 0 = 8  Mbyte register space 
+    bar 2 = 16 Mbyte DDR space 
+    bar 4 = 64 Kbyte SRAM space
+*/
+#define MAPLE_REGS_LENGTH                   0x00800000
+#define MAPLE_DDR_LENGTH                    0x01000000
+#define MAPLE_SRAM_LENGTH                   0x00010000
+
+/* Define special registers address */
+#ifdef TX_ENABLE_EVENT_TRACE
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_LO			0x064014U	
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_HI			0x064018U
+#define PCIE_PCIE_0_MISC_CPU_2_PCIE_MEM_WIN1_BASE_LIMIT	0x064074U	
+#endif
+#define PCIE_REVISION_REGISTER_OFFSET       0x6406C /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_REVISION    */
+#define PCIE_STATUS_REGISTER_OFFSET         0x64068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+#define PCIE_HARD_DEBUG_REGISTER_OFFSET     0x64204U /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_HARD_DEBUG  */
+#define PCIE_INT_STATUS_REGISTER_OFFSET     0x69400 /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_STATUS        */
+#define PCIE_INT_CLEAR_MASK_OFFSET          0x6940C /* PCIE_PCIE_PCIE_0_CPU_INTR1_INTR_MASK_CLEAR    */
+#define PCIE_INTR1_STATUS_REGISTER_OFFSET   0x69300 /* Interrupt Status Register */       	
+
+/* Maple device ID */
+#define PCIE_MAPLE_VENDOR_ID                0x14E4 /* PCIE_CFG_TYPE0_EP_SUBSYSTEM_ID_VENDOR_ID      */
+#define PCIE_MAPLE_DEVICE_ID                0x6862 
+#define PCIE_MAPLE_6863_SKU_DEVICE_ID       0x6863
+#define PCIE_MAPLE_EPON_DEVICE_ID           0x5554
+
+/* Define interrupt vector number for MPC8308 */
+#define DRV_PCIE_INT_IRQ_BASE 96
+#define PCIE_DEV0_IV_0   (DRV_PCIE_INT_IRQ_BASE + 24)
+#define PCIE_DEV0_IV_1   (DRV_PCIE_INT_IRQ_BASE + 25)
+#define PCIE_DEV1_IV_0   (DRV_PCIE_INT_IRQ_BASE + 0)
+#define PCIE_DEV1_IV_1   (DRV_PCIE_INT_IRQ_BASE + 1)
+
+/* Maple device object struct */
+typedef struct  
+{
+    uint32_t llpcie_irq;
+    uint32_t llpcie_status_irq;
+} maple_llpcie_device_irqs;
+
+maple_llpcie_device_irqs llpcie_device_irqs[BCMOLT_MAX_MAPLE_DEVICES] =
+{
+    {PCIE_DEV0_IV_0,PCIE_DEV0_IV_1},
+    {PCIE_DEV1_IV_0,PCIE_DEV1_IV_1}
+};
+
+
+#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY 
+
+typedef struct 
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+
+} maple_llpcie_base_addresses;
+
+maple_llpcie_base_addresses llpcie_base_addresses[BCMOLT_MAX_MAPLE_DEVICES] =
+{
+     {.soc_regs_base = 0xe0000000, .soc_sram_base = 0xe2000000, .soc_ddr_base  = 0xe1000000},
+     /* in this example there is only one device*/
+     {.soc_regs_base = 0x00000000, .soc_sram_base = 0x00000000, .soc_ddr_base  = 0x00000000}
+};
+#endif
+
+/* Maple device object struct */
+typedef struct  
+{
+    bcm_ll_dev_info  device;
+    bcmos_fastlock   lock;
+    int              err_status;
+    int              phylink;
+    int              prev_datalink;
+    int              datalink;
+    uint32_t         deviceid;  // start from 0
+    unsigned int    *traceaddr;
+    void  *pdev;
+    int pciBusNo;       /* PCI bus number */
+    int pciDevNo;       /* PCI device number */
+    int pciFuncNo;      /* PCI function number */
+    uint32_t dev_status_irq;
+} maple_device_info;
+
+/* Maple device objects */
+maple_device_info g_maple_devs_info[BCMOLT_MAX_MAPLE_DEVICES];
+
+int g_maple_dev_num = 0;
+
+/* Device PCIE interface status change callback */
+bcm_ll_pcie_status_change g_dev_status_change_cb;
+
+/** Device status change ISR
+ * \irq          IRQ number
+ * \dev_instance device object 
+ */
+int dev_status_interrupt (int irq, void *dev_instance)
+{
+    uint32_t reg_value = 0;
+    maple_device_info *device_info = NULL;   
+    long flags = 0;
+    int handled = 0;
+    uint32_t dev_id = 0;
+    
+    device_info = (maple_device_info *)dev_instance;
+    dev_id = device_info->deviceid;
+    
+    flags = bcmos_fastlock_lock(&device_info->lock);
+
+    reg_value = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_INT_STATUS_REGISTER_OFFSET));
+    {
+        if (device_info->datalink != device_info->prev_datalink)
+        {
+            if (device_info->datalink == BCM_LL_PCIE_LINK_UP)
+                printf("Device=%d : Link is up !!!\n", dev_id);
+            else
+            {
+                printf("Device=%d : Link is down !!!\n", dev_id);
+                printf("phy status = 0x%x error status = 0x%x\n", device_info->phylink, device_info->err_status);
+            }
+            device_info->prev_datalink = device_info->datalink;
+            if (g_dev_status_change_cb)
+            {
+                g_dev_status_change_cb(dev_id, device_info->datalink); 
+            }
+        }
+        reg_value = bcm_pci_read32(
+                        (uint32_t *)(device_info->device.soc_regs_base + PCIE_INTR1_STATUS_REGISTER_OFFSET));
+        {
+            handled = 1;
+        }
+    }
+    
+    bcmos_fastlock_unlock(&device_info->lock, flags);
+    
+    return handled;
+}
+
+/** Maple device detection and initialization
+ */
+bcmos_errno bcm_ll_pcie_interface_init()
+{
+    STATUS ret_status;
+    maple_device_info *dev_info = NULL; 
+    uint32_t readval = 0;
+    uint8_t readvalb = 0;
+    uint32_t pci_dev_idx = 0;
+
+    printf("%s()\r\n", __FUNCTION__);
+
+    // check maple device number
+    if (g_maple_dev_num >= BCMOLT_MAX_MAPLE_DEVICES)
+    {
+        printf("Maximum Maple devices already defined (%d)\n", BCMOLT_MAX_MAPLE_DEVICES);
+        return BCM_ERR_ALREADY;
+    } 
+
+    // Support multiple Maple devices
+    for (pci_dev_idx = 0; pci_dev_idx < BCMOLT_MAX_MAPLE_DEVICES; pci_dev_idx++)
+    {
+        uint16_t device_id;
+
+        // Init device object struct
+        dev_info = &g_maple_devs_info[pci_dev_idx];
+        memset(dev_info, 0, sizeof(maple_device_info));
+        
+        // Try to find maple device
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_6863_SKU_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_6863_SKU_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        ret_status = pciFindDevice(PCIE_MAPLE_VENDOR_ID,
+            PCIE_MAPLE_EPON_DEVICE_ID,
+            pci_dev_idx,
+            &dev_info->pciBusNo,
+            &dev_info->pciDevNo,
+            &dev_info->pciFuncNo);
+
+        if (ret_status == OK)
+        {
+            device_id = PCIE_MAPLE_EPON_DEVICE_ID;
+            goto found_device_id;
+        }
+
+        printf("No more devices, Found %d maple device(s)\n", g_maple_dev_num);
+        break;
+
+found_device_id:
+        // Found new Maple device
+        printf("Found maple device[%x - %x][%d] @ Bus %d, Dev %d, Func %d\n", 
+            PCIE_MAPLE_VENDOR_ID, PCIE_MAPLE_DEVICE_ID, pci_dev_idx,
+            dev_info->pciBusNo, dev_info->pciDevNo, dev_info->pciFuncNo);
+        g_maple_dev_num += 1;
+        
+        // init    
+        dev_info->deviceid = pci_dev_idx;
+        dev_info->pdev = NULL;        
+    
+
+        // Enable PCI address map
+        pciConfigInByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8 *)&readvalb);
+        printf("CMD reg = 0x%x\n", readvalb);
+
+        readvalb |= 0x6;
+        pciConfigOutByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8)readvalb);
+
+        pciConfigInByte(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_COMMAND,
+                        (UINT8 *)&readvalb);
+        printf("Adjusted CMD reg = 0x%x\n", readvalb);
+
+        // Init base addresses
+
+#ifdef LLPCIE_SET_BASE_ADDRESSES_MANUALLY 
+       dev_info->device.soc_regs_base = llpcie_base_addresses.soc_regs_base;
+       dev_info->device.soc_sram_base = llpcie_base_addresses.soc_sram_base;
+       dev_info->device.soc_ddr_base  = llpcie_base_addresses.soc_ddr_base;
+       dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH; // 16M */
+#else
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_0,
+                        (UINT32 *)&readval);
+        printf("BAR0 = 0x%x\n", readval);
+        dev_info->device.soc_regs_base = (readval & PCI_MEMBASE_MASK);
+
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_2,
+                        (UINT32 *)&readval);
+        printf("BAR2 = 0x%x\n", readval);
+        dev_info->device.soc_ddr_base = (readval & PCI_MEMBASE_MASK);
+        dev_info->device.soc_ddr_length = MAPLE_DDR_LENGTH;         // 16M           
+
+        pciConfigInLong(dev_info->pciBusNo,
+                        dev_info->pciDevNo,
+                        dev_info->pciFuncNo,
+                        PCI_CFG_BASE_ADDRESS_4,
+                        (UINT32 *)&readval);
+        printf("BAR4 = 0x%x\n", readval);
+        dev_info->device.soc_sram_base = (readval & PCI_MEMBASE_MASK);   
+#endif             
+
+        printf("Regs Base = 0x%lx, DDR Base = 0x%lx, DDR Length = 0x%x, SRAM Base = 0x%lx\n",
+            dev_info->device.soc_regs_base,
+            dev_info->device.soc_ddr_base,
+            dev_info->device.soc_ddr_length,
+            dev_info->device.soc_sram_base);
+
+        // init interrupt
+        dev_info->device.irq = llpcie_device_irqs[pci_dev_idx].llpcie_irq;
+        dev_info->dev_status_irq = llpcie_device_irqs[pci_dev_idx].llpcie_status_irq;
+        printf("DMA IRQ = %d, Device status IRQ = %d\n", 
+            dev_info->device.irq, dev_info->dev_status_irq);
+                
+        // read revision register
+        readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_REVISION_REGISTER_OFFSET));
+        printf("readval = 0x%x\n", readval);
+        printf("Card %d version major=%02x minor=%02x\n",
+                    dev_info->deviceid, 
+                    ((readval & 0x0000ff00) >> 8),
+                    (readval & 0x000000ff)); 
+        
+        // read status register
+        readval = bcm_pci_read32((uint32_t *)(dev_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+        printf("readval = 0x%x\n", readval);
+        dev_info->err_status = (readval & 0x0000000f);
+        dev_info->phylink    = ((readval >> 4) & 0x1);
+        dev_info->datalink   = ((readval >> 5) & 0x1);
+        dev_info->prev_datalink  = dev_info->datalink;
+
+        // connect INT for device status
+        bcmos_fastlock_init(&dev_info->lock, 0);
+        bcmos_int_connect((int)dev_info->dev_status_irq, 
+                            0, 
+                            BCMOS_IRQ_SHARED, 
+                            dev_status_interrupt, 
+                            "status_isr", 
+                            dev_info);
+    }
+
+    // Return status
+    if (0 >=g_maple_dev_num)
+    {
+        return BCM_ERR_NODEV;
+    }
+    else
+    {
+        return BCM_ERR_OK;
+    }
+}
+
+/** Get Maple device object struct
+ * \crt devie index,start from 0
+ */
+static maple_device_info *get_maple_pci_info(int crt)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    uint32_t readval = 0;
+    maple_device_info *device_info = NULL;
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (crt >= g_maple_dev_num)
+    {
+        return NULL;
+    }
+    device_info = &g_maple_devs_info[crt];
+
+    /* read status register */
+    readval = bcm_pci_read32((uint32_t *)(device_info->device.soc_regs_base + PCIE_STATUS_REGISTER_OFFSET));
+    device_info->err_status = (readval & 0x0000000f);
+    device_info->phylink    = ((readval >> 4) & 0x1);
+    device_info->datalink   = ((readval >> 5) & 0x1);
+
+    /* return device */
+    return device_info;
+}
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0 
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb)
+{
+    int i;
+    maple_device_info *dev_info; 
+    
+    g_dev_status_change_cb = cb;
+    for (i = 0; i < g_maple_dev_num; i++)
+    {
+        dev_info = get_maple_pci_info(i);
+        g_dev_status_change_cb(i, dev_info->datalink);
+    }
+    
+    return BCM_ERR_OK;
+}
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void)
+{
+    g_dev_status_change_cb = NULL;
+    
+    return BCM_ERR_OK;
+}
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info)
+{
+    maple_device_info *dev_info = NULL; 
+
+    /* check input parameter */    
+    if (NULL == info)
+    {
+        return BCM_ERR_PARM;
+    }
+
+    /* don't access invalid device regs base address */
+    if (dev_id < g_maple_dev_num)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (NULL == dev_info)
+        {
+            return BCM_ERR_NOENT;
+        }
+        if (dev_info->datalink == BCM_LL_PCIE_LINK_DOWN)
+        {
+            return BCM_ERR_IO;
+        }
+
+        *info = dev_info->device;
+        return BCM_ERR_OK;
+    }
+    
+    return BCM_ERR_RANGE;   
+}
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id)
+{
+    maple_device_info *dev_info = NULL; 
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (dev_id < g_maple_dev_num)
+    {
+        dev_info = get_maple_pci_info(dev_id);
+        if (NULL == dev_info)
+        {
+            return NULL;
+        }
+        else
+        {
+            return dev_info->pdev;
+        }
+    } 
+    
+    return NULL;
+}
+
+/** Host reset enable 
+ * \enabled 
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled)
+{
+    uint32_t val;
+
+    /* check input parameter */
+    /* don't access invalid device regs base address */
+    if (dev_id >= g_maple_dev_num)
+    {
+        return BCM_ERR_OVERFLOW;
+    }
+    
+    val = enabled ? 0 : 1;
+    bcm_pci_write32((uint32_t *)(g_maple_devs_info[dev_id].device.soc_regs_base + PCIE_HARD_DEBUG_REGISTER_OFFSET), 
+            val);
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h
new file mode 100755
index 0000000..040d565
--- /dev/null
+++ b/bcm68620_release/release/host_customized/ll_pcie/vxworks/multi_device/bcmolt_llpcie.h
@@ -0,0 +1,105 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcm_llpcie.h - Low-level PCIe driver interface
+ */
+
+#ifndef BCMOLT_LLPCIE_H_
+#define BCMOLT_LLPCIE_H_
+
+#include "bcmos_system.h"
+#define BCMOLT_MAX_MAPLE_DEVICES               2 /* 5 */
+
+/** Low-level device info */
+typedef struct bcmolt_ll_dev_info
+{
+    unsigned long   soc_regs_base;      /**< Device registers base in host address space */
+    unsigned long   soc_sram_base;      /**< Device SRAM base in host address space */
+    unsigned long   soc_ddr_base;       /**< Device DDR base in host address space */
+    uint32_t        soc_ddr_length;     /**< Device DDR window size */
+    uint32_t        irq;                /**< Device irq number */
+} bcm_ll_dev_info;
+
+/** Device PCIe link status change notification callback */
+typedef enum
+{
+    BCM_LL_PCIE_LINK_DOWN,             /**< PCIe link is down */
+    BCM_LL_PCIE_LINK_UP,               /**< PCIe link is up */
+} bcm_ll_pcie_link_status;
+
+/** Low-level device handle */
+typedef void *bcm_ll_pcie_dev;
+
+/** Status change indication */
+typedef void (*bcm_ll_pcie_status_change)(uint8_t dev_id, bcm_ll_pcie_link_status status);
+
+/** Register status change notification callback
+ * \param[in]   cb      Status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_register(bcm_ll_pcie_status_change cb);
+
+/** Unregister status change notification callback
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_status_change_unregister(void);
+
+/** Query PCIe device
+ * \param[in]   dev_id  Device id
+ * \param[out]  info    Device info
+ * \return 0=OK, BCM_ERR_IO-dev_id is in proper range, but link is down
+ */
+bcmos_errno bcm_ll_pcie_query(uint8_t dev_id, bcm_ll_dev_info *info);
+
+/** Get low-level device handle
+ * \param[in]   dev_id  Device id
+ * \param[out]  lldev   Low-level device handle 
+ * \return device handle or NULL if link is down
+ */
+bcm_ll_pcie_dev bcm_ll_pcie_dev_get(uint8_t dev_id);
+
+/** Enable/disable host reset for all PCIe interfaces (automatic
+ *  device reset when host is reset)
+ * \param[in]   enabled Whether or not hot reset should be enabled
+ * \return 0=OK or error <0
+ */
+bcmos_errno bcm_ll_pcie_host_reset_enable(uint8_t dev_id, bcmos_bool enabled);
+
+#ifdef TX_ENABLE_EVENT_TRACE
+/** Handle low-level trace on target
+ * \param[in]   dev_id  Device id
+ * \param[in]  lfile name for trace
+ * \return device handle or NULL if link is down
+ */
+bcmos_errno bcm_ll_pcie_setrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_cleartrace(uint8_t dev_id);
+bcmos_errno bcm_ll_pcie_savetrace(uint8_t dev_id, char *tracefilename);
+#endif
+#endif
diff --git a/bcm68620_release/release/host_customized/model_linux/Makefile b/bcm68620_release/release/host_customized/model_linux/Makefile
new file mode 100644
index 0000000..45c5c31
--- /dev/null
+++ b/bcm68620_release/release/host_customized/model_linux/Makefile
@@ -0,0 +1,19 @@
+# Makefile for building system model as linux module
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = sysmodel
+MOD_DEPS = utils common_api 
+MOD_TYPE = linux_lib
+SRC_DIR = $(MODEL_OUT_DIR)/linux
+srcs = bcmolt_model_types.c bcmolt_msg_pack.c
+
+$(shell mkdir -p $(SRC_DIR); ln -s $(MODEL_OUT_DIR)/*.[ch] $(SRC_DIR)/ 2> /dev/null)
+	 
+# 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/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_ */
diff --git a/bcm68620_release/release/host_customized/pcie/Makefile b/bcm68620_release/release/host_customized/pcie/Makefile
new file mode 100755
index 0000000..338d3cc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/pcie/Makefile
@@ -0,0 +1,24 @@
+# PCIE driver
+# host specific
+#
+MOD_NAME = pcie_mod
+MOD_DEPS = pcie 
+
+MOD_SUPPRESS_OS_DEP = y
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_lib
+    srcs = bcmolt_tr_pcie_specific.c
+else
+    MOD_TYPE = lib
+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
+
+USE_LINT = yes
+
+
diff --git a/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.c b/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.c
new file mode 100755
index 0000000..94102bc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.c
@@ -0,0 +1,106 @@
+/*
+<: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 "bcmtr_pcie.h"
+#include "bcmolt_tr_pcie_specific.h"
+
+extern f_bcmtr_int bcmtr_pcie_rx_irq_handler;
+extern f_bcmtr_int bcmtr_pcie_tx_irq_handler;
+static bcmos_fastlock isr_lock;
+
+/***************************************************************/
+/* need to pass thru all the devices - check if irq is SHARED */
+/***************************************************************/
+static int bcmtr_rx_isr(int irq, void *isr_info)
+{
+    uint32_t isr_reg;
+    uint32_t mask_reg;
+    long flags;
+    int handled = 0;
+    bcm_pcied_isr_data *isr_data = (bcm_pcied_isr_data *)isr_info;
+
+    flags = bcmos_fastlock_lock(&isr_lock);
+
+    isr_reg = bcm_pci_read32((uint32_t*)(isr_data->pcie_reg_base + DMA_INTR_STATUS));
+    mask_reg = ~bcm_pci_read32((uint32_t*)(isr_data->pcie_reg_base + DMA_INTR_MASK_STATUS));
+
+    if ((isr_reg & mask_reg)& DMA_TX_DONE_MASK)
+    {
+        /* handle TX DONE interrupt */
+        isr_data->tx_done_num++;
+
+        if (bcmtr_pcie_tx_irq_handler)
+            bcmtr_pcie_tx_irq_handler(isr_data->device);
+
+        handled = 1;
+    }
+
+    if ((isr_reg & mask_reg ) & DMA_RX_DONE_MASK)
+    {
+        /* handle RX DONE interrupt */
+        isr_data->rx_done_num++;
+
+        if (bcmtr_pcie_rx_irq_handler)
+            bcmtr_pcie_rx_irq_handler(isr_data->device);
+
+        handled = 1;
+    }
+
+    if (isr_reg & (DMA_RX_ERROR_MASK | DMA_TX_ERROR_MASK))
+    {
+        if (isr_reg & DMA_RX_ERROR_MASK)
+            isr_data->rx_err_num++;
+        if (isr_reg & DMA_TX_ERROR_MASK)
+            isr_data->tx_err_num++;
+        /* clear interrupt error interrupt */
+        bcm_pci_write32((uint32_t*)(isr_data->pcie_reg_base + DMA_INTR_CLEAR), DMA_RX_ERROR_MASK | DMA_TX_ERROR_MASK);
+        handled = 1;
+    }
+
+    bcmos_fastlock_unlock(&isr_lock, flags);
+
+    return handled;
+}
+
+void bcmtr_connect_isr(void *isr_info)
+{
+    uint32_t    flags = 0;
+
+    bcm_pcied_isr_data *isr_data = (bcm_pcied_isr_data *)isr_info;
+    bcmos_fastlock_init(&isr_lock, flags);
+    /* connect interrupt to system cpu - 0 */
+    bcmos_int_connect((int)isr_data->rx_irq, 0, BCMOS_IRQ_SHARED, bcmtr_rx_isr, "dmaisr", isr_data);
+}
+
+#ifdef __KERNEL__
+EXPORT_SYMBOL(bcmtr_connect_isr);
+#endif
+
+
diff --git a/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.h b/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.h
new file mode 100644
index 0000000..c8c8ac1
--- /dev/null
+++ b/bcm68620_release/release/host_customized/pcie/bcmolt_tr_pcie_specific.h
@@ -0,0 +1,113 @@
+/*
+<: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 BCMOLT_TR_PCIE_SPECIFIC_H_
+#define BCMOLT_TR_PCIE_SPECIFIC_H_
+
+#include "bcmos_system.h"
+#include "bcmtr_pcie.h"
+
+#define DESCRIPTOR_CONTROL      0x00064410 /* Tx Software Descriptor List Control and Status */
+#define WAKEUP_DMA              0x00064414 /* Tx Wake Control */
+#define ERROR_STATUS            0x00064418 /* Tx Engine Error Status */
+
+#define INTR2_PCI_STATUS        0x00064318 /* PCI interrupt Status Register */
+
+#define DMA_TX_SW_DESC_LIST_CTRL_STS_TX_DMA_RUN_STOP_MASK   0x00000001
+#define DMA_TX_WAKE_CTRL_WAKE_MASK                          0x00000001
+
+#define DMA_INTR_STATUS	        0x00064318 /* PCI interrupt Status Register */
+#define DMA_INTR_CLEAR          0x00064320 /* PCI interrupt Clear Register */
+#define DMA_INTR_MASK_SET       0x00064328 /* PCI interrupt Mask Set Register */
+#define DMA_INTR_MASK_CLEAR     0x0006432c /* PCI interrupt Mask Clear Register */
+#define DMA_INTR_MASK_STATUS    0x00064324 /* PCI interrupt Mask & Status Register */
+
+#define DMA_RX_ERROR_MASK       0x00000008
+#define DMA_RX_DONE_MASK        0x00000004
+#define DMA_TX_DONE_MASK        0x00000001
+#define DMA_TX_ERROR_MASK       0x00000002
+
+#define PCIE_L2_INTR_MASK       0x00000020 /* L2 interrupt bit in L1 interrupt status */
+
+#define DMA_INTR1_STATUS        0x00069300 /* Interrupt Status Register */
+#define DMA_INTR1_MASK_CLEAR    0x0006930c /* Interrupt Mask Clear Register */
+#define DMA_INTR1_MASK_SET      0x00069308 /* Interrupt Mask Set Register */
+#define DMA_INTA_MASK           0x00000002
+#define DMA_INTA_SHIFT          1
+#define PCIE_STATUS_OFFSET      0x00064068 /* PCIE_PCIE_PCIE_0_PCIE_PCIE_0_MISC_PCIE_STATUS */
+
+void bcmtr_connect_isr(void *isr_info);
+
+/* first parameter is the dest PD, the second parameter is the source field */
+static inline void bcmtr_set_dest_buffer_address(uint32_t *pd, void *value)
+{
+    uint64_t tmp = bcmos_virt_to_phys(value);
+
+    bcm_pci_write32(&pd[PCI_PACKET_LOW_INDEX],  (uint32_t)( tmp & 0xffffffffUL));
+    bcm_pci_write32(&pd[PCI_PACKET_HIGH_INDEX], (uint32_t)((tmp >> 32) & 0xffffffffUL));
+}
+
+/* first parameter is the dest PD, the second parameter is the source field */
+static inline void bcmtr_set_source_buffer_address(uint32_t *pd, void *value)
+{
+    uint64_t tmp = bcmos_virt_to_phys(value);
+
+    bcm_pci_write32(&pd[PCI_PACKET_LOW_INDEX],  (uint32_t)( tmp & 0xffffffffUL));
+    bcm_pci_write32(&pd[PCI_PACKET_HIGH_INDEX], (uint32_t)((tmp >> 32) & 0xffffffffUL));
+}
+
+static inline bcmos_errno bcmtr_create_tu_rings(uint32_t txlength, uint32_t rxlength,
+                                          void **txptr, void **rxptr,
+                                          void **txptr_orig, void **rxptr_orig,
+                                          unsigned long pcie_reg_base)
+{
+    *txptr      = NULL;
+    *rxptr_orig = NULL;
+    *txptr      = NULL;
+    *rxptr_orig = NULL;
+
+    return BCM_ERR_OK;
+}
+static inline void bcmtr_pcie_specific_init(unsigned long pcie_reg_base) {}
+static inline void bcmtr_pcie_free_rings(uint32_t device, uint32_t *tx_ptr, uint32_t * rx_ptr){}
+static inline void bcmtr_pcie_free_irq(uint32_t irq, void *priv)
+{
+#ifndef SIMULATION_BUILD
+    bcmos_int_disconnect((int)irq, priv);
+#endif
+}
+
+#define TX_LOCKDEF         bcmos_mutex  tx_lock;
+#define CREATE_TXLOCK(i)   bcmos_mutex_create(&bcmtr_pcie_data[i].tx_lock, 0, NULL)
+#define DESTROY_TXLOCK(i)  bcmos_mutex_destroy(&bcmtr_pcie_data[i].tx_lock)
+#define LOCK_TX()          bcmos_mutex_lock(&current_device->tx_lock)
+#define UNLOCK_TX()        bcmos_mutex_unlock(&current_device->tx_lock)
+
+#endif
+
diff --git a/bcm68620_release/release/host_customized/transport/nl_socket/Makefile b/bcm68620_release/release/host_customized/transport/nl_socket/Makefile
new file mode 100644
index 0000000..7e85eb0
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/nl_socket/Makefile
@@ -0,0 +1,22 @@
+# NL transport driver
+#
+ifeq ("$(OS_KERNEL)", "linux")
+ifeq ("$(CONFIG_TRANSPORT_RAW)", "y")
+
+
+MOD_NAME = nltr
+MOD_TYPE = linux_lib
+MOD_DEPS = trmux tr_plugin_raw
+
+srcs = bcmolt_tr_nl_driver.c
+
+# 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
+
+USE_LINT = yes
+
+endif
+endif
diff --git a/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.c b/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.c
new file mode 100644
index 0000000..a63fca2
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.c
@@ -0,0 +1,232 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * nl_transport.c
+ *
+ * NL-socket based transport. Kernel space module
+ *
+ */
+#include <linux/module.h>       /* Needed by all modules */
+#include <linux/kernel.h>       /* Needed for KERN_INFO */
+#include <net/netlink.h>
+#include <net/sock.h>
+#include <linux/netdevice.h>
+#include <linux/version.h>
+
+#include <bcmolt_tr_mux.h>
+#include <bcmolt_tr_nl_driver.h>
+#include "bcmolt_tr_nl.h"
+
+#define BCMTR_MEM_PACKETS       10000
+#define BCMTR_MEM_OVERHEAD      SKB_TRUESIZE(1024)
+#define BCMTR_MIN_RCVBUF_SIZE   (BCMTR_MEM_PACKETS * BCMTR_MEM_OVERHEAD)
+
+struct sock *bcmtr_nl_sock = NULL;
+
+/* Netlink operations. This driver overrides a couple */
+static struct proto_ops bcmtr_nl_ops;
+static int (*netlink_release_org)(struct socket *sock);
+
+struct bcmtr_nl
+{
+    bcmtrmux_channel channel[BCMTR_MAX_OLTS];
+    int pid;
+    struct sock *sk;
+};
+
+static int bcmtr_netlink_release(struct socket *sock)
+{
+    struct sock *sk = sock->sk;
+    struct bcmtr_nl *nlb = sk->sk_user_data;
+    if (nlb)
+    {
+        int i;
+        for (i = 0; i < BCMTR_MAX_OLTS; i++)
+        {
+            if (nlb->channel[i])
+                bcmtrmux_channel_unregister(i, nlb->channel[i]);
+        }
+        kfree(nlb);
+        sk->sk_user_data = NULL;
+    }
+    return netlink_release_org(sock);
+}
+
+/** Receive message handler */
+static  void _bcmtr_nl_recv(bcmolt_devid device, bcmos_buf *buf, bcmtrmux_channel channel, void *data)
+{
+    uint32_t data_length = bcmos_buf_length(buf);
+    uint32_t device_u32 = (uint32_t)device;
+    struct bcmtr_nl *nlb = (struct bcmtr_nl *)data;
+    uint8_t *p_device;
+    int r;
+
+    NETLINK_CB(&(buf->skb)).dst_group = 0; /* not in mcast group */
+
+    /* Now a tricky part. nlmsg_put() assumes that skb is empty and extends it
+     * by total msg size. We don't want it. Reserve room for nlmsg header and then
+     * set size to 0 and let nlmsg_put() restore it
+     */
+    if (unlikely(skb_headroom(&buf->skb) < NLMSG_HDRLEN + sizeof(uint32_t)))
+    {
+        printk(KERN_INFO "%s: can't prepend NL header\n", __FUNCTION__);
+        bcmos_free(buf);
+        return;
+    }
+    __skb_push(&buf->skb, NLMSG_HDRLEN + sizeof(uint32_t));
+    /* Store device immediately after the NL header */
+    p_device = buf->skb.data + NLMSG_HDRLEN;
+    memcpy(p_device, &device_u32, sizeof(uint32_t));
+    __skb_trim(&buf->skb, 0);
+    nlmsg_put(&buf->skb, 0, 0, NLMSG_DONE, data_length + sizeof(uint32_t), 0);
+
+    r = nlmsg_unicast(nlb->sk, &buf->skb, nlb->pid);
+    if (r)
+    {
+        printk(KERN_INFO "%s: nlmsg_unicast() --> %d len=%u rm_alloc=%d recvbuf=%d\n",
+            __FUNCTION__, r, data_length, atomic_read(&nlb->sk->sk_rmem_alloc), nlb->sk->sk_rcvbuf);
+    }
+}
+
+void bcmtr_nl_input(struct sk_buff *skb)
+{
+    struct nlmsghdr *nlh;
+    struct bcmtr_nl *nlb;
+    uint32_t device;
+    bcmos_errno rc;
+
+    nlh = nlmsg_hdr(skb);
+
+    if(NLMSG_OK(nlh, skb->len))
+    {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,10,0)
+        struct sock *sk = NETLINK_CB(skb).sk;
+#else
+        struct sock *sk = NETLINK_CB(skb).ssk;
+#endif
+
+        /* channel is stored in user_data. If it is 0 - that means that channel
+         * is not allocated yet. Do it here
+         */
+        if (!sk->sk_user_data)
+        {
+            nlb = kmalloc(sizeof(*nlb), GFP_KERNEL);
+            if (!nlb)
+            {
+                printk(KERN_INFO "%s: can't allocate NLB\n", __FUNCTION__);
+                return;
+            }
+            memset(nlb, 0, sizeof(*nlb));
+            nlb->pid = nlh->nlmsg_pid;
+            nlb->sk = sk;
+            sk->sk_user_data = nlb;
+
+            /* Override release callback in order to cleanup */
+            bcmtr_nl_ops = *sk->sk_socket->ops;
+            netlink_release_org = bcmtr_nl_ops.release;
+            bcmtr_nl_ops.release = bcmtr_netlink_release;
+            sk->sk_socket->ops = &bcmtr_nl_ops;
+
+            /* Override sk_rcvbuf size. Set min */
+            if (sk->sk_rcvbuf < BCMTR_MIN_RCVBUF_SIZE)
+            {
+                sk->sk_rcvbuf = BCMTR_MIN_RCVBUF_SIZE;
+            }
+        }
+        else
+        {
+            nlb = (struct bcmtr_nl *)sk->sk_user_data;
+        }
+
+        /* Device id follows NLMSG header */
+        device = skb->data[NLMSG_HDRLEN];
+        if (device >= BCMTR_MAX_OLTS)
+        {
+            printk(KERN_INFO "%s: device %u is insane\n", __FUNCTION__, device);
+            return;
+        }
+
+        if (!nlb->channel[device])
+        {
+            bcmtrmux_channel channel = BCMTRMUX_CHANNEL_AUTO_ASSIGN;
+
+            rc = bcmtrmux_channel_register(device, &channel, _bcmtr_nl_recv, nlb);
+            if (rc)
+            {
+                printk(KERN_INFO "%s: can't register channel for device %u. rc=%d\n", __FUNCTION__, device, (int)rc);
+                return;
+            }
+            nlb->channel[device] = channel;
+        }
+
+
+        /* Cut NL header + device */
+        skb_pull(skb, NLMSG_HDRLEN + sizeof(uint32_t));
+
+        /* Clone skb because caller will release the original one */
+        skb = skb_clone(skb, 0);
+        if (!skb)
+        {
+
+            printk(KERN_ERR "Failed to allocate new skb\n");
+            return;
+        }
+
+        /* Forward to the mux */
+        bcmtrmux_rx_from_host(device, nlb->channel[device], (bcmos_buf *)skb);
+    }
+    else
+    {
+        printk(KERN_INFO "%s: invalid message received frpm pid %d\n", __FUNCTION__, nlh->nlmsg_pid);
+    }
+}
+
+static struct netlink_kernel_cfg bcmtr_nl_cfg = {
+    .input = bcmtr_nl_input,
+};
+
+bcmos_errno bcmtr_nl_init(void)
+{
+    printk(KERN_INFO "Maple netlink-based raw driver transport driver\n");
+    bcmtr_nl_sock = netlink_kernel_create(&init_net, BCMTR_NL_FAMILY, &bcmtr_nl_cfg);
+    if(!bcmtr_nl_sock)
+        return BCM_ERR_NOMEM;
+    return BCM_ERR_OK;
+}
+
+void bcmtr_nl_exit(void)
+{
+    printk("Maple netlink-based raw driver terminated\n");
+    if (bcmtr_nl_sock)
+    {
+        netlink_kernel_release(bcmtr_nl_sock);
+        bcmtr_nl_sock = NULL;
+    }
+}
diff --git a/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.h b/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.h
new file mode 100644
index 0000000..d79c990
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/nl_socket/bcmolt_tr_nl_driver.h
@@ -0,0 +1,42 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmtr_nl_driver.h - host netlink-socket transport driver
+ */
+
+#ifndef BCMOLT_TR_NL_DRIVER_H_
+#define BCMOLT_TR_NL_DRIVER_H_
+
+#include <bcmos_system.h>
+
+bcmos_errno bcmtr_nl_init(void);
+void bcmtr_nl_exit(void);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/Makefile b/bcm68620_release/release/host_customized/transport/plugin/Makefile
new file mode 100644
index 0000000..80f0147
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/Makefile
@@ -0,0 +1,11 @@
+# Transport: Plugin interface
+#
+MOD_NAME = tr_plugin
+MOD_TYPE = lib
+MOD_DEPS = utils common_api model
+
+ifeq ("$(RELEASE_BUILD)", "y")
+MOD_INC_DIRS = $(SRC_DIR) $(TOP_DIR)/host_driver/transport
+else
+MOD_INC_DIRS = $(SRC_DIR) $(SRC_DIR)/..
+endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/bcmtr_plugin.h b/bcm68620_release/release/host_customized/transport/plugin/bcmtr_plugin.h
new file mode 100644
index 0000000..82d3dd2
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/bcmtr_plugin.h
@@ -0,0 +1,113 @@
+/*
+<: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 BCMTR_PLUGIN_H_
+#define BCMTR_PLUGIN_H_
+
+#include <bcmolt_buf.h>
+#include <bcmolt_msg.h>
+
+#include <bcmtr_interface.h>
+#include <bcmtr_header.h>
+
+/** Message transport type */
+typedef enum
+{
+   BCMTR_TYPE_UDP,        /**< UDP transport */
+   BCMTR_TYPE_RAW         /**< Raw transport */
+} bcmtr_transport_type;
+
+/** UDP configuration */
+typedef struct
+{
+    uint32_t my_ip;             /**< Local IP address in host format */
+    uint32_t remote_ip;         /**< Remote IP address in host format */
+    uint16_t my_port;           /**< Local UDP port in host format. INADDR_ANY is acceptable */
+    uint16_t remote_port;       /**< Remote UDP port in host format */
+} bcmtr_udp_cfg;
+
+/** Transport configuration parameters */
+typedef struct
+{
+    bcmtr_transport_type type;     /**< Transport type */
+
+    /** Type-specific configuration */
+    union
+    {
+        /** UDP Plugin parameters */
+        bcmtr_udp_cfg udp;
+
+        /* Raw task forwarder plugin parameters */
+        struct
+        {
+            bcmtr_udp_cfg udp;          /**< UDP configuration - for UDP-based raw driver */
+            uint32_t max_txq_size;      /**< Max transmit queue/pool size */
+            bcmos_task_priority tx_pri; /**< Tx task priority */
+        } forwarder;
+    } x;
+
+    uint32_t headroom;                  /**< Additional headroom length that should be reserved for plugin use */
+
+} bcmtr_plugin_cfg;
+
+/** Plugin channel */
+typedef unsigned long bcmtr_plugin_channel;
+
+/** Transport driver */
+typedef struct {
+    /** Open communication channel, establish communication */
+    bcmos_errno (*open)(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch);
+    /** Close communication channel */
+    bcmos_errno (*close)(bcmtr_plugin_channel ch);
+    /** Send data. It doesn't have to release the tx buffer, but if it does - it must
+     * clear buf->start to prevent double release */
+    bcmos_errno (*send)(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf, bcmtr_send_flags flags);
+    /** Receive data. It is responsible for receive buffer allocation */
+    bcmos_errno (*recv)(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf);
+} bcmtr_driver;
+
+/** Initialize plugin callbacks
+ * \param[in]           cfg     Plugin configuration
+ * \param[in,out]       driver  Transport plugin driver structure
+ * \return error code
+ */
+bcmos_errno bcmtr_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver);
+
+/* UDP comm parameters */
+#ifdef BCMTR_UDP_SUPPORT
+extern uint32_t bcmtr_host_ip;
+extern uint16_t bcmtr_host_udp_port;
+extern uint32_t bcmtr_olt_ip[BCMTR_MAX_OLTS];
+extern uint16_t bcmtr_olt_udp_port[BCMTR_MAX_OLTS];
+#endif
+
+void using_inband_set(bcmos_bool using_inband);
+bcmos_bool using_inband_get(void);
+
+#endif /* BCMTR_PLUGIN_H_ */
diff --git a/bcm68620_release/release/host_customized/transport/plugin/direct/bcmtr_plugin_direct.c b/bcm68620_release/release/host_customized/transport/plugin/direct/bcmtr_plugin_direct.c
new file mode 100644
index 0000000..c00c9ba
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/direct/bcmtr_plugin_direct.c
@@ -0,0 +1,290 @@
+/*
+<: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.
+:>
+*/
+/*
+ * bcmtr_plugin_direct.c
+ *
+ * This plugin
+ * - TX: forwards messages to trmux
+ * - RX: waits on rx task's message queue
+ */
+
+#include <bcmos_system.h>
+
+#include <bcmtr_plugin.h>
+#include <bcm_config.h>
+#include <bcmolt_tr_mux.h>
+
+/* Receive OS message pool and queue */
+static bcmos_msg_pool bcmtr_rx_msg_pool[BCMTR_MAX_OLTS];
+static bcmos_msg_queue bcmtr_rxq[BCMTR_MAX_OLTS];
+
+/* Flags indicating init progress */
+static bcmos_bool rx_pool_created[BCMTR_MAX_OLTS];
+static bcmos_bool rxq_created[BCMTR_MAX_OLTS];
+static void _bcmtr_direct_rx_from_trmux(bcmolt_devid device, bcmos_buf *buf, bcmtrmux_channel channel, void *data);
+
+/* To resolve symbols in user_appl in band not applicable for VXWorks*/
+void using_inband_set(bcmos_bool using_inband){}
+bcmos_bool using_inband_get(void)
+{
+    return BCMOS_FALSE;
+}
+
+
+/* Transport IPC message data */
+typedef struct bcmtr_ipc_data
+{
+    bcmolt_buf buf;             /* Rx buffer */
+    bcmolt_subchannel subch;    /* rx channel */
+} bcmtr_ipc_data;
+
+
+/* System --> OLT buffer translation.
+ * system buffer is released in case of success
+ */
+static bcmos_errno bcmtr_sysbuf_to_oltbuf(bcmos_buf *sysb, bcmolt_buf *oltb)
+{
+    bcmos_errno err;
+
+    err = bcmolt_buf_alloc(oltb, bcmos_buf_length(sysb), BCMTR_BUF_ENDIAN);
+    if (err)
+        return err;
+    bcmolt_buf_write(oltb, bcmos_buf_data(sysb), bcmos_buf_length(sysb));
+    bcmos_buf_free(sysb);
+    oltb->curr = oltb->start;
+    return BCM_ERR_OK;
+}
+
+/* OLT buffer --> system buffer translation.
+ * OLT buffer must have headroom for bcmos_buf header
+ */
+static bcmos_buf *bcmtr_oltbuf_to_sysbuf(bcmolt_buf *oltb)
+{
+    bcmos_buf *sysb;
+    uint32_t len = bcmolt_buf_get_used(oltb);
+
+    sysb = bcmos_buf_alloc(len);
+    if (sysb == NULL)
+        return NULL;
+    memcpy(bcmos_buf_data(sysb), oltb->start, len);
+    bcmos_buf_length_set(sysb, len);
+    /* We don't release the original oltb because it is needed for retransmission.
+     * It will be released by the transport layer
+     */
+    return sysb;
+}
+
+/* Release message data */
+static void bcmtr_msg_data_release(bcmos_msg *msg)
+{
+    bcmtr_ipc_data *data = msg->data;
+    bcmolt_buf_free(&data->buf);
+}
+
+/** Close communication channel */
+static bcmos_errno bcmtr_direct_close(bcmtr_plugin_channel ch)
+{
+    bcmolt_devid device = (bcmolt_devid)(ch >> 8);
+    bcmtrmux_channel muxch = (bcmtrmux_channel)(ch & 0xff);
+
+    /* Unregister from TRMUX */
+    bcmtrmux_channel_unregister(device, muxch);
+
+    /* Destroy rx message pool */
+    if (rx_pool_created[device])
+    {
+        bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
+        rx_pool_created[device] = BCMOS_FALSE;
+    }
+
+    /* Destroy RX message queue */
+    if (rxq_created[device])
+    {
+        bcmos_msg_queue_destroy(&bcmtr_rxq[device]);
+        rxq_created[device] = BCMOS_FALSE;
+    }
+
+    return BCM_ERR_OK;
+}
+
+/** Open communication channel */
+static bcmos_errno bcmtr_direct_open(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch)
+{
+    /* The following variables are declared static in order to protect name string */
+    static bcmos_msg_queue_parm msgq_parm = { .name = "tr_rxq"};
+    bcmos_msg_pool_parm msg_pool_parm = {};
+    bcmtrmux_channel mux_channel = BCMTRMUX_CHANNEL_AUTO_ASSIGN;
+    bcmos_errno err;
+
+    /* Direct plugin supports only 1 application instance */
+    if (device >= BCMTR_MAX_OLTS)
+        BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Device %u is out of range\n", device);
+    if (rx_pool_created[device])
+        BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "Transport is already initialized for device %u\n", device);
+
+    /* Create RX msg pool */
+    msg_pool_parm.size = BCMTR_MAX_RXQ_SIZE;            /* <-- Define parameter in bcmtr_config */
+    msg_pool_parm.data_size = sizeof(bcmtr_ipc_data);
+    msg_pool_parm.data_release = bcmtr_msg_data_release;
+    err = bcmos_msg_pool_create(&bcmtr_rx_msg_pool[device], &msg_pool_parm);
+    if (err)
+        BCMOS_TRACE_RETURN(err, "Can't create rx pool\n");
+
+    /* Create RX queue set */
+    err = bcmos_msg_queue_create(&bcmtr_rxq[device], &msgq_parm);
+    if (err)
+    {
+        bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
+        BCMOS_TRACE_RETURN(err, "Can't create rxq\n");
+    }
+
+    /* Register with trmux */
+    err = bcmtrmux_channel_register(device, &mux_channel, _bcmtr_direct_rx_from_trmux, (void *)NULL );
+    if (err)
+    {
+        bcmos_msg_pool_destroy(&bcmtr_rx_msg_pool[device]);
+        bcmos_msg_queue_destroy(&bcmtr_rxq[device]);
+        BCMOS_TRACE_RETURN(err, "Can't register with trmux\n");
+    }
+
+    rx_pool_created[device] = BCMOS_TRUE;
+    rxq_created[device] = BCMOS_TRUE;
+    *ch = (bcmtr_plugin_channel)((device << 8) | mux_channel);
+
+    return BCM_ERR_OK;
+}
+
+/** Send data */
+static bcmos_errno bcmtr_direct_send(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf,
+    bcmtr_send_flags flags)
+{
+    bcmolt_devid device = (bcmolt_devid)(ch >> 8);
+    bcmtrmux_channel muxch = (bcmtrmux_channel)(ch & 0xff);
+    bcmos_buf *sysb;
+
+    /* Do zero-copy conversion from bcmolt_buf --> bcmos_buf. It is possible because room
+     * for bcmos_buf header is reserved in the beginning of bcmolt_buf
+     */
+    sysb = bcmtr_oltbuf_to_sysbuf(buf);
+    if (!sysb)
+        return BCM_ERR_NOMEM;
+    bcmtrmux_rx_from_host(device, muxch, sysb);
+
+    return BCM_ERR_OK;
+}
+
+/* Receive from trmux. Called in trmux context */
+static void _bcmtr_direct_rx_from_trmux(bcmolt_devid device, bcmos_buf *sysb, bcmtrmux_channel channel, void *data)
+{
+    bcmos_msg *msg;
+    bcmtr_ipc_data *ipc_data;
+    bcmos_errno err;
+
+    msg = bcmos_msg_pool_alloc(&bcmtr_rx_msg_pool[device]);
+    if (!msg)
+    {
+         /* <-- add some statistic here */
+        bcmos_buf_free(sysb);
+        return;
+    }
+    ipc_data = msg->data;
+    err = bcmtr_sysbuf_to_oltbuf(sysb, &ipc_data->buf);
+    if (err)
+    {
+        /* <-- add some statistic here */
+        bcmos_buf_free(sysb);
+        bcmos_msg_free(msg);
+        return;
+    }
+    ipc_data->subch = channel;
+    err = bcmos_msg_send(&bcmtr_rxq[device], msg, BCMOS_MSG_SEND_AUTO_FREE);
+    if (err)
+    {
+        /* <-- add some statistic here */
+    }
+}
+
+/** Receive data */
+static bcmos_errno bcmtr_direct_recv(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf)
+{
+    bcmolt_devid device = (bcmolt_devid)(ch >> 8);
+    bcmos_msg *msg;
+    bcmtr_ipc_data *data;
+    bcmos_errno err;
+
+    err = bcmos_msg_recv(&bcmtr_rxq[device], BCMTR_MSG_TIMEOUT, &msg);
+    if (err)
+    {
+        if (err != BCM_ERR_TIMEOUT)
+            err = BCM_ERR_COMM_FAIL;
+        return err;
+    }
+
+    data = msg->data;
+    *buf = data->buf;
+    *subch = data->subch;
+    /* Prevent buffer release when releasing OS message */
+    data->buf.start = data->buf.curr = NULL;
+    bcmos_msg_free(msg);
+
+    return BCM_ERR_OK;
+}
+
+/** Initialize plugin callbacks
+ * \param[in,out]       driver Transport plugin driver structure
+ * \return error code
+ */
+bcmos_errno bcmtr_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver)
+{
+    driver->open = bcmtr_direct_open;
+    driver->close = bcmtr_direct_close;
+    driver->recv = bcmtr_direct_recv;
+    driver->send = bcmtr_direct_send;
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/transport/plugin/mux/Makefile b/bcm68620_release/release/host_customized/transport/plugin/mux/Makefile
new file mode 100755
index 0000000..acf736a
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/mux/Makefile
@@ -0,0 +1,16 @@
+#
+#  transport plugin
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+ifeq ("$(CONFIG_TRANSPORT_RAW)", "y")
+MOD_NAME = tr_plugin_mux
+MOD_TYPE = lib
+MOD_DEPS =  tr_plugin_raw tr_plugin_raw_ud  
+
+MOD_DEFS = -DBCMTR_PLUGIN_RAW
+
+srcs = bcmtr_nl_ud_mux.c
+
+endif
+endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/mux/bcmtr_nl_ud_mux.c b/bcm68620_release/release/host_customized/transport/plugin/mux/bcmtr_nl_ud_mux.c
new file mode 100755
index 0000000..cabaf47
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/mux/bcmtr_nl_ud_mux.c
@@ -0,0 +1,40 @@
+

+#include <bcmos_system.h>

+#include <bcmtr_plugin.h>

+#include "bcmolt_tr_ud.h"

+#include "bcmolt_tr_nl.h"

+#include "bcmtr_internal.h"

+

+static bcmos_bool use_inband = BCMOS_FALSE;

+void using_inband_set(bcmos_bool using_inband)

+{

+    use_inband = using_inband;

+}

+bcmos_bool using_inband_get(void)

+{

+    return use_inband;

+}

+

+

+/** Initialize plugin callbacks

+ * \param[in,out]       driver Transport plugin driver structure

+ * \return error code

+ */

+bcmos_errno bcmtr_plugin_init(bcmtr_plugin_cfg *plugin_cfg, bcmtr_driver *driver)

+{

+    bcmos_errno rc = BCM_ERR_NOT_SUPPORTED;

+

+#ifdef SIMULATION_BUILD

+    rc = bcmtr_plugin_init(plugin_cfg, driver);

+#else

+    if (using_inband_get())

+    {

+        rc = bcmtr_ud_plugin_init(plugin_cfg, driver);

+    } else

+    {

+        rc = bcmtr_nl_plugin_init(plugin_cfg, driver);

+    }

+#endif

+

+    return rc;

+}

diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_nl/Makefile b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/Makefile
new file mode 100644
index 0000000..8947722
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/Makefile
@@ -0,0 +1,15 @@
+#
+# NL transport plugin
+#
+ifeq ("$(OS_KERNEL)", "linux")
+ifeq ("$(CONFIG_TRANSPORT_RAW)", "y")
+
+MOD_NAME = tr_plugin_raw
+MOD_TYPE = lib
+MOD_DEPS = tr_plugin
+MOD_DEFS = -DBCMTR_PLUGIN_RAW
+
+srcs = bcmolt_tr_plugin_nl_socket.c
+
+endif
+endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_nl.h b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_nl.h
new file mode 100644
index 0000000..0707c3c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_nl.h
@@ -0,0 +1,40 @@
+/*
+<: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 BCMOLT_TR_NL_H_
+#define BCMOLT_TR_NL_H_
+
+#include "bcmtr_internal.h"
+
+/* NL family. Must be some unused number */
+#define BCMTR_NL_FAMILY         28
+
+bcmos_errno bcmtr_nl_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_plugin_nl_socket.c b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_plugin_nl_socket.c
new file mode 100644
index 0000000..df45234
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_nl/bcmolt_tr_plugin_nl_socket.c
@@ -0,0 +1,339 @@
+/*
+<: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 <sys/types.h>
+#include <sys/socket.h>
+#include <linux/netlink.h>
+#include <poll.h>
+
+#include <bcmos_system.h>
+#include <bcmtr_plugin.h>
+#include <bcm_config.h>
+#include <bcmolt_tr_nl.h>
+
+#define BCMNL_TXPREFIX_LEN      (NLMSG_HDRLEN + sizeof(uint32_t))
+
+
+/* Buffer list header */
+typedef struct bcmtr_nl_buf bcmtr_nl_buf;
+struct bcmtr_nl_buf
+{
+    STAILQ_ENTRY(bcmtr_nl_buf) list;
+    uint32_t len; /**< Total Length of buffer */
+};
+
+/* Plugin channel structure */
+typedef struct bcmtr_nl_channel
+{
+    int device;         /* Device */
+    STAILQ_HEAD(nl_buf_list, bcmtr_nl_buf) buf_list;
+    bcmos_sem sem;      /* Semaphore that indicates that new buffer is available */
+    bcmos_mutex lock;   /* lock that protects this structure */
+} bcmtr_nl_channel;
+
+/* A single NL socket is shared by multiple devices.
+ * The following control block is used for socket multiplexing
+ */
+static struct
+{
+    int s;                                      /* Netlink socket */
+    int users;                                  /* Number of users */
+    bcmos_mutex lock;                           /* lock that protects this structure */
+    bcmos_task nl_rx_task;                      /* Task that reads from the shared NL socket */
+    bcmtr_nl_channel *nlch[BCMTR_MAX_OLTS];     /* Channels */
+} bcmtr_nl_common;
+
+/* NL socket RX task handler */
+static int bcmtr_nl_rx_task_handler(long data);
+
+/** Open first communication channel */
+static bcmos_errno bcmtr_nl_open_first(void)
+{
+    struct sockaddr_nl sa = {};
+    bcmos_task_parm tp = {
+        .name = "nl_tx",
+        .handler = bcmtr_nl_rx_task_handler,
+        .priority = TASK_PRIORITY_TRANSPORT_RX
+    };
+    int s;
+    bcmos_errno err;
+
+    s = socket(AF_NETLINK, SOCK_RAW, BCMTR_NL_FAMILY);
+    if (s < 0)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't create NL socket\n");
+    }
+
+    /* Connect to remote */
+    sa.nl_pid = 0;
+    if (connect(s, (struct sockaddr*)&sa, sizeof(sa)) == -1)
+    {
+        close(s);
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't connect NL socket. error %d (%s)\n",
+            errno, strerror(errno));
+    }
+
+    /* Bind local */
+    sa.nl_family = AF_NETLINK;
+    sa.nl_pid = getpid();
+    if (bind(s, (struct sockaddr*)&sa, sizeof(sa) ) == -1)
+    {
+        close(s);
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't bind NL socket. error %d (%s)\n",
+            errno, strerror(errno));
+    }
+
+    bcmtr_nl_common.s = s;
+
+    /* Create RX thread */
+    err = bcmos_task_create(&bcmtr_nl_common.nl_rx_task, &tp);
+    if (err)
+    {
+        close(s);
+        bcmtr_nl_common.s = 0;
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't create NL RX thread. error %d (%s)\n",
+            err, bcmos_strerror(err));
+    }
+
+    return BCM_ERR_OK;
+}
+
+/** Close last communication channel */
+static bcmos_errno bcmtr_nl_close_last(void)
+{
+    close(bcmtr_nl_common.s);
+    return bcmos_task_destroy(&bcmtr_nl_common.nl_rx_task);
+}
+
+/** Open communication channel */
+static bcmos_errno bcmtr_nl_open(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch)
+{
+    bcmtr_nl_channel *nlch;
+    bcmos_errno err = BCM_ERR_OK;
+
+    if ((unsigned)device >= BCMTR_MAX_OLTS)
+        BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Device %d is invalid\n");
+
+    if (bcmtr_nl_common.nlch[device])
+        BCMOS_TRACE_RETURN(BCM_ERR_ALREADY, "Channel for device %d is already opened\n");
+
+    nlch = bcmos_calloc(sizeof(*nlch));
+    if (!nlch)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "No memory\n");
+    }
+    nlch->device = device;
+    STAILQ_INIT(&nlch->buf_list);
+    err = bcmos_mutex_create(&nlch->lock, 0, "tr_nlch");
+    err = err ? err : bcmos_sem_create(&nlch->sem, 0, 0, "tr_nlch");
+
+    /* Tie in with the control block shared by all devices */
+    bcmos_mutex_lock(&bcmtr_nl_common.lock);
+    if (!bcmtr_nl_common.users)
+        err = err ? err : bcmtr_nl_open_first();
+    if (err)
+    {
+        bcmos_mutex_unlock(&bcmtr_nl_common.lock);
+        bcmos_free(nlch);
+        BCMOS_TRACE_RETURN(err, "Failed to open or bind NL socket\n");
+    }
+    ++bcmtr_nl_common.users;
+    bcmtr_nl_common.nlch[device] = nlch;
+    bcmos_mutex_unlock(&bcmtr_nl_common.lock);
+
+    *ch = (bcmtr_plugin_channel)nlch;
+
+    return BCM_ERR_OK;
+}
+
+/** Close communication channel */
+static bcmos_errno bcmtr_nl_close(bcmtr_plugin_channel ch)
+{
+    bcmtr_nl_channel *nlch = (bcmtr_nl_channel *)ch;
+    bcmtr_nl_buf *nl_buf, *nl_buf_tmp;
+    bcmolt_buf buf;
+    bcmos_errno err = BCM_ERR_OK;
+
+    bcmos_mutex_lock(&bcmtr_nl_common.lock);
+    if (bcmtr_nl_common.nlch[nlch->device] == nlch)
+    {
+        bcmtr_nl_common.nlch[nlch->device] = NULL;
+        --bcmtr_nl_common.users;
+        if (bcmtr_nl_common.users)
+            err = bcmtr_nl_close_last();
+    }
+    else
+    {
+        BCMOS_TRACE_ERR("Unexpected NL channel\n");
+        err = BCM_ERR_INTERNAL;
+    }
+    bcmos_mutex_unlock(&bcmtr_nl_common.lock);
+    bcmos_mutex_destroy(&nlch->lock);
+    bcmos_sem_destroy(&nlch->sem);
+    STAILQ_FOREACH_SAFE(nl_buf, &nlch->buf_list, list, nl_buf_tmp)
+    {
+        STAILQ_REMOVE_HEAD(&nlch->buf_list, list);
+        bcmolt_buf_init(&buf, nl_buf->len, (uint8_t *)nl_buf, BCMTR_BUF_ENDIAN);
+        bcmolt_buf_free(&buf);
+    }
+    bcmos_free(nlch);
+
+    return err;
+}
+
+/** Send data */
+static bcmos_errno bcmtr_nl_send(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf,
+    bcmtr_send_flags flags)
+{
+    bcmtr_nl_channel *nlch = (bcmtr_nl_channel *)ch;
+    int total_len = bcmolt_buf_get_used(buf);
+    struct nlmsghdr *nlmsg_hdr = (struct nlmsghdr *)(long)buf->start;
+    struct iovec iov = { buf->start, .iov_len=total_len };
+    struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
+    int rc;
+
+    nlmsg_hdr->nlmsg_len = total_len;
+    nlmsg_hdr->nlmsg_pid = getpid();
+    buf->start[NLMSG_HDRLEN] = nlch->device;
+
+    rc = sendmsg(bcmtr_nl_common.s, &msg, 0);
+
+    return (rc == total_len) ? BCM_ERR_OK : BCM_ERR_COMM_FAIL;
+}
+
+/* NL socket RX task handler */
+static int bcmtr_nl_rx_task_handler(long data)
+{
+    bcmos_task *my_task = bcmos_task_current();
+    struct iovec iov;
+    struct msghdr msg = { .msg_iov = &iov, .msg_iovlen = 1 };
+    uint32_t device;
+    bcmolt_buf buf = {};
+    bcmtr_nl_buf *nl_buf;
+    bcmtr_nl_channel *nlch;
+    bcmos_errno err;
+    int rc;
+
+    while (!my_task->destroy_request)
+    {
+        err = bcmolt_buf_alloc(&buf, BCMTR_MAX_MTU_SIZE + BCMNL_TXPREFIX_LEN, BCMTR_BUF_ENDIAN);
+        if (err)
+        {
+            /* We are out of memory, hopefully temporary. Wait and continue */
+            bcmos_usleep(1000);
+            continue;
+        }
+        iov.iov_base = buf.start;
+        iov.iov_len = buf.len;
+
+        /* Wait for message */
+        rc = recvmsg(bcmtr_nl_common.s, &msg, 0);
+        if (rc < NLMSG_HDRLEN)
+        {
+            BCMOS_TRACE_ERR("Fatal error. recvmsg() failed with error %d (%s)\n", errno, strerror(errno));
+            break;
+        }
+
+        /* Device follows NL header */
+        memcpy(&device, buf.start + NLMSG_HDRLEN, sizeof(uint32_t));
+        if (device >= BCMTR_MAX_OLTS || !(nlch = bcmtr_nl_common.nlch[device]))
+        {
+            BCMOS_TRACE_ERR("Got message from unexpected device %u. Ignored\n", device);
+            bcmolt_buf_free(&buf);
+            continue;
+        }
+
+        /* Put message on the channel's queue */
+        nl_buf = (bcmtr_nl_buf *)(long)buf.start;
+        nl_buf->len = rc;
+        bcmos_mutex_lock(&nlch->lock);
+        STAILQ_INSERT_TAIL(&nlch->buf_list, nl_buf, list);
+        bcmos_mutex_unlock(&nlch->lock);
+        bcmos_sem_post(&nlch->sem);
+
+        /* Buffer is in use elsewhere */
+        buf.start = buf.curr = NULL;
+    }
+
+    bcmolt_buf_free(&buf);
+    my_task->destroyed = BCMOS_TRUE;
+    return 0;
+}
+
+/** Receive data */
+static bcmos_errno bcmtr_nl_recv(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf)
+{
+    bcmtr_nl_channel *nlch = (bcmtr_nl_channel *)ch;
+    bcmtr_nl_buf *nl_buf;
+    bcmos_errno err;
+
+    err = bcmos_sem_wait(&nlch->sem, BCMTR_MSG_TIMEOUT * 1000);
+    if (err)
+        return err;
+    bcmos_mutex_lock(&nlch->lock);
+    nl_buf = STAILQ_FIRST(&nlch->buf_list);
+    if (!nl_buf)
+    {
+        bcmos_mutex_unlock(&nlch->lock);
+        return BCM_ERR_COMM_FAIL;
+    }
+    STAILQ_REMOVE_HEAD(&nlch->buf_list, list);
+    bcmos_mutex_unlock(&nlch->lock);
+
+    /* Got buffer */
+    bcmolt_buf_init(buf, nl_buf->len, (uint8_t *)nl_buf, BCMTR_BUF_ENDIAN);
+    buf->curr = buf->start + BCMNL_TXPREFIX_LEN;
+
+    *subch = 0;
+
+    return BCM_ERR_OK;
+}
+
+/** Initialize plugin callbacks
+ * \param[in,out]       driver Transport plugin driver structure
+ * \return error code
+ */
+bcmos_errno bcmtr_nl_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver)
+{
+    bcmos_errno err;
+
+    bcmos_printf("Launching with a netlink connection\n");
+
+    driver->open = bcmtr_nl_open;
+    driver->close = bcmtr_nl_close;
+    driver->recv = bcmtr_nl_recv;
+    driver->send = bcmtr_nl_send;
+    cfg->headroom = BCMNL_TXPREFIX_LEN;
+
+    err = bcmos_mutex_create(&bcmtr_nl_common.lock, 0, "tr_nl");
+
+    return err;
+}
+
diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_ud/Makefile b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/Makefile
new file mode 100755
index 0000000..4126ef3
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/Makefile
@@ -0,0 +1,14 @@
+#
+# Unix Domain transport plugin
+#
+ifeq ("$(OS_KERNEL)", "linux")
+ifeq ("$(CONFIG_TRANSPORT_RAW)", "y")
+
+MOD_NAME = tr_plugin_raw_ud
+MOD_TYPE = lib
+MOD_DEPS = tr_plugin
+
+srcs = bcmolt_tr_plugin_ud_socket.c
+
+endif
+endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_plugin_ud_socket.c b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_plugin_ud_socket.c
new file mode 100755
index 0000000..14d9003
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_plugin_ud_socket.c
@@ -0,0 +1,182 @@
+/*
+<: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 <sys/socket.h>
+#include <sys/un.h>
+
+#include <bcmos_system.h>
+#include <bcmtr_plugin.h>
+#include <bcm_config.h>
+#include <bcmolt_tr_ud.h>
+
+char socket_path[] = SOCKET_PATH;
+/* Plugin channel structure */
+typedef struct bcmtr_ud_channel
+{
+    int device;         /* Device */
+    int sock;                                   /* UD socket */
+} bcmtr_ud_channel;
+
+
+/* This plugin stores both device id and per-device socket handle in
+ * transport's channel_id handle as
+ * (device_id << 24) | socket_handle.
+ * The following functions recover socket_handle and device_id from the channel_id handle
+ */
+
+
+/** Open communication channel */
+static bcmos_errno bcmtr_ud_open(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch)
+{
+    struct sockaddr_un addr;
+    bcmtr_ud_channel *udch;
+
+    udch = bcmos_calloc(sizeof(*udch));
+    if (!udch)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "No memory\n");
+    }
+
+    if ( (udch->sock = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+            perror("socket error");
+            exit(-1);
+        }
+
+        memset(&addr, 0, sizeof(addr));
+        addr.sun_family = AF_UNIX;
+        BUG_ON(sizeof(socket_path)>=sizeof(addr.sun_path));
+        memcpy(addr.sun_path, socket_path, sizeof(socket_path));
+
+        if (connect(udch->sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+            perror("connect error");
+            exit(-1);
+        }
+
+    bcmos_printf("Opened %d\n", udch->sock);
+
+    udch->device = device;
+
+    *ch = (bcmtr_plugin_channel)udch;
+
+    return BCM_ERR_OK;
+}
+
+/** Close communication channel */
+static bcmos_errno bcmtr_ud_close(bcmtr_plugin_channel ch)
+{
+    bcmtr_ud_channel *udch = (bcmtr_ud_channel *)ch;
+
+    bcmos_printf("Closed %d\n", udch->sock);
+        close(udch->sock);
+    bcmos_free(udch);
+
+    return BCM_ERR_OK;
+}
+
+/** Send data */
+static bcmos_errno bcmtr_ud_send(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf,
+    bcmtr_send_flags flags)
+{
+    bcmtr_ud_channel *udch = (bcmtr_ud_channel *)ch;
+    int buflen = bcmolt_buf_get_used(buf);
+    int len;
+    len = send(udch->sock, buf->start, buflen, 0);
+ 
+    if (len < buflen)
+    {
+        bcmos_printf("%s: sock_sendmsg(%u) --> %d. errno=%d\n", __FUNCTION__, buflen, len, errno);
+        return BCM_ERR_COMM_FAIL;
+    }
+
+    return BCM_ERR_OK;
+}
+
+/** Receive data */
+static bcmos_errno bcmtr_ud_recv(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf)
+{
+    bcmtr_ud_channel *udch = (bcmtr_ud_channel *)ch;
+    int len;
+    fd_set read_fds;
+    struct timeval tv;
+    bcmos_errno err;
+    int rc;
+
+    FD_ZERO(&read_fds);
+    FD_SET(udch->sock, &read_fds);
+    tv.tv_sec = 0;
+    tv.tv_usec = BCMTR_MSG_TIMEOUT * 1000;
+
+    rc = select(udch->sock + 1, &read_fds, NULL, NULL, &tv);
+    if (rc < 0)
+    {
+        perror("select");
+        return BCM_ERR_COMM_FAIL;
+    }
+    if (!rc || !FD_ISSET(udch->sock, &read_fds))
+    {
+        return BCM_ERR_TIMEOUT;
+    }
+
+    err = bcmolt_buf_alloc(buf, BCMTR_MAX_MTU_SIZE, BCMOLT_BUF_ENDIAN_FIXED);
+    if (err)
+        return BCM_ERR_NOMEM;
+
+    len = recv(udch->sock, buf->start, BCMTR_MAX_MTU_SIZE, 0);
+    if (len <= 0)
+    {
+        bcmolt_buf_free(buf);
+        return BCM_ERR_COMM_FAIL;
+    }
+
+    bcmos_printf("Received %d bytes from dev_control\n", len);
+
+    buf->len = len;
+    return BCM_ERR_OK;
+}
+
+/** Initialize plugin callbacks
+ * \param[in,out]       driver Transport plugin driver structure
+ * \return error code
+ */
+bcmos_errno bcmtr_ud_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver)
+{
+    bcmos_errno err = BCM_ERR_OK;
+
+    bcmos_printf("Launching with a unix domain connection\n");
+
+    driver->open = bcmtr_ud_open;
+    driver->close = bcmtr_ud_close;
+    driver->recv = bcmtr_ud_recv;
+    driver->send = bcmtr_ud_send;
+    cfg->headroom = BCMUD_TXPREFIX_LEN;
+
+    return err;
+}
+
diff --git a/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_ud.h b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_ud.h
new file mode 100755
index 0000000..bca32d4
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/raw_ud/bcmolt_tr_ud.h
@@ -0,0 +1,41 @@
+/*
+<: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 BCMOLT_TR_UD_H_
+#define BCMOLT_TR_UD_H_
+
+#include "bcmtr_internal.h"
+
+#define BCMUD_TXPREFIX_LEN (sizeof(uint32_t))
+
+#define SOCKET_PATH "\0bcm68620"
+
+bcmos_errno bcmtr_ud_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/udp/Makefile b/bcm68620_release/release/host_customized/transport/plugin/udp/Makefile
new file mode 100644
index 0000000..8106edc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/udp/Makefile
@@ -0,0 +1,17 @@
+# Transport: UDP Plugin
+#
+
+CONFIG_TRANSPORT_RAW ?= n
+CONFIG_TRANSPORT_UDP ?= y
+ifeq ("$(CONFIG_TRANSPORT_RAW)", "y")
+	CONFIG_TRANSPORT_UDP = n
+endif
+
+ifeq ("$(CONFIG_TRANSPORT_UDP)", "y")
+MOD_NAME = tr_plugin_udp
+MOD_TYPE = lib
+MOD_DEPS = tr_plugin
+MOD_DEFS = -DBCMTR_UDP_SUPPORT
+
+srcs = bcmtr_plugin_udp_socket.c
+endif
diff --git a/bcm68620_release/release/host_customized/transport/plugin/udp/bcmtr_plugin_udp_socket.c b/bcm68620_release/release/host_customized/transport/plugin/udp/bcmtr_plugin_udp_socket.c
new file mode 100644
index 0000000..4ab4444
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/plugin/udp/bcmtr_plugin_udp_socket.c
@@ -0,0 +1,220 @@
+/*
+<: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 <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+
+#include <bcmtr_plugin.h>
+#include <bcm_config.h>
+
+/* Last seen host IP and port */
+static struct sockaddr_in peer_sa[BCMTR_MAX_OLTS];
+
+/* This plugin stores both device id and per-device socket handle in
+ * transport's channel_id handle as
+ * (device_id << 24) | socket_handle.
+ * The following functions recover socket_handle and device_id from the channel_id handle
+ */
+
+static inline int _bcmtr_channel_to_socket(bcmtr_plugin_channel ch)
+{
+    return (int)(ch & 0xffffff);
+}
+
+static inline int _bcmtr_channel_to_device(bcmtr_plugin_channel ch)
+{
+    return (int)((ch >> 24) & 0xff);
+}
+
+/** Open communication channel */
+static bcmos_errno bcmtr_udp_open(int device, bcmtr_plugin_cfg *cfg, bcmtr_plugin_channel *ch)
+{
+    struct sockaddr_in sa = {};
+    struct timeval timeout = { .tv_sec = 0, .tv_usec = BCMTR_MSG_TIMEOUT * 1000 };  
+    int s;
+
+    s = socket(AF_INET, SOCK_DGRAM, 0);
+    if (s < 0)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't create UDP socket\n");
+    }
+
+    /* Bind local */
+    sa.sin_family = AF_INET;
+    sa.sin_port = htons(cfg->x.udp.my_port);
+    sa.sin_addr.s_addr = INADDR_ANY;
+    if (bind(s, (struct sockaddr*)&sa, sizeof(sa) ) == -1)
+    {
+        close(s);
+        perror("bind");
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't bind UDP socket to %d.%d.%d.%d:%d\n",
+            (int)(cfg->x.udp.my_ip >> 24), (int)((cfg->x.udp.my_ip >> 16) & 0xff),
+            (int)((cfg->x.udp.my_ip >> 8) & 0xff), (int)(cfg->x.udp.my_ip & 0xff),
+            (int)cfg->x.udp.my_port);
+    }
+    bcmos_printf("%s: socket bound to port %d\n", __FUNCTION__, (int)cfg->x.udp.my_port);
+
+    if (setsockopt(s, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, sizeof(timeout)) < 0)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_COMM_FAIL, "Can't set socket option for send timeout\n");
+    }
+
+    /* Connect to remote */
+    if (cfg->x.udp.remote_port)
+    {
+        peer_sa[device].sin_family = AF_INET;
+        peer_sa[device].sin_port = htons(cfg->x.udp.remote_port);
+        peer_sa[device].sin_addr.s_addr = htonl(cfg->x.udp.remote_ip);
+    }
+    *ch = (device << 24) | s;
+
+    return BCM_ERR_OK;
+}
+
+/* print error message with throttling: not oftener than ones per second */
+static void _bcmtr_udp_print_err(bcmos_errno err, const char *err_msg)
+{
+    static int nerrors;
+    static uint32_t last_timestamp;
+
+    ++nerrors;
+
+    if (!last_timestamp || bcmos_timestamp() - last_timestamp > 1000000)
+    {
+        BCMOS_TRACE_ERR("Error in low-level UDP transport. %s-%s. Errors since last report: %d\n",
+            err_msg, bcmos_strerror(err), nerrors);
+        last_timestamp = bcmos_timestamp();
+        nerrors = 0;
+    }
+}
+
+/** Close communication channel */
+static bcmos_errno bcmtr_udp_close(bcmtr_plugin_channel ch)
+{
+    close(_bcmtr_channel_to_socket(ch));
+    return BCM_ERR_OK;
+}
+
+/** Send data */
+static bcmos_errno bcmtr_udp_send(bcmtr_plugin_channel ch, bcmolt_subchannel subch, bcmolt_buf *buf,
+    bcmtr_send_flags flags)
+{
+    int sock = _bcmtr_channel_to_socket(ch);
+    int device = _bcmtr_channel_to_device(ch);
+    int buflen = bcmolt_buf_get_used(buf);
+    struct iovec iov = { .iov_base = buf->start, .iov_len = buflen };
+    struct msghdr msg = {
+        .msg_iov = &iov, .msg_iovlen = 1, .msg_flags = 0,
+        .msg_name = (void *)&peer_sa[device], .msg_namelen = sizeof(peer_sa[0])
+    };
+    int len;
+
+    len = sendmsg(sock, &msg, 0);
+    if (len < buflen)
+    {
+        bcmos_printf("%s: sock_sendmsg(%u) --> %d. errno=%d\n", __FUNCTION__, buflen, len, errno);
+        return BCM_ERR_COMM_FAIL;
+    }
+
+    return BCM_ERR_OK;
+}
+
+/** Receive data */
+static bcmos_errno bcmtr_udp_recv(bcmtr_plugin_channel ch, bcmolt_subchannel *subch, bcmolt_buf *buf)
+{
+    int sock = _bcmtr_channel_to_socket(ch);
+    int device = _bcmtr_channel_to_device(ch);
+    struct iovec iov;
+    struct msghdr msg = {
+        .msg_iov = &iov, .msg_iovlen = 1,
+        .msg_name = (void *)&peer_sa[device], .msg_namelen = sizeof(peer_sa[0])
+    };
+    int len;
+    fd_set read_fds;
+    struct timeval tv;
+    bcmos_errno err;
+    int rc;
+
+    FD_ZERO(&read_fds);
+    FD_SET(sock, &read_fds);
+    tv.tv_sec = 0;
+    tv.tv_usec = BCMTR_MSG_TIMEOUT * 1000;
+
+    rc = select(sock + 1, &read_fds, NULL, NULL, &tv);
+    if (rc < 0)
+    {
+        perror("select");
+        return BCM_ERR_COMM_FAIL;
+    }
+    if (!rc || !FD_ISSET(sock, &read_fds))
+    {
+        return BCM_ERR_TIMEOUT;
+    }
+
+    err = bcmolt_buf_alloc(buf, BCMTR_MAX_MTU_SIZE, BCMOLT_BUF_ENDIAN_FIXED);
+    if (err)
+        return BCM_ERR_NOMEM;
+
+    iov.iov_base = buf->start;
+    iov.iov_len = BCMTR_MAX_MTU_SIZE;
+    len = recvmsg(sock, &msg, 0);
+    if (len <= 0)
+    {
+        _bcmtr_udp_print_err(BCM_ERR_COMM_FAIL, "recvmsg() failed\n");
+        bcmolt_buf_free(buf);
+        return BCM_ERR_COMM_FAIL;
+    }
+    buf->len = len;
+    *subch = ntohs(peer_sa[device].sin_port);
+
+    return BCM_ERR_OK;
+}
+
+/** Initialize plugin callbacks
+ * \param[in,out]       driver Transport plugin driver structure
+ * \return error code
+ */
+bcmos_errno bcmtr_plugin_init(bcmtr_plugin_cfg *cfg, bcmtr_driver *driver)
+{
+    if (cfg->type != BCMTR_TYPE_UDP)
+    {
+        BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Invalid plugin type. Expected UDP\n");
+    }
+
+    driver->open = bcmtr_udp_open;
+    driver->close = bcmtr_udp_close;
+    driver->recv = bcmtr_udp_recv;
+    driver->send = bcmtr_udp_send;
+
+    return BCM_ERR_OK;
+}
+
diff --git a/bcm68620_release/release/host_customized/transport/unix_socket/Makefile b/bcm68620_release/release/host_customized/transport/unix_socket/Makefile
new file mode 100644
index 0000000..911e3cc
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/unix_socket/Makefile
@@ -0,0 +1,10 @@
+# UD transport driver
+#
+ifneq ("$(SIMULATION_BUILD)", "y")
+MOD_NAME = udtr
+MOD_TYPE = lib
+MOD_DEPS = trmux tr_plugin_raw_ud
+
+srcs = bcmolt_tr_ud_driver.c
+
+endif
diff --git a/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.c b/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.c
new file mode 100755
index 0000000..30143da
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.c
@@ -0,0 +1,231 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmolt_tr_ud_driver.c
+ *
+ * Unix Domain socket based transport.
+ *
+ */
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <stdlib.h>
+
+#include <bcmolt_tr_mux.h>
+#include <bcmolt_tr_ud_driver.h>
+#include <bcmolt_tr_ud.h>
+
+#define BCMTR_MEM_PACKETS       10000
+#define BCMTR_MEM_OVERHEAD      1024
+#define BCMTR_MIN_RCVBUF_SIZE   (BCMTR_MEM_PACKETS * BCMTR_MEM_OVERHEAD)
+
+char socket_path[] = SOCKET_PATH;
+
+typedef struct ud_conn_info {
+    bcmtrmux_channel channel[BCMTR_MAX_OLTS];
+    int sock;
+} ud_conn_info;
+
+static bcmos_task rx_thread;
+static int fd;
+static ud_conn_info *conn_info[BCMTRMUX_MAX_CHANNELS];
+static int ii;
+
+static void _bcmtr_ud_recv(bcmolt_devid device, bcmos_buf *buf, bcmtrmux_channel channel, void *data)
+{
+    uint32_t data_length = bcmos_buf_length(buf); 
+    int kk;
+
+    /* Find the socket to respond on... */
+    for (kk=0; kk<sizeof(conn_info)/sizeof(conn_info[0]); kk++)
+    {
+        if (conn_info[kk]->channel[device] == channel)
+        {
+            int len = 0;
+            bcmos_printf("Sending to user application for index %d...", kk);
+            len = send(conn_info[kk]->sock, bcmos_buf_data(buf), data_length, 0);
+            if (len < 0)
+            {
+                bcmos_printf("Failed to send respose to user application - what now?\n");
+            }
+            bcmos_printf("Sent %d bytes\n", len);
+            break;
+        }
+    }
+}
+
+static int bcmtr_ud_rx_handler(long arg)
+{
+    int rc, jj;
+    bcmos_buf *buf;
+    struct timeval tv;
+    fd_set read_set;
+
+    while (1)
+    {
+        int count;
+        FD_ZERO(&read_set);
+        for (jj=0; jj<sizeof(conn_info)/sizeof(conn_info[0]); jj++)
+        {
+            if (conn_info[jj])
+            {
+                FD_SET(conn_info[jj]->sock, &read_set);
+            }
+        }
+
+        tv.tv_sec = 0; tv.tv_usec = 100000;
+
+        count = select (FD_SETSIZE, &read_set, NULL, NULL, &tv);
+        if (count < 0)
+            break;
+        
+        for (jj = 0; jj < sizeof(conn_info)/sizeof(conn_info[0]) ; jj++)
+        {
+            if (conn_info[jj] && FD_ISSET(conn_info[jj]->sock, &read_set))
+            {
+                buf = bcmos_buf_alloc(BCMTR_MAX_MTU_SIZE);
+                if (!buf)
+                {
+                    return BCM_ERR_NOMEM;
+                }
+                memset(buf, 0 , sizeof(buf));
+                rc=read(conn_info[jj]->sock, bcmos_buf_data(buf), buf->size);
+                buf->len = rc;
+                buf->data+=BCMUD_TXPREFIX_LEN;
+                if (rc < 0 ) {
+                    perror("read");
+                    exit(-1);
+                }
+                else if (rc == 0) {
+                    close(conn_info[jj]->sock);  
+                    bcmos_free(conn_info[jj]);
+                    conn_info[jj]=0;
+                    bcmos_printf("Closing %d\n", jj);
+                }
+                else {
+                    bcmolt_devid device = 0;  /*  How do we get this?  
+                                                  Need to stuff it at the begining of the message. */
+                    bcmtrmux_rx_from_host(device, conn_info[jj]->channel[device], buf);
+                }
+            }
+        }
+    }
+    return BCM_ERR_OK;
+}
+
+static int next_conn_info(bcmolt_devid device)
+{
+  int jj=0;
+  while (jj<sizeof(conn_info)/sizeof(conn_info[0]))
+    {
+      jj++; ii++;
+      if (ii>sizeof(conn_info)/sizeof(conn_info[0])) ii=0;
+      if (!conn_info[ii]) return 0;
+    }
+  return -1;
+}
+
+bcmos_errno bcmtr_ud_init(void)
+{
+    bcmos_errno err = BCM_ERR_OK;
+    struct sockaddr_un addr;
+    bcmos_task_parm parm = {
+        .priority = TASK_PRIORITY_TRANSPORT_RX,
+        .stack_size = BCMTR_RX_THREAD_STACK,
+        .handler = bcmtr_ud_rx_handler,
+        .name = "ud handler"
+    };
+
+    ii=0;
+    
+    if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
+        perror("socket error");
+        exit(-1);
+    }
+
+    memset(&addr, 0, sizeof(addr));
+    addr.sun_family = AF_UNIX;
+    BUG_ON(sizeof(socket_path)>=sizeof(addr.sun_path));
+    memcpy(addr.sun_path, socket_path, sizeof(socket_path));
+
+    if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
+        perror("bind error");
+        exit(-1);
+    }
+
+    if (listen(fd, 5) == -1) {
+        perror("listen error");
+        exit(-1);
+    }
+
+    err = bcmos_task_create(&rx_thread, &parm);
+ 
+    if (err) return err;
+
+    while (1) {
+        bcmolt_devid device = 0;  /*  How do we get this?  Need to stuff it at the begining of the message. */
+        int s;
+        ud_conn_info *ci;
+        bcmos_errno rc;
+        bcmtrmux_channel channel = BCMTRMUX_CHANNEL_AUTO_ASSIGN;
+
+        if ( (s = accept(fd, NULL, NULL)) == -1) {
+            perror("accept error");
+            sleep(1);
+            continue;
+        }
+
+        ci = bcmos_calloc(sizeof(*ci)); 
+        if (!ci)
+        {
+            BCMOS_TRACE_RETURN(BCM_ERR_NOMEM, "No memory\n");
+        }
+        rc = bcmtrmux_channel_register(device, &channel, _bcmtr_ud_recv, conn_info);
+        if (rc)
+        {
+            bcmos_printf("%s: can't register channel for device %u. rc=%d\n", __FUNCTION__, device, (int)rc);
+            return rc;;
+        }
+        ci->sock = s;
+        ci->channel[device]=channel;
+        conn_info[ii] = ci;
+
+        bcmos_printf("Accepting %d-%d\n", ii, conn_info[ii]->sock);
+
+        if (next_conn_info(device) < 0) return -1;
+    }
+    return BCM_ERR_OK;
+}
+
+void bcmtr_ud_exit(void)
+{
+
+}
diff --git a/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.h b/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.h
new file mode 100755
index 0000000..9726c9c
--- /dev/null
+++ b/bcm68620_release/release/host_customized/transport/unix_socket/bcmolt_tr_ud_driver.h
@@ -0,0 +1,42 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmtr_ud_driver.h - host unix domain socket transport driver
+ */
+
+#ifndef BCMOLT_TR_UD_DRIVER_H_
+#define BCMOLT_TR_UD_DRIVER_H_
+
+#include <bcmos_system.h>
+
+bcmos_errno bcmtr_ud_init(void);
+void bcmtr_ud_exit(void);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/user_config/Makefile b/bcm68620_release/release/host_customized/user_config/Makefile
new file mode 100644
index 0000000..1db59e8
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/Makefile
@@ -0,0 +1,16 @@
+#
+# user_config
+#
+MOD_NAME = user_config
+MOD_DEPS = common_api fld ll_pcie
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_lib
+else
+    MOD_TYPE = lib
+endif
+
+ifneq ("$(BOARD)", "")
+    srcs = board/$(BOARD)/bcmolt_user_utils.c
+    MOD_DEPS += i2c_devs board_selector
+endif
diff --git a/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h b/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h
new file mode 100644
index 0000000..ff32e36
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/bcmolt_user_utils.h
@@ -0,0 +1,75 @@
+/*
+<: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 _BCMOLT_USER_UTILS_H_
+#define _BCMOLT_USER_UTILS_H_
+
+#include <bcmolt_model_types.h>
+#include <bcmos_system.h>
+#include <bcmolt_msg.h>
+#include <bcmolt_fld.h>
+
+/* Validate that the given system mode is supported for the given device.
+ * This function returns BCM_ERR_OK if the system mode is valid or a different error code otherwise. */
+bcmos_errno bcmuser_system_mode_validate(bcmolt_devid device, bcmolt_system_mode system_mode);
+
+/* Read file from a file system into a buffer. */
+int bcmuser_image_read(
+    bcmolt_devid device,
+    bcmolt_device_image_type image_type,
+    uint32_t offset,
+    uint8_t *buf,
+    uint32_t buf_size);
+
+/* Turn off the processor of the embedded device. */
+bcmos_errno bcmuser_device_off(bcmolt_devid device);
+
+/* Turn on the processor of the embedded device. */
+bcmos_errno bcmuser_device_on(bcmolt_devid device);
+
+/* Check whether or not the embedded device processor is running. */
+bcmos_errno bcmuser_device_is_running(bcmolt_devid device, bcmos_bool *is_cpu_on);
+
+/* Prepare the PCIe bus for communication with the embedded devices */
+bcmos_errno bcmuser_pcie_prepare(void);
+
+/* Prepare the PCIe channel for communication with the embedded device.
+ * For example, this function may re-enumerate the PCI-E bus. */
+bcmos_errno bcmuser_pcie_channel_prepare(bcmolt_devid device);
+
+bcmos_errno bcmuser_pcie_channel_prepare_for_kt2(bcmolt_devid device);
+
+/* Remove the PCIe channel for communication with the embedded device.
+ * For example, this function may re-enumerate the PCI-E bus. */
+bcmos_errno bcmuser_pcie_channel_remove(bcmolt_devid device);
+
+/* Reset the host processor. */
+bcmos_errno bcmuser_host_reset(void);
+
+#endif
diff --git a/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c b/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c
new file mode 100644
index 0000000..94f58a9
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board/wrx/bcmolt_user_utils.c
@@ -0,0 +1,533 @@
+/*
+<: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 <linux/fs.h>
+#include <linux/buffer_head.h>
+#include <linux/reboot.h>
+#include <linux/pci.h>
+#include <asm/segment.h>
+#include <asm/uaccess.h>
+#include <bcmos_system.h>
+#include <bcm_config.h>
+#include <bcmolt_msg.h>
+#include <bcmolt_fld.h>
+#include <bcmolt_llpcie.h>
+#include <bcmolt_conv.h>
+#include <bcmolt_i2c_devs.h>
+#include <bcmolt_board_selector.h>
+#include "bcmolt_user_utils.h"
+
+#define BCM_I2C_DEV_ADDR_START typedef enum {
+#define BCM_I2C_DEV_ADDR(name, desc, val) name = val,
+#define BCM_I2C_DEV_ADDR_END } bcm_i2c_dev_addr;
+#include <bcmolt_i2c_devs_addr.h>
+
+#define BOOT_FILE                       "/opt/bcm68620/bcm68620_boot.bin"
+#define APPL_FILE                       "/opt/bcm68620/bcm68620_appl.bin"
+#define ONU_FW_FILE                     "/opt/bcm68620/dummy_onu_firmware.bin"
+
+#define FPGA_REG_FPGA_VERSION 0x0
+#define FPGA_REG_BOARD_CONF 0x1
+#define FPGA_REG_RESETS 0x2
+
+#define FPGA_RST_BIT_DEVICE 0x0
+#define FPGA_DEVICE_SWITCH  4
+
+#define FPGA_ENABLE_ALL_DEVICES 0x1f
+#define FPGA_ENABLE_SWITCH              (1 << FPGA_DEVICE_SWITCH)
+/* For now swap devices for consistency with PCI enumeration */
+#define FPGA_DEVICE_RESET_BIT(dev)      (1 << (FPGA_RST_BIT_DEVICE + dev))
+
+/* Minimum required FPGA version for reading default system mode via BOARD_CONF register. */
+#define FPGA_VER_FOR_SVK_CONFIG 6
+
+/* Lock that protects critical sections */
+static bcmos_mutex user_lock;
+static bcmos_bool user_lock_initialized;
+
+typedef enum
+{
+    SVK_BOARD_ID_1    = 0x7, /* SVK #1 - BCM968620S: all PON flavors supported, SFP+ */
+    SVK_BOARD_ID_2_XG = 0x6, /* SVK #2 - BCM968620XG: XGPON */
+    SVK_BOARD_ID_2_XE = 0x5, /* SVK #2 - BCM968620XE: 10G EPON */
+    SVK_BOARD_ID_3    = 0x4, /* SVK #3 - BCM968620K: all PON flavors supported, XFP */
+    DVT_BOARD_ID      = 0x3, /* DVT board */
+} svk_board_id;
+
+typedef enum
+{
+    SVK_MODE_GPON_16X     = 0xF, /* SVK #1/3: 16x GPON mode, SVK #2: only valid mode */
+    SVK_MODE_EPON_1G_16X  = 0xE, /* SVK #1/3: 16x 1G EPON mode */
+    SVK_MODE_XGPON        = 0xD, /* SVK #1/3: 8x XGPON mode */
+    SVK_MODE_EPON_10G_8X  = 0xC, /* SVK #1/3: 8x 10G EPON mode */
+    SVK_MODE_EPON_GPON_8X = 0xB, /* SVK #1/3: 8x 10G EPON + 8x GPON coexistence mode */
+} svk_mode;
+
+
+#define CHECK_RETURN_ERROR(cond,rc) \
+		do { \
+			if (cond) {\
+				bcmos_printf("%s#%d: failed with rc=%d\n", __FUNCTION__, __LINE__, rc);\
+				return rc;\
+			}\
+		} while (0)
+
+
+static void userlock_lock(void)
+{
+    if (!user_lock_initialized)
+    {
+        bcmos_mutex_create(&user_lock, 0, "reset_lock");
+        user_lock_initialized = BCMOS_TRUE;
+    }
+    bcmos_mutex_lock(&user_lock);
+}
+
+
+static void userlock_unlock(void)
+{
+    bcmos_mutex_unlock(&user_lock);
+}
+
+static struct file *file_open(const char *path, int flags)
+{
+    struct file *fd = NULL;
+    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+    fd = filp_open(path, flags, mode);
+    if(IS_ERR(fd))
+        return NULL;
+    return fd;
+}
+
+static void file_close(struct file *file)
+{
+    filp_close(file, NULL);
+}
+
+static int file_read(struct file *file, uint32_t offset, uint8_t *data, unsigned int size)
+{
+    unsigned long long o = offset;
+    mm_segment_t oldfs;
+    int bytes_read;
+
+    oldfs = get_fs();
+    set_fs(get_ds());
+    bytes_read = vfs_read(file, data, size, &o);
+    set_fs(oldfs);
+    if (bytes_read < 0)
+    {
+        BCMOS_TRACE_ERR("vfs_read returned error %d\n", bytes_read);
+        return (int)BCM_ERR_IO;
+    }
+    return bytes_read;
+}
+
+static int file_write(struct file* file, unsigned long long offset, unsigned char* data, unsigned int size)
+{
+    mm_segment_t oldfs;
+    int ret;
+
+    oldfs = get_fs();
+    set_fs(get_ds());
+
+    ret = vfs_write(file, data, size, &offset);
+
+    set_fs(oldfs);
+    return ret;
+}
+
+static bcmos_errno file_write_1(const char *path)
+{
+    struct file *fd;
+    char to_write[] = { '1' };
+    loff_t pos = 0;
+    ssize_t bytes_written;
+
+    fd = file_open(path, O_WRONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        BCMOS_TRACE_ERR("Can't open file %s for writing. Error %s\n",
+            path, bcmos_strerror(fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT));
+        return (fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT);
+    }
+
+    bytes_written = file_write(fd, pos, to_write, sizeof(to_write));
+    if (bytes_written != sizeof(to_write))
+    {
+        BCMOS_TRACE_ERR("vfs_write returned incorrect number of characters written: %d\n", bytes_written);
+    }
+
+    file_close(fd);
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno i2c_fpga_read(uint32_t reg, uint32_t *val)
+{
+    return maple_i2c_read_fpga(maple_i2c_get_client(FPGA_I2C_ADDR), reg, val);
+}
+
+static bcmos_errno i2c_fpga_write(uint32_t reg, uint32_t val)
+{
+    return maple_i2c_write_fpga(maple_i2c_get_client(FPGA_I2C_ADDR), reg, val);
+}
+
+static bcmos_errno i2c_config_switch(void)
+{
+    uint8_t to_write = 1;
+    int ret;
+
+    ret = maple_i2c_write(maple_i2c_get_client(I2C_SW0_I2C_ADDR), &to_write, 1);
+    if (ret != 0)
+    {
+        BCMOS_TRACE_ERR("Failed to write switch: %d\n", ret);
+        return BCM_ERR_INTERNAL;
+    }
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_errno i2c_fpga_version_get(uint32_t *version)
+{
+    return i2c_fpga_read(FPGA_REG_FPGA_VERSION, version);
+}
+
+static bcmos_errno i2c_svk_config_get(svk_board_id *board_id, svk_mode *mode)
+{
+    uint32_t val;
+    bcmos_errno rc;
+
+    rc = i2c_fpga_read(FPGA_REG_BOARD_CONF, &val);
+    if (rc == BCM_ERR_OK)
+    {
+        *board_id = (svk_board_id)(val & 0x7);
+        *mode = (svk_mode)((val >> 4) & 0xF);
+    }
+
+    return rc;
+}
+
+static bcmos_errno i2c_device_cpu_state_set(bcmolt_devid device, bcmos_bool is_on)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+
+    /* Prevent race condition when this function is called for 2 devices simultaneously */
+    userlock_lock();
+
+    do
+    {
+        rc = i2c_config_switch();
+        if (rc)
+            break;
+
+        /* Read-modify-write so we can set only the relevant bit */
+        rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+        if (rc)
+            break;
+
+        if (is_on)
+            reset_values |= FPGA_DEVICE_RESET_BIT(device);
+        else
+            reset_values &= ~FPGA_DEVICE_RESET_BIT(device);
+
+        rc = i2c_fpga_write(FPGA_REG_RESETS, reset_values);
+
+    } while (0);
+
+    userlock_unlock();
+
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    bcmos_usleep(1000);
+
+    return BCM_ERR_OK;
+}
+
+static bcmos_bool bcmuser_system_mode_is_valid(bcmolt_system_mode system_mode, svk_board_id board_id, svk_mode svk_mode)
+{
+    switch (board_id)
+    {
+    case SVK_BOARD_ID_1:
+    case SVK_BOARD_ID_3:
+        switch (svk_mode)
+        {
+        case SVK_MODE_GPON_16X:
+            return (system_mode == BCMOLT_SYSTEM_MODE_GPON__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON__16_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_GPON_8_XGPON_4_X_COEXISTENCE ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G);
+        case SVK_MODE_EPON_1G_16X:
+            return (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__16_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G ||
+                    system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+        case SVK_MODE_XGPON:
+            return (system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                    system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G);
+        case SVK_MODE_EPON_10G_8X:
+            return
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G) ||
+                (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+        default:
+            return BCMOS_FALSE;
+        }
+    case SVK_BOARD_ID_2_XG:
+        return (system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__8_X ||
+                system_mode == BCMOLT_SYSTEM_MODE_XGPON_1__4_X ||
+                system_mode == BCMOLT_SYSTEM_MODE_NGPON2__8_X_2_P_5_G ||
+                system_mode == BCMOLT_SYSTEM_MODE_XGS__2_X_10_G ||
+                system_mode == BCMOLT_SYSTEM_MODE_NGPON2__2_X_10_G);
+    case SVK_BOARD_ID_2_XE:
+        return
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_AE_8_X) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__2_X_10_G) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__4_X_10_G) ||
+            (system_mode == BCMOLT_SYSTEM_MODE_EPON__8_X_10_G);
+    case DVT_BOARD_ID:
+        return BCMOS_TRUE;
+    default:
+        return BCMOS_FALSE;
+    }
+}
+
+bcmos_errno bcmuser_system_mode_validate(bcmolt_devid device, bcmolt_system_mode system_mode)
+{
+    bcmos_errno rc;
+    uint32_t version;
+    svk_board_id board_id;
+    svk_mode svk_mode;
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_version_get(&version);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read FPGA version\n");
+        return rc;
+    }
+
+    if (version < FPGA_VER_FOR_SVK_CONFIG)
+    {
+        /* this FPGA version don't support reading the SVK version, so we must assume it's OK */
+        return BCM_ERR_OK;
+    }
+
+    rc = i2c_svk_config_get(&board_id, &svk_mode);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read SVK config\n");
+        return rc;
+    }
+
+    if (bcmuser_system_mode_is_valid(system_mode, board_id, svk_mode))
+    {
+        return BCM_ERR_OK;
+    }
+    else
+    {
+        BCMOS_TRACE_INFO(
+            "System mode %s is not supported for board ID %d, SVK mode %d\n",
+            bcmolt_system_mode_name(system_mode),
+            board_id,
+            svk_mode);
+        return BCM_ERR_NOT_SUPPORTED;
+    }
+}
+
+int bcmuser_image_read(bcmolt_devid device, bcmolt_device_image_type image_type,
+    uint32_t offset, uint8_t *buf, uint32_t buf_size)
+{
+    struct file *fd;
+    int bytes_read;
+    bcmos_errno rc;
+    static int2str_t image_type2str[] =
+    {
+        {BCMOLT_DEVICE_IMAGE_TYPE_BOOTLOADER, BOOT_FILE},
+        {BCMOLT_DEVICE_IMAGE_TYPE_APPLICATION, APPL_FILE},
+        {BCMOLT_DEVICE_IMAGE_TYPE_ITU_PON_ONU_FIRMWARE, ONU_FW_FILE},
+        {-1}
+    };
+    const char *filename;
+
+    filename = int2str(image_type2str, image_type);
+    fd = file_open(filename, O_RDONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        rc = (fd == NULL ? BCM_ERR_NULL : BCM_ERR_NOENT);
+        BCMOS_TRACE_ERR("filp_open returned error %s (%d)\n", bcmos_strerror(rc), rc);
+        return rc;
+    }
+    bytes_read = file_read(fd, offset, buf, buf_size);
+    file_close(fd);
+    if (bytes_read < 0)
+    {
+        return (int)BCM_ERR_IO;
+    }
+    return bytes_read;
+}
+
+bcmos_errno bcmuser_device_off(bcmolt_devid device)
+{
+    /* Ignore request for non-existing device */
+    if (device >= bcmolt_board_num_maple_devices())
+        return BCM_ERR_OK;
+    BCMOS_TRACE_INFO("device=%u\n", device);
+    return i2c_device_cpu_state_set(device, BCMOS_FALSE);
+}
+
+bcmos_errno bcmuser_device_on(bcmolt_devid device)
+{
+    bcmos_errno rc;
+
+    BCMOS_TRACE_INFO("device=%u\n", device);
+    if (device >= bcmolt_board_num_maple_devices())
+        return BCM_ERR_RANGE;
+
+    rc = i2c_device_cpu_state_set(device, BCMOS_TRUE);
+    /* Wait a moment to make sure the device is discoverable in case it just booted. */
+    bcmos_usleep(50 * 1000);
+
+    return rc;
+}
+
+bcmos_errno bcmuser_device_is_running(bcmolt_devid device, bcmos_bool *is_running)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+    uint32_t version;
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_version_get(&version);
+    if (rc != BCM_ERR_OK)
+    {
+        BCMOS_TRACE_INFO("Failed to read FPGA version\n");
+        return rc;
+    }
+    if (!bcmolt_board_supports_standalone(version))
+    {
+        /* For older FPGAs that don't support standalone mode, the device is taken out of reset at boot.  We need to lie
+           and tell device control that it's not running, so it will be programmed from scratch. */
+        BCMOS_TRACE_INFO("FPGA version %d doesn't support standalone mode\n", version);
+        *is_running = BCMOS_FALSE;
+        return BCM_ERR_OK;
+    }
+
+    rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    *is_running = ((reset_values & FPGA_DEVICE_RESET_BIT(device)) != 0);
+
+    return BCM_ERR_OK;
+}
+
+bcmos_errno bcmuser_host_reset(void)
+{
+    bcm_ll_pcie_cleanup();
+    kernel_restart(NULL);
+    return BCM_ERR_OK; /* will never be reached */
+}
+
+bcmos_errno bcmuser_pcie_prepare(void)
+{
+    bcmos_errno rc;
+    uint32_t reset_values;
+    const char *pcie_rescan_file = bcmolt_board_pci_rescan_string_get();
+    int i;
+
+    /* - Take all devices out of reset
+     * - rescan bus
+     * - restore reset value
+     */
+
+    rc = i2c_config_switch();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    /* Read-modify-write so we can set only the relevant bit */
+    rc = i2c_fpga_read(FPGA_REG_RESETS, &reset_values);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    rc = i2c_fpga_write(FPGA_REG_RESETS, FPGA_ENABLE_ALL_DEVICES);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    bcmos_usleep(50000);
+
+    /* Now recan PCI bus */
+    /* Now re-enumerate the PCI bus by writing a 1 to the 'rescan' file. */
+    rc = file_write_1(pcie_rescan_file);
+    if (rc != BCM_ERR_OK)
+        BCMOS_TRACE_ERR("file write returned error %s (%d)\n", bcmos_strerror(rc), rc);
+    bcmos_usleep(100 * 1000);
+
+    /* Now initialize ll_pcie driver and map maple devices */
+    rc = bcm_ll_pcie_init();
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    /* Now restore rest values. Keep switch out of reset */
+    for (i = 0; i < bcmolt_board_num_maple_devices(); i++)
+    {
+        if ((FPGA_DEVICE_RESET_BIT(i) & reset_values) == 0)
+            bcmuser_pcie_channel_remove(i);
+    }
+    rc = i2c_fpga_write(FPGA_REG_RESETS, reset_values | FPGA_ENABLE_SWITCH);
+    CHECK_RETURN_ERROR(rc != BCM_ERR_OK, rc);
+
+    return 0;
+}
+
+bcmos_errno bcmuser_pcie_channel_prepare(bcmolt_devid device)
+{
+    bcmos_errno rc;
+
+    rc = bcm_ll_pcie_dev_enable(device);
+    if (rc)
+        BCMOS_TRACE_ERR("Couldn't prepare device %d. Error %s\n", device, bcmos_strerror(rc));
+
+    return rc;
+}
+
+bcmos_errno bcmuser_pcie_channel_remove(bcmolt_devid device)
+{
+    bcm_ll_pcie_dev_disable(device);
+    return BCM_ERR_OK;
+}
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/Makefile b/bcm68620_release/release/host_customized/user_config/board_selector/Makefile
new file mode 100644
index 0000000..bfbfe46
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/Makefile
@@ -0,0 +1,15 @@
+#
+# board_selector
+#
+MOD_NAME = board_selector
+MOD_SUPPRESS_OS_DEP = y
+
+ifeq ("$(OS_KERNEL)", "linux")
+    MOD_TYPE = linux_lib
+else
+    MOD_TYPE = lib
+endif
+
+ifneq ("$(BOARD)", "")
+    srcs = $(BOARD)/bcmolt_board_selector.c
+endif
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h b/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h
new file mode 100644
index 0000000..74a8103
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/bcmolt_board_selector.h
@@ -0,0 +1,61 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmolt_board_selector.h
+ */
+
+#ifndef _BCMOLT_BOARD_SELECTOR_H_
+#define _BCMOLT_BOARD_SELECTOR_H_
+
+#include <bcmos_system.h>
+
+/* bus, devfn --> device mapping table */
+typedef struct
+{
+    int bus;
+    int devfn;
+    int device;
+} bus_devfn_devid;
+
+/* Get PCI rescan string. It is used in linux to rescan PCIe bus */
+const char *bcmolt_board_pci_rescan_string_get(void);
+
+/* Get bus, devfn --> dev_id mapping table.
+ * The table is terminated by row with bus=-1,devfn=-1
+ */
+const bus_devfn_devid *bcmolt_board_pci_map_table_get(void);
+
+/* Return TRUE if board supports Maple-standalone mode */
+bcmos_bool bcmolt_board_supports_standalone(uint32_t version);
+
+/* Returns number of maple devices on the board */
+uint8_t bcmolt_board_num_maple_devices(void);
+
+#endif /* _BCMOLT_BOARD_SELECTOR_H_ */
diff --git a/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c b/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c
new file mode 100644
index 0000000..c997a12
--- /dev/null
+++ b/bcm68620_release/release/host_customized/user_config/board_selector/wrx/bcmolt_board_selector.c
@@ -0,0 +1,113 @@
+/*
+<: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.
+
+:>
+ */
+
+/*
+ * bcmolt_board_selector.c
+ */
+
+#include <linux/fs.h>
+#include "bcmolt_board_selector.h"
+
+static bus_devfn_devid bus_devfn_devid_table_svk4[] = {
+    { 5, 0, 0},
+    { 3, 0, 1},
+    {-1,-1,-1},
+};
+
+static bus_devfn_devid bus_devfn_devid_table_svk1_3[] = {
+    { 3, 0, 0},
+    {-1,-1,-1},
+};
+
+#define SVK4_IDENT_FILE                 "/etc/svk4"
+
+#define PCIE_DEVICE_RESCAN_FILE_SVK4    "/sys/bus/pci/devices/0000:02:00.0/rescan"
+#define PCIE_DEVICE_RESCAN_FILE_SVK1_3  "/sys/bus/pci/devices/0000:02:01.0/rescan"
+
+/* Minimum required FPGA version for standalone mode (host / embedded processors running disconnected). */
+#define FPGA_VER_FOR_STANDALONE 7
+
+static struct file *file_open(const char *path, int flags)
+{
+    struct file *fd = NULL;
+    mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
+
+    fd = filp_open(path, flags, mode);
+    if(IS_ERR(fd))
+        return NULL;
+    return fd;
+}
+
+static void file_close(struct file *file)
+{
+    filp_close(file, NULL);
+}
+
+static bcmos_bool can_read_file(const char *path)
+{
+    struct file *fd = file_open(path, O_RDONLY);
+    if ((fd == NULL) || (fd == (void *)-ENOENT)) /* -ENOENT; No such file or directory */
+    {
+        return BCMOS_FALSE;
+    }
+
+    file_close(fd);
+    return BCMOS_TRUE;
+}
+
+static bcmos_bool board_is_svk4(void)
+{
+    return can_read_file(SVK4_IDENT_FILE);
+}
+
+/* Get PCI rescan string. It is used in linux to rescan PCIe bus */
+const char *bcmolt_board_pci_rescan_string_get(void)
+{
+    return board_is_svk4() ? PCIE_DEVICE_RESCAN_FILE_SVK4 : PCIE_DEVICE_RESCAN_FILE_SVK1_3;
+}
+
+/* Get bus, devfn --> dev_id mapping table.
+ * The table is terminated by row with bus=-1,devfn=-1
+ */
+const bus_devfn_devid *bcmolt_board_pci_map_table_get(void)
+{
+    return board_is_svk4() ? bus_devfn_devid_table_svk4 : bus_devfn_devid_table_svk1_3;
+}
+
+/* Return TRUE if board supports Maple-standalone mode */
+bcmos_bool bcmolt_board_supports_standalone(uint32_t version)
+{
+    return board_is_svk4() || version >= FPGA_VER_FOR_STANDALONE;
+}
+
+/* Returns number of maple devices on the board */
+uint8_t bcmolt_board_num_maple_devices(void)
+{
+    return board_is_svk4() ? 2 : 1;
+}
diff --git a/bcm68620_release/release/host_customized/utils_linux/Makefile b/bcm68620_release/release/host_customized/utils_linux/Makefile
new file mode 100644
index 0000000..78867d8
--- /dev/null
+++ b/bcm68620_release/release/host_customized/utils_linux/Makefile
@@ -0,0 +1,15 @@
+# Makefile for building utilities as linux module
+#
+ifeq ("$(OS_KERNEL)", "linux")
+
+MOD_NAME = utils_linux
+MOD_TYPE = linux_lib
+srcs = bcmolt_buf.c
+
+# 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/utils_linux/bcmolt_buf.c b/bcm68620_release/release/host_customized/utils_linux/bcmolt_buf.c
new file mode 120000
index 0000000..f7b8320
--- /dev/null
+++ b/bcm68620_release/release/host_customized/utils_linux/bcmolt_buf.c
@@ -0,0 +1 @@
+../../host_driver/utils/bcmolt_buf.c
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/utils_linux/bcmolt_buf.h b/bcm68620_release/release/host_customized/utils_linux/bcmolt_buf.h
new file mode 120000
index 0000000..4f773fe
--- /dev/null
+++ b/bcm68620_release/release/host_customized/utils_linux/bcmolt_buf.h
@@ -0,0 +1 @@
+../../host_driver/utils/bcmolt_buf.h
\ No newline at end of file
diff --git a/bcm68620_release/release/host_customized/utils_linux/bcmolt_conv.h b/bcm68620_release/release/host_customized/utils_linux/bcmolt_conv.h
new file mode 120000
index 0000000..6fb8c97
--- /dev/null
+++ b/bcm68620_release/release/host_customized/utils_linux/bcmolt_conv.h
@@ -0,0 +1 @@
+../../host_driver/utils/bcmolt_conv.h
\ No newline at end of file