blob: 0c4c0c64930b23bed18f83f44f1ab598a17b15b8 [file] [log] [blame]
yuezonghe824eb0c2024-06-27 02:32:26 -07001/*******************************************************************************
2* °æÈ¨ËùÓÐ (C)2016, ÖÐÐËͨѶ¹É·ÝÓÐÏÞ¹«Ë¾¡£
3*
4* ÎļþÃû³Æ: vsim.c
5* Îļþ±êʶ: vsim.c
6* ÄÚÈÝÕªÒª: vsim
7* ʹÓ÷½·¨:
8*
9* ÐÞ¸ÄÈÕÆÚ °æ±¾ºÅ Ð޸ıê¼Ç ÐÞ¸ÄÈË ÐÞ¸ÄÄÚÈÝ
10* ------------------------------------------------------------------------------
11* 2016/6/10 V1.0 Create zjk
12*
13*******************************************************************************/
14
15/*******************************************************************************
16* Í·Îļþ *
17*******************************************************************************/
18
19#include <linux/module.h>
20#include <linux/init.h>
21
22#include <linux/kernel.h> /* printk() */
23#include <linux/slab.h> /* kmalloc() */
24#include <linux/fs.h> /* everything... */
25#include <linux/errno.h> /* error codes */
26#include <linux/types.h> /* size_t */
27#include <linux/mm.h>
28#include <linux/kdev_t.h>
29
30#include <linux/cdev.h>
31
32#include <linux/device.h>
33#include <asm/uaccess.h>
34#include <linux/delay.h>
35
36#include <linux/mutex.h>
37
38#include <linux/soc/zte/rpm/rpmsg.h>
39
40
41/*******************************************************************************
42* Íⲿº¯ÊýÉùÃ÷ *
43*******************************************************************************/
44/* icp api */
45extern int zDrvRpMsg_CreateChannel(
46 T_ZDrvRpMsg_ActorID actorID,
47 T_ZDrvRpMsg_ChID chID,
48 unsigned int size);
49extern int zDrvRpMsg_Write(const T_ZDrvRpMsg_Msg *pMsg);
50extern int zDrvRpMsg_Read(const T_ZDrvRpMsg_Msg *pMsg);
51
52/*******************************************************************************
53* ºê¶¨Òå *
54*******************************************************************************/
55#define VSIM_MAJOR (220)
56#define VSIM_ICP_CHANNEL_SIZE (10*1024)
57#define VSIM_ICP_WRITE_MAX_SIZE (5*1024)
58#define VSIM_ICP_CHANNEL (ICP_CHANNEL_VSIM)
59#define VSIM_ICP_MSG_HEADER_SIZE (16)
60#define VSIM_ICP_BUF_SIZE (VSIM_ICP_WRITE_MAX_SIZE-VSIM_ICP_MSG_HEADER_SIZE)
61
62/***********************************1024********************************************
63* Êý¾ÝÀàÐͶ¨Òå *
64*******************************************************************************/
65typedef struct
66{
67 unsigned long addr;
68 void * buf;
69 unsigned long len;
70} data_spec_write_t;
71enum
72{
73 RECOVERY = 0,
74 WRITE_SPECIFY = 1,
75};
76
77typedef struct
78{
79 unsigned long addr;
80 int len;
81 char buf[VSIM_ICP_BUF_SIZE];
82} icp_msg_data_t;
83
84typedef struct
85{
86 unsigned long cmd;
87 unsigned long total;
88 icp_msg_data_t data;
89} icp_msg_t;
90
91enum
92{
93 VSIM_CMD_RECOVERY = 1,
94 VSIM_CMD_WRITE_FACTORY,
95 VSIM_CMD_WRITE_SPECIAL,
96};
97
98/*******************************************************************************
99* È«¾Ö±äÁ¿ÉùÃ÷ *
100*******************************************************************************/
101static const char *vsim_name = "vsim";
102
103static int vsim_major = VSIM_MAJOR;
104static struct class *nv_class;
105
106static struct mutex vsim_lock;
107
108/*******************************************************************************
109* È«¾Öº¯ÊýÉùÃ÷ *
110*******************************************************************************/
111
112/*******************************************************************************
113* ¾Ö²¿º¯ÊýʵÏÖ *
114*******************************************************************************/
115
116/*
117 * Open the device; in fact, there's nothing to do here.
118 */
119static int vsim_open (struct inode *inode, struct file *file)
120{
121 return 0;
122}
123
124/*
125 * Closing is just as open.
126 */
127static int vsim_release(struct inode *inode, struct file *file)
128{
129 return 0;
130}
131
132/*
133 * read.
134 */
135static ssize_t vsim_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
136{
137 return -EPERM;
138}
139
140/*
141 * vsim_icp_split_package
142 */
143static int vsim_icp_split_package(char *buf, size_t len, icp_msg_t *vsim_msg)
144{
145 int ret = -EPERM;
146 int read_buf;
147 char *buf_tmp;
148 int len_tmp;
149 T_ZDrvRpMsg_Msg pMsg;
150
151 if (buf == NULL || len == 0)
152 return -EINVAL;
153
154 pMsg.actorID = PS_ID;
155 pMsg.chID = VSIM_ICP_CHANNEL;
156
157 len_tmp = len;
158 buf_tmp = buf;
159 mutex_lock(&vsim_lock);
160 while (len_tmp > 0)
161 {
162 vsim_msg->data.len = min(len_tmp, VSIM_ICP_BUF_SIZE);
163 if (copy_from_user(vsim_msg->data.buf, buf_tmp, vsim_msg->data.len))
164 panic("[ZXIC]VSIM copy_from_user failed\n");
165
166 pMsg.buf = vsim_msg;
167 pMsg.len = sizeof(icp_msg_t);
168 pMsg.flag = RPMSG_WRITE_INT;
169 ret = zDrvRpMsg_Write(&pMsg);
170 if (ret <= 0)
171 panic("[ZXIC]VSIM zDrvRpMsg_Write failed\n");
172
173 len_tmp -= vsim_msg->data.len;
174 buf_tmp += vsim_msg->data.len;
175
176 read_buf = 0;
177 pMsg.buf = &read_buf;
178 pMsg.len = sizeof(read_buf);
179 pMsg.flag = ~RPMSG_READ_POLL;
180 ret = zDrvRpMsg_Read(&pMsg);
181 if (ret <= 0)
182 panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
183 }
184
185 read_buf = 0;
186 pMsg.buf = &read_buf;
187 pMsg.len = sizeof(read_buf);
188 pMsg.flag = ~RPMSG_READ_POLL;
189 ret = zDrvRpMsg_Read(&pMsg);
190 if (ret <= 0)
191 panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
192
193 mutex_unlock(&vsim_lock);
194
195 return read_buf;
196}
197
198/*
199 * write fac.
200 */
201static ssize_t vsim_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
202{
203 int ret = -EPERM;
204 icp_msg_t *vsim_msg = NULL;
205
206 if (*ppos || buf == NULL) //shoud start at offset 0;
207 return -EINVAL;
208
209 vsim_msg = kmalloc(sizeof(icp_msg_t), GFP_KERNEL);
210 if (vsim_msg == NULL)
211 return -ENOMEM;
212
213 vsim_msg->cmd = VSIM_CMD_WRITE_FACTORY;
214 vsim_msg->total = count;
215
216 ret = vsim_icp_split_package(buf, count, vsim_msg);
217
218 kfree(vsim_msg);
219 return ret;
220}
221
222/*
223 * ioctl to control write.
224 */
225static ssize_t vsim_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
226{
227 int ret = -EPERM;
228 int read_buf;
229 icp_msg_t *vsim_msg = NULL;
230 T_ZDrvRpMsg_Msg pMsg;
231
232 vsim_msg = kmalloc(sizeof(icp_msg_t), GFP_KERNEL);
233 if (vsim_msg == NULL)
234 return -ENOMEM;
235
236 switch (cmd)
237 {
238 case RECOVERY:
239 mutex_lock(&vsim_lock);
240 vsim_msg->cmd = VSIM_CMD_RECOVERY;
241 vsim_msg->total = vsim_msg->data.len = 0;
242
243 pMsg.actorID = PS_ID;
244 pMsg.chID = VSIM_ICP_CHANNEL;
245 pMsg.buf = vsim_msg;
246 pMsg.len = sizeof(icp_msg_t);
247 pMsg.flag = RPMSG_WRITE_INT;
248 ret = zDrvRpMsg_Write(&pMsg);
249 if (ret <= 0)
250 panic("[ZXIC]VSIM zDrvRpMsg_Write failed\n");
251
252 pMsg.buf = &read_buf;
253 pMsg.len = sizeof(read_buf);
254 pMsg.flag = ~RPMSG_READ_POLL;
255 ret = zDrvRpMsg_Read(&pMsg);
256 if (ret <= 0)
257 panic("[ZXIC]VSIM zDrvRpMsg_Read failed\n");
258
259 mutex_unlock(&vsim_lock);
260 break;
261
262 case WRITE_SPECIFY:
263 if (arg != 0)
264 {
265 vsim_msg->cmd = VSIM_CMD_WRITE_SPECIAL;
266 vsim_msg->total = ((data_spec_write_t *)arg)->len;
267 vsim_msg->data.addr = ((data_spec_write_t *)arg)->addr;
268 ret = vsim_icp_split_package(((data_spec_write_t *)arg)->buf,((data_spec_write_t *)arg)->len, vsim_msg);
269 }
270
271 break;
272 default :
273 break;
274 }
275
276 kfree(vsim_msg);
277
278 return (ret >= 0) ? 0 : -EPERM;
279}
280
281
282static struct file_operations vsim_fops = {
283 .owner = THIS_MODULE,
284 .open = vsim_open,
285 .release = vsim_release,
286 .read = vsim_read,
287 .write = vsim_write,
288 .unlocked_ioctl = vsim_ioctl,
289};
290
291static char *vsim_devnode(struct device *dev, umode_t *mode)
292{
293 return NULL;
294}
295
296
297/*
298 * Module init.
299 */
300static int vsim_init(void)
301{
302 int ret;
303
304 ret = register_chrdev(vsim_major, vsim_name, &vsim_fops);
305 if (ret < 0)
306 {
307 printk(KERN_WARNING "vsim: unable to get major %d\n", vsim_major);
308 return ret;
309 }
310
311 if (vsim_major == 0)
312 vsim_major = ret; /* dynamic major number*/
313
314 nv_class = class_create(THIS_MODULE, "nv");
315 if (IS_ERR(nv_class))
316 return PTR_ERR(nv_class);
317
318 nv_class->devnode = vsim_devnode;
319
320 device_create(nv_class, NULL, MKDEV(vsim_major, 0), NULL, vsim_name);
321
322 /* lock init */
323 mutex_init(&vsim_lock);
324
325 /* icp init */
326 ret = zDrvRpMsg_CreateChannel(PS_ID, VSIM_ICP_CHANNEL, VSIM_ICP_CHANNEL_SIZE);
327 if (ret != RPMSG_SUCCESS)
328 printk(KERN_WARNING "[ZXIC] os extend remote call lib init failed, err is %d\n", ret);
329
330 return 0;
331}
332
333static void vsim_cleanup(void)
334{
335 unregister_chrdev(vsim_major, vsim_name);
336}
337
338
339
340module_init(vsim_init);
341module_exit(vsim_cleanup);
342MODULE_LICENSE("Dual BSD/GPL");
343