#include "../comedidev.h"
+#include "comedi_fc.h"
+
#define PCL726_AO_MSB_REG(x) (0x00 + ((x) * 2))
#define PCL726_AO_LSB_REG(x) (0x01 + ((x) * 2))
#define PCL726_DO_MSB_REG 0x0c
struct pcl726_private {
const struct comedi_lrange *rangelist[12];
unsigned int ao_readback[12];
+ unsigned int cmd_running:1;
};
+static int pcl818_intr_insn_bits(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_insn *insn,
+ unsigned int *data)
+{
+ data[1] = 0;
+ return insn->n;
+}
+
+static int pcl818_intr_cmdtest(struct comedi_device *dev,
+ struct comedi_subdevice *s,
+ struct comedi_cmd *cmd)
+{
+ int err = 0;
+
+ /* Step 1 : check if triggers are trivially valid */
+
+ err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW);
+ err |= cfc_check_trigger_src(&cmd->scan_begin_src, TRIG_EXT);
+ err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_FOLLOW);
+ err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
+ err |= cfc_check_trigger_src(&cmd->stop_src, TRIG_NONE);
+
+ if (err)
+ return 1;
+
+ /* Step 2a : make sure trigger sources are unique */
+ /* Step 2b : and mutually compatible */
+
+ if (err)
+ return 2;
+
+ /* Step 3: check if arguments are trivially valid */
+
+ err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_begin_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
+ err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, 1);
+ err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
+
+ if (err)
+ return 3;
+
+ /* step 4: ignored */
+
+ if (err)
+ return 4;
+
+ return 0;
+}
+
+static int pcl818_intr_cmd(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pcl726_private *devpriv = dev->private;
+
+ devpriv->cmd_running = 1;
+
+ return 0;
+}
+
+static int pcl818_intr_cancel(struct comedi_device *dev,
+ struct comedi_subdevice *s)
+{
+ struct pcl726_private *devpriv = dev->private;
+
+ devpriv->cmd_running = 0;
+
+ return 0;
+}
+
static irqreturn_t pcl818_interrupt(int irq, void *d)
{
+ struct comedi_device *dev = d;
+ struct comedi_subdevice *s = dev->read_subdev;
+ struct pcl726_private *devpriv = dev->private;
+
+ if (devpriv->cmd_running) {
+ pcl818_intr_cancel(dev, s);
+
+ comedi_buf_put(s->async, 0);
+ s->async->events |= (COMEDI_CB_BLOCK | COMEDI_CB_EOS);
+ comedi_event(dev, s);
+ }
+
return IRQ_HANDLED;
}
const struct pcl726_board *board = comedi_board(dev);
struct pcl726_private *devpriv;
struct comedi_subdevice *s;
+ int subdev;
int ret;
int i;
devpriv->rangelist[i] = &range_unknown;
}
- ret = comedi_alloc_subdevices(dev, board->have_dio ? 3 : 1);
+ subdev = board->have_dio ? 3 : 1;
+ if (dev->irq)
+ subdev++;
+ ret = comedi_alloc_subdevices(dev, subdev);
if (ret)
return ret;
+ subdev = 0;
+
/* Analog Output subdevice */
- s = &dev->subdevices[0];
+ s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_AO;
s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
s->n_chan = board->ao_nchan;
if (board->have_dio) {
/* Digital Input subdevice */
- s = &dev->subdevices[1];
+ s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_DI;
s->subdev_flags = SDF_READABLE;
s->n_chan = 16;
s->range_table = &range_digital;
/* Digital Output subdevice */
- s = &dev->subdevices[2];
+ s = &dev->subdevices[subdev++];
s->type = COMEDI_SUBD_DO;
s->subdev_flags = SDF_WRITABLE;
s->n_chan = 16;
s->range_table = &range_digital;
}
+ if (dev->irq) {
+ /* Digial Input subdevice - Interrupt support */
+ s = &dev->subdevices[subdev++];
+ dev->read_subdev = s;
+ s->type = COMEDI_SUBD_DI;
+ s->subdev_flags = SDF_READABLE | SDF_CMD_READ;
+ s->n_chan = 1;
+ s->maxdata = 1;
+ s->range_table = &range_digital;
+ s->insn_bits = pcl818_intr_insn_bits;
+ s->do_cmdtest = pcl818_intr_cmdtest;
+ s->do_cmd = pcl818_intr_cmd;
+ s->cancel = pcl818_intr_cancel;
+ }
+
return 0;
}