[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