vf_stereo3d: Adjust d_height instead of bad ad-hoc scaling
[mplayer/glamo.git] / vidix / dhahelper / dhahelper.c
bloba187388ef35f9ae2b202639747864d272e1b04f0
1 /*
2 * Direct Hardware Access (DHA) kernel helper
4 * Copyright (C) 2002 Alex Beregszaszi <alex@fsn.hu>
6 * This file is part of MPlayer.
8 * MPlayer is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * MPlayer is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License along
19 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 Accessing hardware from userspace as USER (no root needed!)
26 Tested on 2.2.x (2.2.19) and 2.4.x (2.4.3,2.4.17).
28 WARNING! THIS MODULE VIOLATES SEVERAL SECURITY LINES! DON'T USE IT
29 ON PRODUCTION SYSTEMS, ONLY AT HOME, ON A "SINGLE-USER" SYSTEM.
30 NO WARRANTY!
32 Tech:
33 Communication between userspace and kernelspace goes over character
34 device using ioctl.
36 Usage:
37 mknod -m 666 /dev/dhahelper c 180 0
39 Also you can change the major number, setting the "dhahelper_major"
40 module parameter, the default is 180, specified in dhahelper.h.
42 Note: do not use other than minor==0, the module forbids it.
44 TODO:
45 * do memory mapping without fops:mmap
46 * implement unmap memory
47 * select (request?) a "valid" major number (from Linux project? ;)
48 * make security
49 * is pci handling needed? (libdha does this with lowlevel port funcs)
50 * is mttr handling needed?
51 * test on older kernels (2.0.x (?))
54 #ifndef MODULE
55 #define MODULE
56 #endif
58 #ifndef __KERNEL__
59 #define __KERNEL__
60 #endif
62 #include <linux/config.h>
64 #ifdef CONFIG_MODVERSION
65 #define MODVERSION
66 #include <linux/modversions.h>
67 #endif
69 #include <linux/version.h>
70 #include <linux/module.h>
71 #include <linux/types.h>
72 #include <linux/kernel.h>
73 #include <linux/sched.h>
74 #include <linux/mm.h>
75 #include <linux/string.h>
76 #include <linux/errno.h>
78 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,10)
79 #include <linux/malloc.h>
80 #else
81 #include <linux/slab.h>
82 #endif
84 #include <linux/pci.h>
85 #include <linux/ioport.h>
86 #include <linux/init.h>
88 #include <asm/uaccess.h>
89 #include <asm/system.h>
90 #include <asm/io.h>
92 #include <linux/mman.h>
94 #include <linux/fs.h>
95 #include <linux/unistd.h>
97 #include "dhahelper.h"
99 MODULE_AUTHOR("Alex Beregszaszi <alex@fsn.hu>");
100 MODULE_DESCRIPTION("Provides userspace access to hardware (security violation!)");
101 #ifdef MODULE_LICENSE
102 MODULE_LICENSE("GPL");
103 #endif
105 static int dhahelper_major = DEFAULT_MAJOR;
106 MODULE_PARM(dhahelper_major, "i");
107 MODULE_PARM_DESC(dhahelper_major, "Major number of dhahelper characterdevice");
109 /* 0 = silent */
110 /* 1 = report errors (default) */
111 /* 2 = debug */
112 static int dhahelper_verbosity = 1;
113 MODULE_PARM(dhahelper_verbosity, "i");
114 MODULE_PARM_DESC(dhahelper_verbosity, "Level of verbosity (0 = silent, 1 = only errors, 2 = debug)");
116 static dhahelper_memory_t last_mem_request;
119 static int dhahelper_open(struct inode *inode, struct file *file)
121 if (dhahelper_verbosity > 1)
122 printk(KERN_DEBUG "dhahelper: device opened\n");
124 if (MINOR(inode->i_rdev) != 0)
125 return -ENXIO;
127 MOD_INC_USE_COUNT;
129 return 0;
132 static int dhahelper_release(struct inode *inode, struct file *file)
134 if (dhahelper_verbosity > 1)
135 printk(KERN_DEBUG "dhahelper: device released\n");
137 if (MINOR(inode->i_rdev) != 0)
138 return -ENXIO;
140 MOD_DEC_USE_COUNT;
142 return 0;
145 static int dhahelper_ioctl(struct inode *inode, struct file *file,
146 unsigned int cmd, unsigned long arg)
148 if (dhahelper_verbosity > 1)
149 printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
150 cmd, arg);
152 if (MINOR(inode->i_rdev) != 0)
153 return -ENXIO;
155 switch(cmd)
157 case DHAHELPER_GET_VERSION:
159 int version = API_VERSION;
161 if (copy_to_user((int *)arg, &version, sizeof(int)))
163 if (dhahelper_verbosity > 0)
164 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
165 return -EFAULT;
168 break;
170 case DHAHELPER_PORT:
172 dhahelper_port_t port;
174 if (copy_from_user(&port, (dhahelper_port_t *)arg, sizeof(dhahelper_port_t)))
176 if (dhahelper_verbosity > 0)
177 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
178 return -EFAULT;
181 switch(port.operation)
183 case PORT_OP_READ:
185 switch(port.size)
187 case 1:
188 port.value = inb(port.addr);
189 break;
190 case 2:
191 port.value = inw(port.addr);
192 break;
193 case 4:
194 port.value = inl(port.addr);
195 break;
196 default:
197 if (dhahelper_verbosity > 0)
198 printk(KERN_ERR "dhahelper: invalid port read size (%d)\n",
199 port.size);
200 return -EINVAL;
202 break;
204 case PORT_OP_WRITE:
206 switch(port.size)
208 case 1:
209 outb(port.value, port.addr);
210 break;
211 case 2:
212 outw(port.value, port.addr);
213 break;
214 case 4:
215 outl(port.value, port.addr);
216 break;
217 default:
218 if (dhahelper_verbosity > 0)
219 printk(KERN_ERR "dhahelper: invalid port write size (%d)\n",
220 port.size);
221 return -EINVAL;
223 break;
225 default:
226 if (dhahelper_verbosity > 0)
227 printk(KERN_ERR "dhahelper: invalid port operation (%d)\n",
228 port.operation);
229 return -EINVAL;
232 /* copy back only if read was performed */
233 if (port.operation == PORT_OP_READ)
234 if (copy_to_user((dhahelper_port_t *)arg, &port, sizeof(dhahelper_port_t)))
236 if (dhahelper_verbosity > 0)
237 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
238 return -EFAULT;
241 break;
243 case DHAHELPER_MEMORY:
245 dhahelper_memory_t mem;
247 if (copy_from_user(&mem, (dhahelper_memory_t *)arg, sizeof(dhahelper_memory_t)))
249 if (dhahelper_verbosity > 0)
250 printk(KERN_ERR "dhahelper: failed copy from userspace\n");
251 return -EFAULT;
254 switch(mem.operation)
256 case MEMORY_OP_MAP:
258 #if 1
259 memcpy(&last_mem_request, &mem, sizeof(dhahelper_memory_t));
260 #else
261 mem.ret = do_mmap(file, mem.start, mem.size, PROT_READ|PROT_WRITE,
262 MAP_SHARED, mem.offset);
263 #endif
265 break;
267 case MEMORY_OP_UNMAP:
268 break;
269 default:
270 if (dhahelper_verbosity > 0)
271 printk(KERN_ERR "dhahelper: invalid memory operation (%d)\n",
272 mem.operation);
273 return -EINVAL;
276 if (copy_to_user((dhahelper_memory_t *)arg, &mem, sizeof(dhahelper_memory_t)))
278 if (dhahelper_verbosity > 0)
279 printk(KERN_ERR "dhahelper: failed copy to userspace\n");
280 return -EFAULT;
283 break;
285 default:
286 if (dhahelper_verbosity > 0)
287 printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
288 return -EINVAL;
291 return 0;
294 static int dhahelper_mmap(struct file *file, struct vm_area_struct *vma)
296 if (last_mem_request.operation != MEMORY_OP_MAP)
298 if (dhahelper_verbosity > 0)
299 printk(KERN_ERR "dhahelper: mapping not requested before mmap\n");
300 return -EFAULT;
303 if (dhahelper_verbosity > 1)
304 printk(KERN_INFO "dhahelper: mapping %x (size: %x)\n",
305 last_mem_request.start+last_mem_request.offset, last_mem_request.size);
307 if (remap_page_range(0, last_mem_request.start + last_mem_request.offset,
308 last_mem_request.size, vma->vm_page_prot))
310 if (dhahelper_verbosity > 0)
311 printk(KERN_ERR "dhahelper: error mapping memory\n");
312 return -EFAULT;
315 return 0;
318 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
319 static struct file_operations dhahelper_fops =
321 /*llseek*/ NULL,
322 /*read*/ NULL,
323 /*write*/ NULL,
324 /*readdir*/ NULL,
325 /*poll*/ NULL,
326 /*ioctl*/ dhahelper_ioctl,
327 /*mmap*/ dhahelper_mmap,
328 /*open*/ dhahelper_open,
329 /*flush*/ NULL,
330 /*release*/ dhahelper_release,
331 /* zero out the last 5 entries too ? */
333 #else
334 static struct file_operations dhahelper_fops =
336 owner: THIS_MODULE,
337 ioctl: dhahelper_ioctl,
338 mmap: dhahelper_mmap,
339 open: dhahelper_open,
340 release: dhahelper_release
342 #endif
344 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
345 int init_module(void)
346 #else
347 static int __init init_dhahelper(void)
348 #endif
350 printk(KERN_INFO "Direct Hardware Access kernel helper (C) Alex Beregszaszi\n");
352 if(register_chrdev(dhahelper_major, "dhahelper", &dhahelper_fops))
354 if (dhahelper_verbosity > 0)
355 printk(KERN_ERR "dhahelper: unable to register character device (major: %d)\n",
356 dhahelper_major);
357 return -EIO;
360 return 0;
363 #if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
364 void cleanup_module(void)
365 #else
366 static void __exit exit_dhahelper(void)
367 #endif
369 unregister_chrdev(dhahelper_major, "dhahelper");
372 EXPORT_NO_SYMBOLS;
374 #if KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
375 module_init(init_dhahelper);
376 module_exit(exit_dhahelper);
377 #endif