On moving the function into the driver proper, also check the device is asserting the shared interrupt line. This patch also fixes the interrupt handling for the digital input change-of-state interrupts. Signed-off-by: Chase Southwood <chase.southwood@xxxxxxxxx> Cc: Ian Abbott <abbotti@xxxxxxxxx> Cc: H Hartley Sweeten <hsweeten@xxxxxxxxxxxxxxxxxxx> --- .../comedi/drivers/addi-data/hwdrv_apci1564.c | 146 ------------------- drivers/staging/comedi/drivers/addi_apci_1564.c | 157 ++++++++++++++++++++- 2 files changed, 153 insertions(+), 150 deletions(-) diff --git a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c index 697ee76..ef419b4 100644 --- a/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c +++ b/drivers/staging/comedi/drivers/addi-data/hwdrv_apci1564.c @@ -357,149 +357,3 @@ static int apci1564_do_read(struct comedi_device *dev, *data = devpriv->do_int_type; return insn->n; } - -/* - * Interrupt handler for the interruptible digital inputs - */ -static void apci1564_interrupt(int irq, void *d) -{ - struct comedi_device *dev = d; - struct apci1564_private *devpriv = dev->private; - unsigned int ui_DO, ui_DI; - unsigned int ui_Timer; - unsigned int ui_C1, ui_C2, ui_C3, ui_C4; - unsigned int ul_Command2 = 0; - - ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG) & 0x01; - ui_DO = inl(devpriv->amcc_iobase + APCI1564_DO_IRQ_REG) & 0x01; - ui_Timer = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG) & 0x01; - ui_C1 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1; - ui_C2 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1; - ui_C3 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1; - ui_C4 = - inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1; - if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 - && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { - dev_err(dev->class_dev, "Interrupt from unknown source.\n"); - } - - if (ui_DI == 1) { - ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); - outl(0x0, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); - /* send signal to the sample */ - send_sig(SIGIO, devpriv->tsk_current, 0); - /* enable the interrupt */ - outl(ui_DI, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); - return; - } - - if (ui_DO == 1) { - /* Check for Digital Output interrupt Type */ - /* 1: VCC interrupt */ - /* 2: CC interrupt */ - devpriv->do_int_type = inl(devpriv->amcc_iobase + - APCI1564_DO_INT_STATUS_REG) & 0x3; - /* Disable the Interrupt */ - outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG); - - /* Sends signal to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - } - - if (ui_Timer == 1) { - devpriv->timer_select_mode = ADDIDATA_TIMER; - if (devpriv->timer_select_mode) { - - /* Disable Timer Interrupt */ - ul_Command2 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); - outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - - /* Enable Timer Interrupt */ - - outl(ul_Command2, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); - } - } - - if (ui_C1 == 1) { - devpriv->timer_select_mode = ADDIDATA_COUNTER; - if (devpriv->timer_select_mode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); - } - } - - if (ui_C2 == 1) { - devpriv->timer_select_mode = ADDIDATA_COUNTER; - if (devpriv->timer_select_mode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); - } - } - - if (ui_C3 == 1) { - devpriv->timer_select_mode = ADDIDATA_COUNTER; - if (devpriv->timer_select_mode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); - } - } - - if (ui_C4 == 1) { - devpriv->timer_select_mode = ADDIDATA_COUNTER; - if (devpriv->timer_select_mode) { - - /* Disable Counter Interrupt */ - ul_Command2 = - inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - outl(0x0, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - - /* Send a signal to from kernel to user space */ - send_sig(SIGIO, devpriv->tsk_current, 0); - - /* Enable Counter Interrupt */ - outl(ul_Command2, - dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); - } - } - return; -} diff --git a/drivers/staging/comedi/drivers/addi_apci_1564.c b/drivers/staging/comedi/drivers/addi_apci_1564.c index fec478c..f71ee02 100644 --- a/drivers/staging/comedi/drivers/addi_apci_1564.c +++ b/drivers/staging/comedi/drivers/addi_apci_1564.c @@ -3,6 +3,7 @@ #include "../comedidev.h" #include "comedi_fc.h" +#include "amcc_s5933.h" #include "addi-data/addi_common.h" @@ -51,10 +52,158 @@ static int apci1564_reset(struct comedi_device *dev) return 0; } -static irqreturn_t v_ADDI_Interrupt(int irq, void *d) +static irqreturn_t apci1564_interrupt(int irq, void *d) { - apci1564_interrupt(irq, d); - return IRQ_RETVAL(1); + struct comedi_device *dev = d; + struct apci1564_private *devpriv = dev->private; + struct comedi_subdevice *s = dev->read_subdev; + unsigned int ui_DO, ui_DI; + unsigned int ui_Timer; + unsigned int ui_C1, ui_C2, ui_C3, ui_C4; + unsigned int ul_Command2 = 0; + + /* check interrupt is from this device */ + if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) & + INTCSR_INTR_ASSERTED) == 0) + return IRQ_NONE; + + /* check which interrupt was triggered */ + ui_DI = inl(devpriv->amcc_iobase + APCI1564_DI_IRQ_REG) & + APCI1564_DI_INT_ENABLE; + ui_DO = inl(devpriv->amcc_iobase + APCI1564_DO_IRQ_REG) & 0x01; + ui_Timer = inl(devpriv->amcc_iobase + APCI1564_TIMER_IRQ_REG) & 0x01; + ui_C1 = + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER1)) & 0x1; + ui_C2 = + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER2)) & 0x1; + ui_C3 = + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER3)) & 0x1; + ui_C4 = + inl(dev->iobase + APCI1564_TCW_IRQ_REG(APCI1564_COUNTER4)) & 0x1; + if (ui_DI == 0 && ui_DO == 0 && ui_Timer == 0 && ui_C1 == 0 + && ui_C2 == 0 && ui_C3 == 0 && ui_C4 == 0) { + return IRQ_HANDLED; + } + + if (ui_DI) { + /* disable the interrupt */ + outl(ui_DI & APCI1564_DI_INT_DISABLE, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + + s->state = inl(dev->iobase + APCI1564_DI_INT_STATUS_REG) & 0xffff; + comedi_buf_put(s, s->state); + s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; + comedi_event(dev, s); + + /* enable the interrupt */ + outl(ui_DI, devpriv->amcc_iobase + APCI1564_DI_IRQ_REG); + } + + if (ui_DO == 1) { + /* Check for Digital Output interrupt Type */ + /* 1: VCC interrupt */ + /* 2: CC interrupt */ + devpriv->do_int_type = inl(devpriv->amcc_iobase + + APCI1564_DO_INT_STATUS_REG) & 0x3; + /* Disable the Interrupt */ + outl(0x0, devpriv->amcc_iobase + APCI1564_DO_INT_CTRL_REG); + + /* Sends signal to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + } + + if (ui_Timer == 1) { + devpriv->timer_select_mode = ADDIDATA_TIMER; + if (devpriv->timer_select_mode) { + + /* Disable Timer Interrupt */ + ul_Command2 = inl(devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + outl(0x0, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Timer Interrupt */ + + outl(ul_Command2, devpriv->amcc_iobase + APCI1564_TIMER_CTRL_REG); + } + } + + if (ui_C1 == 1) { + devpriv->timer_select_mode = ADDIDATA_COUNTER; + if (devpriv->timer_select_mode) { + + /* Disable Counter Interrupt */ + ul_Command2 = + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + outl(0x0, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Counter Interrupt */ + outl(ul_Command2, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER1)); + } + } + + if (ui_C2 == 1) { + devpriv->timer_select_mode = ADDIDATA_COUNTER; + if (devpriv->timer_select_mode) { + + /* Disable Counter Interrupt */ + ul_Command2 = + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + outl(0x0, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Counter Interrupt */ + outl(ul_Command2, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER2)); + } + } + + if (ui_C3 == 1) { + devpriv->timer_select_mode = ADDIDATA_COUNTER; + if (devpriv->timer_select_mode) { + + /* Disable Counter Interrupt */ + ul_Command2 = + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + outl(0x0, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Counter Interrupt */ + outl(ul_Command2, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER3)); + } + } + + if (ui_C4 == 1) { + devpriv->timer_select_mode = ADDIDATA_COUNTER; + if (devpriv->timer_select_mode) { + + /* Disable Counter Interrupt */ + ul_Command2 = + inl(dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + outl(0x0, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + + /* Send a signal to from kernel to user space */ + send_sig(SIGIO, devpriv->tsk_current, 0); + + /* Enable Counter Interrupt */ + outl(ul_Command2, + dev->iobase + APCI1564_TCW_CTRL_REG(APCI1564_COUNTER4)); + } + } + return IRQ_HANDLED; } static int apci1564_di_insn_bits(struct comedi_device *dev, @@ -295,7 +444,7 @@ static int apci1564_auto_attach(struct comedi_device *dev, apci1564_reset(dev); if (pcidev->irq > 0) { - ret = request_irq(pcidev->irq, v_ADDI_Interrupt, IRQF_SHARED, + ret = request_irq(pcidev->irq, apci1564_interrupt, IRQF_SHARED, dev->board_name, dev); if (ret == 0) dev->irq = pcidev->irq; -- 1.9.3 _______________________________________________ devel mailing list devel@xxxxxxxxxxxxxxxxxxxxxx http://driverdev.linuxdriverproject.org/mailman/listinfo/driverdev-devel