[Linux-parport] Interrupt Sharing on PCIe
Robert Thomas Barrows
barrowsr at uwm.edu
Tue Jun 1 18:46:04 EDT 2010
If anyone on this list may be able to shed some light on where I am going wrong with this. Logic seems
sound and the code is (almost) functional. Just don't know what I am missing.
I have have been able to write code to service an interrupt on a machine with a built in parallel port.
This code also runs on a separate machine with a StarTech PEX1P PCIe Parallel Port Card with one key difference.
The PCIe card shares IRQ 16 with some real heavy hitters:
$ cat /proc/interrupts
CPU0 CPU1 CPU2 CPU3
edited ...
16: 103307 8887197 155256881 0 IO-APIC-fasteoi uhci_hcd:usb3, pata_jmicron, xhci_hcd:usb9, parport0
edited ...
I have tried forcing parport_pc to be IRQ 7 on boot with
options io=0xAF00 irq=7
but it seems the interrupts I generate still remain on IRQ 16, so I ditched that idea.
Then I thought that by setting the "handle" in parport_register_device I would be able to check that handle when an interrupt
happened to determine if it was from my device.
parport_register_device( ... , ... , ... , ... , irq_func irq, 0, void *handle);
Unfortunately it seems all interrupts on IRQ 16 then suddenly have this handle, even if I don't trigger any on the PCIe Parallel Port.
Meaning my interrupt services ALL of those interrupts listed in my /proc/interrupts
The question is am I doing this wrong or am I attempting something that isn't possible?
Is there an alternative solution, that maybe is radically different?
Thank you for your Time
-Robb
My makefile and code is as follows:
------------Makefile--------------------------------------------
obj-m := irqCatcher.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
default:
$(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
clean:
rm -f *.o *.ko Module.* *.mod.* *~ modules.order
------------Code: irqCatcher.c-----------------------------------
#include <linux/module.h>
#include <linux/parport.h>
#include <linux/init.h>
MODULE_AUTHOR("This Guy");
MODULE_DESCRIPTION("Driver to catch parallel port interupts.");
MODULE_LICENSE("GPL");
static unsigned int irqCatcher_pp_no;
module_param_named(port, irqCatcher_pp_no, int, 0);
MODULE_PARM_DESC(port, "Which parallel port number are we talking to (default is 0)");
static struct pardevice *irqCatcher_pardevice;
static struct parport *irqCatcher_parport;
int jInts;
int jNullInts;
static void irqCatcher_interrupt(void *handle)
{
struct parport *local_parport = handle;
if (local_parport->name != irqCatcher_parport->name) {
printk("%d Null Interrupts!\n", ++jNullInts);
return;
}
printk("local_parport->name: %s \n", local_parport->name);
printk("irqCatcher_pardevice->port->name: %s \n", irqCatcher_pardevice->port->name);
printk("Interupt Handled %d Times!\n", ++jInts);
}
static int irqCatcher_getport(void)
{
jInts = 0;
jNullInts = 0;
irqCatcher_parport = parport_find_number(irqCatcher_pp_no);
if (irqCatcher_parport == NULL) {
printk(KERN_ERR "irqCatcher: no such parport\n");
return -ENODEV;
}
//irqCatcher_pardevice = parport_register_device(irqCatcher_parport, "irqCatcher", NULL, NULL, irqCatcher_interrupt, PARPORT_DEV_EXCL, irqCatcher_parport);
irqCatcher_pardevice = parport_register_device(irqCatcher_parport, "irqCatcher", NULL, NULL, irqCatcher_interrupt, 0, irqCatcher_parport);
parport_put_port(irqCatcher_parport);
if (!irqCatcher_pardevice)
return -ENODEV;
if (parport_claim(irqCatcher_pardevice)) {
parport_unregister_device(irqCatcher_pardevice);
return -EBUSY;
}
printk("getport success!\n");
return 0;
}
static int __init irqCatcher_init(void)
{
int err;
printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
err = irqCatcher_getport();
if (err)
return err;
printk("Init Complete!\n");
parport_write_data(irqCatcher_pardevice->port, 0xFF);
msleep(1);
parport_write_data(irqCatcher_pardevice->port, 0x00);
msleep(1);
parport_write_data(irqCatcher_pardevice->port, 0xFF);
msleep(1);
parport_write_data(irqCatcher_pardevice->port, 0x00);
msleep(1);
return 0;
}
static void __exit irqCatcher_exit(void)
{
parport_release(irqCatcher_pardevice);
parport_unregister_device(irqCatcher_pardevice);
printk("Device removed!\n");
printk("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n");
}
module_init(irqCatcher_init);
module_exit(irqCatcher_exit);
More information about the Linux-parport
mailing list