summaryrefslogtreecommitdiff
path: root/src/video_out/libdha/kernelhelper/dhahelper.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_out/libdha/kernelhelper/dhahelper.c')
-rw-r--r--src/video_out/libdha/kernelhelper/dhahelper.c176
1 files changed, 169 insertions, 7 deletions
diff --git a/src/video_out/libdha/kernelhelper/dhahelper.c b/src/video_out/libdha/kernelhelper/dhahelper.c
index b438364d0..4f41dd9dd 100644
--- a/src/video_out/libdha/kernelhelper/dhahelper.c
+++ b/src/video_out/libdha/kernelhelper/dhahelper.c
@@ -2,7 +2,7 @@
Direct Hardware Access kernel helper
(C) 2002 Alex Beregszaszi <alex@naxine.org>
- (C) 2002 Nick Kurshev <nickols_k@mail.ru>
+ (C) 2002-2003 Nick Kurshev <nickols_k@mail.ru>
Accessing hardware from userspace as USER (no root needed!)
@@ -90,13 +90,25 @@
#include <linux/fs.h>
#include <linux/unistd.h>
+#ifdef CONFIG_MTRR
+#include <asm/mtrr.h>
+#endif
#ifdef CONFIG_DEVFS_FS
#include <linux/devfs_fs_kernel.h>
#endif
#include "dhahelper.h"
-MODULE_AUTHOR("Alex Beregszaszi <alex@naxine.org> and Nick Kurshev <nickols_k@mail.ru>");
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+#define DEV_MINOR(d) minor(d)
+#define pte_offset(p,a) pte_offset_kernel(p,a)
+#define LockPage(p) SetPageLocked(p)
+#define UnlockPage(p) ClearPageLocked(p)
+#else
+#define DEV_MINOR(d) MINOR(d)
+#endif
+
+MODULE_AUTHOR("Alex Beregszaszi <alex@naxine.org>, Nick Kurshev <nickols_k@mail.ru>, Måns Rullgård <mru@users.sf.net>");
MODULE_DESCRIPTION("Provides userspace access to hardware");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL");
@@ -118,10 +130,12 @@ 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)
+ if (DEV_MINOR(inode->i_rdev) != 0)
return -ENXIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
MOD_INC_USE_COUNT;
+#endif
return 0;
}
@@ -131,10 +145,12 @@ 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)
+ if (DEV_MINOR(inode->i_rdev) != 0)
return -ENXIO;
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,0)
MOD_DEC_USE_COUNT;
+#endif
return 0;
}
@@ -735,6 +751,140 @@ static int dhahelper_cpu_flush(dhahelper_cpu_flush_t *arg)
return 0;
}
+static struct pci_dev *pdev = NULL;
+static int dhahelper_pci_find(dhahelper_pci_device_t *arg)
+{
+ dhahelper_pci_device_t this_dev;
+ pdev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, pdev);
+ if(pdev)
+ {
+ this_dev.bus = pdev->bus->number;
+ this_dev.card = PCI_SLOT(pdev->devfn);
+ this_dev.func = PCI_FUNC(pdev->devfn);
+ this_dev.vendor = pdev->vendor;
+ this_dev.device = pdev->device;
+ this_dev.base0 = pci_resource_start (pdev, 0);
+ this_dev.base1 = pci_resource_start (pdev, 1);
+ this_dev.base2 = pci_resource_start (pdev, 2);
+ pci_read_config_dword(pdev, pdev->rom_base_reg, (u32*)&this_dev.baserom);
+ this_dev.base3 = pci_resource_start (pdev, 3);
+ this_dev.base4 = pci_resource_start (pdev, 4);
+ this_dev.base5 = pci_resource_start (pdev, 5);
+ pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &this_dev.irq);
+ pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &this_dev.ipin);
+ pci_read_config_byte(pdev, PCI_MIN_GNT, &this_dev.gnt);
+ pci_read_config_byte(pdev, PCI_MAX_LAT, &this_dev.lat);
+ }
+ else memset(&this_dev,0,sizeof(dhahelper_pci_device_t));
+ if (copy_to_user(arg, &this_dev, sizeof(dhahelper_pci_device_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ return pdev?0:-ENODATA;
+}
+
+static int dhahelper_pci_config(dhahelper_pci_config_t *arg)
+{
+ dhahelper_pci_config_t op;
+ struct pci_dev *pdev;
+ if (copy_from_user(&op, arg, sizeof(dhahelper_pci_config_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ pdev = pci_find_slot(op.bus,PCI_DEVFN(op.dev,op.func));
+ if(!pdev)
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: can't identify device\n");
+ return -EFAULT;
+ }
+ switch(op.operation)
+ {
+ case PCI_OP_READ:
+ switch(op.size)
+ {
+ case 1:
+ pci_read_config_byte(pdev,op.cmd,(u8*)&op.ret);
+ break;
+ case 2:
+ pci_read_config_word(pdev,op.cmd,(u16*)&op.ret);
+ break;
+ case 4:
+ pci_read_config_dword(pdev,op.cmd,(u32*)&op.ret);
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: wrong size of pci operation: %u \n",op.size);
+ return -EFAULT;
+ }
+ case PCI_OP_WRITE:
+ switch(op.size)
+ {
+ case 1:
+ pci_write_config_byte(pdev,op.cmd,op.ret);
+ break;
+ case 2:
+ pci_write_config_word(pdev,op.cmd,op.ret);
+ break;
+ case 4:
+ pci_write_config_dword(pdev,op.cmd,op.ret);
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: wrong size of pci operation: %u \n",op.size);
+ return -EFAULT;
+ }
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: unknown pci operation %i\n",op.operation);
+ return -EFAULT;
+ }
+ if (copy_to_user(arg, &op, sizeof(dhahelper_pci_device_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+static int dhahelper_mtrr(dhahelper_mtrr_t *arg)
+{
+#ifdef CONFIG_MTRR
+ dhahelper_mtrr_t op;
+ if (copy_from_user(&op, arg, sizeof(dhahelper_pci_config_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy from userspace\n");
+ return -EFAULT;
+ }
+ switch(op.operation)
+ {
+ case MTRR_OP_ADD:
+ op.privat = mtrr_add (op.start,op.size,op.type,1);
+ break;
+ case MTRR_OP_DEL:
+ mtrr_del(op.privat, op.start, op.size);
+ break;
+ default:
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: unknown mtrr operation %i\n",op.operation);
+ return -EFAULT;
+ }
+ if (copy_to_user(arg, &op, sizeof(dhahelper_mtrr_t)))
+ {
+ if (dhahelper_verbosity > 0)
+ printk(KERN_ERR "dhahelper: failed copy to userspace\n");
+ return -EFAULT;
+ }
+#endif
+ return 0;
+}
+
static int dhahelper_ioctl(struct inode *inode, struct file *file,
unsigned int cmd, unsigned long arg)
{
@@ -742,13 +892,15 @@ static int dhahelper_ioctl(struct inode *inode, struct file *file,
printk(KERN_DEBUG "dhahelper: ioctl(cmd=%x, arg=%lx)\n",
cmd, arg);
- if (MINOR(inode->i_rdev) != 0)
+ if (DEV_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_MTRR: return dhahelper_mtrr((dhahelper_mtrr_t *)arg);
+ case DHAHELPER_PCI_CONFIG: return dhahelper_pci_config((dhahelper_pci_config_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);
case DHAHELPER_ALLOC_PA:return dhahelper_alloc_pa((dhahelper_mem_t *)arg);
@@ -759,6 +911,7 @@ static int dhahelper_ioctl(struct inode *inode, struct file *file,
case DHAHELPER_ACK_IRQ: return dhahelper_ack_irq((dhahelper_irq_t *)arg);
case DHAHELPER_FREE_IRQ: return dhahelper_free_irq((dhahelper_irq_t *)arg);
case DHAHELPER_CPU_FLUSH: return dhahelper_cpu_flush((dhahelper_cpu_flush_t *)arg);
+ case DHAHELPER_PCI_FIND: return dhahelper_pci_find((dhahelper_pci_device_t *)arg);
default:
if (dhahelper_verbosity > 0)
printk(KERN_ERR "dhahelper: invalid ioctl (%x)\n", cmd);
@@ -927,6 +1080,7 @@ static inline int noncached_address(unsigned long addr)
static int dhahelper_mmap(struct file * file, struct vm_area_struct * vma)
{
unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
+ int err;
/*
* Accessing memory above the top the kernel knows about or
@@ -945,8 +1099,14 @@ static int dhahelper_mmap(struct file * file, struct vm_area_struct * vma)
if (offset >= __pa(high_memory) || (file->f_flags & O_SYNC))
vma->vm_flags |= VM_IO;
- if (remap_page_range(vma->vm_start, offset, vma->vm_end-vma->vm_start,
- vma->vm_page_prot))
+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
+ err = remap_page_range(vma, vma->vm_start, offset,
+ vma->vm_end-vma->vm_start, vma->vm_page_prot);
+#else
+ err = remap_page_range(vma->vm_start, offset,
+ vma->vm_end-vma->vm_start, vma->vm_page_prot);
+#endif
+ if(err)
return -EAGAIN;
return 0;
}
@@ -1035,7 +1195,9 @@ static void __exit exit_dhahelper(void)
#endif
}
+#ifdef EXPORT_NO_SYMBOLS
EXPORT_NO_SYMBOLS;
+#endif
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
module_init(init_dhahelper);