BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
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");