[Mplayer-cvslog] CVS: main/libdha/kernelhelper test.c,NONE,1.1 dhahelper.h,NONE,1.1 dhahelper.c,NONE,1.1
Alex Beregszaszi
alex at mplayer.dev.hu
Sat Feb 2 07:28:52 CET 2002
Update of /cvsroot/mplayer/main/libdha/kernelhelper
In directory mplayer:/var/tmp.root/cvs-serv15701
Added Files:
test.c dhahelper.h dhahelper.c
Log Message:
initial
--- NEW FILE ---
#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 %p\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);
}
}
--- NEW FILE ---
/*
Direct Hardware Access kernel helper
(C) 2002 Alex Beregszaszi <alex at naxine.org>
*/
#ifndef DHAHELPER_H
#define DHAHELPER_H
#include <linux/ioctl.h>
/* feel free to change */
#define DEFAULT_MAJOR 180
#define API_VERSION 0x1
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;
#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)
#endif /* DHAHELPER_H */
--- NEW FILE ---
/*
Direct Hardware Access kernel helper
(C) 2002 Alex Beregszaszi <alex at naxine.org>
Accessing hardware from userspace as USER (no root needed!)
WARNING!
Don't use this on a production system! Use only at home, on a
"single-user" Unix system.
Tech:
Communication between userspace and kernelspace is going trought
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 mappin without fops:mmap
* implement unmap memory
* select (request?) a "valid" major number
* make security
* is pci handling needed? (libdha does this with lowlevel port funcs)
* test on older kernels (2.0.x (?) and 2.2.x)
*/
#ifndef MODULE
#define MODULE
#endif
#ifndef __KERNEL__
#define __KERNEL__
#endif
#include <linux/config.h>
#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,10)
#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 at naxine.org>");
#ifdef MODULE_LICENSE
MODULE_LICENSE("GPL"); /* modulelicensesh*t */
#endif
static int dhahelper_major = DEFAULT_MAJOR;
MODULE_PARM(dhahelper_major, "i");
/* 0 = silent */
/* 1 = report errors (default) */
/* 2 = debug */
static int dhahelper_verbosity = 1;
MODULE_PARM(dhahelper_verbosity, "i");
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_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:
{
int version = API_VERSION;
if (copy_to_user((int *)arg, &version, sizeof(int)))
{
if (dhahelper_verbosity > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return(-EFAULT);
}
break;
}
case DHAHELPER_PORT:
{
dhahelper_port_t port;
if (copy_from_user(&port, (dhahelper_port_t *)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((dhahelper_port_t *)arg, &port, sizeof(dhahelper_port_t)))
{
if (dhahelper_verbosity > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return(-EFAULT);
}
break;
}
case DHAHELPER_MEMORY:
{
dhahelper_memory_t mem;
if (copy_from_user(&mem, (dhahelper_memory_t *)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:
{
memcpy(&last_mem_request, &mem, sizeof(dhahelper_memory_t));
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((dhahelper_memory_t *)arg, &mem, sizeof(dhahelper_memory_t)))
{
if (dhahelper_verbosity > 0)
printk(KERN_ERR "dhahelper: failed copy to userspace\n");
return(-EFAULT);
}
break;
}
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
static int __init init_dhahelper(void)
{
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);
}
static void __exit exit_dhahelper(void)
{
unregister_chrdev(dhahelper_major, "dhahelper");
}
EXPORT_NO_SYMBOLS;
module_init(init_dhahelper);
module_exit(exit_dhahelper);
More information about the MPlayer-cvslog
mailing list