static irqreturn_t apci1032_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct apci1032_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; unsigned int ctrl; /* check interrupt is from this device */ if ((inl(devpriv->amcc_iobase + AMCC_OP_REG_INTCSR) & INTCSR_INTR_ASSERTED) == 0) return IRQ_NONE; /* check interrupt is enabled */ ctrl = inl(dev->iobase + APCI1032_CTRL_REG); if ((ctrl & APCI1032_CTRL_INT_ENA) == 0) return IRQ_HANDLED; /* disable the interrupt */ outl(ctrl & ~APCI1032_CTRL_INT_ENA, dev->iobase + APCI1032_CTRL_REG); s->state = inl(dev->iobase + APCI1032_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(ctrl, dev->iobase + APCI1032_CTRL_REG); return IRQ_HANDLED; }
static irqreturn_t atmio16d_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = &dev->subdevices[0]; comedi_buf_put(s->async, inw(dev->iobase + AD_FIFO_REG)); comedi_event(dev, s); return IRQ_HANDLED; }
static void dio200_read_scan_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int triggered) { struct dio200_subdev_intr *subpriv = s->private; struct comedi_cmd *cmd = &s->async->cmd; unsigned short val; unsigned int n, ch; val = 0; for (n = 0; n < cmd->chanlist_len; n++) { ch = CR_CHAN(cmd->chanlist[n]); if (triggered & (1U << ch)) val |= (1U << n); } /* Write the scan to the buffer. */ if (comedi_buf_put(s, val)) { s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS); } else { /* Error! Stop acquisition. */ dio200_stop_intr(dev, s); s->async->events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW; dev_err(dev->class_dev, "buffer overflow\n"); } /* Check for end of acquisition. */ if (cmd->stop_src == TRIG_COUNT) { if (subpriv->stopcount > 0) { subpriv->stopcount--; if (subpriv->stopcount == 0) { s->async->events |= COMEDI_CB_EOA; dio200_stop_intr(dev, s); } } } }
static irqreturn_t nidio_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices; struct comedi_async *async = s->async; struct mite_struct *mite = devpriv->mite; long int AuxData = 0; short data1 = 0; short data2 = 0; int flags; int status; int work = 0; unsigned int m_status = 0; unsigned long irq_flags; if (dev->attached == 0) { return IRQ_NONE; } status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n", status, flags); ni_pcidio_print_flags(flags); ni_pcidio_print_status(status); spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); #ifdef MITE_DEBUG mite_print_chsr(m_status); #endif if (m_status & CHSR_INT) { if (m_status & CHSR_LINKC) { writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(devpriv->di_mite_chan->channel)); mite_sync_input_dma(devpriv->di_mite_chan, s->async); } if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | CHSR_DRQ1 | CHSR_MRDY)) { DPRINTK("unknown mite interrupt, disabling IRQ\n"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; disable_irq(dev->irq); } } spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); while (status & DataLeft) { work++; if (work > 20) { DPRINTK("too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); break; } flags &= IntEn; if (flags & TransferReady) { while (flags & TransferReady) { work++; if (work > 100) { DPRINTK("too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); goto out; } AuxData = readl(devpriv->mite->daq_io_addr + Group_1_FIFO); data1 = AuxData & 0xffff; data2 = (AuxData & 0xffff0000) >> 16; comedi_buf_put(async, data1); comedi_buf_put(async, data2); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); } async->events |= COMEDI_CB_BLOCK; } if (flags & CountExpired) { DPRINTK("CountExpired\n"); writeb(ClearExpired, devpriv->mite->daq_io_addr + Group_1_Second_Clear); async->events |= COMEDI_CB_EOA; writeb(0x00, devpriv->mite->daq_io_addr + OpMode); break; } else if (flags & Waited) { DPRINTK("Waited\n"); writeb(ClearWaited, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { DPRINTK("PrimaryTC\n"); writeb(ClearPrimaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } else if (flags & SecondaryTC) { DPRINTK("SecondaryTC\n"); writeb(ClearSecondaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } #if 0 else { printk("ni_pcidio: unknown interrupt\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); } #endif flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); } out: ni_pcidio_event(dev, s); #if 0 if (!tag) { writeb(0x03, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); } #endif return IRQ_HANDLED; }
/* analogue IN - interrupt service routine */ static void usbduxsub_ai_isoc_irq(struct urb *urb) { struct comedi_device *dev = urb->context; struct comedi_subdevice *s = dev->read_subdev; struct usbdux_private *devpriv = dev->private; int i, err, n; /* first we test if something unusual has just happened */ switch (urb->status) { case 0: /* copy the result in the transfer buffer */ memcpy(devpriv->in_buf, urb->transfer_buffer, SIZEINBUF); break; case -EILSEQ: /* error in the ISOchronous data */ /* we don't copy the data into the transfer buffer */ /* and recycle the last data byte */ dev_dbg(dev->class_dev, "CRC error in ISO IN stream\n"); break; case -ECONNRESET: case -ENOENT: case -ESHUTDOWN: case -ECONNABORTED: /* happens after an unlink command */ if (devpriv->ai_cmd_running) { s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* stop the transfer w/o unlink */ usbdux_ai_stop(dev, 0); } return; default: /* a real error on the bus */ /* pass error to comedi if we are really running a command */ if (devpriv->ai_cmd_running) { dev_err(dev->class_dev, "Non-zero urb status received in ai intr context: %d\n", urb->status); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* don't do an unlink here */ usbdux_ai_stop(dev, 0); } return; } /* * at this point we are reasonably sure that nothing dodgy has happened * are we running a command? */ if (unlikely(!devpriv->ai_cmd_running)) { /* * not running a command, do not continue execution if no * asynchronous command is running in particular not resubmit */ return; } urb->dev = comedi_to_usb_dev(dev); /* resubmit the urb */ err = usb_submit_urb(urb, GFP_ATOMIC); if (unlikely(err < 0)) { dev_err(dev->class_dev, "urb resubmit failed in int-context! err=%d\n", err); if (err == -EL2NSYNC) dev_err(dev->class_dev, "buggy USB host controller or bug in IRQ handler!\n"); s->async->events |= COMEDI_CB_EOA; s->async->events |= COMEDI_CB_ERROR; comedi_event(dev, s); /* don't do an unlink here */ usbdux_ai_stop(dev, 0); return; } devpriv->ai_counter--; if (likely(devpriv->ai_counter > 0)) return; /* timer zero, transfer measurements to comedi */ devpriv->ai_counter = devpriv->ai_timer; /* test, if we transmit only a fixed number of samples */ if (!devpriv->ai_continous) { /* not continuous, fixed number of samples */ devpriv->ai_sample_count--; /* all samples received? */ if (devpriv->ai_sample_count < 0) { /* prevent a resubmit next time */ usbdux_ai_stop(dev, 0); /* say comedi that the acquistion is over */ s->async->events |= COMEDI_CB_EOA; comedi_event(dev, s); return; } } /* get the data from the USB bus and hand it over to comedi */ n = s->async->cmd.chanlist_len; for (i = 0; i < n; i++) { unsigned int range = CR_RANGE(s->async->cmd.chanlist[i]); int16_t val = le16_to_cpu(devpriv->in_buf[i]); /* bipolar data is two's-complement */ if (comedi_range_is_bipolar(s, range)) val ^= ((s->maxdata + 1) >> 1); /* transfer data */ err = comedi_buf_put(s->async, val); if (unlikely(err == 0)) { /* buffer overflow */ usbdux_ai_stop(dev, 0); return; } } /* tell comedi that data is there */ s->async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS; comedi_event(dev, s); }
static irqreturn_t nidio_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->subdevices; struct comedi_async *async = s->async; struct mite_struct *mite = devpriv->mite; /* int i, j; */ long int AuxData = 0; short data1 = 0; short data2 = 0; int flags; int status; int work = 0; unsigned int m_status = 0; unsigned long irq_flags; /* interrupcions parasites */ if (dev->attached == 0) { /* assume it's from another card */ return IRQ_NONE; } status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); DPRINTK("ni_pcidio_interrupt: status=0x%02x,flags=0x%02x\n", status, flags); ni_pcidio_print_flags(flags); ni_pcidio_print_status(status); /* printk("buf[0]=%08x\n",*(unsigned int *)async->prealloc_buf); */ /* printk("buf[4096]=%08x\n", *(unsigned int *)(async->prealloc_buf+4096)); */ spin_lock_irqsave(&devpriv->mite_channel_lock, irq_flags); if (devpriv->di_mite_chan) m_status = mite_get_status(devpriv->di_mite_chan); #ifdef MITE_DEBUG mite_print_chsr(m_status); #endif /* printk("mite_bytes_transferred: %d\n", mite_bytes_transferred(mite,DI_DMA_CHAN)); */ /* mite_dump_regs(mite); */ if (m_status & CHSR_INT) { if (m_status & CHSR_LINKC) { writel(CHOR_CLRLC, mite->mite_io_addr + MITE_CHOR(devpriv->di_mite_chan->channel)); mite_sync_input_dma(devpriv->di_mite_chan, s->async); /* XXX need to byteswap */ } if (m_status & ~(CHSR_INT | CHSR_LINKC | CHSR_DONE | CHSR_DRDY | CHSR_DRQ1 | CHSR_MRDY)) { DPRINTK("unknown mite interrupt, disabling IRQ\n"); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; disable_irq(dev->irq); } } spin_unlock_irqrestore(&devpriv->mite_channel_lock, irq_flags); while (status & DataLeft) { work++; if (work > 20) { DPRINTK("too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); break; } flags &= IntEn; if (flags & TransferReady) { /* DPRINTK("TransferReady\n"); */ while (flags & TransferReady) { work++; if (work > 100) { DPRINTK("too much work in interrupt\n"); writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control ); goto out; } AuxData = readl(devpriv->mite->daq_io_addr + Group_1_FIFO); data1 = AuxData & 0xffff; data2 = (AuxData & 0xffff0000) >> 16; comedi_buf_put(async, data1); comedi_buf_put(async, data2); /* DPRINTK("read:%d, %d\n",data1,data2); */ flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); } /* DPRINTK("buf_int_count: %d\n", async->buf_int_count); */ /* DPRINTK("1) IntEn=%d,flags=%d,status=%d\n", IntEn,flags,status); */ /* ni_pcidio_print_flags(flags); */ /* ni_pcidio_print_status(status); */ async->events |= COMEDI_CB_BLOCK; } if (flags & CountExpired) { DPRINTK("CountExpired\n"); writeb(ClearExpired, devpriv->mite->daq_io_addr + Group_1_Second_Clear); async->events |= COMEDI_CB_EOA; writeb(0x00, devpriv->mite->daq_io_addr + OpMode); break; } else if (flags & Waited) { DPRINTK("Waited\n"); writeb(ClearWaited, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA | COMEDI_CB_ERROR; break; } else if (flags & PrimaryTC) { DPRINTK("PrimaryTC\n"); writeb(ClearPrimaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } else if (flags & SecondaryTC) { DPRINTK("SecondaryTC\n"); writeb(ClearSecondaryTC, devpriv->mite->daq_io_addr + Group_1_First_Clear); async->events |= COMEDI_CB_EOA; } #if 0 else { printk("ni_pcidio: unknown interrupt\n"); async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA; writeb(0x00, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); } #endif flags = readb(devpriv->mite->daq_io_addr + Group_1_Flags); status = readb(devpriv->mite->daq_io_addr + Interrupt_And_Window_Status); /* DPRINTK("loop end: IntEn=0x%02x,flags=0x%02x," "status=0x%02x\n", IntEn, flags, status); */ /* ni_pcidio_print_flags(flags); */ /* ni_pcidio_print_status(status); */ } out: ni_pcidio_event(dev, s); #if 0 if (!tag) { writeb(0x03, devpriv->mite->daq_io_addr + Master_DMA_And_Interrupt_Control); } #endif return IRQ_HANDLED; }