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/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 *)¶ms, (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(¶ms);
+ 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");