|
@@ -437,6 +437,78 @@ static void apci3120_set_chanlist(struct comedi_device *dev,
|
|
|
|
|
|
#include "addi-data/hwdrv_apci3120.c"
|
|
#include "addi-data/hwdrv_apci3120.c"
|
|
|
|
|
|
|
|
+static irqreturn_t apci3120_interrupt(int irq, void *d)
|
|
|
|
+{
|
|
|
|
+ struct comedi_device *dev = d;
|
|
|
|
+ struct apci3120_private *devpriv = dev->private;
|
|
|
|
+ struct comedi_subdevice *s = dev->read_subdev;
|
|
|
|
+ struct comedi_async *async = s->async;
|
|
|
|
+ struct comedi_cmd *cmd = &async->cmd;
|
|
|
|
+ unsigned int status;
|
|
|
|
+ unsigned int int_amcc;
|
|
|
|
+
|
|
|
|
+ status = inw(dev->iobase + APCI3120_STATUS_REG);
|
|
|
|
+ int_amcc = inl(devpriv->amcc + AMCC_OP_REG_INTCSR);
|
|
|
|
+
|
|
|
|
+ if (!(status & APCI3120_STATUS_INT_MASK) &&
|
|
|
|
+ !(int_amcc & ANY_S593X_INT)) {
|
|
|
|
+ dev_err(dev->class_dev, "IRQ from unknown source\n");
|
|
|
|
+ return IRQ_NONE;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ outl(int_amcc | AINT_INT_MASK, devpriv->amcc + AMCC_OP_REG_INTCSR);
|
|
|
|
+
|
|
|
|
+ if (devpriv->ctrl & APCI3120_CTRL_EXT_TRIG)
|
|
|
|
+ apci3120_exttrig_enable(dev, false);
|
|
|
|
+
|
|
|
|
+ if (int_amcc & MASTER_ABORT_INT)
|
|
|
|
+ dev_err(dev->class_dev, "AMCC IRQ - MASTER DMA ABORT!\n");
|
|
|
|
+ if (int_amcc & TARGET_ABORT_INT)
|
|
|
|
+ dev_err(dev->class_dev, "AMCC IRQ - TARGET DMA ABORT!\n");
|
|
|
|
+
|
|
|
|
+ if ((status & APCI3120_STATUS_EOC_INT) == 0 &&
|
|
|
|
+ (devpriv->mode & APCI3120_MODE_EOC_IRQ_ENA)) {
|
|
|
|
+ /* nothing to do... EOC mode is not currently used */
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if ((status & APCI3120_STATUS_EOS_INT) &&
|
|
|
|
+ (devpriv->mode & APCI3120_MODE_EOS_IRQ_ENA)) {
|
|
|
|
+ unsigned short val;
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < cmd->chanlist_len; i++) {
|
|
|
|
+ val = inw(dev->iobase + APCI3120_AI_FIFO_REG);
|
|
|
|
+ comedi_buf_write_samples(s, &val, 1);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ devpriv->mode |= APCI3120_MODE_EOS_IRQ_ENA;
|
|
|
|
+ outb(devpriv->mode, dev->iobase + APCI3120_MODE_REG);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (status & APCI3120_STATUS_TIMER2_INT) {
|
|
|
|
+ /*
|
|
|
|
+ * for safety...
|
|
|
|
+ * timer2 interrupts are not enabled in the driver
|
|
|
|
+ */
|
|
|
|
+ apci3120_clr_timer2_interrupt(dev);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (status & APCI3120_STATUS_AMCC_INT) {
|
|
|
|
+ /* AMCC- Clear write complete interrupt (DMA) */
|
|
|
|
+ outl(AINT_WT_COMPLETE, devpriv->amcc + AMCC_OP_REG_INTCSR);
|
|
|
|
+
|
|
|
|
+ /* do some data transfer */
|
|
|
|
+ apci3120_interrupt_dma(irq, d);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg)
|
|
|
|
+ async->events |= COMEDI_CB_EOA;
|
|
|
|
+
|
|
|
|
+ comedi_handle_events(dev, s);
|
|
|
|
+
|
|
|
|
+ return IRQ_HANDLED;
|
|
|
|
+}
|
|
|
|
+
|
|
static int apci3120_ai_cmd(struct comedi_device *dev,
|
|
static int apci3120_ai_cmd(struct comedi_device *dev,
|
|
struct comedi_subdevice *s)
|
|
struct comedi_subdevice *s)
|
|
{
|
|
{
|