unsigned int ao_readback[2];
};
+/*
+ * "instructions" read/write data in "one-shot" or "software-triggered"
+ * mode.
+ */
static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+ const struct cb_pcimdas_board *thisboard = comedi_board(dev);
+ struct cb_pcimdas_private *devpriv = dev->private;
+ int n, i;
+ unsigned int d;
+ unsigned int busy;
+ int chan = CR_CHAN(insn->chanspec);
+ unsigned short chanlims;
+ int maxchans;
+
+ /* only support sw initiated reads from a single channel */
+
+ /* check channel number */
+ if ((inb(devpriv->BADR3 + 2) & 0x20) == 0) /* differential mode */
+ maxchans = thisboard->ai_diff_chans;
+ else
+ maxchans = thisboard->ai_se_chans;
+
+ if (chan > (maxchans - 1))
+ return -ETIMEDOUT; /* *** Wrong error code. Fixme. */
+
+ /* configure for sw initiated read */
+ d = inb(devpriv->BADR3 + 5);
+ if ((d & 0x03) > 0) { /* only reset if needed. */
+ d = d & 0xfd;
+ outb(d, devpriv->BADR3 + 5);
+ }
+ outb(0x01, devpriv->BADR3 + 6); /* set bursting off, conversions on */
+ outb(0x00, devpriv->BADR3 + 7); /* set range to 10V. UP/BP is controlled by a switch on the board */
+
+ /*
+ * write channel limits to multiplexer, set Low (bits 0-3) and
+ * High (bits 4-7) channels to chan.
+ */
+ chanlims = chan | (chan << 4);
+ outb(chanlims, devpriv->BADR3 + 0);
+
+ /* convert n samples */
+ for (n = 0; n < insn->n; n++) {
+ /* trigger conversion */
+ outw(0, dev->iobase + 0);
+
+#define TIMEOUT 1000 /* typically takes 5 loops on a lightly loaded Pentium 100MHz, */
+ /* this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit. */
+
+ /* wait for conversion to end */
+ for (i = 0; i < TIMEOUT; i++) {
+ busy = inb(devpriv->BADR3 + 2) & 0x80;
+ if (!busy)
+ break;
+ }
+ if (i == TIMEOUT) {
+ printk("timeout\n");
+ return -ETIMEDOUT;
+ }
+ /* read data */
+ d = inw(dev->iobase + 0);
+
+ /* mangle the data as necessary */
+ /* d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. */
+
+ data[n] = d;
+ }
+
+ /* return the number of samples read/written */
+ return n;
+}
+
static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct cb_pcimdas_private *devpriv = dev->private;
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+
+ /* Writing a list of values to an AO channel is probably not
+ * very useful, but that's how the interface is defined. */
+ for (i = 0; i < insn->n; i++) {
+ switch (chan) {
+ case 0:
+ outw(data[i] & 0x0FFF, dev->iobase + DAC0_OFFSET);
+ break;
+ case 1:
+ outw(data[i] & 0x0FFF, dev->iobase + DAC1_OFFSET);
+ break;
+ default:
+ return -1;
+ }
+ devpriv->ao_readback[chan] = data[i];
+ }
+
+ /* return the number of samples read/written */
+ return i;
+}
+
+/* AO subdevices should have a read insn as well as a write insn.
+ * Usually this means copying a value stored in devpriv. */
static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data);
+ struct comedi_insn *insn, unsigned int *data)
+{
+ struct cb_pcimdas_private *devpriv = dev->private;
+ int i;
+ int chan = CR_CHAN(insn->chanspec);
+
+ for (i = 0; i < insn->n; i++)
+ data[i] = devpriv->ao_readback[chan];
+
+ return i;
+}
static struct pci_dev *cb_pcimdas_find_pci_dev(struct comedi_device *dev,
struct comedi_devconfig *it)
return NULL;
}
-/*
- * Attach is called by the Comedi core to configure the driver
- * for a particular board. If you specified a board_name array
- * in the driver structure, dev->board_ptr contains that
- * address.
- */
static int cb_pcimdas_attach(struct comedi_device *dev,
struct comedi_devconfig *it)
{
}
}
-/*
- * "instructions" read/write data in "one-shot" or "software-triggered"
- * mode.
- */
-static int cb_pcimdas_ai_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- const struct cb_pcimdas_board *thisboard = comedi_board(dev);
- struct cb_pcimdas_private *devpriv = dev->private;
- int n, i;
- unsigned int d;
- unsigned int busy;
- int chan = CR_CHAN(insn->chanspec);
- unsigned short chanlims;
- int maxchans;
-
- /* only support sw initiated reads from a single channel */
-
- /* check channel number */
- if ((inb(devpriv->BADR3 + 2) & 0x20) == 0) /* differential mode */
- maxchans = thisboard->ai_diff_chans;
- else
- maxchans = thisboard->ai_se_chans;
-
- if (chan > (maxchans - 1))
- return -ETIMEDOUT; /* *** Wrong error code. Fixme. */
-
- /* configure for sw initiated read */
- d = inb(devpriv->BADR3 + 5);
- if ((d & 0x03) > 0) { /* only reset if needed. */
- d = d & 0xfd;
- outb(d, devpriv->BADR3 + 5);
- }
- outb(0x01, devpriv->BADR3 + 6); /* set bursting off, conversions on */
- outb(0x00, devpriv->BADR3 + 7); /* set range to 10V. UP/BP is controlled by a switch on the board */
-
- /*
- * write channel limits to multiplexer, set Low (bits 0-3) and
- * High (bits 4-7) channels to chan.
- */
- chanlims = chan | (chan << 4);
- outb(chanlims, devpriv->BADR3 + 0);
-
- /* convert n samples */
- for (n = 0; n < insn->n; n++) {
- /* trigger conversion */
- outw(0, dev->iobase + 0);
-
-#define TIMEOUT 1000 /* typically takes 5 loops on a lightly loaded Pentium 100MHz, */
- /* this is likely to be 100 loops on a 2GHz machine, so set 1000 as the limit. */
-
- /* wait for conversion to end */
- for (i = 0; i < TIMEOUT; i++) {
- busy = inb(devpriv->BADR3 + 2) & 0x80;
- if (!busy)
- break;
- }
- if (i == TIMEOUT) {
- printk("timeout\n");
- return -ETIMEDOUT;
- }
- /* read data */
- d = inw(dev->iobase + 0);
-
- /* mangle the data as necessary */
- /* d ^= 1<<(thisboard->ai_bits-1); // 16 bit data from ADC, so no mangle needed. */
-
- data[n] = d;
- }
-
- /* return the number of samples read/written */
- return n;
-}
-
-static int cb_pcimdas_ao_winsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct cb_pcimdas_private *devpriv = dev->private;
- int i;
- int chan = CR_CHAN(insn->chanspec);
-
- /* Writing a list of values to an AO channel is probably not
- * very useful, but that's how the interface is defined. */
- for (i = 0; i < insn->n; i++) {
- switch (chan) {
- case 0:
- outw(data[i] & 0x0FFF, dev->iobase + DAC0_OFFSET);
- break;
- case 1:
- outw(data[i] & 0x0FFF, dev->iobase + DAC1_OFFSET);
- break;
- default:
- return -1;
- }
- devpriv->ao_readback[chan] = data[i];
- }
-
- /* return the number of samples read/written */
- return i;
-}
-
-/* AO subdevices should have a read insn as well as a write insn.
- * Usually this means copying a value stored in devpriv. */
-static int cb_pcimdas_ao_rinsn(struct comedi_device *dev,
- struct comedi_subdevice *s,
- struct comedi_insn *insn, unsigned int *data)
-{
- struct cb_pcimdas_private *devpriv = dev->private;
- int i;
- int chan = CR_CHAN(insn->chanspec);
-
- for (i = 0; i < insn->n; i++)
- data[i] = devpriv->ao_readback[chan];
-
- return i;
-}
-
static struct comedi_driver cb_pcimdas_driver = {
.driver_name = "cb_pcimdas",
.module = THIS_MODULE,