zte's code,first commit
Change-Id: I9a04da59e459a9bc0d67f101f700d9d7dc8d681b
diff --git a/ap/os/linux/linux-3.4.x/drivers/os-extend/vsim/vsim.c b/ap/os/linux/linux-3.4.x/drivers/os-extend/vsim/vsim.c
new file mode 100755
index 0000000..0c4c0c6
--- /dev/null
+++ b/ap/os/linux/linux-3.4.x/drivers/os-extend/vsim/vsim.c
@@ -0,0 +1,343 @@
+/*******************************************************************************
+* °æÈ¨ËùÓÐ (C)2016, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
+*
+* ÎļþÃû³Æ: vsim.c
+* Îļþ±êʶ: vsim.c
+* ÄÚÈÝÕªÒª: vsim
+* ʹÓ÷½·¨:
+*
+* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
+* ------------------------------------------------------------------------------
+* 2016/6/10 V1.0 Create zjk
+*
+*******************************************************************************/
+
+/*******************************************************************************
+* Í·Îļþ *
+*******************************************************************************/
+
+#include <linux/module.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h> /* printk() */
+#include <linux/slab.h> /* kmalloc() */
+#include <linux/fs.h> /* everything... */
+#include <linux/errno.h> /* error codes */
+#include <linux/types.h> /* size_t */
+#include <linux/mm.h>
+#include <linux/kdev_t.h>
+
+#include <linux/cdev.h>
+
+#include <linux/device.h>
+#include <asm/uaccess.h>
+#include <linux/delay.h>
+
+#include <linux/mutex.h>
+
+#include <linux/soc/zte/rpm/rpmsg.h>
+
+
+/*******************************************************************************
+* Íⲿº¯ÊýÉùÃ÷ *
+*******************************************************************************/
+/* icp api */
+extern int zDrvRpMsg_CreateChannel(
+ T_ZDrvRpMsg_ActorID actorID,
+ T_ZDrvRpMsg_ChID chID,
+ unsigned int size);
+extern int zDrvRpMsg_Write(const T_ZDrvRpMsg_Msg *pMsg);
+extern int zDrvRpMsg_Read(const T_ZDrvRpMsg_Msg *pMsg);
+
+/*******************************************************************************
+* ºê¶¨Òå *
+*******************************************************************************/
+#define VSIM_MAJOR (220)
+#define VSIM_ICP_CHANNEL_SIZE (10*1024)
+#define VSIM_ICP_WRITE_MAX_SIZE (5*1024)
+#define VSIM_ICP_CHANNEL (ICP_CHANNEL_VSIM)
+#define VSIM_ICP_MSG_HEADER_SIZE (16)
+#define VSIM_ICP_BUF_SIZE (VSIM_ICP_WRITE_MAX_SIZE-VSIM_ICP_MSG_HEADER_SIZE)
+
+/***********************************1024********************************************
+* Êý¾ÝÀàÐͶ¨Òå *
+*******************************************************************************/
+typedef struct
+{
+ unsigned long addr;
+ void * buf;
+ unsigned long len;
+} data_spec_write_t;
+enum
+{
+ RECOVERY = 0,
+ WRITE_SPECIFY = 1,
+};
+
+typedef struct
+{
+ unsigned long addr;
+ int len;
+ char buf[VSIM_ICP_BUF_SIZE];
+} icp_msg_data_t;
+
+typedef struct
+{
+ unsigned long cmd;
+ unsigned long total;
+ icp_msg_data_t data;
+} icp_msg_t;
+
+enum
+{
+ VSIM_CMD_RECOVERY = 1,
+ VSIM_CMD_WRITE_FACTORY,
+ VSIM_CMD_WRITE_SPECIAL,
+};
+
+/*******************************************************************************
+* È«¾Ö±äÁ¿ÉùÃ÷ *
+*******************************************************************************/
+static const char *vsim_name = "vsim";
+
+static int vsim_major = VSIM_MAJOR;
+static struct class *nv_class;
+
+static struct mutex vsim_lock;
+
+/*******************************************************************************
+* È«¾Öº¯ÊýÉùÃ÷ *
+*******************************************************************************/
+
+/*******************************************************************************
+* ¾Ö²¿º¯ÊýʵÏÖ *
+*******************************************************************************/
+
+/*
+ * Open the device; in fact, there's nothing to do here.
+ */
+static int vsim_open (struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/*
+ * Closing is just as open.
+ */
+static int vsim_release(struct inode *inode, struct file *file)
+{
+ return 0;
+}
+
+/*
+ * read.
+ */
+static ssize_t vsim_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
+{
+ return -EPERM;
+}
+
+/*
+ * vsim_icp_split_package
+ */
+static int vsim_icp_split_package(char *buf, size_t len, icp_msg_t *vsim_msg)
+{
+ int ret = -EPERM;
+ int read_buf;
+ char *buf_tmp;
+ int len_tmp;
+ T_ZDrvRpMsg_Msg pMsg;
+
+ if (buf == NULL || len == 0)
+ return -EINVAL;
+
+ pMsg.actorID = PS_ID;
+ pMsg.chID = VSIM_ICP_CHANNEL;
+
+ len_tmp = len;
+ buf_tmp = buf;
+ mutex_lock(&vsim_lock);
+ while (len_tmp > 0)
+ {
+ vsim_msg->data.len = min(len_tmp, VSIM_ICP_BUF_SIZE);
+ if (copy_from_user(vsim_msg->data.buf, buf_tmp, vsim_msg->data.len))
+ panic("[ZXIC]VSIM copy_from_user failed\n");
+
+ pMsg.buf = vsim_msg;
+ pMsg.len = sizeof(icp_msg_t);
+ pMsg.flag = RPMSG_WRITE_INT;
+ ret = zDrvRpMsg_Write(&pMsg);
+ if (ret <= 0)
+ panic("[ZXIC]VSIM zDrvRpMsg_Write failed\n");
+
+ len_tmp -= vsim_msg->data.len;
+ buf_tmp += vsim_msg->data.len;
+
+ read_buf = 0;
+ pMsg.buf = &read_buf;
+ pMsg.len = sizeof(read_buf);
+ pMsg.flag = ~RPMSG_READ_POLL;
+ ret = zDrvRpMsg_Read(&pMsg);
+ if (ret <= 0)
+ panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
+ }
+
+ read_buf = 0;
+ pMsg.buf = &read_buf;
+ pMsg.len = sizeof(read_buf);
+ pMsg.flag = ~RPMSG_READ_POLL;
+ ret = zDrvRpMsg_Read(&pMsg);
+ if (ret <= 0)
+ panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
+
+ mutex_unlock(&vsim_lock);
+
+ return read_buf;
+}
+
+/*
+ * write fac.
+ */
+static ssize_t vsim_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
+{
+ int ret = -EPERM;
+ icp_msg_t *vsim_msg = NULL;
+
+ if (*ppos || buf == NULL) //shoud start at offset 0;
+ return -EINVAL;
+
+ vsim_msg = kmalloc(sizeof(icp_msg_t), GFP_KERNEL);
+ if (vsim_msg == NULL)
+ return -ENOMEM;
+
+ vsim_msg->cmd = VSIM_CMD_WRITE_FACTORY;
+ vsim_msg->total = count;
+
+ ret = vsim_icp_split_package(buf, count, vsim_msg);
+
+ kfree(vsim_msg);
+ return ret;
+}
+
+/*
+ * ioctl to control write.
+ */
+static ssize_t vsim_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+ int ret = -EPERM;
+ int read_buf;
+ icp_msg_t *vsim_msg = NULL;
+ T_ZDrvRpMsg_Msg pMsg;
+
+ vsim_msg = kmalloc(sizeof(icp_msg_t), GFP_KERNEL);
+ if (vsim_msg == NULL)
+ return -ENOMEM;
+
+ switch (cmd)
+ {
+ case RECOVERY:
+ mutex_lock(&vsim_lock);
+ vsim_msg->cmd = VSIM_CMD_RECOVERY;
+ vsim_msg->total = vsim_msg->data.len = 0;
+
+ pMsg.actorID = PS_ID;
+ pMsg.chID = VSIM_ICP_CHANNEL;
+ pMsg.buf = vsim_msg;
+ pMsg.len = sizeof(icp_msg_t);
+ pMsg.flag = RPMSG_WRITE_INT;
+ ret = zDrvRpMsg_Write(&pMsg);
+ if (ret <= 0)
+ panic("[ZXIC]VSIM zDrvRpMsg_Write failed\n");
+
+ pMsg.buf = &read_buf;
+ pMsg.len = sizeof(read_buf);
+ pMsg.flag = ~RPMSG_READ_POLL;
+ ret = zDrvRpMsg_Read(&pMsg);
+ if (ret <= 0)
+ panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
+
+ mutex_unlock(&vsim_lock);
+ break;
+
+ case WRITE_SPECIFY:
+ if (arg != 0)
+ {
+ vsim_msg->cmd = VSIM_CMD_WRITE_SPECIAL;
+ vsim_msg->total = ((data_spec_write_t *)arg)->len;
+ vsim_msg->data.addr = ((data_spec_write_t *)arg)->addr;
+ ret = vsim_icp_split_package(((data_spec_write_t *)arg)->buf,((data_spec_write_t *)arg)->len, vsim_msg);
+ }
+
+ break;
+ default :
+ break;
+ }
+
+ kfree(vsim_msg);
+
+ return (ret >= 0) ? 0 : -EPERM;
+}
+
+
+static struct file_operations vsim_fops = {
+ .owner = THIS_MODULE,
+ .open = vsim_open,
+ .release = vsim_release,
+ .read = vsim_read,
+ .write = vsim_write,
+ .unlocked_ioctl = vsim_ioctl,
+};
+
+static char *vsim_devnode(struct device *dev, umode_t *mode)
+{
+ return NULL;
+}
+
+
+/*
+ * Module init.
+ */
+static int vsim_init(void)
+{
+ int ret;
+
+ ret = register_chrdev(vsim_major, vsim_name, &vsim_fops);
+ if (ret < 0)
+ {
+ printk(KERN_WARNING "vsim: unable to get major %d\n", vsim_major);
+ return ret;
+ }
+
+ if (vsim_major == 0)
+ vsim_major = ret; /* dynamic major number*/
+
+ nv_class = class_create(THIS_MODULE, "nv");
+ if (IS_ERR(nv_class))
+ return PTR_ERR(nv_class);
+
+ nv_class->devnode = vsim_devnode;
+
+ device_create(nv_class, NULL, MKDEV(vsim_major, 0), NULL, vsim_name);
+
+ /* lock init */
+ mutex_init(&vsim_lock);
+
+ /* icp init */
+ ret = zDrvRpMsg_CreateChannel(PS_ID, VSIM_ICP_CHANNEL, VSIM_ICP_CHANNEL_SIZE);
+ if (ret != RPMSG_SUCCESS)
+ printk(KERN_WARNING "[ZXIC] os extend remote call lib init failed, err is %d\n", ret);
+
+ return 0;
+}
+
+static void vsim_cleanup(void)
+{
+ unregister_chrdev(vsim_major, vsim_name);
+}
+
+
+
+module_init(vsim_init);
+module_exit(vsim_cleanup);
+MODULE_LICENSE("Dual BSD/GPL");
+