summaryrefslogtreecommitdiff
path: root/src/video_out/libdha/kernelhelper
diff options
context:
space:
mode:
authorDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2002-06-01 14:08:36 +0000
committerDaniel Caujolle-Bert <f1rmb@users.sourceforge.net>2002-06-01 14:08:36 +0000
commitbb7a31a69bac993ffb9cfb195b84c1e374308e08 (patch)
treedfa504dd8c27837562c4850308d668afef851dd2 /src/video_out/libdha/kernelhelper
parentc49645144f4d31c88610c449059d48493736b5b6 (diff)
downloadxine-lib-bb7a31a69bac993ffb9cfb195b84c1e374308e08.tar.gz
xine-lib-bb7a31a69bac993ffb9cfb195b84c1e374308e08.tar.bz2
Add vidix/libdha from mplayerxp and Miguel's video ouput vidix.
CVS patchset: 1976 CVS date: 2002/06/01 14:08:36
Diffstat (limited to 'src/video_out/libdha/kernelhelper')
-rw-r--r--src/video_out/libdha/kernelhelper/Makefile.am41
-rw-r--r--src/video_out/libdha/kernelhelper/README34
-rw-r--r--src/video_out/libdha/kernelhelper/dhahelper.c416
-rw-r--r--src/video_out/libdha/kernelhelper/dhahelper.h78
-rw-r--r--src/video_out/libdha/kernelhelper/test.c60
5 files changed, 629 insertions, 0 deletions
diff --git a/src/video_out/libdha/kernelhelper/Makefile.am b/src/video_out/libdha/kernelhelper/Makefile.am
new file mode 100644
index 000000000..4d603c0e7
--- /dev/null
+++ b/src/video_out/libdha/kernelhelper/Makefile.am
@@ -0,0 +1,41 @@
+EXTRA_DIST = README dhahelper.c
+
+CFLAGS = -O2 -Wall -D__KERNEL__ -DMODULE
+
+## CLEAN ME
+KVERSION = $(shell $(SHELL) -c 'uname -r')
+MISC_KDIR = /lib/modules/$(KVERSION)/misc
+
+KCOMPILE = $(CC) $(CFLAGS) $(INCLUDES) $(LINUX_INCLUDE)
+
+noinst_HEADERS = dhahelper.h
+
+EXTRA_PROGRAMS = test
+test_SOURCES = test.c
+
+dhahelper.o:
+ $(KCOMPILE) -c `test -f $< || echo '$(srcdir)/'`$<
+
+install-data-local: @HAVE_LINUX_TRUE@ dhahelper.o
+@HAVE_LINUX_TRUE@ if test ! -d $(MISC_KDIR); then \
+@HAVE_LINUX_TRUE@ mkdir -p $(MISC_KDIR); \
+@HAVE_LINUX_TRUE@ fi
+@HAVE_LINUX_TRUE@ $(INSTALL_DATA) dhahelper.o $(MISC_KDIR)/dhahelper.o
+@HAVE_LINUX_TRUE@ $(DEPMOD) -a
+@HAVE_LINUX_TRUE@ if test ! -c /dev/dhahelper; then \
+@HAVE_LINUX_TRUE@ $(MKNOD) -m 666 /dev/dhahelper c 180 0; \
+@HAVE_LINUX_TRUE@ fi
+
+uninstall-local:
+@HAVE_LINUX_TRUE@ rm -f $(MISC_KDIR)/dhahelper.o
+
+debug:
+install-debug: install
+
+mostlyclean-generic:
+ -rm -f *~ \#* .*~ .\#* test
+
+maintainer-clean-generic:
+ -@echo "This command is intended for maintainers to use;"
+ -@echo "it deletes files that may require special tools to rebuild."
+ -rm -f Makefile.in
diff --git a/src/video_out/libdha/kernelhelper/README b/src/video_out/libdha/kernelhelper/README
new file mode 100644
index 000000000..cb5964cb8
--- /dev/null
+++ b/src/video_out/libdha/kernelhelper/README
@@ -0,0 +1,34 @@
+dhahelper is small driver to provide some kernel function into userspace.
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Main goal why you need to use that it's busmastering.
+(Btw, lacking of possibility to implement convertion of
+virtual addresses into physical in userspace caused
+implementing of so-called DRM drivers for Linux from
+XFree86 side).
+Second goal (still is unfinished) - provide possibility
+to control port and physical memory access through
+groups and access rights of this driver. (Unix way).
+
+Installation:
+~~~~~~~~~~~~~
+just type in this directory:
+make all install
+
+If you have compiled this driver first-time then
+type also:
+make nodes
+
+Porting:
+~~~~~~~~
+This driver was developed only for Linux.
+So if someone will port that on other unicies
+then any patches are gladly accepted.
+
+WARNING:
+~~~~~~~~
+This driver violates some kernel's security rules.
+To keep this driver from anonymous access I suggest
+you create new group for mplayerxp and /dev/dhahelper
+only.
+
+Good luck!
diff --git a/src/video_out/libdha/kernelhelper/dhahelper.c b/src/video_out/libdha/kernelhelper/dhahelper.c
new file mode 100644
index 000000000..f85b4efd1
--- /dev/null
+++ b/src/video_out/libdha/kernelhelper/dhahelper.c
@@ -0,0 +1,416 @@
+/*
+ Direct Hardware Access kernel helper
+
+ (C) 2002 Alex Beregszaszi <alex@naxine.org>
+
+ Accessing hardware from userspace as USER (no root needed!)
+
+ Tested on 2.2.x (2.2.19) and 2.4.x (2.4.3,2.4.17).
+
+ License: GPL
+
+ WARNING! THIS MODULE VIOLATES SEVERAL SECURITY LINES! DON'T USE IT
+ ON PRODUCTION SYSTEMS, ONLY AT HOME, ON A "SINGLE-USER" SYSTEM.
+ NO WARRANTY!
+
+ Tech:
+ Communication between userspace and kernelspace goes over character
+ device using ioctl.
+
+ Usage:
+ mknod -m 666 /dev/dhahelper c 180 0
+
+ Also you can change the major number, setting the "dhahelper_major"
+ module parameter, the default is 180, specified in dhahelper.h.
+
+ Note: do not use other than minor==0, the module forbids it.
+
+ TODO:
+ * do memory mapping without fops:mmap
+ * implement unmap memory
+ * select (request?) a "valid" major number (from Linux project? ;)
+ * make security
+ * is pci handling needed? (libdha does this with lowlevel port funcs)
+ * is mttr handling needed?
+ * test on older kernels (2.0.x (?))
+*/
+
+#ifndef MODULE
+#define MODULE
+#endif
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <linux/config.h>
+
+#ifdef CONFIG_MODVERSION
+#define MODVERSION
+#include <linux/modversions.h>
+#endif
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+#include <linux/malloc.h>
+#else
+#include <linux/slab.h>
+#endif
+
+#include <linux/pci.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/io.h>
+
+#include <linux/mman.h>
+
+#include <linux/fs.h>
+#include <linux/unistd.h>
+
+#include "dhahelper.h"
+
+MODULE_AUTHOR("Alex Beregszaszi <alex@naxine.org>");
+MODULE_DESCRIPTION("Provides userspace access to hardware (security violation!)");
+#ifdef MODULE_LICENSE
+MODULE_LICENSE("GPL");
+#endif
+
+static int dhahelper_major = DEFAULT_MAJOR;
+MODULE_PARM(dhahelper_major, "i");
+MODULE_PARM_DESC(dhahelper_major, "Major number of dhahelper characterdevice");
+
+/* 0 = silent */
+/* 1 = report errors (default) */
+/* 2 = debug */
+static int dhahelper_verbosity = 1;
+MODULE_PARM(dhahelper_verbosity, "i");
+MODULE_PARM_DESC(dhahelper_verbosity, "Level of verbosity (0 = silent, 1 = only errors, 2 = debug)");
+
+static dhahelper_memory_t last_mem_request;
+
+
+static int dhahelper_open(struct inode *inode, struct file *file)
+{
+ if (dhahelper_verbosity > 1)
+ printk(KERN_DEBUG "dhahelper: device opened\n");
+
+ if (MINOR(inode->i_rdev) != 0)
+ return -ENXIO;
+
+ MOD_INC_USE_COUNT;
+
+ return 0;
+}
+
+static int dhahelper_release(struct inode *inode, struct file *file)
+{
+ if (dhahelper_verbosity > 1)
+ printk(KERN_DEBUG "dhahelper: device released\n");
+
+ if (MINOR(inode->i_rdev) != 0)
+ return -ENXIO;
+
+ MOD_DEC_USE_COUNT;
+
+ return 0;
+}
+
+static int dhahelper_get_version(int * arg)
+{
+ int version = API_VERSION;
+
+ if (copy_to_user(arg, &version, sizeof(int)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int dhahelper_port(dhahelper_port_t * arg)
+{
+ dhahelper_port_t port;
+ if (copy_from_user(&port, arg, sizeof(dhahelper_port_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ switch(port.operation)
+ {
+ case PORT_OP_READ:
+ {
+ switch(port.size)
+ {
+ case 1:
+ port.value = inb(port.addr);
+ break;
+ case 2:
+ port.value = inw(port.addr);
+ break;
+ case 4:
+ port.value = inl(port.addr);
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: invalid port read size (%d)\n",
+ port.size);
+ return -EINVAL;
+ }
+ break;
+ }
+ case PORT_OP_WRITE:
+ {
+ switch(port.size)
+ {
+ case 1:
+ outb(port.value, port.addr);
+ break;
+ case 2:
+ outw(port.value, port.addr);
+ break;
+ case 4:
+ outl(port.value, port.addr);
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: invalid port write size (%d)\n",
+ port.size);
+ return -EINVAL;
+ }
+ break;
+ }
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: invalid port operation (%d)\n",
+ port.operation);
+ return -EINVAL;
+ }
+ /* copy back only if read was performed */
+ if (port.operation == PORT_OP_READ)
+ if (copy_to_user(arg, &port, sizeof(dhahelper_port_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int dhahelper_memory(dhahelper_memory_t * arg)
+{
+ dhahelper_memory_t mem;
+ if (copy_from_user(&mem, arg, sizeof(dhahelper_memory_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ switch(mem.operation)
+ {
+ case MEMORY_OP_MAP:
+ {
+#if 1
+ memcpy(&last_mem_request, &mem, sizeof(dhahelper_memory_t));
+#else
+ mem.ret = do_mmap(file, mem.start, mem.size, PROT_READ|PROT_WRITE,
+ MAP_SHARED, mem.offset);
+#endif
+ break;
+ }
+ case MEMORY_OP_UNMAP:
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: invalid memory operation (%d)\n",
+ mem.operation);
+ return -EINVAL;
+ }
+ if (copy_to_user(arg, &mem, sizeof(dhahelper_memory_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int dhahelper_virt_to_phys(dhahelper_vmi_t *arg)
+{
+ dhahelper_vmi_t mem;
+ unsigned long i,nitems;
+ char *addr;
+ if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ nitems = mem.length / PAGE_SIZE;
+ if(mem.length % PAGE_SIZE) nitems++;
+ addr = mem.virtaddr;
+ for(i=0;i<nitems;i++)
+ {
+ unsigned long result;
+ result = virt_to_phys(addr);
+ if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ addr += PAGE_SIZE;
+ }
+ return 0;
+}
+
+static int dhahelper_virt_to_bus(dhahelper_vmi_t *arg)
+{
+ dhahelper_vmi_t mem;
+ unsigned long i,nitems;
+ char *addr;
+ if (copy_from_user(&mem, arg, sizeof(dhahelper_vmi_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ nitems = mem.length / PAGE_SIZE;
+ if(mem.length % PAGE_SIZE) nitems++;
+ addr = mem.virtaddr;
+ for(i=0;i<nitems;i++)
+ {
+ unsigned long result;
+ result = virt_to_bus(addr);
+ if (copy_to_user(&mem.realaddr[i], &result, sizeof(unsigned long)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ addr += PAGE_SIZE;
+ }
+ return 0;
+}
+
+static int dhahelper_ioctl(struct inode *inode, struct file *file,
+ unsigned int cmd, unsigned long arg)
+{
+ if (dhahelper_verbosity > 1)
+ printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
+ cmd, arg);
+
+ if (MINOR(inode->i_rdev) != 0)
+ return -ENXIO;
+
+ switch(cmd)
+ {
+ case DHAHELPER_GET_VERSION: return dhahelper_get_version((int *)arg);
+ case DHAHELPER_PORT: return dhahelper_port((dhahelper_port_t *)arg);
+ case DHAHELPER_MEMORY: return dhahelper_memory((dhahelper_memory_t *)arg);
+ case DHAHELPER_VIRT_TO_PHYS:return dhahelper_virt_to_phys((dhahelper_vmi_t *)arg);
+ case DHAHELPER_VIRT_TO_BUS: return dhahelper_virt_to_bus((dhahelper_vmi_t *)arg);
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int dhahelper_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ if (last_mem_request.operation != MEMORY_OP_MAP)
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: mapping not requested before mmap\n");
+ return -EFAULT;
+ }
+
+ if (dhahelper_verbosity > 1)
+ printk(KERN_INFO "dhahelper: mapping %x (size: %x)\n",
+ last_mem_request.start+last_mem_request.offset, last_mem_request.size);
+
+ if (remap_page_range(0, last_mem_request.start + last_mem_request.offset,
+ last_mem_request.size, vma->vm_page_prot))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: error mapping memory\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
+static struct file_operations dhahelper_fops =
+{
+ /*llseek*/ NULL,
+ /*read*/ NULL,
+ /*write*/ NULL,
+ /*readdir*/ NULL,
+ /*poll*/ NULL,
+ /*ioctl*/ dhahelper_ioctl,
+ /*mmap*/ dhahelper_mmap,
+ /*open*/ dhahelper_open,
+ /*flush*/ NULL,
+ /*release*/ dhahelper_release,
+ /* zero out the last 5 entries too ? */
+};
+#else
+static struct file_operations dhahelper_fops =
+{
+ owner: THIS_MODULE,
+ ioctl: dhahelper_ioctl,
+ mmap: dhahelper_mmap,
+ open: dhahelper_open,
+ release: dhahelper_release
+};
+#endif
+
+#if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
+int init_module(void)
+#else
+static int __init init_dhahelper(void)
+#endif
+{
+ printk(KERN_INFO "Direct Hardware Access kernel helper (C) Alex Beregszaszi\n");
+
+ if(register_chrdev(dhahelper_major, "dhahelper", &dhahelper_fops))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: unable to register character device (major: %d)\n",
+ dhahelper_major);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+#if KERNEL_VERSION < KERNEL_VERSION(2,4,0)
+void cleanup_module(void)
+#else
+static void __exit exit_dhahelper(void)
+#endif
+{
+ unregister_chrdev(dhahelper_major, "dhahelper");
+}
+
+EXPORT_NO_SYMBOLS;
+
+#if KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
+module_init(init_dhahelper);
+module_exit(exit_dhahelper);
+#endif
diff --git a/src/video_out/libdha/kernelhelper/dhahelper.h b/src/video_out/libdha/kernelhelper/dhahelper.h
new file mode 100644
index 000000000..2cbcb5550
--- /dev/null
+++ b/src/video_out/libdha/kernelhelper/dhahelper.h
@@ -0,0 +1,78 @@
+/*
+ Direct Hardware Access kernel helper
+
+ (C) 2002 Alex Beregszaszi <alex@naxine.org>
+*/
+
+#ifndef DHAHELPER_H
+#define DHAHELPER_H
+
+#include <linux/ioctl.h>
+
+/* feel free to change */
+#define DEFAULT_MAJOR 180
+
+#define API_VERSION 0x2
+
+typedef struct dhahelper_port_s
+{
+#define PORT_OP_READ 1
+#define PORT_OP_WRITE 2
+ int operation;
+ int size;
+ int addr;
+ int value;
+} dhahelper_port_t;
+
+typedef struct dhahelper_memory_s
+{
+#define MEMORY_OP_MAP 1
+#define MEMORY_OP_UNMAP 2
+ int operation;
+ int start;
+ int offset;
+ int size;
+ int ret;
+#define MEMORY_FLAG_NOCACHE 1
+ int flags;
+} dhahelper_memory_t;
+
+typedef struct dhahelper_mtrr_s
+{
+#define MTRR_OP_ADD 1
+#define MTRR_OP_DEL 2
+ int operation;
+ int start;
+ int size;
+ int type;
+} dhahelper_mtrr_t;
+
+typedef struct dhahelper_pci_s
+{
+#define PCI_OP_READ 1
+#define PCI_OP_WRITE 1
+ int operation;
+ int bus;
+ int dev;
+ int func;
+ int cmd;
+ int size;
+ int ret;
+} dhahelper_pci_t;
+
+typedef struct dhahelper_vmi_s
+{
+ void * virtaddr;
+ unsigned long length;
+ unsigned long *realaddr;
+}dhahelper_vmi_t;
+
+#define DHAHELPER_GET_VERSION _IOW('D', 0, int)
+#define DHAHELPER_PORT _IOWR('D', 1, dhahelper_port_t)
+#define DHAHELPER_MEMORY _IOWR('D', 2, dhahelper_memory_t)
+#define DHAHELPER_MTRR _IOWR('D', 3, dhahelper_mtrr_t)
+#define DHAHELPER_PCI _IOWR('D', 4, dhahelper_pci_t)
+#define DHAHELPER_VIRT_TO_PHYS _IOWR('D', 5, dhahelper_vmi_t)
+#define DHAHELPER_VIRT_TO_BUS _IOWR('D', 6, dhahelper_vmi_t)
+
+#endif /* DHAHELPER_H */
diff --git a/src/video_out/libdha/kernelhelper/test.c b/src/video_out/libdha/kernelhelper/test.c
new file mode 100644
index 000000000..3dca94c74
--- /dev/null
+++ b/src/video_out/libdha/kernelhelper/test.c
@@ -0,0 +1,60 @@
+#include <string.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+
+#include "dhahelper.h"
+
+int main(int argc, char *argv[])
+{
+ int fd;
+ int ret;
+
+ fd = open("/dev/dhahelper", O_RDWR);
+
+ ioctl(fd, DHAHELPER_GET_VERSION, &ret);
+
+ printf("api version: %d\n", ret);
+ if (ret != API_VERSION)
+ printf("incompatible api!\n");
+
+ {
+ dhahelper_memory_t mem;
+
+ mem.operation = MEMORY_OP_MAP;
+ //mem.start = 0xe0000000;
+ mem.start = 0xe4000008;
+ mem.offset = 0;
+ mem.size = 0x4000;
+ mem.ret = 0;
+
+ ret = ioctl(fd, DHAHELPER_MEMORY, &mem);
+
+ printf("ret: %s\n", strerror(errno));
+
+ mem.ret = (int)mmap(NULL, (size_t)mem.size, PROT_READ, MAP_SHARED, fd, (off_t)0);
+ printf("allocated to %x\n", mem.ret);
+
+ if (argc > 1)
+ if (mem.ret != 0)
+ {
+ int i;
+
+ for (i = 0; i < 256; i++)
+ printf("[%x] ", *(int *)(mem.ret+i));
+ printf("\n");
+ }
+
+ munmap((void *)mem.ret, mem.size);
+
+ mem.operation = MEMORY_OP_UNMAP;
+ mem.start = mem.ret;
+
+ ioctl(fd, DHAHELPER_MEMORY, &mem);
+ }
+
+ return(0);
+}