2 comedi/drivers/cb_pcidas.c
4 Developed by Ivan Martinez and Frank Mori Hess, with valuable help from
5 David Schleef and the rest of the Comedi developers comunity.
7 Copyright (C) 2001-2003 Ivan Martinez <imr@oersted.dtu.dk>
8 Copyright (C) 2001,2002 Frank Mori Hess <fmhess@users.sourceforge.net>
10 COMEDI - Linux Control and Measurement Device Interface
11 Copyright (C) 1997-8 David A. Schleef <ds@schleef.org>
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
25 Description: MeasurementComputing PCI-DAS series
26 with the AMCC S5933 PCI controller
27 Author: Ivan Martinez <imr@oersted.dtu.dk>,
28 Frank Mori Hess <fmhess@users.sourceforge.net>
30 Devices: [Measurement Computing] PCI-DAS1602/16 (cb_pcidas),
31 PCI-DAS1602/16jr, PCI-DAS1602/12, PCI-DAS1200, PCI-DAS1200jr,
32 PCI-DAS1000, PCI-DAS1001, PCI_DAS1002
35 There are many reports of the driver being used with most of the
36 supported cards. Despite no detailed log is maintained, it can
37 be said that the driver is quite tested and stable.
39 The boards may be autocalibrated using the comedi_calibrate
42 Configuration options: not applicable, uses PCI auto config
44 For commands, the scanned channels must be consecutive
45 (i.e. 4-5-6-7, 2-3-4,...), and must all have the same
49 For start_src == TRIG_EXT, the A/D EXTERNAL TRIGGER IN (pin 45) is used.
50 For 1602 series, the start_arg is interpreted as follows:
51 start_arg == 0 => gated trigger (level high)
52 start_arg == CR_INVERT => gated trigger (level low)
53 start_arg == CR_EDGE => Rising edge
54 start_arg == CR_EDGE | CR_INVERT => Falling edge
55 For the other boards the trigger will be done on rising edge
61 analog triggering on 1602 series
64 #include <linux/module.h>
65 #include <linux/delay.h>
66 #include <linux/interrupt.h>
68 #include "../comedi_pci.h"
70 #include "comedi_8254.h"
72 #include "amcc_s5933.h"
74 #define AI_BUFFER_SIZE 1024 /* max ai fifo size */
75 #define AO_BUFFER_SIZE 1024 /* max ao fifo size */
76 #define NUM_CHANNELS_8800 8
77 #define NUM_CHANNELS_7376 1
78 #define NUM_CHANNELS_8402 2
79 #define NUM_CHANNELS_DAC08 1
81 /* Control/Status registers */
82 #define INT_ADCFIFO 0 /* INTERRUPT / ADC FIFO register */
83 #define INT_EOS 0x1 /* int end of scan */
84 #define INT_FHF 0x2 /* int fifo half full */
85 #define INT_FNE 0x3 /* int fifo not empty */
86 #define INT_MASK 0x3 /* mask of int select bits */
87 #define INTE 0x4 /* int enable */
88 #define DAHFIE 0x8 /* dac half full int enable */
89 #define EOAIE 0x10 /* end of acq. int enable */
90 #define DAHFI 0x20 /* dac half full status / clear */
91 #define EOAI 0x40 /* end of acq. int status / clear */
92 #define INT 0x80 /* int status / clear */
93 #define EOBI 0x200 /* end of burst int status */
94 #define ADHFI 0x400 /* half-full int status */
95 #define ADNEI 0x800 /* fifo not empty int status (latch) */
96 #define ADNE 0x1000 /* fifo not empty status (realtime) */
97 #define DAEMIE 0x1000 /* dac empty int enable */
98 #define LADFUL 0x2000 /* fifo overflow / clear */
99 #define DAEMI 0x4000 /* dac fifo empty int status / clear */
101 #define ADCMUX_CONT 2 /* ADC CHANNEL MUX AND CONTROL reg */
102 #define BEGIN_SCAN(x) ((x) & 0xf)
103 #define END_SCAN(x) (((x) & 0xf) << 4)
104 #define GAIN_BITS(x) (((x) & 0x3) << 8)
105 #define UNIP 0x800 /* Analog front-end unipolar mode */
106 #define SE 0x400 /* Inputs in single-ended mode */
107 #define PACER_MASK 0x3000 /* pacer source bits */
108 #define PACER_INT 0x1000 /* int. pacer */
109 #define PACER_EXT_FALL 0x2000 /* ext. falling edge */
110 #define PACER_EXT_RISE 0x3000 /* ext. rising edge */
111 #define EOC 0x4000 /* adc not busy */
113 #define TRIG_CONTSTAT 4 /* TRIGGER CONTROL/STATUS register */
114 #define SW_TRIGGER 0x1 /* software start trigger */
115 #define EXT_TRIGGER 0x2 /* ext. start trigger */
116 #define ANALOG_TRIGGER 0x3 /* ext. analog trigger */
117 #define TRIGGER_MASK 0x3 /* start trigger mask */
118 #define TGPOL 0x04 /* invert trigger (1602 only) */
119 #define TGSEL 0x08 /* edge/level trigerred (1602 only) */
120 #define TGEN 0x10 /* enable external start trigger */
121 #define BURSTE 0x20 /* burst mode enable */
122 #define XTRCL 0x80 /* clear external trigger */
124 #define CALIBRATION_REG 6 /* CALIBRATION register */
125 #define SELECT_8800_BIT 0x100 /* select 8800 caldac */
126 #define SELECT_TRIMPOT_BIT 0x200 /* select ad7376 trim pot */
127 #define SELECT_DAC08_BIT 0x400 /* select dac08 caldac */
128 #define CAL_SRC_BITS(x) (((x) & 0x7) << 11)
129 #define CAL_EN_BIT 0x4000 /* calibration source enable */
130 #define SERIAL_DATA_IN_BIT 0x8000 /* serial data bit going to caldac */
132 #define DAC_CSR 0x8 /* dac control and status register */
133 #define DACEN 0x02 /* dac enable */
134 #define DAC_MODE_UPDATE_BOTH 0x80 /* update both dacs */
136 static inline unsigned int DAC_RANGE(unsigned int channel, unsigned int range)
138 return (range & 0x3) << (8 + 2 * (channel & 0x1));
141 static inline unsigned int DAC_RANGE_MASK(unsigned int channel)
143 return 0x3 << (8 + 2 * (channel & 0x1));
146 /* bits for 1602 series only */
147 #define DAC_EMPTY 0x1 /* fifo empty, read, write clear */
148 #define DAC_START 0x4 /* start/arm fifo operations */
149 #define DAC_PACER_MASK 0x18 /* bits that set pacer source */
150 #define DAC_PACER_INT 0x8 /* int. pacing */
151 #define DAC_PACER_EXT_FALL 0x10 /* ext. pacing, falling edge */
152 #define DAC_PACER_EXT_RISE 0x18 /* ext. pacing, rising edge */
154 static inline unsigned int DAC_CHAN_EN(unsigned int channel)
156 return 1 << (5 + (channel & 0x1)); /* enable channel 0 or 1 */
159 /* analog input fifo */
160 #define ADCDATA 0 /* ADC DATA register */
161 #define ADCFIFOCLR 2 /* ADC FIFO CLEAR */
163 /* pacer, counter, dio registers */
168 /* analog output registers for 100x, 1200 series */
169 static inline unsigned int DAC_DATA_REG(unsigned int channel)
171 return 2 * (channel & 0x1);
174 /* analog output registers for 1602 series*/
175 #define DACDATA 0 /* DAC DATA register */
176 #define DACFIFOCLR 2 /* DAC FIFO CLEAR */
178 #define IS_UNIPOLAR 0x4 /* unipolar range mask */
180 /* analog input ranges for most boards */
181 static const struct comedi_lrange cb_pcidas_ranges = {
194 /* pci-das1001 input ranges */
195 static const struct comedi_lrange cb_pcidas_alt_ranges = {
208 /* analog output ranges */
209 static const struct comedi_lrange cb_pcidas_ao_ranges = {
223 enum cb_pcidas_boardid {
228 BOARD_PCIDAS1602_16_JR,
234 struct cb_pcidas_board {
236 int ai_nchan; /* Inputs in single-ended mode */
237 int ai_bits; /* analog input resolution */
238 int ai_speed; /* fastest conversion period in ns */
239 int ao_nchan; /* number of analog out channels */
240 int has_ao_fifo; /* analog output has fifo */
241 int ao_scan_speed; /* analog output scan speed for 1602 series */
242 int fifo_size; /* number of samples fifo can hold */
243 const struct comedi_lrange *ranges;
244 enum trimpot_model trimpot;
245 unsigned has_dac08:1;
249 static const struct cb_pcidas_board cb_pcidas_boards[] = {
250 [BOARD_PCIDAS1602_16] = {
251 .name = "pci-das1602/16",
257 .ao_scan_speed = 10000,
259 .ranges = &cb_pcidas_ranges,
264 [BOARD_PCIDAS1200] = {
265 .name = "pci-das1200",
271 .ranges = &cb_pcidas_ranges,
274 [BOARD_PCIDAS1602_12] = {
275 .name = "pci-das1602/12",
281 .ao_scan_speed = 4000,
283 .ranges = &cb_pcidas_ranges,
287 [BOARD_PCIDAS1200_JR] = {
288 .name = "pci-das1200/jr",
293 .ranges = &cb_pcidas_ranges,
296 [BOARD_PCIDAS1602_16_JR] = {
297 .name = "pci-das1602/16/jr",
302 .ranges = &cb_pcidas_ranges,
307 [BOARD_PCIDAS1000] = {
308 .name = "pci-das1000",
313 .ranges = &cb_pcidas_ranges,
316 [BOARD_PCIDAS1001] = {
317 .name = "pci-das1001",
323 .ranges = &cb_pcidas_alt_ranges,
326 [BOARD_PCIDAS1002] = {
327 .name = "pci-das1002",
333 .ranges = &cb_pcidas_ranges,
338 struct cb_pcidas_private {
339 struct comedi_8254 *ao_pacer;
341 unsigned long s5933_config;
342 unsigned long control_status;
343 unsigned long adc_fifo;
344 unsigned long ao_registers;
345 /* bits to write to registers */
346 unsigned int adc_fifo_bits;
347 unsigned int s5933_intcsr_bits;
348 unsigned int ao_control_bits;
350 unsigned short ai_buffer[AI_BUFFER_SIZE];
351 unsigned short ao_buffer[AO_BUFFER_SIZE];
352 unsigned int calibration_source;
355 static inline unsigned int cal_enable_bits(struct comedi_device *dev)
357 struct cb_pcidas_private *devpriv = dev->private;
359 return CAL_EN_BIT | CAL_SRC_BITS(devpriv->calibration_source);
362 static int cb_pcidas_ai_eoc(struct comedi_device *dev,
363 struct comedi_subdevice *s,
364 struct comedi_insn *insn,
365 unsigned long context)
367 struct cb_pcidas_private *devpriv = dev->private;
370 status = inw(devpriv->control_status + ADCMUX_CONT);
376 static int cb_pcidas_ai_rinsn(struct comedi_device *dev,
377 struct comedi_subdevice *s,
378 struct comedi_insn *insn, unsigned int *data)
380 struct cb_pcidas_private *devpriv = dev->private;
381 unsigned int chan = CR_CHAN(insn->chanspec);
382 unsigned int range = CR_RANGE(insn->chanspec);
383 unsigned int aref = CR_AREF(insn->chanspec);
388 /* enable calibration input if appropriate */
389 if (insn->chanspec & CR_ALT_SOURCE) {
390 outw(cal_enable_bits(dev),
391 devpriv->control_status + CALIBRATION_REG);
394 outw(0, devpriv->control_status + CALIBRATION_REG);
397 /* set mux limits and gain */
398 bits = BEGIN_SCAN(chan) | END_SCAN(chan) | GAIN_BITS(range);
399 /* set unipolar/bipolar */
400 if (range & IS_UNIPOLAR)
402 /* set single-ended/differential */
403 if (aref != AREF_DIFF)
405 outw(bits, devpriv->control_status + ADCMUX_CONT);
408 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
410 /* convert n samples */
411 for (n = 0; n < insn->n; n++) {
412 /* trigger conversion */
413 outw(0, devpriv->adc_fifo + ADCDATA);
415 /* wait for conversion to end */
416 ret = comedi_timeout(dev, s, insn, cb_pcidas_ai_eoc, 0);
421 data[n] = inw(devpriv->adc_fifo + ADCDATA);
424 /* return the number of samples read/written */
428 static int ai_config_insn(struct comedi_device *dev, struct comedi_subdevice *s,
429 struct comedi_insn *insn, unsigned int *data)
431 struct cb_pcidas_private *devpriv = dev->private;
433 unsigned int source = data[1];
436 case INSN_CONFIG_ALT_SOURCE:
438 dev_err(dev->class_dev,
439 "invalid calibration source: %i\n",
443 devpriv->calibration_source = source;
451 /* analog output insn for pcidas-1000 and 1200 series */
452 static int cb_pcidas_ao_nofifo_winsn(struct comedi_device *dev,
453 struct comedi_subdevice *s,
454 struct comedi_insn *insn,
457 struct cb_pcidas_private *devpriv = dev->private;
458 unsigned int chan = CR_CHAN(insn->chanspec);
459 unsigned int range = CR_RANGE(insn->chanspec);
462 /* set channel and range */
463 spin_lock_irqsave(&dev->spinlock, flags);
464 devpriv->ao_control_bits &= (~DAC_MODE_UPDATE_BOTH &
465 ~DAC_RANGE_MASK(chan));
466 devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range));
467 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
468 spin_unlock_irqrestore(&dev->spinlock, flags);
470 /* remember value for readback */
471 s->readback[chan] = data[0];
474 outw(data[0], devpriv->ao_registers + DAC_DATA_REG(chan));
479 /* analog output insn for pcidas-1602 series */
480 static int cb_pcidas_ao_fifo_winsn(struct comedi_device *dev,
481 struct comedi_subdevice *s,
482 struct comedi_insn *insn, unsigned int *data)
484 struct cb_pcidas_private *devpriv = dev->private;
485 unsigned int chan = CR_CHAN(insn->chanspec);
486 unsigned int range = CR_RANGE(insn->chanspec);
490 outw(0, devpriv->ao_registers + DACFIFOCLR);
492 /* set channel and range */
493 spin_lock_irqsave(&dev->spinlock, flags);
494 devpriv->ao_control_bits &= (~DAC_CHAN_EN(0) & ~DAC_CHAN_EN(1) &
495 ~DAC_RANGE_MASK(chan) & ~DAC_PACER_MASK);
496 devpriv->ao_control_bits |= (DACEN | DAC_RANGE(chan, range) |
497 DAC_CHAN_EN(chan) | DAC_START);
498 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
499 spin_unlock_irqrestore(&dev->spinlock, flags);
501 /* remember value for readback */
502 s->readback[chan] = data[0];
505 outw(data[0], devpriv->ao_registers + DACDATA);
510 static int wait_for_nvram_ready(unsigned long s5933_base_addr)
512 static const int timeout = 1000;
515 for (i = 0; i < timeout; i++) {
516 if ((inb(s5933_base_addr +
517 AMCC_OP_REG_MCSR_NVCMD) & MCSR_NV_BUSY)
525 static int nvram_read(struct comedi_device *dev, unsigned int address,
528 struct cb_pcidas_private *devpriv = dev->private;
529 unsigned long iobase = devpriv->s5933_config;
531 if (wait_for_nvram_ready(iobase) < 0)
534 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_LOW_ADDR,
535 iobase + AMCC_OP_REG_MCSR_NVCMD);
536 outb(address & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
537 outb(MCSR_NV_ENABLE | MCSR_NV_LOAD_HIGH_ADDR,
538 iobase + AMCC_OP_REG_MCSR_NVCMD);
539 outb((address >> 8) & 0xff, iobase + AMCC_OP_REG_MCSR_NVDATA);
540 outb(MCSR_NV_ENABLE | MCSR_NV_READ, iobase + AMCC_OP_REG_MCSR_NVCMD);
542 if (wait_for_nvram_ready(iobase) < 0)
545 *data = inb(iobase + AMCC_OP_REG_MCSR_NVDATA);
550 static int eeprom_read_insn(struct comedi_device *dev,
551 struct comedi_subdevice *s,
552 struct comedi_insn *insn, unsigned int *data)
557 retval = nvram_read(dev, CR_CHAN(insn->chanspec), &nvram_data);
561 data[0] = nvram_data;
566 static void write_calibration_bitstream(struct comedi_device *dev,
567 unsigned int register_bits,
568 unsigned int bitstream,
569 unsigned int bitstream_length)
571 struct cb_pcidas_private *devpriv = dev->private;
572 static const int write_delay = 1;
575 for (bit = 1 << (bitstream_length - 1); bit; bit >>= 1) {
577 register_bits |= SERIAL_DATA_IN_BIT;
579 register_bits &= ~SERIAL_DATA_IN_BIT;
581 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
585 static void caldac_8800_write(struct comedi_device *dev,
586 unsigned int chan, uint8_t val)
588 struct cb_pcidas_private *devpriv = dev->private;
589 static const int bitstream_length = 11;
590 unsigned int bitstream = ((chan & 0x7) << 8) | val;
591 static const int caldac_8800_udelay = 1;
593 write_calibration_bitstream(dev, cal_enable_bits(dev), bitstream,
596 udelay(caldac_8800_udelay);
597 outw(cal_enable_bits(dev) | SELECT_8800_BIT,
598 devpriv->control_status + CALIBRATION_REG);
599 udelay(caldac_8800_udelay);
600 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
603 static int cb_pcidas_caldac_insn_write(struct comedi_device *dev,
604 struct comedi_subdevice *s,
605 struct comedi_insn *insn,
608 unsigned int chan = CR_CHAN(insn->chanspec);
611 unsigned int val = data[insn->n - 1];
613 if (s->readback[chan] != val) {
614 caldac_8800_write(dev, chan, val);
615 s->readback[chan] = val;
622 /* 1602/16 pregain offset */
623 static void dac08_write(struct comedi_device *dev, unsigned int value)
625 struct cb_pcidas_private *devpriv = dev->private;
628 value |= cal_enable_bits(dev);
630 /* latch the new value into the caldac */
631 outw(value, devpriv->control_status + CALIBRATION_REG);
633 outw(value | SELECT_DAC08_BIT,
634 devpriv->control_status + CALIBRATION_REG);
636 outw(value, devpriv->control_status + CALIBRATION_REG);
640 static int cb_pcidas_dac08_insn_write(struct comedi_device *dev,
641 struct comedi_subdevice *s,
642 struct comedi_insn *insn,
645 unsigned int chan = CR_CHAN(insn->chanspec);
648 unsigned int val = data[insn->n - 1];
650 if (s->readback[chan] != val) {
651 dac08_write(dev, val);
652 s->readback[chan] = val;
659 static int trimpot_7376_write(struct comedi_device *dev, uint8_t value)
661 struct cb_pcidas_private *devpriv = dev->private;
662 static const int bitstream_length = 7;
663 unsigned int bitstream = value & 0x7f;
664 unsigned int register_bits;
665 static const int ad7376_udelay = 1;
667 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
668 udelay(ad7376_udelay);
669 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
671 write_calibration_bitstream(dev, register_bits, bitstream,
674 udelay(ad7376_udelay);
675 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
682 * ch 1 : adc postgain offset */
683 static int trimpot_8402_write(struct comedi_device *dev, unsigned int channel,
686 struct cb_pcidas_private *devpriv = dev->private;
687 static const int bitstream_length = 10;
688 unsigned int bitstream = ((channel & 0x3) << 8) | (value & 0xff);
689 unsigned int register_bits;
690 static const int ad8402_udelay = 1;
692 register_bits = cal_enable_bits(dev) | SELECT_TRIMPOT_BIT;
693 udelay(ad8402_udelay);
694 outw(register_bits, devpriv->control_status + CALIBRATION_REG);
696 write_calibration_bitstream(dev, register_bits, bitstream,
699 udelay(ad8402_udelay);
700 outw(cal_enable_bits(dev), devpriv->control_status + CALIBRATION_REG);
705 static void cb_pcidas_trimpot_write(struct comedi_device *dev,
706 unsigned int chan, unsigned int val)
708 const struct cb_pcidas_board *board = dev->board_ptr;
710 switch (board->trimpot) {
712 trimpot_7376_write(dev, val);
715 trimpot_8402_write(dev, chan, val);
718 dev_err(dev->class_dev, "driver bug?\n");
723 static int cb_pcidas_trimpot_insn_write(struct comedi_device *dev,
724 struct comedi_subdevice *s,
725 struct comedi_insn *insn,
728 unsigned int chan = CR_CHAN(insn->chanspec);
731 unsigned int val = data[insn->n - 1];
733 if (s->readback[chan] != val) {
734 cb_pcidas_trimpot_write(dev, chan, val);
735 s->readback[chan] = val;
742 static int cb_pcidas_ai_check_chanlist(struct comedi_device *dev,
743 struct comedi_subdevice *s,
744 struct comedi_cmd *cmd)
746 unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
747 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
750 for (i = 1; i < cmd->chanlist_len; i++) {
751 unsigned int chan = CR_CHAN(cmd->chanlist[i]);
752 unsigned int range = CR_RANGE(cmd->chanlist[i]);
754 if (chan != (chan0 + i) % s->n_chan) {
755 dev_dbg(dev->class_dev,
756 "entries in chanlist must be consecutive channels, counting upwards\n");
760 if (range != range0) {
761 dev_dbg(dev->class_dev,
762 "entries in chanlist must all have the same gain\n");
769 static int cb_pcidas_ai_cmdtest(struct comedi_device *dev,
770 struct comedi_subdevice *s,
771 struct comedi_cmd *cmd)
773 const struct cb_pcidas_board *board = dev->board_ptr;
777 /* Step 1 : check if triggers are trivially valid */
779 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
780 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
781 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
782 err |= comedi_check_trigger_src(&cmd->convert_src,
783 TRIG_TIMER | TRIG_NOW | TRIG_EXT);
784 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
785 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
790 /* Step 2a : make sure trigger sources are unique */
792 err |= comedi_check_trigger_is_unique(cmd->start_src);
793 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
794 err |= comedi_check_trigger_is_unique(cmd->convert_src);
795 err |= comedi_check_trigger_is_unique(cmd->stop_src);
797 /* Step 2b : and mutually compatible */
799 if (cmd->scan_begin_src == TRIG_FOLLOW && cmd->convert_src == TRIG_NOW)
801 if (cmd->scan_begin_src != TRIG_FOLLOW && cmd->convert_src != TRIG_NOW)
803 if (cmd->start_src == TRIG_EXT &&
804 (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT))
810 /* Step 3: check if arguments are trivially valid */
812 switch (cmd->start_src) {
814 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
817 /* External trigger, only CR_EDGE and CR_INVERT flags allowed */
819 & (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) != 0) {
820 cmd->start_arg &= ~(CR_FLAGS_MASK &
821 ~(CR_EDGE | CR_INVERT));
824 if (!board->is_1602 && (cmd->start_arg & CR_INVERT)) {
825 cmd->start_arg &= (CR_FLAGS_MASK & ~CR_INVERT);
831 if (cmd->scan_begin_src == TRIG_TIMER) {
832 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
837 if (cmd->convert_src == TRIG_TIMER) {
838 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
842 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
845 if (cmd->stop_src == TRIG_COUNT)
846 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
848 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
853 /* step 4: fix up any arguments */
855 if (cmd->scan_begin_src == TRIG_TIMER) {
856 arg = cmd->scan_begin_arg;
857 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
858 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
860 if (cmd->convert_src == TRIG_TIMER) {
861 arg = cmd->convert_arg;
862 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
863 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
869 /* Step 5: check channel list if it exists */
870 if (cmd->chanlist && cmd->chanlist_len > 0)
871 err |= cb_pcidas_ai_check_chanlist(dev, s, cmd);
879 static int cb_pcidas_ai_cmd(struct comedi_device *dev,
880 struct comedi_subdevice *s)
882 const struct cb_pcidas_board *board = dev->board_ptr;
883 struct cb_pcidas_private *devpriv = dev->private;
884 struct comedi_async *async = s->async;
885 struct comedi_cmd *cmd = &async->cmd;
889 /* make sure CAL_EN_BIT is disabled */
890 outw(0, devpriv->control_status + CALIBRATION_REG);
891 /* initialize before settings pacer source and count values */
892 outw(0, devpriv->control_status + TRIG_CONTSTAT);
894 outw(0, devpriv->adc_fifo + ADCFIFOCLR);
896 /* set mux limits, gain and pacer source */
897 bits = BEGIN_SCAN(CR_CHAN(cmd->chanlist[0])) |
898 END_SCAN(CR_CHAN(cmd->chanlist[cmd->chanlist_len - 1])) |
899 GAIN_BITS(CR_RANGE(cmd->chanlist[0]));
900 /* set unipolar/bipolar */
901 if (CR_RANGE(cmd->chanlist[0]) & IS_UNIPOLAR)
903 /* set singleended/differential */
904 if (CR_AREF(cmd->chanlist[0]) != AREF_DIFF)
906 /* set pacer source */
907 if (cmd->convert_src == TRIG_EXT || cmd->scan_begin_src == TRIG_EXT)
908 bits |= PACER_EXT_RISE;
911 outw(bits, devpriv->control_status + ADCMUX_CONT);
914 if (cmd->scan_begin_src == TRIG_TIMER ||
915 cmd->convert_src == TRIG_TIMER) {
916 comedi_8254_update_divisors(dev->pacer);
917 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
920 /* enable interrupts */
921 spin_lock_irqsave(&dev->spinlock, flags);
922 devpriv->adc_fifo_bits |= INTE;
923 devpriv->adc_fifo_bits &= ~INT_MASK;
924 if (cmd->flags & CMDF_WAKE_EOS) {
925 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1) {
926 /* interrupt end of burst */
927 devpriv->adc_fifo_bits |= INT_EOS;
929 /* interrupt fifo not empty */
930 devpriv->adc_fifo_bits |= INT_FNE;
933 /* interrupt fifo half full */
934 devpriv->adc_fifo_bits |= INT_FHF;
937 /* enable (and clear) interrupts */
938 outw(devpriv->adc_fifo_bits | EOAI | INT | LADFUL,
939 devpriv->control_status + INT_ADCFIFO);
940 spin_unlock_irqrestore(&dev->spinlock, flags);
942 /* set start trigger and burst mode */
944 if (cmd->start_src == TRIG_NOW) {
946 } else { /* TRIG_EXT */
947 bits |= EXT_TRIGGER | TGEN | XTRCL;
948 if (board->is_1602) {
949 if (cmd->start_arg & CR_INVERT)
951 if (cmd->start_arg & CR_EDGE)
955 if (cmd->convert_src == TRIG_NOW && cmd->chanlist_len > 1)
957 outw(bits, devpriv->control_status + TRIG_CONTSTAT);
962 static int cb_pcidas_ao_check_chanlist(struct comedi_device *dev,
963 struct comedi_subdevice *s,
964 struct comedi_cmd *cmd)
966 unsigned int chan0 = CR_CHAN(cmd->chanlist[0]);
968 if (cmd->chanlist_len > 1) {
969 unsigned int chan1 = CR_CHAN(cmd->chanlist[1]);
971 if (chan0 != 0 || chan1 != 1) {
972 dev_dbg(dev->class_dev,
973 "channels must be ordered channel 0, channel 1 in chanlist\n");
981 static int cb_pcidas_ao_cmdtest(struct comedi_device *dev,
982 struct comedi_subdevice *s,
983 struct comedi_cmd *cmd)
985 const struct cb_pcidas_board *board = dev->board_ptr;
986 struct cb_pcidas_private *devpriv = dev->private;
989 /* Step 1 : check if triggers are trivially valid */
991 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT);
992 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
993 TRIG_TIMER | TRIG_EXT);
994 err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
995 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
996 err |= comedi_check_trigger_src(&cmd->stop_src, TRIG_COUNT | TRIG_NONE);
1001 /* Step 2a : make sure trigger sources are unique */
1003 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
1004 err |= comedi_check_trigger_is_unique(cmd->stop_src);
1006 /* Step 2b : and mutually compatible */
1011 /* Step 3: check if arguments are trivially valid */
1013 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
1015 if (cmd->scan_begin_src == TRIG_TIMER) {
1016 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg,
1017 board->ao_scan_speed);
1020 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
1023 if (cmd->stop_src == TRIG_COUNT)
1024 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
1025 else /* TRIG_NONE */
1026 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
1031 /* step 4: fix up any arguments */
1033 if (cmd->scan_begin_src == TRIG_TIMER) {
1034 unsigned int arg = cmd->scan_begin_arg;
1036 comedi_8254_cascade_ns_to_timer(devpriv->ao_pacer,
1038 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
1044 /* Step 5: check channel list if it exists */
1045 if (cmd->chanlist && cmd->chanlist_len > 0)
1046 err |= cb_pcidas_ao_check_chanlist(dev, s, cmd);
1054 /* cancel analog input command */
1055 static int cb_pcidas_cancel(struct comedi_device *dev,
1056 struct comedi_subdevice *s)
1058 struct cb_pcidas_private *devpriv = dev->private;
1059 unsigned long flags;
1061 spin_lock_irqsave(&dev->spinlock, flags);
1062 /* disable interrupts */
1063 devpriv->adc_fifo_bits &= ~INTE & ~EOAIE;
1064 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1065 spin_unlock_irqrestore(&dev->spinlock, flags);
1067 /* disable start trigger source and burst mode */
1068 outw(0, devpriv->control_status + TRIG_CONTSTAT);
1069 /* software pacer source */
1070 outw(0, devpriv->control_status + ADCMUX_CONT);
1075 static void cb_pcidas_ao_load_fifo(struct comedi_device *dev,
1076 struct comedi_subdevice *s,
1077 unsigned int nsamples)
1079 struct cb_pcidas_private *devpriv = dev->private;
1080 unsigned int nbytes;
1082 nsamples = comedi_nsamples_left(s, nsamples);
1083 nbytes = comedi_buf_read_samples(s, devpriv->ao_buffer, nsamples);
1085 nsamples = comedi_bytes_to_samples(s, nbytes);
1086 outsw(devpriv->ao_registers + DACDATA, devpriv->ao_buffer, nsamples);
1089 static int cb_pcidas_ao_inttrig(struct comedi_device *dev,
1090 struct comedi_subdevice *s,
1091 unsigned int trig_num)
1093 const struct cb_pcidas_board *board = dev->board_ptr;
1094 struct cb_pcidas_private *devpriv = dev->private;
1095 struct comedi_async *async = s->async;
1096 struct comedi_cmd *cmd = &async->cmd;
1097 unsigned long flags;
1099 if (trig_num != cmd->start_arg)
1102 cb_pcidas_ao_load_fifo(dev, s, board->fifo_size);
1104 /* enable dac half-full and empty interrupts */
1105 spin_lock_irqsave(&dev->spinlock, flags);
1106 devpriv->adc_fifo_bits |= DAEMIE | DAHFIE;
1108 /* enable and clear interrupts */
1109 outw(devpriv->adc_fifo_bits | DAEMI | DAHFI,
1110 devpriv->control_status + INT_ADCFIFO);
1113 devpriv->ao_control_bits |= DAC_START | DACEN | DAC_EMPTY;
1114 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1116 spin_unlock_irqrestore(&dev->spinlock, flags);
1118 async->inttrig = NULL;
1123 static int cb_pcidas_ao_cmd(struct comedi_device *dev,
1124 struct comedi_subdevice *s)
1126 struct cb_pcidas_private *devpriv = dev->private;
1127 struct comedi_async *async = s->async;
1128 struct comedi_cmd *cmd = &async->cmd;
1130 unsigned long flags;
1132 /* set channel limits, gain */
1133 spin_lock_irqsave(&dev->spinlock, flags);
1134 for (i = 0; i < cmd->chanlist_len; i++) {
1135 /* enable channel */
1136 devpriv->ao_control_bits |=
1137 DAC_CHAN_EN(CR_CHAN(cmd->chanlist[i]));
1139 devpriv->ao_control_bits |= DAC_RANGE(CR_CHAN(cmd->chanlist[i]),
1144 /* disable analog out before settings pacer source and count values */
1145 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1146 spin_unlock_irqrestore(&dev->spinlock, flags);
1149 outw(0, devpriv->ao_registers + DACFIFOCLR);
1152 if (cmd->scan_begin_src == TRIG_TIMER) {
1153 comedi_8254_update_divisors(devpriv->ao_pacer);
1154 comedi_8254_pacer_enable(devpriv->ao_pacer, 1, 2, true);
1157 /* set pacer source */
1158 spin_lock_irqsave(&dev->spinlock, flags);
1159 switch (cmd->scan_begin_src) {
1161 devpriv->ao_control_bits |= DAC_PACER_INT;
1164 devpriv->ao_control_bits |= DAC_PACER_EXT_RISE;
1167 spin_unlock_irqrestore(&dev->spinlock, flags);
1168 dev_err(dev->class_dev, "error setting dac pacer source\n");
1171 spin_unlock_irqrestore(&dev->spinlock, flags);
1173 async->inttrig = cb_pcidas_ao_inttrig;
1178 /* cancel analog output command */
1179 static int cb_pcidas_ao_cancel(struct comedi_device *dev,
1180 struct comedi_subdevice *s)
1182 struct cb_pcidas_private *devpriv = dev->private;
1183 unsigned long flags;
1185 spin_lock_irqsave(&dev->spinlock, flags);
1186 /* disable interrupts */
1187 devpriv->adc_fifo_bits &= ~DAHFIE & ~DAEMIE;
1188 outw(devpriv->adc_fifo_bits, devpriv->control_status + INT_ADCFIFO);
1190 /* disable output */
1191 devpriv->ao_control_bits &= ~DACEN & ~DAC_PACER_MASK;
1192 outw(devpriv->ao_control_bits, devpriv->control_status + DAC_CSR);
1193 spin_unlock_irqrestore(&dev->spinlock, flags);
1198 static void handle_ao_interrupt(struct comedi_device *dev, unsigned int status)
1200 const struct cb_pcidas_board *board = dev->board_ptr;
1201 struct cb_pcidas_private *devpriv = dev->private;
1202 struct comedi_subdevice *s = dev->write_subdev;
1203 struct comedi_async *async = s->async;
1204 struct comedi_cmd *cmd = &async->cmd;
1205 unsigned long flags;
1207 if (status & DAEMI) {
1208 /* clear dac empty interrupt latch */
1209 spin_lock_irqsave(&dev->spinlock, flags);
1210 outw(devpriv->adc_fifo_bits | DAEMI,
1211 devpriv->control_status + INT_ADCFIFO);
1212 spin_unlock_irqrestore(&dev->spinlock, flags);
1213 if (inw(devpriv->ao_registers + DAC_CSR) & DAC_EMPTY) {
1214 if (cmd->stop_src == TRIG_COUNT &&
1215 async->scans_done >= cmd->stop_arg) {
1216 async->events |= COMEDI_CB_EOA;
1218 dev_err(dev->class_dev, "dac fifo underflow\n");
1219 async->events |= COMEDI_CB_ERROR;
1222 } else if (status & DAHFI) {
1223 cb_pcidas_ao_load_fifo(dev, s, board->fifo_size / 2);
1225 /* clear half-full interrupt latch */
1226 spin_lock_irqsave(&dev->spinlock, flags);
1227 outw(devpriv->adc_fifo_bits | DAHFI,
1228 devpriv->control_status + INT_ADCFIFO);
1229 spin_unlock_irqrestore(&dev->spinlock, flags);
1232 comedi_handle_events(dev, s);
1235 static irqreturn_t cb_pcidas_interrupt(int irq, void *d)
1237 struct comedi_device *dev = (struct comedi_device *)d;
1238 const struct cb_pcidas_board *board = dev->board_ptr;
1239 struct cb_pcidas_private *devpriv = dev->private;
1240 struct comedi_subdevice *s = dev->read_subdev;
1241 struct comedi_async *async;
1242 struct comedi_cmd *cmd;
1243 int status, s5933_status;
1244 int half_fifo = board->fifo_size / 2;
1245 unsigned int num_samples, i;
1246 static const int timeout = 10000;
1247 unsigned long flags;
1255 s5933_status = inl(devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1257 if ((INTCSR_INTR_ASSERTED & s5933_status) == 0)
1260 /* make sure mailbox 4 is empty */
1261 inl_p(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1262 /* clear interrupt on amcc s5933 */
1263 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1264 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1266 status = inw(devpriv->control_status + INT_ADCFIFO);
1268 /* check for analog output interrupt */
1269 if (status & (DAHFI | DAEMI))
1270 handle_ao_interrupt(dev, status);
1271 /* check for analog input interrupts */
1272 /* if fifo half-full */
1273 if (status & ADHFI) {
1275 num_samples = comedi_nsamples_left(s, half_fifo);
1276 insw(devpriv->adc_fifo + ADCDATA, devpriv->ai_buffer,
1278 comedi_buf_write_samples(s, devpriv->ai_buffer, num_samples);
1280 if (cmd->stop_src == TRIG_COUNT &&
1281 async->scans_done >= cmd->stop_arg)
1282 async->events |= COMEDI_CB_EOA;
1284 /* clear half-full interrupt latch */
1285 spin_lock_irqsave(&dev->spinlock, flags);
1286 outw(devpriv->adc_fifo_bits | INT,
1287 devpriv->control_status + INT_ADCFIFO);
1288 spin_unlock_irqrestore(&dev->spinlock, flags);
1289 /* else if fifo not empty */
1290 } else if (status & (ADNEI | EOBI)) {
1291 for (i = 0; i < timeout; i++) {
1294 /* break if fifo is empty */
1295 if ((ADNE & inw(devpriv->control_status +
1298 val = inw(devpriv->adc_fifo);
1299 comedi_buf_write_samples(s, &val, 1);
1301 if (cmd->stop_src == TRIG_COUNT &&
1302 async->scans_done >= cmd->stop_arg) {
1303 async->events |= COMEDI_CB_EOA;
1307 /* clear not-empty interrupt latch */
1308 spin_lock_irqsave(&dev->spinlock, flags);
1309 outw(devpriv->adc_fifo_bits | INT,
1310 devpriv->control_status + INT_ADCFIFO);
1311 spin_unlock_irqrestore(&dev->spinlock, flags);
1312 } else if (status & EOAI) {
1313 dev_err(dev->class_dev,
1314 "bug! encountered end of acquisition interrupt?\n");
1315 /* clear EOA interrupt latch */
1316 spin_lock_irqsave(&dev->spinlock, flags);
1317 outw(devpriv->adc_fifo_bits | EOAI,
1318 devpriv->control_status + INT_ADCFIFO);
1319 spin_unlock_irqrestore(&dev->spinlock, flags);
1321 /* check for fifo overflow */
1322 if (status & LADFUL) {
1323 dev_err(dev->class_dev, "fifo overflow\n");
1324 /* clear overflow interrupt latch */
1325 spin_lock_irqsave(&dev->spinlock, flags);
1326 outw(devpriv->adc_fifo_bits | LADFUL,
1327 devpriv->control_status + INT_ADCFIFO);
1328 spin_unlock_irqrestore(&dev->spinlock, flags);
1329 async->events |= COMEDI_CB_ERROR;
1332 comedi_handle_events(dev, s);
1337 static int cb_pcidas_auto_attach(struct comedi_device *dev,
1338 unsigned long context)
1340 struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1341 const struct cb_pcidas_board *board = NULL;
1342 struct cb_pcidas_private *devpriv;
1343 struct comedi_subdevice *s;
1347 if (context < ARRAY_SIZE(cb_pcidas_boards))
1348 board = &cb_pcidas_boards[context];
1351 dev->board_ptr = board;
1352 dev->board_name = board->name;
1354 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1358 ret = comedi_pci_enable(dev);
1362 devpriv->s5933_config = pci_resource_start(pcidev, 0);
1363 devpriv->control_status = pci_resource_start(pcidev, 1);
1364 devpriv->adc_fifo = pci_resource_start(pcidev, 2);
1365 dev->iobase = pci_resource_start(pcidev, 3);
1366 if (board->ao_nchan)
1367 devpriv->ao_registers = pci_resource_start(pcidev, 4);
1369 /* disable and clear interrupts on amcc s5933 */
1370 outl(INTCSR_INBOX_INTR_STATUS,
1371 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1373 ret = request_irq(pcidev->irq, cb_pcidas_interrupt, IRQF_SHARED,
1374 dev->board_name, dev);
1376 dev_dbg(dev->class_dev, "unable to allocate irq %d\n",
1380 dev->irq = pcidev->irq;
1382 dev->pacer = comedi_8254_init(dev->iobase + ADC8254,
1383 I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1387 devpriv->ao_pacer = comedi_8254_init(dev->iobase + DAC8254,
1388 I8254_OSC_BASE_10MHZ,
1390 if (!devpriv->ao_pacer)
1393 ret = comedi_alloc_subdevices(dev, 7);
1397 s = &dev->subdevices[0];
1398 /* analog input subdevice */
1399 dev->read_subdev = s;
1400 s->type = COMEDI_SUBD_AI;
1401 s->subdev_flags = SDF_READABLE | SDF_GROUND | SDF_DIFF | SDF_CMD_READ;
1402 /* WARNING: Number of inputs in differential mode is ignored */
1403 s->n_chan = board->ai_nchan;
1404 s->len_chanlist = board->ai_nchan;
1405 s->maxdata = (1 << board->ai_bits) - 1;
1406 s->range_table = board->ranges;
1407 s->insn_read = cb_pcidas_ai_rinsn;
1408 s->insn_config = ai_config_insn;
1409 s->do_cmd = cb_pcidas_ai_cmd;
1410 s->do_cmdtest = cb_pcidas_ai_cmdtest;
1411 s->cancel = cb_pcidas_cancel;
1413 /* analog output subdevice */
1414 s = &dev->subdevices[1];
1415 if (board->ao_nchan) {
1416 s->type = COMEDI_SUBD_AO;
1417 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_GROUND;
1418 s->n_chan = board->ao_nchan;
1420 * analog out resolution is the same as
1421 * analog input resolution, so use ai_bits
1423 s->maxdata = (1 << board->ai_bits) - 1;
1424 s->range_table = &cb_pcidas_ao_ranges;
1425 /* default to no fifo (*insn_write) */
1426 s->insn_write = cb_pcidas_ao_nofifo_winsn;
1428 ret = comedi_alloc_subdev_readback(s);
1432 if (board->has_ao_fifo) {
1433 dev->write_subdev = s;
1434 s->subdev_flags |= SDF_CMD_WRITE;
1435 /* use fifo (*insn_write) instead */
1436 s->insn_write = cb_pcidas_ao_fifo_winsn;
1437 s->do_cmdtest = cb_pcidas_ao_cmdtest;
1438 s->do_cmd = cb_pcidas_ao_cmd;
1439 s->cancel = cb_pcidas_ao_cancel;
1442 s->type = COMEDI_SUBD_UNUSED;
1446 s = &dev->subdevices[2];
1447 ret = subdev_8255_init(dev, s, NULL, DIO_8255);
1451 /* serial EEPROM, */
1452 s = &dev->subdevices[3];
1453 s->type = COMEDI_SUBD_MEMORY;
1454 s->subdev_flags = SDF_READABLE | SDF_INTERNAL;
1457 s->insn_read = eeprom_read_insn;
1460 s = &dev->subdevices[4];
1461 s->type = COMEDI_SUBD_CALIB;
1462 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1463 s->n_chan = NUM_CHANNELS_8800;
1465 s->insn_write = cb_pcidas_caldac_insn_write;
1467 ret = comedi_alloc_subdev_readback(s);
1471 for (i = 0; i < s->n_chan; i++) {
1472 caldac_8800_write(dev, i, s->maxdata / 2);
1473 s->readback[i] = s->maxdata / 2;
1476 /* trim potentiometer */
1477 s = &dev->subdevices[5];
1478 s->type = COMEDI_SUBD_CALIB;
1479 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1480 if (board->trimpot == AD7376) {
1481 s->n_chan = NUM_CHANNELS_7376;
1484 s->n_chan = NUM_CHANNELS_8402;
1487 s->insn_write = cb_pcidas_trimpot_insn_write;
1489 ret = comedi_alloc_subdev_readback(s);
1493 for (i = 0; i < s->n_chan; i++) {
1494 cb_pcidas_trimpot_write(dev, i, s->maxdata / 2);
1495 s->readback[i] = s->maxdata / 2;
1499 s = &dev->subdevices[6];
1500 if (board->has_dac08) {
1501 s->type = COMEDI_SUBD_CALIB;
1502 s->subdev_flags = SDF_READABLE | SDF_WRITABLE | SDF_INTERNAL;
1503 s->n_chan = NUM_CHANNELS_DAC08;
1505 s->insn_write = cb_pcidas_dac08_insn_write;
1507 ret = comedi_alloc_subdev_readback(s);
1511 for (i = 0; i < s->n_chan; i++) {
1512 dac08_write(dev, s->maxdata / 2);
1513 s->readback[i] = s->maxdata / 2;
1516 s->type = COMEDI_SUBD_UNUSED;
1519 /* make sure mailbox 4 is empty */
1520 inl(devpriv->s5933_config + AMCC_OP_REG_IMB4);
1521 /* Set bits to enable incoming mailbox interrupts on amcc s5933. */
1522 devpriv->s5933_intcsr_bits =
1523 INTCSR_INBOX_BYTE(3) | INTCSR_INBOX_SELECT(3) |
1524 INTCSR_INBOX_FULL_INT;
1525 /* clear and enable interrupt on amcc s5933 */
1526 outl(devpriv->s5933_intcsr_bits | INTCSR_INBOX_INTR_STATUS,
1527 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1532 static void cb_pcidas_detach(struct comedi_device *dev)
1534 struct cb_pcidas_private *devpriv = dev->private;
1537 if (devpriv->s5933_config)
1538 outl(INTCSR_INBOX_INTR_STATUS,
1539 devpriv->s5933_config + AMCC_OP_REG_INTCSR);
1540 kfree(devpriv->ao_pacer);
1542 comedi_pci_detach(dev);
1545 static struct comedi_driver cb_pcidas_driver = {
1546 .driver_name = "cb_pcidas",
1547 .module = THIS_MODULE,
1548 .auto_attach = cb_pcidas_auto_attach,
1549 .detach = cb_pcidas_detach,
1552 static int cb_pcidas_pci_probe(struct pci_dev *dev,
1553 const struct pci_device_id *id)
1555 return comedi_pci_auto_config(dev, &cb_pcidas_driver,
1559 static const struct pci_device_id cb_pcidas_pci_table[] = {
1560 { PCI_VDEVICE(CB, 0x0001), BOARD_PCIDAS1602_16 },
1561 { PCI_VDEVICE(CB, 0x000f), BOARD_PCIDAS1200 },
1562 { PCI_VDEVICE(CB, 0x0010), BOARD_PCIDAS1602_12 },
1563 { PCI_VDEVICE(CB, 0x0019), BOARD_PCIDAS1200_JR },
1564 { PCI_VDEVICE(CB, 0x001c), BOARD_PCIDAS1602_16_JR },
1565 { PCI_VDEVICE(CB, 0x004c), BOARD_PCIDAS1000 },
1566 { PCI_VDEVICE(CB, 0x001a), BOARD_PCIDAS1001 },
1567 { PCI_VDEVICE(CB, 0x001b), BOARD_PCIDAS1002 },
1570 MODULE_DEVICE_TABLE(pci, cb_pcidas_pci_table);
1572 static struct pci_driver cb_pcidas_pci_driver = {
1573 .name = "cb_pcidas",
1574 .id_table = cb_pcidas_pci_table,
1575 .probe = cb_pcidas_pci_probe,
1576 .remove = comedi_pci_auto_unconfig,
1578 module_comedi_pci_driver(cb_pcidas_driver, cb_pcidas_pci_driver);
1580 MODULE_AUTHOR("Comedi http://www.comedi.org");
1581 MODULE_DESCRIPTION("Comedi low-level driver");
1582 MODULE_LICENSE("GPL");