[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