static irqreturn_t pc236_interrupt(int irq, void *d) { struct comedi_device *dev = d; struct comedi_subdevice *s = dev->read_subdev; bool handled; handled = pc236_intr_check(dev); if (dev->attached && handled) { comedi_buf_write_samples(s, &s->state, 1); comedi_handle_events(dev, s); } return IRQ_RETVAL(handled); }
void labpc_drain_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; int status; unsigned long flags; unsigned int max_points, num_points, residue, leftover; status = devpriv->stat1; flags = claim_dma_lock(); disable_dma(devpriv->dma_chan); /* clear flip-flop to make sure 2-byte registers for * count and address get set correctly */ clear_dma_ff(devpriv->dma_chan); /* figure out how many points to read */ max_points = devpriv->dma_transfer_size / sample_size; /* residue is the number of points left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ residue = get_dma_residue(devpriv->dma_chan) / sample_size; num_points = max_points - residue; if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_points) num_points = devpriv->count; /* figure out how many points will be stored next time */ leftover = 0; if (cmd->stop_src != TRIG_COUNT) { leftover = devpriv->dma_transfer_size / sample_size; } else if (devpriv->count > num_points) { leftover = devpriv->count - num_points; if (leftover > max_points) leftover = max_points; } comedi_buf_write_samples(s, devpriv->dma_buffer, num_points); if (cmd->stop_src == TRIG_COUNT) devpriv->count -= num_points; /* set address and count for next transfer */ set_dma_addr(devpriv->dma_chan, devpriv->dma_addr); set_dma_count(devpriv->dma_chan, leftover * sample_size); release_dma_lock(flags); }
static void usbduxsigma_ai_handle_urb(struct comedi_device *dev, struct comedi_subdevice *s, struct urb *urb) { struct usbduxsigma_private *devpriv = dev->private; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; uint32_t val; int ret; int i; if ((urb->actual_length > 0) && (urb->status != -EXDEV)) { devpriv->ai_counter--; if (devpriv->ai_counter == 0) { devpriv->ai_counter = devpriv->ai_timer; /* get the data from the USB bus and hand it over to comedi */ for (i = 0; i < cmd->chanlist_len; i++) { /* transfer data, note first byte is the DIO state */ val = be32_to_cpu(devpriv->in_buf[i+1]); val &= 0x00ffffff; /* strip status byte */ val ^= 0x00800000; /* convert to unsigned */ if (!comedi_buf_write_samples(s, &val, 1)) return; } if (cmd->stop_src == TRIG_COUNT && async->scans_done >= cmd->stop_arg) async->events |= COMEDI_CB_EOA; } } /* if command is still running, resubmit urb */ if (!(async->events & COMEDI_CB_CANCEL_MASK)) { urb->dev = comedi_to_usb_dev(dev); ret = usb_submit_urb(urb, GFP_ATOMIC); if (ret < 0) { dev_err(dev->class_dev, "urb resubmit failed (%d)\n", ret); if (ret == -EL2NSYNC) dev_err(dev->class_dev, "buggy USB host controller or bug in IRQ handler\n"); async->events |= COMEDI_CB_ERROR; } } }
void labpc_drain_dma(struct comedi_device *dev) { struct labpc_private *devpriv = dev->private; struct comedi_isadma_desc *desc = &devpriv->dma->desc[0]; struct comedi_subdevice *s = dev->read_subdev; struct comedi_async *async = s->async; struct comedi_cmd *cmd = &async->cmd; unsigned int max_samples = comedi_bytes_to_samples(s, desc->size); unsigned int residue; unsigned int nsamples; unsigned int leftover; /* * residue is the number of bytes left to be done on the dma * transfer. It should always be zero at this point unless * the stop_src is set to external triggering. */ residue = comedi_isadma_disable(desc->chan); /* * Figure out how many samples to read for this transfer and * how many will be stored for next time. */ nsamples = max_samples - comedi_bytes_to_samples(s, residue); if (cmd->stop_src == TRIG_COUNT) { if (devpriv->count <= nsamples) { nsamples = devpriv->count; leftover = 0; } else { leftover = devpriv->count - nsamples; if (leftover > max_samples) leftover = max_samples; } devpriv->count -= nsamples; } else { leftover = max_samples; } desc->size = comedi_samples_to_bytes(s, leftover); comedi_buf_write_samples(s, desc->virt_addr, nsamples); }
static void dio200_read_scan_intr(struct comedi_device *dev, struct comedi_subdevice *s, unsigned int triggered) { 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); } comedi_buf_write_samples(s, &val, 1); if (cmd->stop_src == TRIG_COUNT && s->async->scans_done >= cmd->stop_arg) s->async->events |= COMEDI_CB_EOA; }