1 /************************************
2 *filename :_001_globalmem.c
3 *func :a character program
4 *bookpages:code_list 6.17 (page:164)
5 *versions :v0.1
6 ************************************/
7 #include <linux/module.h>
8 #include <linux/fs.h>
9 #include <linux/init.h>
10 #include <linux/cdev.h>
11 #include <linux/slab.h>
12 #include <linux/uaccess.h>
13
14 #define MEMSIZE 100
15 #define GLOBALMEM_MAJOR 230
16 #define MEM_CLEAR 0x1
17
18 int globalmem_major = GLOBALMEM_MAJOR;
19 struct globalmem_cdev{
20 struct cdev;
21 char mem[MEMSIZE];
22
23 };
24
25 struct globalmem_cdev globalmem;
26
27
28 static int globalmem_open (struct inode *inode, struct file *filep)
29 {
30 filep->private_data = globalmem;
31 return 0;
32
33 }
34
35 static int globalmem_release (struct inode * inode, struct file * filep)
36 {
37 return 0;
38 }
39
40 static long globalmem_unlocked_ioctl (struct file * filep, unsigned int cmd, unsigned long arg)
41 {
42 struct globalmem_cdev *dev = filep->private_data;
43
44 switch(cmd){
45 case MEM_CLEAR:
46 memset(dev->mem, 0 , MEMSIZE );
47 printk(KERN_INFO "globalmem is set to zero\n");
48 break;
49 default:
50 return -EINVAL;
51
52
53 }
54
55 return 0;
56 }
57
58 static ssize_t globalmem_read (struct file * filep, char __user * buf, size_t size, loff_t * ppos)
59 {
60 unsigned long p = *ppos;
61 unsigned int count = size;
62 int ret = 0;
63 struct globalmem_cdev *dev = filep->private_data;
64
65 if (p >= MEMSIZE)
66 return 0;
67
68 if (count > MEMSIZE - p)
69 count = MEMSIZE -p;
70
71 if (copy_to_user(buf, dev->mem + p, count)){
72 ret = -EFAULT;
73 } else {
74 *ppos += count;
75 ret = count;
76
77 printk(KERN_INFO " read %u bytes(s) form %lu\n ", count ,p);
78 }
79
80 return ret;
81 }
82 static ssize_t globalmem_write (struct file *filep, const char __user buf *, size_t size, loff_t *ppos)
83 {
84 unsigned long p = *ppos;
85 unsigned int count = size;
86 int ret = 0;
87 struct globalmem_cdev *dev = filep->private_data;
88
89 if ( p >= MEMSIZE)
90 return 0;
91
92 if (count > MEMSIZE - p)
93 count = MEMSIZE -p;
94
95 if (copy_from_user(dev->mem + p, buf, count)){
96 ret = -EFAULT;
97 } else {
98 *ppos += count;
99 ret = count;
100
101 printk(KERN_INFO "written %u bytes(s) from %lu \n", count ,p);
102 }
103
104 return ret;
105 }
106
107 static loff_t globalmem_llseek (struct file *filep, loff_t offset, int orig)
108 {
109 loff_t ret =0;
110 switch(orig){
111 case 0:
112 if (offset < 0){
113 ret = -EINVAL;
114 break;
115 }
116
117 if ((unsigned int ) offset > MEMSIZE){
118 ret = -EINVAL;
119 break;
120 }
121
122 filep->f_ops = (unsigned int )offset;
123 ret = filep->f_ops;
124 break;
125 case 1:
126 if ((filep->f_ops + offset) > MEMSIZE){
127 ret = -EINVAL;
128 break;
129 }
130
131 if ((filep->f_pos + offset) < 0){
132 ret = -EINVAL;
133 break;
134 }
135
136 filep->f_ops += offset;
137 ret = filep->f_ops;
138 break;
139
140 default:
141 ret = -EINVAL;
142 break;
143 }
144
145 return ret;
146 }
147
148 static int globalmem_mmap (struct file *, struct vm_area_struct *)
149 {
150 return 0;
151 }
152
153 static void globalmem_setup_cdev(struct globalmem_cdev *dev,int index)
154 {
155 int err,devno = MKDEV(globalmem_major,index);
156 cdev_init(dev->cdev,&globalmem_ops);
157 dev->cdev.owner = THIS_MODULE;
158 err = cdev_add(&dev,devno,1);
159 if (err)
160 printk(KERN_NOTICE "ERR %d adding globalmem %d",err,index);
161 }
162
163
164
165
166
167 static struct file_operations globalmem_ops = {
168 .owner = THIS_MODULE,
169 .read = globalmem_read,
170 .write = globalmem_write,
171 .llseek = globalmem_llseek,
172 .unlocked_ioctl =globalmem_unlocked_ioctl,
173 .open = globalmem_open,
174 .release = globalmem_release,
175 };
176
177
178
179
180
181
182
183 static int __init globalmem_init(void)
184 {
185 int ret;
186 dev_t devno = MKDEV(globalmem_major,0);
187 if (globalmem_major){
188 ret = register_chrdev_region(devno,1,"globalmem");
189 }else{
190 ret = alloc_chrdev_region(&devno,0,1,"globalmem");
191 globalmem_major = MAJOR(devno);
192 }
193
194 if (ret < 0)
195 return ret;
196
197 globalmem = kzalloc(sizeof(struct globalmem_cdev),GFP_KERNEL);
198 if (!globalmem){
199 ret = -ENOMEM;
200 goto fail_alloc;
201 }
202
203 globalmem_setup_cdev(globalmem,0);
204 return 0;
205
206 fail_alloc:
207 unregister_chrdev_region(devno,1);
208 return ret;
209 }
210
211 static void __exit globalmem_exit(void)
212 {
213 cdev_del(&globalmem->cdev);
214 kfree(globalmem);
215 unregister_chrdev_region(MKDEV(globalmem_major,0),1)
216
217 }
218
219 module_init(globalmem_init);
220 module_exit(globalmem_exit);
221
222 MODULE_LICENSE("GPL v2");
223 MODULE_AUTHOR("OzTaking");
224 MODULE_DESCRIPTION("a character program");