Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
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);
			}
		}
	}
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/* 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);
}
Exemplo n.º 6
0
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;
}