annotate vidix/kernelhelper/dhahelper.c @ 25661:293aeec83153

Replace the persistent CODECS_FLAG_SELECTED by a local "stringset" with an almost-trivial implementation. This allows making the builtin codec structs const, and it also makes clearer that this "selected" status is not used outside the init functions.
author reimar
date Sat, 12 Jan 2008 14:05:46 +0000
parents a9e111b88c4a
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