1 #include <linux/module.h>
2 #include <linux/types.h>
3 #include <linux/fs.h>
4 #include <linux/errno.h>
5 #include <linux/mm.h>
6 #include <linux/sched.h>
7 #include <linux/init.h>
8 #include <linux/cdev.h>
9 #include <asm/io.h>
10 #include <asm/system.h>
11 #include <asm/uaccess.h>
12
13 #define GLOBALMEM_SIZE 0x1000 /*全局内存最大4K字节*/
14 #define MEM_CLEAR 0x1 /*清0全局内存*/
15 #define GLOBALMEM_MAJOR 254 /*预设的globalmem的主设备号*/
16
17 static globalmem_major = GLOBALMEM_MAJOR;
18 /*globalmem设备结构体*/
19 struct globalmem_dev
20 {
21 struct cdev cdev; /*cdev结构体*/
22 unsigned char mem[GLOBALMEM_SIZE]; /*全局内存*/
23 };
24
25 struct globalmem_dev *globalmem_devp; /*设备结构体指针*/
26 /*文件打开函数*/
27 int globalmem_open(struct inode *inode, struct file *filp)
28 {
29 /*将设备结构体指针赋值给文件私有数据指针*/
30 filp->private_data = globalmem_devp;
31 return 0;
32 }
33 /*文件释放函数*/
34 int globalmem_release(struct inode *inode, struct file *filp)
35 {
36 return 0;
37 }
38
39 /* ioctl设备控制函数 */
40 static int globalmem_ioctl(struct inode *inodep, struct file *filp, unsigned
41 int cmd, unsigned long arg)
42 {
43 struct globalmem_dev *dev = filp->private_data;/*获得设备结构体指针*/
44
45 switch (cmd)
46 {
47 case MEM_CLEAR:
48 memset(dev->mem, 0, GLOBALMEM_SIZE);
49 printk(KERN_INFO "globalmem is set to zero/n");
50 break;
51
52 default:
53 return - EINVAL;
54 }
55 return 0;
56 }
57
58 /*读函数*/
59 static ssize_t globalmem_read(struct file *filp, char __user *buf, size_t size,
60 loff_t *ppos)
61 {
62 unsigned long p = *ppos;
63 unsigned int count = size;
64 int ret = 0;
65 struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
66
67 /*分析和获取有效的写长度*/
68 if (p >= GLOBALMEM_SIZE)
69 return count ? - ENXIO: 0;
70 if (count > GLOBALMEM_SIZE - p)
71 count = GLOBALMEM_SIZE - p;
72
73 /*内核空间->用户空间*/
74 if (copy_to_user(buf, (void*)(dev->mem + p), count))
75 {
76 ret = - EFAULT;
77 }
78 else
79 {
80 *ppos += count;
81 ret = count;
82
83 printk(KERN_INFO "read %d bytes(s) from %d/n", count, p);
84 }
85
86 return ret;
87 }
88
89 /*写函数*/
90 static ssize_t globalmem_write(struct file *filp, const char __user *buf,
91 size_t size, loff_t *ppos)
92 {
93 unsigned long p = *ppos;
94 unsigned int count = size;
95 int ret = 0;
96 struct globalmem_dev *dev = filp->private_data; /*获得设备结构体指针*/
97
98 /*分析和获取有效的写长度*/
99 if (p >= GLOBALMEM_SIZE)
100 return count ? - ENXIO: 0;
101 if (count > GLOBALMEM_SIZE - p)
102 count = GLOBALMEM_SIZE - p;
103
104 /*用户空间->内核空间*/
105 if (copy_from_user(dev->mem + p, buf, count))
106 ret = - EFAULT;
107 else
108 {
109 *ppos += count;
110 ret = count;
111
112 printk(KERN_INFO "written %d bytes(s) from %d/n", count, p);
113 }
114
115 return ret;
116 }
117
118 /* seek文件定位函数 */
119 static loff_t globalmem_llseek(struct file *filp, loff_t offset, int orig)
120 {
121 loff_t ret = 0;
122 switch (orig)
123 {
124 case 0: /*相对文件开始位置偏移*/
125 if (offset < 0)
126 {
127 ret = - EINVAL;
128 break;
129 }
130 if ((unsigned int)offset > GLOBALMEM_SIZE)
131 {
132 ret = - EINVAL;
133 break;
134 }
135 filp->f_pos = (unsigned int)offset;
136 ret = filp->f_pos;
137 break;
138 case 1: /*相对文件当前位置偏移*/
139 if ((filp->f_pos + offset) > GLOBALMEM_SIZE)
140 {
141 ret = - EINVAL;
142 break;
143 }
144 if ((filp->f_pos + offset) < 0)
145 {
146 ret = - EINVAL;
147 break;
148 }
149 filp->f_pos += offset;
150 ret = filp->f_pos;
151 break;
152 default:
153 ret = - EINVAL;
154 break;
155 }
156 return ret;
157 }
158
159 /*文件操作结构体*/
160 static const struct file_operations globalmem_fops =
161 {
162 .owner = THIS_MODULE,
163 .llseek = globalmem_llseek,
164 .read = globalmem_read,
165 .write = globalmem_write,
166 .ioctl = globalmem_ioctl,
167 .open = globalmem_open,
168 .release = globalmem_release,
169 };
170
171 /*初始化并注册cdev*/
172 static void globalmem_setup_cdev(struct globalmem_dev *dev, int index)
173 {
174 int err, devno = MKDEV(globalmem_major, index);
175
176 cdev_init(&dev->cdev, &globalmem_fops);
177 dev->cdev.owner = THIS_MODULE;
178 dev->cdev.ops = &globalmem_fops;
179 err = cdev_add(&dev->cdev, devno, 1);
180 if (err)
181 printk(KERN_NOTICE "Error %d adding LED%d", err, index);
182 }
183
184 /*设备驱动模块加载函数*/
185 int globalmem_init(void)
186 {
187 int result;
188 dev_t devno = MKDEV(globalmem_major, 0);
189
190 /* 申请设备号*/
191 if (globalmem_major)
192 result = register_chrdev_region(devno, 1, "globalmem");
193 else /* 动态申请设备号 */
194 {
195 result = alloc_chrdev_region(&devno, 0, 1, "globalmem");
196 globalmem_major = MAJOR(devno);
197 }
198 if (result < 0)
199 return result;
200
201 /* 动态申请设备结构体的内存*/
202 globalmem_devp = kmalloc(sizeof(struct globalmem_dev), GFP_KERNEL);
203 if (!globalmem_devp) /*申请失败*/
204 {
205 result = - ENOMEM;
206 goto fail_malloc;
207 }
208 memset(globalmem_devp, 0, sizeof(struct globalmem_dev));
209
210 globalmem_setup_cdev(globalmem_devp, 0);
211 return 0;
212
213 fail_malloc: unregister_chrdev_region(devno, 1);
214 return result;
215 }
216
217 /*模块卸载函数*/
218 void globalmem_exit(void)
219 {
220 cdev_del(&globalmem_devp->cdev); /*注销cdev*/
221 kfree(globalmem_devp); /*释放设备结构体内存*/
222 unregister_chrdev_region(MKDEV(globalmem_major, 0), 1); /*释放设备号*/
223 }
224
225 MODULE_AUTHOR("Song Baohua");
226 MODULE_LICENSE("Dual BSD/GPL");
227
228 module_param(globalmem_major, int, S_IRUGO);
229
230 module_init(globalmem_init);
231 module_exit(globalmem_exit);