static int ni_pcidio_poll(struct comedi_device *dev, struct comedi_subdevice *s) { unsigned long irq_flags; int count; spin_lock_irqsave(&dev->spinlock, irq_flags); spin_lock(&devpriv->mite_channel_lock); if (devpriv->di_mite_chan) mite_sync_input_dma(devpriv->di_mite_chan, s->async); spin_unlock(&devpriv->mite_channel_lock); count = s->async->buf_write_count - s->async->buf_read_count; spin_unlock_irqrestore(&dev->spinlock, irq_flags); return count; }
void ni_tio_handle_interrupt(struct ni_gpct *counter, struct comedi_subdevice *s) { unsigned cidx = counter->counter_index; unsigned gpct_mite_status; unsigned long flags; int gate_error; int tc_error; int perm_stale_data; ni_tio_acknowledge_and_confirm(counter, &gate_error, &tc_error, &perm_stale_data, NULL); if (gate_error) { dev_notice(counter->counter_dev->dev->class_dev, "%s: Gi_Gate_Error detected.\n", __func__); s->async->events |= COMEDI_CB_OVERFLOW; } if (perm_stale_data) s->async->events |= COMEDI_CB_ERROR; switch (counter->counter_dev->variant) { case ni_gpct_variant_m_series: case ni_gpct_variant_660x: if (read_register(counter, NITIO_DMA_STATUS_REG(cidx)) & Gi_DRQ_Error_Bit) { dev_notice(counter->counter_dev->dev->class_dev, "%s: Gi_DRQ_Error detected.\n", __func__); s->async->events |= COMEDI_CB_OVERFLOW; } break; case ni_gpct_variant_e_series: break; } spin_lock_irqsave(&counter->lock, flags); if (counter->mite_chan == NULL) { spin_unlock_irqrestore(&counter->lock, flags); return; } gpct_mite_status = mite_get_status(counter->mite_chan); if (gpct_mite_status & CHSR_LINKC) { writel(CHOR_CLRLC, counter->mite_chan->mite->mite_io_addr + MITE_CHOR(counter->mite_chan->channel)); } mite_sync_input_dma(counter->mite_chan, s->async); spin_unlock_irqrestore(&counter->lock, flags); }
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; }
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; }