annotate vidix/kernelhelper/dhahelper.c @ 22900:a9e111b88c4a

merged libdha and libvidix, moved all files from libdha to vidix directory
author ben
date Fri, 06 Apr 2007 15:20:49 +0000
parents libdha/kernelhelper/dhahelper.c@0165fc26bd12
children 502f04b67653
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
4470
2d28c737ed13 initial
alex
parents:
diff changeset
1 /*
2d28c737ed13 initial
alex
parents:
diff changeset
2 Direct Hardware Access kernel helper
2d28c737ed13 initial
alex
parents:
diff changeset
3
10416
0165fc26bd12 changed my non-working mail address
alex
parents: 4479
diff changeset
4 (C) 2002 Alex Beregszaszi <alex@fsn.hu>
4470
2d28c737ed13 initial
alex
parents:
diff changeset
5
2d28c737ed13 initial
alex
parents:
diff changeset
6 Accessing hardware from userspace as USER (no root needed!)
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
7
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
8 Tested on 2.2.x (2.2.19) and 2.4.x (2.4.3,2.4.17).
4470
2d28c737ed13 initial
alex
parents:
diff changeset
9
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
10 License: GPL
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
11
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
12 WARNING! THIS MODULE VIOLATES SEVERAL SECURITY LINES! DON'T USE IT
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
13 ON PRODUCTION SYSTEMS, ONLY AT HOME, ON A "SINGLE-USER" SYSTEM.
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
14 NO WARRANTY!
4470
2d28c737ed13 initial
alex
parents:
diff changeset
15
2d28c737ed13 initial
alex
parents:
diff changeset
16 Tech:
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
17 Communication between userspace and kernelspace goes over character
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
18 device using ioctl.
4470
2d28c737ed13 initial
alex
parents:
diff changeset
19
2d28c737ed13 initial
alex
parents:
diff changeset
20 Usage:
2d28c737ed13 initial
alex
parents:
diff changeset
21 mknod -m 666 /dev/dhahelper c 180 0
2d28c737ed13 initial
alex
parents:
diff changeset
22
2d28c737ed13 initial
alex
parents:
diff changeset
23 Also you can change the major number, setting the "dhahelper_major"
2d28c737ed13 initial
alex
parents:
diff changeset
24 module parameter, the default is 180, specified in dhahelper.h.
2d28c737ed13 initial
alex
parents:
diff changeset
25
2d28c737ed13 initial
alex
parents:
diff changeset
26 Note: do not use other than minor==0, the module forbids it.
2d28c737ed13 initial
alex
parents:
diff changeset
27
2d28c737ed13 initial
alex
parents:
diff changeset
28 TODO:
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
29 * do memory mapping without fops:mmap
4470
2d28c737ed13 initial
alex
parents:
diff changeset
30 * implement unmap memory
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
31 * select (request?) a "valid" major number (from Linux project? ;)
4470
2d28c737ed13 initial
alex
parents:
diff changeset
32 * make security
2d28c737ed13 initial
alex
parents:
diff changeset
33 * is pci handling needed? (libdha does this with lowlevel port funcs)
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
34 * is mttr handling needed?
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
35 * test on older kernels (2.0.x (?))
4470
2d28c737ed13 initial
alex
parents:
diff changeset
36 */
2d28c737ed13 initial
alex
parents:
diff changeset
37
2d28c737ed13 initial
alex
parents:
diff changeset
38 #ifndef MODULE
2d28c737ed13 initial
alex
parents:
diff changeset
39 #define MODULE
2d28c737ed13 initial
alex
parents:
diff changeset
40 #endif
2d28c737ed13 initial
alex
parents:
diff changeset
41
2d28c737ed13 initial
alex
parents:
diff changeset
42 #ifndef __KERNEL__
2d28c737ed13 initial
alex
parents:
diff changeset
43 #define __KERNEL__
2d28c737ed13 initial
alex
parents:
diff changeset
44 #endif
2d28c737ed13 initial
alex
parents:
diff changeset
45
2d28c737ed13 initial
alex
parents:
diff changeset
46 #include <linux/config.h>
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
47
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
48 #ifdef CONFIG_MODVERSION
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
49 #define MODVERSION
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
50 #include <linux/modversions.h>
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
51 #endif
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
52
4470
2d28c737ed13 initial
alex
parents:
diff changeset
53 #include <linux/version.h>
2d28c737ed13 initial
alex
parents:
diff changeset
54 #include <linux/module.h>
2d28c737ed13 initial
alex
parents:
diff changeset
55 #include <linux/types.h>
2d28c737ed13 initial
alex
parents:
diff changeset
56 #include <linux/kernel.h>
2d28c737ed13 initial
alex
parents:
diff changeset
57 #include <linux/sched.h>
2d28c737ed13 initial
alex
parents:
diff changeset
58 #include <linux/mm.h>
2d28c737ed13 initial
alex
parents:
diff changeset
59 #include <linux/string.h>
2d28c737ed13 initial
alex
parents:
diff changeset
60 #include <linux/errno.h>
2d28c737ed13 initial
alex
parents:
diff changeset
61
2d28c737ed13 initial
alex
parents:
diff changeset
62 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
2d28c737ed13 initial
alex
parents:
diff changeset
63 #include <linux/malloc.h>
2d28c737ed13 initial
alex
parents:
diff changeset
64 #else
2d28c737ed13 initial
alex
parents:
diff changeset
65 #include <linux/slab.h>
2d28c737ed13 initial
alex
parents:
diff changeset
66 #endif
2d28c737ed13 initial
alex
parents:
diff changeset
67
2d28c737ed13 initial
alex
parents:
diff changeset
68 #include <linux/pci.h>
2d28c737ed13 initial
alex
parents:
diff changeset
69 #include <linux/ioport.h>
2d28c737ed13 initial
alex
parents:
diff changeset
70 #include <linux/init.h>
2d28c737ed13 initial
alex
parents:
diff changeset
71
2d28c737ed13 initial
alex
parents:
diff changeset
72 #include <asm/uaccess.h>
2d28c737ed13 initial
alex
parents:
diff changeset
73 #include <asm/system.h>
2d28c737ed13 initial
alex
parents:
diff changeset
74 #include <asm/io.h>
2d28c737ed13 initial
alex
parents:
diff changeset
75
2d28c737ed13 initial
alex
parents:
diff changeset
76 #include <linux/mman.h>
2d28c737ed13 initial
alex
parents:
diff changeset
77
2d28c737ed13 initial
alex
parents:
diff changeset
78 #include <linux/fs.h>
2d28c737ed13 initial
alex
parents:
diff changeset
79 #include <linux/unistd.h>
2d28c737ed13 initial
alex
parents:
diff changeset
80
2d28c737ed13 initial
alex
parents:
diff changeset
81 #include "dhahelper.h"
2d28c737ed13 initial
alex
parents:
diff changeset
82
10416
0165fc26bd12 changed my non-working mail address
alex
parents: 4479
diff changeset
83 MODULE_AUTHOR("Alex Beregszaszi <alex@fsn.hu>");
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
84 MODULE_DESCRIPTION("Provides userspace access to hardware (security violation!)");
4470
2d28c737ed13 initial
alex
parents:
diff changeset
85 #ifdef MODULE_LICENSE
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
86 MODULE_LICENSE("GPL");
4470
2d28c737ed13 initial
alex
parents:
diff changeset
87 #endif
2d28c737ed13 initial
alex
parents:
diff changeset
88
2d28c737ed13 initial
alex
parents:
diff changeset
89 static int dhahelper_major = DEFAULT_MAJOR;
2d28c737ed13 initial
alex
parents:
diff changeset
90 MODULE_PARM(dhahelper_major, "i");
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
91 MODULE_PARM_DESC(dhahelper_major, "Major number of dhahelper characterdevice");
4470
2d28c737ed13 initial
alex
parents:
diff changeset
92
2d28c737ed13 initial
alex
parents:
diff changeset
93 /* 0 = silent */
2d28c737ed13 initial
alex
parents:
diff changeset
94 /* 1 = report errors (default) */
2d28c737ed13 initial
alex
parents:
diff changeset
95 /* 2 = debug */
2d28c737ed13 initial
alex
parents:
diff changeset
96 static int dhahelper_verbosity = 1;
2d28c737ed13 initial
alex
parents:
diff changeset
97 MODULE_PARM(dhahelper_verbosity, "i");
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
98 MODULE_PARM_DESC(dhahelper_verbosity, "Level of verbosity (0 = silent, 1 = only errors, 2 = debug)");
4470
2d28c737ed13 initial
alex
parents:
diff changeset
99
2d28c737ed13 initial
alex
parents:
diff changeset
100 static dhahelper_memory_t last_mem_request;
2d28c737ed13 initial
alex
parents:
diff changeset
101
2d28c737ed13 initial
alex
parents:
diff changeset
102
2d28c737ed13 initial
alex
parents:
diff changeset
103 static int dhahelper_open(struct inode *inode, struct file *file)
2d28c737ed13 initial
alex
parents:
diff changeset
104 {
2d28c737ed13 initial
alex
parents:
diff changeset
105 if (dhahelper_verbosity > 1)
2d28c737ed13 initial
alex
parents:
diff changeset
106 printk(KERN_DEBUG "dhahelper: device opened\n");
2d28c737ed13 initial
alex
parents:
diff changeset
107
2d28c737ed13 initial
alex
parents:
diff changeset
108 if (MINOR(inode->i_rdev) != 0)
2d28c737ed13 initial
alex
parents:
diff changeset
109 return(-ENXIO);
2d28c737ed13 initial
alex
parents:
diff changeset
110
2d28c737ed13 initial
alex
parents:
diff changeset
111 MOD_INC_USE_COUNT;
2d28c737ed13 initial
alex
parents:
diff changeset
112
2d28c737ed13 initial
alex
parents:
diff changeset
113 return(0);
2d28c737ed13 initial
alex
parents:
diff changeset
114 }
2d28c737ed13 initial
alex
parents:
diff changeset
115
2d28c737ed13 initial
alex
parents:
diff changeset
116 static int dhahelper_release(struct inode *inode, struct file *file)
2d28c737ed13 initial
alex
parents:
diff changeset
117 {
2d28c737ed13 initial
alex
parents:
diff changeset
118 if (dhahelper_verbosity > 1)
2d28c737ed13 initial
alex
parents:
diff changeset
119 printk(KERN_DEBUG "dhahelper: device released\n");
2d28c737ed13 initial
alex
parents:
diff changeset
120
2d28c737ed13 initial
alex
parents:
diff changeset
121 if (MINOR(inode->i_rdev) != 0)
2d28c737ed13 initial
alex
parents:
diff changeset
122 return(-ENXIO);
2d28c737ed13 initial
alex
parents:
diff changeset
123
2d28c737ed13 initial
alex
parents:
diff changeset
124 MOD_DEC_USE_COUNT;
2d28c737ed13 initial
alex
parents:
diff changeset
125
2d28c737ed13 initial
alex
parents:
diff changeset
126 return(0);
2d28c737ed13 initial
alex
parents:
diff changeset
127 }
2d28c737ed13 initial
alex
parents:
diff changeset
128
2d28c737ed13 initial
alex
parents:
diff changeset
129 static int dhahelper_ioctl(struct inode *inode, struct file *file,
2d28c737ed13 initial
alex
parents:
diff changeset
130 unsigned int cmd, unsigned long arg)
2d28c737ed13 initial
alex
parents:
diff changeset
131 {
2d28c737ed13 initial
alex
parents:
diff changeset
132 if (dhahelper_verbosity > 1)
2d28c737ed13 initial
alex
parents:
diff changeset
133 printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
134 cmd, arg);
2d28c737ed13 initial
alex
parents:
diff changeset
135
2d28c737ed13 initial
alex
parents:
diff changeset
136 if (MINOR(inode->i_rdev) != 0)
2d28c737ed13 initial
alex
parents:
diff changeset
137 return(-ENXIO);
2d28c737ed13 initial
alex
parents:
diff changeset
138
2d28c737ed13 initial
alex
parents:
diff changeset
139 switch(cmd)
2d28c737ed13 initial
alex
parents:
diff changeset
140 {
2d28c737ed13 initial
alex
parents:
diff changeset
141 case DHAHELPER_GET_VERSION:
2d28c737ed13 initial
alex
parents:
diff changeset
142 {
2d28c737ed13 initial
alex
parents:
diff changeset
143 int version = API_VERSION;
2d28c737ed13 initial
alex
parents:
diff changeset
144
2d28c737ed13 initial
alex
parents:
diff changeset
145 if (copy_to_user((int *)arg, &version, sizeof(int)))
2d28c737ed13 initial
alex
parents:
diff changeset
146 {
2d28c737ed13 initial
alex
parents:
diff changeset
147 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
148 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
2d28c737ed13 initial
alex
parents:
diff changeset
149 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
150 }
2d28c737ed13 initial
alex
parents:
diff changeset
151
2d28c737ed13 initial
alex
parents:
diff changeset
152 break;
2d28c737ed13 initial
alex
parents:
diff changeset
153 }
2d28c737ed13 initial
alex
parents:
diff changeset
154 case DHAHELPER_PORT:
2d28c737ed13 initial
alex
parents:
diff changeset
155 {
2d28c737ed13 initial
alex
parents:
diff changeset
156 dhahelper_port_t port;
2d28c737ed13 initial
alex
parents:
diff changeset
157
2d28c737ed13 initial
alex
parents:
diff changeset
158 if (copy_from_user(&port, (dhahelper_port_t *)arg, sizeof(dhahelper_port_t)))
2d28c737ed13 initial
alex
parents:
diff changeset
159 {
2d28c737ed13 initial
alex
parents:
diff changeset
160 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
161 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
2d28c737ed13 initial
alex
parents:
diff changeset
162 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
163 }
2d28c737ed13 initial
alex
parents:
diff changeset
164
2d28c737ed13 initial
alex
parents:
diff changeset
165 switch(port.operation)
2d28c737ed13 initial
alex
parents:
diff changeset
166 {
2d28c737ed13 initial
alex
parents:
diff changeset
167 case PORT_OP_READ:
2d28c737ed13 initial
alex
parents:
diff changeset
168 {
2d28c737ed13 initial
alex
parents:
diff changeset
169 switch(port.size)
2d28c737ed13 initial
alex
parents:
diff changeset
170 {
2d28c737ed13 initial
alex
parents:
diff changeset
171 case 1:
2d28c737ed13 initial
alex
parents:
diff changeset
172 port.value = inb(port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
173 break;
2d28c737ed13 initial
alex
parents:
diff changeset
174 case 2:
2d28c737ed13 initial
alex
parents:
diff changeset
175 port.value = inw(port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
176 break;
2d28c737ed13 initial
alex
parents:
diff changeset
177 case 4:
2d28c737ed13 initial
alex
parents:
diff changeset
178 port.value = inl(port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
179 break;
2d28c737ed13 initial
alex
parents:
diff changeset
180 default:
2d28c737ed13 initial
alex
parents:
diff changeset
181 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
182 printk(KERN_ERR "dhahelper: invalid port read size (%d)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
183 port.size);
2d28c737ed13 initial
alex
parents:
diff changeset
184 return(-EINVAL);
2d28c737ed13 initial
alex
parents:
diff changeset
185 }
2d28c737ed13 initial
alex
parents:
diff changeset
186 break;
2d28c737ed13 initial
alex
parents:
diff changeset
187 }
2d28c737ed13 initial
alex
parents:
diff changeset
188 case PORT_OP_WRITE:
2d28c737ed13 initial
alex
parents:
diff changeset
189 {
2d28c737ed13 initial
alex
parents:
diff changeset
190 switch(port.size)
2d28c737ed13 initial
alex
parents:
diff changeset
191 {
2d28c737ed13 initial
alex
parents:
diff changeset
192 case 1:
2d28c737ed13 initial
alex
parents:
diff changeset
193 outb(port.value, port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
194 break;
2d28c737ed13 initial
alex
parents:
diff changeset
195 case 2:
2d28c737ed13 initial
alex
parents:
diff changeset
196 outw(port.value, port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
197 break;
2d28c737ed13 initial
alex
parents:
diff changeset
198 case 4:
2d28c737ed13 initial
alex
parents:
diff changeset
199 outl(port.value, port.addr);
2d28c737ed13 initial
alex
parents:
diff changeset
200 break;
2d28c737ed13 initial
alex
parents:
diff changeset
201 default:
2d28c737ed13 initial
alex
parents:
diff changeset
202 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
203 printk(KERN_ERR "dhahelper: invalid port write size (%d)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
204 port.size);
2d28c737ed13 initial
alex
parents:
diff changeset
205 return(-EINVAL);
2d28c737ed13 initial
alex
parents:
diff changeset
206 }
2d28c737ed13 initial
alex
parents:
diff changeset
207 break;
2d28c737ed13 initial
alex
parents:
diff changeset
208 }
2d28c737ed13 initial
alex
parents:
diff changeset
209 default:
2d28c737ed13 initial
alex
parents:
diff changeset
210 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
211 printk(KERN_ERR "dhahelper: invalid port operation (%d)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
212 port.operation);
2d28c737ed13 initial
alex
parents:
diff changeset
213 return(-EINVAL);
2d28c737ed13 initial
alex
parents:
diff changeset
214 }
2d28c737ed13 initial
alex
parents:
diff changeset
215
2d28c737ed13 initial
alex
parents:
diff changeset
216 /* copy back only if read was performed */
2d28c737ed13 initial
alex
parents:
diff changeset
217 if (port.operation == PORT_OP_READ)
2d28c737ed13 initial
alex
parents:
diff changeset
218 if (copy_to_user((dhahelper_port_t *)arg, &port, sizeof(dhahelper_port_t)))
2d28c737ed13 initial
alex
parents:
diff changeset
219 {
2d28c737ed13 initial
alex
parents:
diff changeset
220 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
221 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
2d28c737ed13 initial
alex
parents:
diff changeset
222 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
223 }
2d28c737ed13 initial
alex
parents:
diff changeset
224
2d28c737ed13 initial
alex
parents:
diff changeset
225 break;
2d28c737ed13 initial
alex
parents:
diff changeset
226 }
2d28c737ed13 initial
alex
parents:
diff changeset
227 case DHAHELPER_MEMORY:
2d28c737ed13 initial
alex
parents:
diff changeset
228 {
2d28c737ed13 initial
alex
parents:
diff changeset
229 dhahelper_memory_t mem;
2d28c737ed13 initial
alex
parents:
diff changeset
230
2d28c737ed13 initial
alex
parents:
diff changeset
231 if (copy_from_user(&mem, (dhahelper_memory_t *)arg, sizeof(dhahelper_memory_t)))
2d28c737ed13 initial
alex
parents:
diff changeset
232 {
2d28c737ed13 initial
alex
parents:
diff changeset
233 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
234 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
2d28c737ed13 initial
alex
parents:
diff changeset
235 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
236 }
2d28c737ed13 initial
alex
parents:
diff changeset
237
2d28c737ed13 initial
alex
parents:
diff changeset
238 switch(mem.operation)
2d28c737ed13 initial
alex
parents:
diff changeset
239 {
2d28c737ed13 initial
alex
parents:
diff changeset
240 case MEMORY_OP_MAP:
2d28c737ed13 initial
alex
parents:
diff changeset
241 {
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
242 #if 1
4470
2d28c737ed13 initial
alex
parents:
diff changeset
243 memcpy(&last_mem_request, &mem, sizeof(dhahelper_memory_t));
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
244 #else
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
245 mem.ret = do_mmap(file, mem.start, mem.size, PROT_READ|PROT_WRITE,
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
246 MAP_SHARED, mem.offset);
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
247 #endif
4470
2d28c737ed13 initial
alex
parents:
diff changeset
248
2d28c737ed13 initial
alex
parents:
diff changeset
249 break;
2d28c737ed13 initial
alex
parents:
diff changeset
250 }
2d28c737ed13 initial
alex
parents:
diff changeset
251 case MEMORY_OP_UNMAP:
2d28c737ed13 initial
alex
parents:
diff changeset
252 break;
2d28c737ed13 initial
alex
parents:
diff changeset
253 default:
2d28c737ed13 initial
alex
parents:
diff changeset
254 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
255 printk(KERN_ERR "dhahelper: invalid memory operation (%d)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
256 mem.operation);
2d28c737ed13 initial
alex
parents:
diff changeset
257 return(-EINVAL);
2d28c737ed13 initial
alex
parents:
diff changeset
258 }
2d28c737ed13 initial
alex
parents:
diff changeset
259
2d28c737ed13 initial
alex
parents:
diff changeset
260 if (copy_to_user((dhahelper_memory_t *)arg, &mem, sizeof(dhahelper_memory_t)))
2d28c737ed13 initial
alex
parents:
diff changeset
261 {
2d28c737ed13 initial
alex
parents:
diff changeset
262 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
263 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
2d28c737ed13 initial
alex
parents:
diff changeset
264 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
265 }
2d28c737ed13 initial
alex
parents:
diff changeset
266
2d28c737ed13 initial
alex
parents:
diff changeset
267 break;
2d28c737ed13 initial
alex
parents:
diff changeset
268 }
2d28c737ed13 initial
alex
parents:
diff changeset
269 default:
2d28c737ed13 initial
alex
parents:
diff changeset
270 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
271 printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
2d28c737ed13 initial
alex
parents:
diff changeset
272 return(-EINVAL);
2d28c737ed13 initial
alex
parents:
diff changeset
273 }
2d28c737ed13 initial
alex
parents:
diff changeset
274
2d28c737ed13 initial
alex
parents:
diff changeset
275 return(0);
2d28c737ed13 initial
alex
parents:
diff changeset
276 }
2d28c737ed13 initial
alex
parents:
diff changeset
277
2d28c737ed13 initial
alex
parents:
diff changeset
278 static int dhahelper_mmap(struct file *file, struct vm_area_struct *vma)
2d28c737ed13 initial
alex
parents:
diff changeset
279 {
2d28c737ed13 initial
alex
parents:
diff changeset
280 if (last_mem_request.operation != MEMORY_OP_MAP)
2d28c737ed13 initial
alex
parents:
diff changeset
281 {
2d28c737ed13 initial
alex
parents:
diff changeset
282 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
283 printk(KERN_ERR "dhahelper: mapping not requested before mmap\n");
2d28c737ed13 initial
alex
parents:
diff changeset
284 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
285 }
2d28c737ed13 initial
alex
parents:
diff changeset
286
2d28c737ed13 initial
alex
parents:
diff changeset
287 if (dhahelper_verbosity > 1)
2d28c737ed13 initial
alex
parents:
diff changeset
288 printk(KERN_INFO "dhahelper: mapping %x (size: %x)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
289 last_mem_request.start+last_mem_request.offset, last_mem_request.size);
2d28c737ed13 initial
alex
parents:
diff changeset
290
2d28c737ed13 initial
alex
parents:
diff changeset
291 if (remap_page_range(0, last_mem_request.start + last_mem_request.offset,
2d28c737ed13 initial
alex
parents:
diff changeset
292 last_mem_request.size, vma->vm_page_prot))
2d28c737ed13 initial
alex
parents:
diff changeset
293 {
2d28c737ed13 initial
alex
parents:
diff changeset
294 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
295 printk(KERN_ERR "dhahelper: error mapping memory\n");
2d28c737ed13 initial
alex
parents:
diff changeset
296 return(-EFAULT);
2d28c737ed13 initial
alex
parents:
diff changeset
297 }
2d28c737ed13 initial
alex
parents:
diff changeset
298
2d28c737ed13 initial
alex
parents:
diff changeset
299 return(0);
2d28c737ed13 initial
alex
parents:
diff changeset
300 }
2d28c737ed13 initial
alex
parents:
diff changeset
301
2d28c737ed13 initial
alex
parents:
diff changeset
302 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
2d28c737ed13 initial
alex
parents:
diff changeset
303 static struct file_operations dhahelper_fops =
2d28c737ed13 initial
alex
parents:
diff changeset
304 {
2d28c737ed13 initial
alex
parents:
diff changeset
305 /*llseek*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
306 /*read*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
307 /*write*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
308 /*readdir*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
309 /*poll*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
310 /*ioctl*/ dhahelper_ioctl,
2d28c737ed13 initial
alex
parents:
diff changeset
311 /*mmap*/ dhahelper_mmap,
2d28c737ed13 initial
alex
parents:
diff changeset
312 /*open*/ dhahelper_open,
2d28c737ed13 initial
alex
parents:
diff changeset
313 /*flush*/ NULL,
2d28c737ed13 initial
alex
parents:
diff changeset
314 /*release*/ dhahelper_release,
2d28c737ed13 initial
alex
parents:
diff changeset
315 /* zero out the last 5 entries too ? */
2d28c737ed13 initial
alex
parents:
diff changeset
316 };
2d28c737ed13 initial
alex
parents:
diff changeset
317 #else
2d28c737ed13 initial
alex
parents:
diff changeset
318 static struct file_operations dhahelper_fops =
2d28c737ed13 initial
alex
parents:
diff changeset
319 {
2d28c737ed13 initial
alex
parents:
diff changeset
320 owner: THIS_MODULE,
2d28c737ed13 initial
alex
parents:
diff changeset
321 ioctl: dhahelper_ioctl,
2d28c737ed13 initial
alex
parents:
diff changeset
322 mmap: dhahelper_mmap,
2d28c737ed13 initial
alex
parents:
diff changeset
323 open: dhahelper_open,
2d28c737ed13 initial
alex
parents:
diff changeset
324 release: dhahelper_release
2d28c737ed13 initial
alex
parents:
diff changeset
325 };
2d28c737ed13 initial
alex
parents:
diff changeset
326 #endif
2d28c737ed13 initial
alex
parents:
diff changeset
327
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
328 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
329 int init_module(void)
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
330 #else
4470
2d28c737ed13 initial
alex
parents:
diff changeset
331 static int __init init_dhahelper(void)
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
332 #endif
4470
2d28c737ed13 initial
alex
parents:
diff changeset
333 {
2d28c737ed13 initial
alex
parents:
diff changeset
334 printk(KERN_INFO "Direct Hardware Access kernel helper (C) Alex Beregszaszi\n");
2d28c737ed13 initial
alex
parents:
diff changeset
335
2d28c737ed13 initial
alex
parents:
diff changeset
336 if(register_chrdev(dhahelper_major, "dhahelper", &dhahelper_fops))
2d28c737ed13 initial
alex
parents:
diff changeset
337 {
2d28c737ed13 initial
alex
parents:
diff changeset
338 if (dhahelper_verbosity > 0)
2d28c737ed13 initial
alex
parents:
diff changeset
339 printk(KERN_ERR "dhahelper: unable to register character device (major: %d)\n",
2d28c737ed13 initial
alex
parents:
diff changeset
340 dhahelper_major);
2d28c737ed13 initial
alex
parents:
diff changeset
341 return(-EIO);
2d28c737ed13 initial
alex
parents:
diff changeset
342 }
2d28c737ed13 initial
alex
parents:
diff changeset
343
2d28c737ed13 initial
alex
parents:
diff changeset
344 return(0);
2d28c737ed13 initial
alex
parents:
diff changeset
345 }
2d28c737ed13 initial
alex
parents:
diff changeset
346
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
347 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
348 void cleanup_module(void)
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
349 #else
4470
2d28c737ed13 initial
alex
parents:
diff changeset
350 static void __exit exit_dhahelper(void)
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
351 #endif
4470
2d28c737ed13 initial
alex
parents:
diff changeset
352 {
2d28c737ed13 initial
alex
parents:
diff changeset
353 unregister_chrdev(dhahelper_major, "dhahelper");
2d28c737ed13 initial
alex
parents:
diff changeset
354 }
2d28c737ed13 initial
alex
parents:
diff changeset
355
2d28c737ed13 initial
alex
parents:
diff changeset
356 EXPORT_NO_SYMBOLS;
2d28c737ed13 initial
alex
parents:
diff changeset
357
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
358 #if KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
4470
2d28c737ed13 initial
alex
parents:
diff changeset
359 module_init(init_dhahelper);
2d28c737ed13 initial
alex
parents:
diff changeset
360 module_exit(exit_dhahelper);
4479
423ce4451ca8 tested and fixed on 2.2.x, more comments
alex
parents: 4470
diff changeset
361 #endif