diff -urN linux-2.6.6.orig/drivers/pci/proc.c linux-2.6.6.sigirq/drivers/pci/proc.c
--- linux-2.6.6.orig/drivers/pci/proc.c	2004-05-10 03:32:38.000000000 +0100
+++ linux-2.6.6.sigirq/drivers/pci/proc.c	2004-06-15 04:22:25.217724016 +0100
@@ -12,6 +12,7 @@
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
 #include <linux/smp_lock.h>
+#include <linux/interrupt.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -199,8 +200,43 @@
 struct pci_filp_private {
 	enum pci_mmap_state mmap_state;
 	int write_combine;
+	pid_t sigpid;
+	int signum;
+	void *sigptr;
 };
 
+#ifdef HAVE_PCI_MMAP
+static irqreturn_t user_irqhandler(int irq, void *p, struct pt_regs *regs)
+{
+	struct file *f = p;
+	struct inode *inode = f->f_dentry->d_inode;
+	struct pci_filp_private *fpriv = f->private_data;
+	const struct proc_dir_entry *dp = PDE(inode);
+	struct pci_dev *dev = dp->data;
+	struct task_struct *tsk;
+	static siginfo_t si;
+
+	read_lock(&tasklist_lock);
+
+	/* Serialised under tasklist_lock so can be static */
+	memset(&si, 0, sizeof(si));
+	si.si_signo = fpriv->signum;
+	si.si_code = irq;
+
+	if ( fpriv->sigpid ) {
+		tsk = find_task_by_pid(fpriv->sigpid);
+
+		if ( tsk )
+			send_sig_info(fpriv->signum, &si, tsk);
+		else
+			free_irq(dev->irq, p);
+	}
+
+	read_unlock(&tasklist_lock);
+	return IRQ_HANDLED;
+}
+#endif
+
 static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
 {
 	const struct proc_dir_entry *dp = PDE(inode);
@@ -216,6 +252,44 @@
 		break;
 
 #ifdef HAVE_PCI_MMAP
+	case PCIIOC_SIGIRQ: {
+		struct pci_sigirq t;
+
+		if (copy_from_user(&t, (void __user *)arg, sizeof(t)))
+			return -EFAULT;
+
+		if ( dev->irq == 0 ) {
+			ret = -ESRCH;
+			break;
+		}
+
+		/* This approach races between an IRQ happening on another
+		 * CPU, but the race is small, and the fix pointless?
+		 */
+		if ( fpriv->signum ) {
+			free_irq(dev->irq, file);
+			fpriv->sigpid = 0;
+			fpriv->signum = 0;
+			fpriv->sigptr = NULL;
+		}
+
+		if ( t.sig ) {
+			fpriv->sigpid = current->pid;
+			fpriv->signum = t.sig;
+			fpriv->sigptr = t.ptr;
+			ret = request_irq(dev->irq,
+					user_irqhandler,
+					0, "pci",
+					file);
+			if ( ret ) {
+				fpriv->signum = 0;
+				return -EIO;
+			}
+		}
+
+		break;
+	}
+
 	case PCIIOC_MMAP_IS_IO:
 		fpriv->mmap_state = pci_mmap_io;
 		break;
@@ -271,6 +345,9 @@
 
 	fpriv->mmap_state = pci_mmap_io;
 	fpriv->write_combine = 0;
+	fpriv->sigpid = 0;
+	fpriv->signum = 0;
+	fpriv->sigptr = NULL;
 
 	file->private_data = fpriv;
 
@@ -279,6 +356,12 @@
 
 static int proc_bus_pci_release(struct inode *inode, struct file *file)
 {
+	struct pci_filp_private *fpriv = file->private_data;
+	const struct proc_dir_entry *dp = PDE(inode);
+	struct pci_dev *dev = dp->data;
+
+	if ( fpriv->signum )
+		free_irq(dev->irq, file);
 	kfree(file->private_data);
 	file->private_data = NULL;
 
diff -urN linux-2.6.6.orig/include/linux/pci.h linux-2.6.6.sigirq/include/linux/pci.h
--- linux-2.6.6.orig/include/linux/pci.h	2004-05-10 03:32:29.000000000 +0100
+++ linux-2.6.6.sigirq/include/linux/pci.h	2004-06-15 04:22:32.166667616 +0100
@@ -411,6 +411,11 @@
 #define PCIIOC_MMAP_IS_IO	(PCIIOC_BASE | 0x01)	/* Set mmap state to I/O space. */
 #define PCIIOC_MMAP_IS_MEM	(PCIIOC_BASE | 0x02)	/* Set mmap state to MEM space. */
 #define PCIIOC_WRITE_COMBINE	(PCIIOC_BASE | 0x03)	/* Enable/disable write-combining. */
+#define PCIIOC_SIGIRQ		(PCIIOC_BASE | 0x04)	/* Send user-defined rtsignal for irqs */
+struct pci_sigirq {
+	int sig;
+	void *ptr;
+};
 
 #ifdef __KERNEL__
 
