whitespace cosmetics: Remove all trailing whitespace.
[mplayer/glamo.git] / vidix / dhahelper / dhahelper.c
blob498f6537e64ff1eb693aa488d7ac2ef0d84df655
1 /*
2 * Direct Hardware Access (DHA) kernel helper
4 * Copyright (C) 2002 Alex Beregszaszi <alex@fsn.hu>
5 * This file is part of MPlayer.
7 * MPlayer is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * MPlayer is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 Accessing hardware from userspace as USER (no root needed!)
25 Tested on 2.2.x (2.2.19) and 2.4.x (2.4.3,2.4.17).
27 WARNING! THIS MODULE VIOLATES SEVERAL SECURITY LINES! DON'T USE IT
28 ON PRODUCTION SYSTEMS, ONLY AT HOME, ON A "SINGLE-USER" SYSTEM.
29 NO WARRANTY!
31 Tech:
32 Communication between userspace and kernelspace goes over character
33 device using ioctl.
35 Usage:
36 mknod -m 666 /dev/dhahelper c 180 0
38 Also you can change the major number, setting the "dhahelper_major"
39 module parameter, the default is 180, specified in dhahelper.h.
41 Note: do not use other than minor==0, the module forbids it.
43 TODO:
44 * do memory mapping without fops:mmap
45 * implement unmap memory
46 * select (request?) a "valid" major number (from Linux project? ;)
47 * make security
48 * is pci handling needed? (libdha does this with lowlevel port funcs)
49 * is mttr handling needed?
50 * test on older kernels (2.0.x (?))
53 #ifndef MODULE
54 #define MODULE
55 #endif
57 #ifndef __KERNEL__
58 #define __KERNEL__
59 #endif
61 #include <linux/config.h>
63 #ifdef CONFIG_MODVERSION
64 #define MODVERSION
65 #include <linux/modversions.h>
66 #endif
68 #include <linux/version.h>
69 #include <linux/module.h>
70 #include <linux/types.h>
71 #include <linux/kernel.h>
72 #include <linux/sched.h>
73 #include <linux/mm.h>
74 #include <linux/string.h>
75 #include <linux/errno.h>
77 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
78 #include <linux/malloc.h>
79 #else
80 #include <linux/slab.h>
81 #endif
83 #include <linux/pci.h>
84 #include <linux/ioport.h>
85 #include <linux/init.h>
87 #include <asm/uaccess.h>
88 #include <asm/system.h>
89 #include <asm/io.h>
91 #include <linux/mman.h>
93 #include <linux/fs.h>
94 #include <linux/unistd.h>
96 #include "dhahelper.h"
98 MODULE_AUTHOR("Alex Beregszaszi <alex@fsn.hu>");
99 MODULE_DESCRIPTION("Provides userspace access to hardware (security violation!)");
100 #ifdef MODULE_LICENSE
101 MODULE_LICENSE("GPL");
102 #endif
104 static int dhahelper_major = DEFAULT_MAJOR;
105 MODULE_PARM(dhahelper_major, "i");
106 MODULE_PARM_DESC(dhahelper_major, "Major number of dhahelper characterdevice");
108 /* 0 = silent */
109 /* 1 = report errors (default) */
110 /* 2 = debug */
111 static int dhahelper_verbosity = 1;
112 MODULE_PARM(dhahelper_verbosity, "i");
113 MODULE_PARM_DESC(dhahelper_verbosity, "Level of verbosity (0 = silent, 1 = only errors, 2 = debug)");
115 static dhahelper_memory_t last_mem_request;
118 static int dhahelper_open(struct inode *inode, struct file *file)
120 if (dhahelper_verbosity > 1)
121 printk(KERN_DEBUG "dhahelper: device opened\n");
123 if (MINOR(inode->i_rdev) != 0)
124 return -ENXIO;
126 MOD_INC_USE_COUNT;
128 return 0;
131 static int dhahelper_release(struct inode *inode, struct file *file)
133 if (dhahelper_verbosity > 1)
134 printk(KERN_DEBUG "dhahelper: device released\n");
136 if (MINOR(inode->i_rdev) != 0)
137 return -ENXIO;
139 MOD_DEC_USE_COUNT;
141 return 0;
144 static int dhahelper_ioctl(struct inode *inode, struct file *file,
145 unsigned int cmd, unsigned long arg)
147 if (dhahelper_verbosity > 1)
148 printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
149 cmd, arg);
151 if (MINOR(inode->i_rdev) != 0)
152 return -ENXIO;
154 switch(cmd)
156 case DHAHELPER_GET_VERSION:
158 int version = API_VERSION;
160 if (copy_to_user((int *)arg, &version, sizeof(int)))
162 if (dhahelper_verbosity > 0)
163 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
164 return -EFAULT;
167 break;
169 case DHAHELPER_PORT:
171 dhahelper_port_t port;
173 if (copy_from_user(&port, (dhahelper_port_t *)arg, sizeof(dhahelper_port_t)))
175 if (dhahelper_verbosity > 0)
176 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
177 return -EFAULT;
180 switch(port.operation)
182 case PORT_OP_READ:
184 switch(port.size)
186 case 1:
187 port.value = inb(port.addr);
188 break;
189 case 2:
190 port.value = inw(port.addr);
191 break;
192 case 4:
193 port.value = inl(port.addr);
194 break;
195 default:
196 if (dhahelper_verbosity > 0)
197 printk(KERN_ERR "dhahelper: invalid port read size (%d)\n",
198 port.size);
199 return -EINVAL;
201 break;
203 case PORT_OP_WRITE:
205 switch(port.size)
207 case 1:
208 outb(port.value, port.addr);
209 break;
210 case 2:
211 outw(port.value, port.addr);
212 break;
213 case 4:
214 outl(port.value, port.addr);
215 break;
216 default:
217 if (dhahelper_verbosity > 0)
218 printk(KERN_ERR "dhahelper: invalid port write size (%d)\n",
219 port.size);
220 return -EINVAL;
222 break;
224 default:
225 if (dhahelper_verbosity > 0)
226 printk(KERN_ERR "dhahelper: invalid port operation (%d)\n",
227 port.operation);
228 return -EINVAL;
231 /* copy back only if read was performed */
232 if (port.operation == PORT_OP_READ)
233 if (copy_to_user((dhahelper_port_t *)arg, &port, sizeof(dhahelper_port_t)))
235 if (dhahelper_verbosity > 0)
236 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
237 return -EFAULT;
240 break;
242 case DHAHELPER_MEMORY:
244 dhahelper_memory_t mem;
246 if (copy_from_user(&mem, (dhahelper_memory_t *)arg, sizeof(dhahelper_memory_t)))
248 if (dhahelper_verbosity > 0)
249 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
250 return -EFAULT;
253 switch(mem.operation)
255 case MEMORY_OP_MAP:
257 #if 1
258 memcpy(&last_mem_request, &mem, sizeof(dhahelper_memory_t));
259 #else
260 mem.ret = do_mmap(file, mem.start, mem.size, PROT_READ|PROT_WRITE,
261 MAP_SHARED, mem.offset);
262 #endif
264 break;
266 case MEMORY_OP_UNMAP:
267 break;
268 default:
269 if (dhahelper_verbosity > 0)
270 printk(KERN_ERR "dhahelper: invalid memory operation (%d)\n",
271 mem.operation);
272 return -EINVAL;
275 if (copy_to_user((dhahelper_memory_t *)arg, &mem, sizeof(dhahelper_memory_t)))
277 if (dhahelper_verbosity > 0)
278 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
279 return -EFAULT;
282 break;
284 default:
285 if (dhahelper_verbosity > 0)
286 printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
287 return -EINVAL;
290 return 0;
293 static int dhahelper_mmap(struct file *file, struct vm_area_struct *vma)
295 if (last_mem_request.operation != MEMORY_OP_MAP)
297 if (dhahelper_verbosity > 0)
298 printk(KERN_ERR "dhahelper: mapping not requested before mmap\n");
299 return -EFAULT;
302 if (dhahelper_verbosity > 1)
303 printk(KERN_INFO "dhahelper: mapping %x (size: %x)\n",
304 last_mem_request.start+last_mem_request.offset, last_mem_request.size);
306 if (remap_page_range(0, last_mem_request.start + last_mem_request.offset,
307 last_mem_request.size, vma->vm_page_prot))
309 if (dhahelper_verbosity > 0)
310 printk(KERN_ERR "dhahelper: error mapping memory\n");
311 return -EFAULT;
314 return 0;
317 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
318 static struct file_operations dhahelper_fops =
320 /*llseek*/ NULL,
321 /*read*/ NULL,
322 /*write*/ NULL,
323 /*readdir*/ NULL,
324 /*poll*/ NULL,
325 /*ioctl*/ dhahelper_ioctl,
326 /*mmap*/ dhahelper_mmap,
327 /*open*/ dhahelper_open,
328 /*flush*/ NULL,
329 /*release*/ dhahelper_release,
330 /* zero out the last 5 entries too ? */
332 #else
333 static struct file_operations dhahelper_fops =
335 owner: THIS_MODULE,
336 ioctl: dhahelper_ioctl,
337 mmap: dhahelper_mmap,
338 open: dhahelper_open,
339 release: dhahelper_release
341 #endif
343 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
344 int init_module(void)
345 #else
346 static int __init init_dhahelper(void)
347 #endif
349 printk(KERN_INFO "Direct Hardware Access kernel helper (C) Alex Beregszaszi\n");
351 if(register_chrdev(dhahelper_major, "dhahelper", &dhahelper_fops))
353 if (dhahelper_verbosity > 0)
354 printk(KERN_ERR "dhahelper: unable to register character device (major: %d)\n",
355 dhahelper_major);
356 return -EIO;
359 return 0;
362 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
363 void cleanup_module(void)
364 #else
365 static void __exit exit_dhahelper(void)
366 #endif
368 unregister_chrdev(dhahelper_major, "dhahelper");
371 EXPORT_NO_SYMBOLS;
373 #if KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
374 module_init(init_dhahelper);
375 module_exit(exit_dhahelper);
376 #endif