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; }