Messages in this thread | | | Subject | Re: Getting DMA and IRQ in userspace program | Date | Fri, 11 Jul 1997 09:28:17 +0200 (MET DST) | From | (Rogier Wolff) |
| |
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.
Hi,
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 occurs.
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. :-)
Roger.
/* * interrupt.c V0.2 * * Copyright (C) by R.E.Wolff -- R.E.Wolff@BitWizard.nl * * 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 R.E.Wolff@BitWizard.nl * * /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 #endif
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; }
MOD_INC_USE_COUNT; return 0; }
static void int_release(struct inode * inode, struct file * file) { int minor = MINOR(inode->i_rdev);
free_irq (minor,current); MOD_DEC_USE_COUNT; }
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; */ }
unregister_chrdev(INT_MAJOR,"int");
printk ("int_cleanup: Bye bye...\n"); } #else #warning I am not sure if you can compile this into the kernel..... #warning For instance the initialization is never called.... #endif
| |