Re: Getting DMA and IRQ in userspace program

Rogier Wolff (
Fri, 11 Jul 1997 09:28:17 +0200 (MET DST)

Teunis Peters wrote:
> I suppose this is kind of a silly request, but I need access to hardware
> IRQ's (at least) if not also DMA on hardware devices.


I have written a device driver that gives you two possibilities to
use harware interrupts. First you can use use signals. You get a signal
when the interrupt occurs. This is most "interrupt-like".

If you want to simply block, waiting for interrupt, you can issue
a read from the interrupt device, which will block until the interrupt

Figure out the manual from the source.....

Anybody interested in this, I have no (longer any) use for this, so I
cannot really test it. It compiles though. :-)


* interrupt.c V0.2
* Copyright (C) by R.E.Wolff --
* This software may be used and distributed according to the terms
* of the GNU Public License, incorporated herein by reference.
* I prefer if you try to contact me if you have enhancements,
* instead of forking off a different branch.....
* date by what
* Written: Jul 11 1996 REW initial revision
* Changed: Jul 11 1997 REW Added blocking read functionality.
* who-is-who:
* initials full name Email address
* REW Roger E. Wolff
* /dev/irq<num> with major INT_MAJOR (currently default 61) and minor
* <num> allows a user process access to hardware interrupt <num>.
* Simply open the device to be notified of the occurrance of the
* interrupt. Close it when you are done.
* read/writes to the device will return EINVAL or something like
* that.....
* Open a file descriptor to this device. This will cause your program
* to recieve a SIGUSR1 whenever the interrupt occurs.

#include <linux/module.h>
#include <linux/errno.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/malloc.h>

#ifndef INT_MAJOR
#define INT_MAJOR 61

struct test {
int minor;
struct task_struct * ts;
int pid;

struct wait_queue *locks[16];

static int int_read(struct inode *inode, struct file *file, char *buf, int count)
int minor = MINOR(inode->i_rdev);

interruptible_sleep_on (& locks[minor & 0x0f]);
return count;

static void int_intr(int irq, void *dev_id, struct pt_regs *regs)
struct test *t = (struct test *) dev_id;

printk ("Got irq %d, minor = %d for process %d.\n",irq,t->minor,t->pid);
if (t->minor & 0x10) {
wake_up_interruptible (&locks[irq]);
} else {
send_sig(SIGALRM, t->ts, 1);

static int int_open(struct inode * inode, struct file * file)
int minor = MINOR(inode->i_rdev);
struct test *t;

pr_debug ("int_open called. Minor = %d.\n", minor);

t = kmalloc (sizeof (struct test), GFP_KERNEL);

t->pid = current-> pid;
t->minor = minor;
t->ts = current;
if (request_irq (minor, int_intr, SA_SHIRQ, "int", t)) {
return -EBUSY;

return 0;

static void int_release(struct inode * inode, struct file * file)
int minor = MINOR(inode->i_rdev);

free_irq (minor,current);

static struct file_operations int_fops = {
NULL, /* int_lseek */
int_read, /* int_read */
NULL, /* int_write */
NULL, /* int_readdir */
NULL, /* int_select */
NULL, /* int_ioctl */
NULL, /* int_mmap */
int_open, /* int_open */
int_release /* int_release */

#ifdef MODULE

int init_module (void)
if (register_chrdev(INT_MAJOR,"int",&int_fops)) {
printk("int: unable to get major %d\n", INT_MAJOR);
return -EIO;
printk ("int driver installed.\n");

return 0;

void cleanup_module(void)

/* Most modules don't check this it must be ok to continue anyway.... */
if (MOD_IN_USE) {
printk ("int module is still in use. Now what?\n");
/* return; */


printk ("int_cleanup: Bye bye...\n");
#warning I am not sure if you can compile this into the kernel.....
#warning For instance the initialization is never called....