Commit d6dc9aa6 authored by H Hartley Sweeten's avatar H Hartley Sweeten Committed by Greg Kroah-Hartman

staging: comedi: addi_apci_1500: handle shared interrupt

The interrupt used by this driver is shared. If the board did not cause
the interrupt the driver should return IRQ_NONE so that another driver
can handle it. Fix the interrupt handler so this happens.

Tidy up the interrupt handler a bit.
Signed-off-by: default avatarH Hartley Sweeten <hsweeten@visionengravers.com>
Reviewed-by: default avatarIan Abbott <abbotti@mev.co.uk>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent eae27ff7
...@@ -1483,115 +1483,104 @@ static irqreturn_t apci1500_interrupt(int irq, void *d) ...@@ -1483,115 +1483,104 @@ static irqreturn_t apci1500_interrupt(int irq, void *d)
struct comedi_device *dev = d; struct comedi_device *dev = d;
struct apci1500_private *devpriv = dev->private; struct apci1500_private *devpriv = dev->private;
unsigned int status; unsigned int val;
int i_RegValue = 0;
/* Clear the interrupt mask */ /* Clear the interrupt mask */
i_InterruptMask = 0; i_InterruptMask = 0;
/* Read the board interrupt status */ val = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
status = inl(devpriv->amcc + AMCC_OP_REG_INTCSR); if (!(val & INTCSR_INTR_ASSERTED))
return IRQ_NONE;
/* Test if board generated a interrupt */
if (status & INTCSR_INTR_ASSERTED) {
/* Disable all Interrupt */
/* Selects the master interrupt control register */
/* Disables the main interrupt on the board */
i_RegValue = z8536_read(dev,
APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
if ((i_RegValue & 0x60) == 0x60) {
/* Deletes the interrupt of port A */
i_RegValue = (i_RegValue & 0x0F) | 0x20;
z8536_write(dev, i_RegValue,
APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
i_InterruptMask = i_InterruptMask | 1;
if (i_Logic == APCI1500_OR_PRIORITY) {
i_RegValue = z8536_read(dev,
APCI1500_RW_PORT_A_SPECIFICATION);
i_RegValue = z8536_read(dev, /* Disable all Interrupt */
APCI1500_RW_PORT_A_INTERRUPT_CONTROL); /* Selects the master interrupt control register */
/* Disables the main interrupt on the board */
val = z8536_read(dev, APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
if ((val & 0x60) == 0x60) {
/* Deletes the interrupt of port A */
val &= 0x0f;
val |= 0x20;
z8536_write(dev, val, APCI1500_RW_PORT_A_COMMAND_AND_STATUS);
i_InterruptMask = i_InterruptMask | 1;
if (i_Logic == APCI1500_OR_PRIORITY) {
val = z8536_read(dev, APCI1500_RW_PORT_A_SPECIFICATION);
i_InputChannel = 1 + (i_RegValue >> 1); val = z8536_read(dev,
APCI1500_RW_PORT_A_INTERRUPT_CONTROL);
} else { i_InputChannel = 1 + (val >> 1);
i_InputChannel = 0;
}
}
i_RegValue = z8536_read(dev,
APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
if ((i_RegValue & 0x60) == 0x60) {
/* Deletes the interrupt of port B */
i_RegValue = (i_RegValue & 0x0F) | 0x20;
z8536_write(dev, i_RegValue,
APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
/* Reads port B */
i_RegValue = inb(dev->iobase +
APCI1500_Z8536_PORTB_REG);
i_RegValue = i_RegValue & 0xC0;
/* Tests if this is an external error */
if (i_RegValue) {
/* Disable the interrupt */
/* Selects the command and status register of port B */
outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR);
if (i_RegValue & 0x80) {
i_InterruptMask =
i_InterruptMask | 0x40;
}
if (i_RegValue & 0x40) { } else {
i_InterruptMask = i_InputChannel = 0;
i_InterruptMask | 0x80;
}
} else {
i_InterruptMask = i_InterruptMask | 2;
}
} }
}
i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS); val = z8536_read(dev, APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
if ((i_RegValue & 0x60) == 0x60) { if ((val & 0x60) == 0x60) {
/* Deletes the interrupt of timer 1 */ /* Deletes the interrupt of port B */
i_RegValue = (i_RegValue & 0x0F) | 0x20; val &= 0x0f;
z8536_write(dev, i_RegValue, val |= 0x20;
APCI1500_RW_CPT_TMR1_CMD_STATUS); z8536_write(dev, val, APCI1500_RW_PORT_B_COMMAND_AND_STATUS);
i_InterruptMask = i_InterruptMask | 4;
/* Reads port B */
val = inb(dev->iobase + APCI1500_Z8536_PORTB_REG);
val &= 0xc0;
/* Tests if this is an external error */
if (val) {
/* Disable the interrupt */
/* Selects the command and status register of port B */
outl(0x0, devpriv->amcc + AMCC_OP_REG_INTCSR);
if (val & 0x80)
i_InterruptMask |= 0x40;
if (val & 0x40) {
i_InterruptMask |= 0x80;
}
} else {
i_InterruptMask |= 0x02;
} }
}
i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS); val = z8536_read(dev, APCI1500_RW_CPT_TMR1_CMD_STATUS);
if ((i_RegValue & 0x60) == 0x60) { if ((val & 0x60) == 0x60) {
/* Deletes the interrupt of timer 2 */ /* Deletes the interrupt of timer 1 */
i_RegValue = (i_RegValue & 0x0F) | 0x20; val &= 0x0f;
z8536_write(dev, i_RegValue, val |= 0x20;
APCI1500_RW_CPT_TMR2_CMD_STATUS); z8536_write(dev, val, APCI1500_RW_CPT_TMR1_CMD_STATUS);
i_InterruptMask = i_InterruptMask | 8;
}
i_RegValue = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS); i_InterruptMask |= 0x04;
if ((i_RegValue & 0x60) == 0x60) { }
/* Deletes the interrupt of timer 3 */
i_RegValue = (i_RegValue & 0x0F) | 0x20;
z8536_write(dev, i_RegValue,
APCI1500_RW_CPT_TMR3_CMD_STATUS);
if (i_CounterLogic == APCI1500_COUNTER)
i_InterruptMask = i_InterruptMask | 0x10;
else
i_InterruptMask = i_InterruptMask | 0x20;
}
send_sig(SIGIO, devpriv->tsk_Current, 0); /* send signal to the sample */ val = z8536_read(dev, APCI1500_RW_CPT_TMR2_CMD_STATUS);
if ((val & 0x60) == 0x60) {
/* Deletes the interrupt of timer 2 */
val &= 0x0f;
val |= 0x20;
z8536_write(dev, val, APCI1500_RW_CPT_TMR2_CMD_STATUS);
/* Authorizes the main interrupt on the board */ i_InterruptMask |= 0x08;
z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL); }
} else {
dev_warn(dev->class_dev,
"Interrupt from unknown source\n");
val = z8536_read(dev, APCI1500_RW_CPT_TMR3_CMD_STATUS);
if ((val & 0x60) == 0x60) {
/* Deletes the interrupt of timer 3 */
val &= 0x0f;
val |= 0x20;
z8536_write(dev, val, APCI1500_RW_CPT_TMR3_CMD_STATUS);
if (i_CounterLogic == APCI1500_COUNTER)
i_InterruptMask |= 0x10;
else
i_InterruptMask |= 0x20;
} }
/* send signal to the sample */
send_sig(SIGIO, devpriv->tsk_Current, 0);
/* Authorizes the main interrupt on the board */
z8536_write(dev, 0xd0, APCI1500_RW_MASTER_INTERRUPT_CONTROL);
return IRQ_HANDLED; return IRQ_HANDLED;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment