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");
+