1 // SPDX-License-Identifier: GPL-2.0+
3 * Comedi driver for Keithley DAS-1700/DAS-1800 series boards
4 * Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
6 * COMEDI - Linux Control and Measurement Device Interface
7 * Copyright (C) 2000 David A. Schleef <ds@schleef.org>
12 * Description: Keithley Metrabyte DAS1800 (& compatibles)
13 * Author: Frank Mori Hess <fmhess@users.sourceforge.net>
14 * Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
15 * DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
16 * DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
17 * DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
18 * DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
19 * DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
20 * DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
21 * DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
22 * DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
23 * DAS-1802AO (das-1802ao)
26 * Configuration options:
27 * [0] - I/O port base address
28 * [1] - IRQ (optional, required for analog input cmd support)
29 * [2] - DMA0 (optional, requires irq)
30 * [3] - DMA1 (optional, requires irq and dma0)
32 * analog input cmd triggers supported:
34 * start_src TRIG_NOW command starts immediately
35 * TRIG_EXT command starts on external pin TGIN
37 * scan_begin_src TRIG_FOLLOW paced/external scans start immediately
38 * TRIG_TIMER burst scans start periodically
39 * TRIG_EXT burst scans start on external pin XPCLK
41 * scan_end_src TRIG_COUNT scan ends after last channel
43 * convert_src TRIG_TIMER paced/burst conversions are timed
44 * TRIG_EXT conversions on external pin XPCLK
45 * (requires scan_begin_src == TRIG_FOLLOW)
47 * stop_src TRIG_COUNT command stops after stop_arg scans
48 * TRIG_EXT command stops on external pin TGIN
49 * TRIG_NONE command runs until canceled
51 * If TRIG_EXT is used for both the start_src and stop_src, the first TGIN
52 * trigger starts the command, and the second trigger will stop it. If only
53 * one is TRIG_EXT, the first trigger will either stop or start the command.
54 * The external pin TGIN is normally set for negative edge triggering. It
55 * can be set to positive edge with the CR_INVERT flag. If TRIG_EXT is used
56 * for both the start_src and stop_src they must have the same polarity.
58 * Minimum conversion speed is limited to 64 microseconds (convert_arg <= 64000)
59 * for 'burst' scans. This limitation does not apply for 'paced' scans. The
60 * maximum conversion speed is limited by the board (convert_arg >= ai_speed).
61 * Maximum conversion speeds are not always achievable depending on the
62 * board setup (see user manual).
65 * Only the DAS-1801ST has been tested by me.
66 * Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
68 * The waveform analog output on the 'ao' cards is not supported.
69 * If you need it, send me (Frank Hess) an email.
72 #include <linux/module.h>
73 #include <linux/interrupt.h>
74 #include <linux/slab.h>
76 #include <linux/comedi/comedidev.h>
77 #include <linux/comedi/comedi_8254.h>
78 #include <linux/comedi/comedi_isadma.h>
81 #define DAS1800_SIZE 16 /* uses 16 io addresses */
82 #define FIFO_SIZE 1024 /* 1024 sample fifo */
83 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
85 /* Registers for the das1800 */
86 #define DAS1800_FIFO 0x0
87 #define DAS1800_QRAM 0x0
88 #define DAS1800_DAC 0x0
89 #define DAS1800_SELECT 0x2
92 #define DAC(a) (0x2 + a)
93 #define DAS1800_DIGITAL 0x3
94 #define DAS1800_CONTROL_A 0x4
102 #define DAS1800_CONTROL_B 0x5
106 #define DMA_CH5_CH6 0x5
107 #define DMA_CH6_CH7 0x6
108 #define DMA_CH7_CH5 0x7
109 #define DMA_ENABLED 0x3
118 #define DAS1800_CONTROL_C 0X6
126 #define DAS1800_STATUS 0x7
134 #define CVEN_MASK 0x40
135 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
136 #define DAS1800_BURST_LENGTH 0x8
137 #define DAS1800_BURST_RATE 0x9
138 #define DAS1800_QRAM_ADDRESS 0xa
139 #define DAS1800_COUNTER 0xc
141 #define IOBASE2 0x400
143 static const struct comedi_lrange das1801_ai_range = {
145 BIP_RANGE(5), /* bipolar gain = 1 */
146 BIP_RANGE(1), /* bipolar gain = 10 */
147 BIP_RANGE(0.1), /* bipolar gain = 50 */
148 BIP_RANGE(0.02), /* bipolar gain = 250 */
149 UNI_RANGE(5), /* unipolar gain = 1 */
150 UNI_RANGE(1), /* unipolar gain = 10 */
151 UNI_RANGE(0.1), /* unipolar gain = 50 */
152 UNI_RANGE(0.02) /* unipolar gain = 250 */
156 static const struct comedi_lrange das1802_ai_range = {
158 BIP_RANGE(10), /* bipolar gain = 1 */
159 BIP_RANGE(5), /* bipolar gain = 2 */
160 BIP_RANGE(2.5), /* bipolar gain = 4 */
161 BIP_RANGE(1.25), /* bipolar gain = 8 */
162 UNI_RANGE(10), /* unipolar gain = 1 */
163 UNI_RANGE(5), /* unipolar gain = 2 */
164 UNI_RANGE(2.5), /* unipolar gain = 4 */
165 UNI_RANGE(1.25) /* unipolar gain = 8 */
170 * The waveform analog outputs on the 'ao' boards are not currently
171 * supported. They have a comedi_lrange of:
172 * { 2, { BIP_RANGE(10), BIP_RANGE(5) } }
175 enum das1800_boardid {
196 /* board probe id values (hi byte of the digital input register) */
197 #define DAS1800_ID_ST_DA 0x3
198 #define DAS1800_ID_HR_DA 0x4
199 #define DAS1800_ID_AO 0x5
200 #define DAS1800_ID_HR 0x6
201 #define DAS1800_ID_ST 0x7
202 #define DAS1800_ID_HC 0x8
204 struct das1800_board {
207 unsigned int ai_speed;
208 unsigned int is_01_series:1;
211 static const struct das1800_board das1800_boards[] = {
212 [BOARD_DAS1701ST] = {
213 .name = "das-1701st",
218 [BOARD_DAS1701ST_DA] = {
219 .name = "das-1701st-da",
220 .id = DAS1800_ID_ST_DA,
224 [BOARD_DAS1702ST] = {
225 .name = "das-1702st",
229 [BOARD_DAS1702ST_DA] = {
230 .name = "das-1702st-da",
231 .id = DAS1800_ID_ST_DA,
234 [BOARD_DAS1702HR] = {
235 .name = "das-1702hr",
239 [BOARD_DAS1702HR_DA] = {
240 .name = "das-1702hr-da",
241 .id = DAS1800_ID_HR_DA,
244 [BOARD_DAS1701AO] = {
245 .name = "das-1701ao",
250 [BOARD_DAS1702AO] = {
251 .name = "das-1702ao",
255 [BOARD_DAS1801ST] = {
256 .name = "das-1801st",
261 [BOARD_DAS1801ST_DA] = {
262 .name = "das-1801st-da",
263 .id = DAS1800_ID_ST_DA,
267 [BOARD_DAS1802ST] = {
268 .name = "das-1802st",
272 [BOARD_DAS1802ST_DA] = {
273 .name = "das-1802st-da",
274 .id = DAS1800_ID_ST_DA,
277 [BOARD_DAS1802HR] = {
278 .name = "das-1802hr",
282 [BOARD_DAS1802HR_DA] = {
283 .name = "das-1802hr-da",
284 .id = DAS1800_ID_HR_DA,
287 [BOARD_DAS1801HC] = {
288 .name = "das-1801hc",
293 [BOARD_DAS1802HC] = {
294 .name = "das-1802hc",
298 [BOARD_DAS1801AO] = {
299 .name = "das-1801ao",
304 [BOARD_DAS1802AO] = {
305 .name = "das-1802ao",
311 struct das1800_private {
312 struct comedi_isadma *dma;
315 unsigned short *fifo_buf;
316 unsigned long iobase2;
320 static void das1800_ai_munge(struct comedi_device *dev,
321 struct comedi_subdevice *s,
322 void *data, unsigned int num_bytes,
323 unsigned int start_chan_index)
325 struct das1800_private *devpriv = dev->private;
326 unsigned short *array = data;
327 unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
330 if (devpriv->ai_is_unipolar)
333 for (i = 0; i < num_samples; i++)
334 array[i] = comedi_offset_munge(s, array[i]);
337 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
338 struct comedi_subdevice *s)
340 struct das1800_private *devpriv = dev->private;
341 unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
343 insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
344 comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
347 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
348 struct comedi_subdevice *s)
350 struct comedi_cmd *cmd = &s->async->cmd;
353 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
354 dpnt = inw(dev->iobase + DAS1800_FIFO);
355 comedi_buf_write_samples(s, &dpnt, 1);
357 if (cmd->stop_src == TRIG_COUNT &&
358 s->async->scans_done >= cmd->stop_arg)
363 static void das1800_flush_dma_channel(struct comedi_device *dev,
364 struct comedi_subdevice *s,
365 struct comedi_isadma_desc *desc)
367 unsigned int residue = comedi_isadma_disable(desc->chan);
368 unsigned int nbytes = desc->size - residue;
369 unsigned int nsamples;
371 /* figure out how many points to read */
372 nsamples = comedi_bytes_to_samples(s, nbytes);
373 nsamples = comedi_nsamples_left(s, nsamples);
375 comedi_buf_write_samples(s, desc->virt_addr, nsamples);
378 static void das1800_flush_dma(struct comedi_device *dev,
379 struct comedi_subdevice *s)
381 struct das1800_private *devpriv = dev->private;
382 struct comedi_isadma *dma = devpriv->dma;
383 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
384 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
386 das1800_flush_dma_channel(dev, s, desc);
389 /* switch to other channel and flush it */
390 dma->cur_dma = 1 - dma->cur_dma;
391 desc = &dma->desc[dma->cur_dma];
392 das1800_flush_dma_channel(dev, s, desc);
395 /* get any remaining samples in fifo */
396 das1800_handle_fifo_not_empty(dev, s);
399 static void das1800_handle_dma(struct comedi_device *dev,
400 struct comedi_subdevice *s, unsigned int status)
402 struct das1800_private *devpriv = dev->private;
403 struct comedi_isadma *dma = devpriv->dma;
404 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
405 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
407 das1800_flush_dma_channel(dev, s, desc);
409 /* re-enable dma channel */
410 comedi_isadma_program(desc);
412 if (status & DMATC) {
413 /* clear DMATC interrupt bit */
414 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
415 /* switch dma channels for next time, if appropriate */
417 dma->cur_dma = 1 - dma->cur_dma;
421 static int das1800_ai_cancel(struct comedi_device *dev,
422 struct comedi_subdevice *s)
424 struct das1800_private *devpriv = dev->private;
425 struct comedi_isadma *dma = devpriv->dma;
426 struct comedi_isadma_desc *desc;
429 /* disable and stop conversions */
430 outb(0x0, dev->iobase + DAS1800_STATUS);
431 outb(0x0, dev->iobase + DAS1800_CONTROL_B);
432 outb(0x0, dev->iobase + DAS1800_CONTROL_A);
435 for (i = 0; i < 2; i++) {
436 desc = &dma->desc[i];
438 comedi_isadma_disable(desc->chan);
445 static void das1800_ai_handler(struct comedi_device *dev)
447 struct das1800_private *devpriv = dev->private;
448 struct comedi_subdevice *s = dev->read_subdev;
449 struct comedi_async *async = s->async;
450 struct comedi_cmd *cmd = &async->cmd;
451 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
453 /* select adc register (spinlock is already held) */
454 outb(ADC, dev->iobase + DAS1800_SELECT);
456 /* get samples with dma, fifo, or polled as necessary */
457 if (devpriv->irq_dma_bits & DMA_ENABLED)
458 das1800_handle_dma(dev, s, status);
459 else if (status & FHF)
460 das1800_handle_fifo_half_full(dev, s);
461 else if (status & FNE)
462 das1800_handle_fifo_not_empty(dev, s);
464 /* if the card's fifo has overflowed */
466 /* clear OVF interrupt bit */
467 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
468 dev_err(dev->class_dev, "FIFO overflow\n");
469 async->events |= COMEDI_CB_ERROR;
470 comedi_handle_events(dev, s);
473 /* stop taking data if appropriate */
474 /* stop_src TRIG_EXT */
475 if (status & CT0TC) {
476 /* clear CT0TC interrupt bit */
477 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
478 /* get all remaining samples before quitting */
479 if (devpriv->irq_dma_bits & DMA_ENABLED)
480 das1800_flush_dma(dev, s);
482 das1800_handle_fifo_not_empty(dev, s);
483 async->events |= COMEDI_CB_EOA;
484 } else if (cmd->stop_src == TRIG_COUNT &&
485 async->scans_done >= cmd->stop_arg) {
486 async->events |= COMEDI_CB_EOA;
489 comedi_handle_events(dev, s);
492 static int das1800_ai_poll(struct comedi_device *dev,
493 struct comedi_subdevice *s)
498 * Protects the indirect addressing selected by DAS1800_SELECT
499 * in das1800_ai_handler() also prevents race with das1800_interrupt().
501 spin_lock_irqsave(&dev->spinlock, flags);
503 das1800_ai_handler(dev);
505 spin_unlock_irqrestore(&dev->spinlock, flags);
507 return comedi_buf_n_bytes_ready(s);
510 static irqreturn_t das1800_interrupt(int irq, void *d)
512 struct comedi_device *dev = d;
515 if (!dev->attached) {
516 dev_err(dev->class_dev, "premature interrupt\n");
521 * Protects the indirect addressing selected by DAS1800_SELECT
522 * in das1800_ai_handler() also prevents race with das1800_ai_poll().
524 spin_lock(&dev->spinlock);
526 status = inb(dev->iobase + DAS1800_STATUS);
528 /* if interrupt was not caused by das-1800 */
529 if (!(status & INT)) {
530 spin_unlock(&dev->spinlock);
533 /* clear the interrupt status bit INT */
534 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
535 /* handle interrupt */
536 das1800_ai_handler(dev);
538 spin_unlock(&dev->spinlock);
542 static int das1800_ai_fixup_paced_timing(struct comedi_device *dev,
543 struct comedi_cmd *cmd)
545 unsigned int arg = cmd->convert_arg;
549 * scan_begin_src is TRIG_FOLLOW
550 * convert_src is TRIG_TIMER
552 * The convert_arg sets the pacer sample acquisition time.
553 * The max acquisition speed is limited to the boards
554 * 'ai_speed' (this was already verified). The min speed is
555 * limited by the cascaded 8254 timer.
557 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
558 return comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
561 static int das1800_ai_fixup_burst_timing(struct comedi_device *dev,
562 struct comedi_cmd *cmd)
564 unsigned int arg = cmd->convert_arg;
569 * scan_begin_src is TRIG_TIMER or TRIG_EXT
570 * convert_src is TRIG_TIMER
572 * The convert_arg sets burst sample acquisition time.
573 * The max acquisition speed is limited to the boards
574 * 'ai_speed' (this was already verified). The min speed is
575 * limiited to 64 microseconds,
577 err |= comedi_check_trigger_arg_max(&arg, 64000);
579 /* round to microseconds then verify */
580 switch (cmd->flags & CMDF_ROUND_MASK) {
581 case CMDF_ROUND_NEAREST:
583 arg = DIV_ROUND_CLOSEST(arg, 1000);
585 case CMDF_ROUND_DOWN:
589 arg = DIV_ROUND_UP(arg, 1000);
592 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg * 1000);
595 * The pacer can be used to set the scan sample rate. The max scan
596 * speed is limited by the conversion speed and the number of channels
597 * to convert. The min speed is limited by the cascaded 8254 timer.
599 if (cmd->scan_begin_src == TRIG_TIMER) {
600 arg = cmd->convert_arg * cmd->chanlist_len;
601 err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
603 arg = cmd->scan_begin_arg;
604 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
605 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
611 static int das1800_ai_check_chanlist(struct comedi_device *dev,
612 struct comedi_subdevice *s,
613 struct comedi_cmd *cmd)
615 unsigned int range = CR_RANGE(cmd->chanlist[0]);
616 bool unipolar0 = comedi_range_is_unipolar(s, range);
619 for (i = 1; i < cmd->chanlist_len; i++) {
620 range = CR_RANGE(cmd->chanlist[i]);
622 if (unipolar0 != comedi_range_is_unipolar(s, range)) {
623 dev_dbg(dev->class_dev,
624 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
632 static int das1800_ai_cmdtest(struct comedi_device *dev,
633 struct comedi_subdevice *s,
634 struct comedi_cmd *cmd)
636 const struct das1800_board *board = dev->board_ptr;
639 /* Step 1 : check if triggers are trivially valid */
641 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
642 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
643 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
644 err |= comedi_check_trigger_src(&cmd->convert_src,
645 TRIG_TIMER | TRIG_EXT);
646 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
647 err |= comedi_check_trigger_src(&cmd->stop_src,
648 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
653 /* Step 2a : make sure trigger sources are unique */
655 err |= comedi_check_trigger_is_unique(cmd->start_src);
656 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
657 err |= comedi_check_trigger_is_unique(cmd->convert_src);
658 err |= comedi_check_trigger_is_unique(cmd->stop_src);
660 /* Step 2b : and mutually compatible */
662 /* burst scans must use timed conversions */
663 if (cmd->scan_begin_src != TRIG_FOLLOW &&
664 cmd->convert_src != TRIG_TIMER)
667 /* the external pin TGIN must use the same polarity */
668 if (cmd->start_src == TRIG_EXT && cmd->stop_src == TRIG_EXT)
669 err |= comedi_check_trigger_arg_is(&cmd->start_arg,
675 /* Step 3: check if arguments are trivially valid */
677 if (cmd->start_arg == TRIG_NOW)
678 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
680 if (cmd->convert_src == TRIG_TIMER) {
681 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
685 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
686 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
689 switch (cmd->stop_src) {
691 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
694 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
703 /* Step 4: fix up any arguments */
705 if (cmd->convert_src == TRIG_TIMER) {
706 if (cmd->scan_begin_src == TRIG_FOLLOW)
707 err |= das1800_ai_fixup_paced_timing(dev, cmd);
708 else /* TRIG_TIMER or TRIG_EXT */
709 err |= das1800_ai_fixup_burst_timing(dev, cmd);
715 /* Step 5: check channel list if it exists */
716 if (cmd->chanlist && cmd->chanlist_len > 0)
717 err |= das1800_ai_check_chanlist(dev, s, cmd);
725 static unsigned char das1800_ai_chanspec_bits(struct comedi_subdevice *s,
726 unsigned int chanspec)
728 unsigned int range = CR_RANGE(chanspec);
729 unsigned int aref = CR_AREF(chanspec);
733 if (aref != AREF_DIFF)
735 if (aref == AREF_COMMON)
737 if (comedi_range_is_unipolar(s, range))
743 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
744 struct comedi_subdevice *s,
745 unsigned int maxbytes,
748 struct comedi_cmd *cmd = &s->async->cmd;
749 unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
750 unsigned int samples;
752 samples = max_samples;
754 /* for timed modes, make dma buffer fill in 'ns' time */
755 switch (cmd->scan_begin_src) {
756 case TRIG_FOLLOW: /* not in burst mode */
757 if (cmd->convert_src == TRIG_TIMER)
758 samples = ns / cmd->convert_arg;
761 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
765 /* limit samples to what is remaining in the command */
766 samples = comedi_nsamples_left(s, samples);
768 if (samples > max_samples)
769 samples = max_samples;
773 return comedi_samples_to_bytes(s, samples);
776 static void das1800_ai_setup_dma(struct comedi_device *dev,
777 struct comedi_subdevice *s)
779 struct das1800_private *devpriv = dev->private;
780 struct comedi_isadma *dma = devpriv->dma;
781 struct comedi_isadma_desc *desc;
784 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
788 desc = &dma->desc[0];
790 /* determine a dma transfer size to fill buffer in 0.3 sec */
791 bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
794 comedi_isadma_program(desc);
796 /* set up dual dma if appropriate */
797 if (devpriv->irq_dma_bits & DMA_DUAL) {
798 desc = &dma->desc[1];
800 comedi_isadma_program(desc);
804 static void das1800_ai_set_chanlist(struct comedi_device *dev,
805 unsigned int *chanlist, unsigned int len)
810 /* protects the indirect addressing selected by DAS1800_SELECT */
811 spin_lock_irqsave(&dev->spinlock, flags);
813 /* select QRAM register and set start address */
814 outb(QRAM, dev->iobase + DAS1800_SELECT);
815 outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
817 /* make channel / gain list */
818 for (i = 0; i < len; i++) {
819 unsigned int chan = CR_CHAN(chanlist[i]);
820 unsigned int range = CR_RANGE(chanlist[i]);
823 val = chan | ((range & 0x3) << 8);
824 outw(val, dev->iobase + DAS1800_QRAM);
827 /* finish write to QRAM */
828 outb(len - 1, dev->iobase + DAS1800_QRAM_ADDRESS);
830 spin_unlock_irqrestore(&dev->spinlock, flags);
833 static int das1800_ai_cmd(struct comedi_device *dev,
834 struct comedi_subdevice *s)
836 struct das1800_private *devpriv = dev->private;
837 int control_a, control_c;
838 struct comedi_async *async = s->async;
839 const struct comedi_cmd *cmd = &async->cmd;
840 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
843 * Disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY (because dma in
844 * handler is unsafe at hard real-time priority).
846 if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
847 devpriv->irq_dma_bits &= ~DMA_ENABLED;
849 devpriv->irq_dma_bits |= devpriv->dma_bits;
850 /* interrupt on end of conversion for CMDF_WAKE_EOS */
851 if (cmd->flags & CMDF_WAKE_EOS) {
852 /* interrupt fifo not empty */
853 devpriv->irq_dma_bits &= ~FIMD;
855 /* interrupt fifo half full */
856 devpriv->irq_dma_bits |= FIMD;
859 das1800_ai_cancel(dev, s);
861 devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0);
864 if (cmd->stop_src == TRIG_EXT)
866 if (cmd->start_src == TRIG_EXT)
867 control_a |= TGEN | CGSL;
870 if (control_a & (ATEN | TGEN)) {
871 if ((cmd->start_arg & CR_INVERT) || (cmd->stop_arg & CR_INVERT))
875 control_c = das1800_ai_chanspec_bits(s, cmd->chanlist[0]);
876 /* set clock source to internal or external */
877 if (cmd->scan_begin_src == TRIG_FOLLOW) {
878 /* not in burst mode */
879 if (cmd->convert_src == TRIG_TIMER) {
880 /* trig on cascaded counters */
882 } else { /* TRIG_EXT */
883 /* trig on falling edge of external trigger */
886 } else if (cmd->scan_begin_src == TRIG_TIMER) {
887 /* burst mode with internal pacer clock */
888 control_c |= BMDE | IPCLK;
889 } else { /* TRIG_EXT */
890 /* burst mode with external trigger */
891 control_c |= BMDE | XPCLK;
894 das1800_ai_set_chanlist(dev, cmd->chanlist, cmd->chanlist_len);
896 /* setup cascaded counters for conversion/scan frequency */
897 if ((cmd->scan_begin_src == TRIG_FOLLOW ||
898 cmd->scan_begin_src == TRIG_TIMER) &&
899 cmd->convert_src == TRIG_TIMER) {
900 comedi_8254_update_divisors(dev->pacer);
901 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
904 /* setup counter 0 for 'about triggering' */
905 if (cmd->stop_src == TRIG_EXT)
906 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
908 das1800_ai_setup_dma(dev, s);
909 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
910 /* set conversion rate and length for burst mode */
911 if (control_c & BMDE) {
912 outb(cmd->convert_arg / 1000 - 1, /* microseconds - 1 */
913 dev->iobase + DAS1800_BURST_RATE);
914 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
917 /* enable and start conversions */
918 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);
919 outb(control_a, dev->iobase + DAS1800_CONTROL_A);
920 outb(CVEN, dev->iobase + DAS1800_STATUS);
925 static int das1800_ai_eoc(struct comedi_device *dev,
926 struct comedi_subdevice *s,
927 struct comedi_insn *insn,
928 unsigned long context)
930 unsigned char status;
932 status = inb(dev->iobase + DAS1800_STATUS);
938 static int das1800_ai_insn_read(struct comedi_device *dev,
939 struct comedi_subdevice *s,
940 struct comedi_insn *insn,
943 unsigned int range = CR_RANGE(insn->chanspec);
944 bool is_unipolar = comedi_range_is_unipolar(s, range);
950 outb(das1800_ai_chanspec_bits(s, insn->chanspec),
951 dev->iobase + DAS1800_CONTROL_C); /* software pacer */
952 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
953 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
954 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
956 das1800_ai_set_chanlist(dev, &insn->chanspec, 1);
958 /* protects the indirect addressing selected by DAS1800_SELECT */
959 spin_lock_irqsave(&dev->spinlock, flags);
961 /* select ai fifo register */
962 outb(ADC, dev->iobase + DAS1800_SELECT);
964 for (n = 0; n < insn->n; n++) {
965 /* trigger conversion */
966 outb(0, dev->iobase + DAS1800_FIFO);
968 ret = comedi_timeout(dev, s, insn, das1800_ai_eoc, 0);
972 dpnt = inw(dev->iobase + DAS1800_FIFO);
974 dpnt = comedi_offset_munge(s, dpnt);
977 spin_unlock_irqrestore(&dev->spinlock, flags);
979 return ret ? ret : insn->n;
982 static int das1800_ao_insn_write(struct comedi_device *dev,
983 struct comedi_subdevice *s,
984 struct comedi_insn *insn,
987 unsigned int chan = CR_CHAN(insn->chanspec);
988 unsigned int update_chan = s->n_chan - 1;
992 /* protects the indirect addressing selected by DAS1800_SELECT */
993 spin_lock_irqsave(&dev->spinlock, flags);
995 for (i = 0; i < insn->n; i++) {
996 unsigned int val = data[i];
998 s->readback[chan] = val;
1000 val = comedi_offset_munge(s, val);
1002 /* load this channel (and update if it's the last channel) */
1003 outb(DAC(chan), dev->iobase + DAS1800_SELECT);
1004 outw(val, dev->iobase + DAS1800_DAC);
1006 /* update all channels */
1007 if (chan != update_chan) {
1008 val = comedi_offset_munge(s, s->readback[update_chan]);
1010 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);
1011 outw(val, dev->iobase + DAS1800_DAC);
1014 spin_unlock_irqrestore(&dev->spinlock, flags);
1019 static int das1800_di_insn_bits(struct comedi_device *dev,
1020 struct comedi_subdevice *s,
1021 struct comedi_insn *insn,
1024 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1030 static int das1800_do_insn_bits(struct comedi_device *dev,
1031 struct comedi_subdevice *s,
1032 struct comedi_insn *insn,
1035 if (comedi_dio_update_state(s, data))
1036 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1043 static void das1800_init_dma(struct comedi_device *dev,
1044 struct comedi_devconfig *it)
1046 struct das1800_private *devpriv = dev->private;
1047 unsigned int *dma_chan;
1050 * it->options[2] is DMA channel 0
1051 * it->options[3] is DMA channel 1
1053 * Encode the DMA channels into 2 digit hexadecimal for switch.
1055 dma_chan = &it->options[2];
1057 switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1058 case 0x5: /* dma0 == 5 */
1059 devpriv->dma_bits = DMA_CH5;
1061 case 0x6: /* dma0 == 6 */
1062 devpriv->dma_bits = DMA_CH6;
1064 case 0x7: /* dma0 == 7 */
1065 devpriv->dma_bits = DMA_CH7;
1067 case 0x65: /* dma0 == 5, dma1 == 6 */
1068 devpriv->dma_bits = DMA_CH5_CH6;
1070 case 0x76: /* dma0 == 6, dma1 == 7 */
1071 devpriv->dma_bits = DMA_CH6_CH7;
1073 case 0x57: /* dma0 == 7, dma1 == 5 */
1074 devpriv->dma_bits = DMA_CH7_CH5;
1080 /* DMA can use 1 or 2 buffers, each with a separate channel */
1081 devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1082 dma_chan[0], dma_chan[1],
1083 DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1085 devpriv->dma_bits = 0;
1088 static void das1800_free_dma(struct comedi_device *dev)
1090 struct das1800_private *devpriv = dev->private;
1093 comedi_isadma_free(devpriv->dma);
1096 static int das1800_probe(struct comedi_device *dev)
1098 const struct das1800_board *board = dev->board_ptr;
1101 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1104 * The dev->board_ptr will be set by comedi_device_attach() if the
1105 * board name provided by the user matches a board->name in this
1106 * driver. If so, this function sanity checks the id to verify that
1107 * the board is correct.
1110 if (board->id == id)
1112 dev_err(dev->class_dev,
1113 "probed id does not match board id (0x%x != 0x%x)\n",
1119 * If the dev->board_ptr is not set, the user is trying to attach
1120 * an unspecified board to this driver. In this case the id is used
1121 * to 'probe' for the dev->board_ptr.
1124 case DAS1800_ID_ST_DA:
1125 /* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */
1126 board = &das1800_boards[BOARD_DAS1801ST_DA];
1128 case DAS1800_ID_HR_DA:
1129 /* das-1702hr-da, das-1802hr-da */
1130 board = &das1800_boards[BOARD_DAS1802HR_DA];
1133 /* das-1701ao, das-1702ao, das-1801ao, das-1802ao */
1134 board = &das1800_boards[BOARD_DAS1801AO];
1137 /* das-1702hr, das-1802hr */
1138 board = &das1800_boards[BOARD_DAS1802HR];
1141 /* das-1701st, das-1702st, das-1801st, das-1802st */
1142 board = &das1800_boards[BOARD_DAS1801ST];
1145 /* das-1801hc, das-1802hc */
1146 board = &das1800_boards[BOARD_DAS1801HC];
1149 dev_err(dev->class_dev, "invalid probe id 0x%x\n", id);
1152 dev->board_ptr = board;
1153 dev->board_name = board->name;
1154 dev_warn(dev->class_dev,
1155 "probed id 0x%0x: %s series (not recommended)\n",
1160 static int das1800_attach(struct comedi_device *dev,
1161 struct comedi_devconfig *it)
1163 const struct das1800_board *board;
1164 struct das1800_private *devpriv;
1165 struct comedi_subdevice *s;
1166 unsigned int irq = it->options[1];
1171 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1175 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1179 ret = das1800_probe(dev);
1182 board = dev->board_ptr;
1184 is_16bit = board->id == DAS1800_ID_HR || board->id == DAS1800_ID_HR_DA;
1186 /* waveform 'ao' boards have additional io ports */
1187 if (board->id == DAS1800_ID_AO) {
1188 unsigned long iobase2 = dev->iobase + IOBASE2;
1190 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1193 devpriv->iobase2 = iobase2;
1196 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1198 ret = request_irq(irq, das1800_interrupt, 0,
1199 dev->board_name, dev);
1205 devpriv->irq_dma_bits |= 0x8;
1208 devpriv->irq_dma_bits |= 0x10;
1211 devpriv->irq_dma_bits |= 0x18;
1214 devpriv->irq_dma_bits |= 0x28;
1217 devpriv->irq_dma_bits |= 0x30;
1220 devpriv->irq_dma_bits |= 0x38;
1226 /* an irq and one dma channel is required to use dma */
1227 if (dev->irq & it->options[2])
1228 das1800_init_dma(dev, it);
1230 devpriv->fifo_buf = kmalloc_array(FIFO_SIZE,
1231 sizeof(*devpriv->fifo_buf),
1233 if (!devpriv->fifo_buf)
1236 dev->pacer = comedi_8254_io_alloc(dev->iobase + DAS1800_COUNTER,
1237 I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1238 if (IS_ERR(dev->pacer))
1239 return PTR_ERR(dev->pacer);
1241 ret = comedi_alloc_subdevices(dev, 4);
1246 * Analog Input subdevice
1248 * The "hc" type boards have 64 analog input channels and a 64
1251 * All the other board types have 16 on-board channels. Each channel
1252 * can be expanded to 16 channels with the addition of an EXP-1800
1253 * expansion board for a total of 256 channels. The QRAM fifo on
1254 * these boards has 256 entries.
1256 * From the datasheets it's not clear what the comedi channel to
1257 * actual physical channel mapping is when EXP-1800 boards are used.
1259 s = &dev->subdevices[0];
1260 s->type = COMEDI_SUBD_AI;
1261 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1262 if (board->id != DAS1800_ID_HC)
1263 s->subdev_flags |= SDF_COMMON;
1264 s->n_chan = (board->id == DAS1800_ID_HC) ? 64 : 256;
1265 s->maxdata = is_16bit ? 0xffff : 0x0fff;
1266 s->range_table = board->is_01_series ? &das1801_ai_range
1267 : &das1802_ai_range;
1268 s->insn_read = das1800_ai_insn_read;
1270 dev->read_subdev = s;
1271 s->subdev_flags |= SDF_CMD_READ;
1272 s->len_chanlist = s->n_chan;
1273 s->do_cmd = das1800_ai_cmd;
1274 s->do_cmdtest = das1800_ai_cmdtest;
1275 s->poll = das1800_ai_poll;
1276 s->cancel = das1800_ai_cancel;
1277 s->munge = das1800_ai_munge;
1280 /* Analog Output subdevice */
1281 s = &dev->subdevices[1];
1282 if (board->id == DAS1800_ID_ST_DA || board->id == DAS1800_ID_HR_DA) {
1283 s->type = COMEDI_SUBD_AO;
1284 s->subdev_flags = SDF_WRITABLE;
1285 s->n_chan = (board->id == DAS1800_ID_ST_DA) ? 4 : 2;
1286 s->maxdata = is_16bit ? 0xffff : 0x0fff;
1287 s->range_table = &range_bipolar10;
1288 s->insn_write = das1800_ao_insn_write;
1290 ret = comedi_alloc_subdev_readback(s);
1294 /* initialize all channels to 0V */
1295 for (i = 0; i < s->n_chan; i++) {
1296 /* spinlock is not necessary during the attach */
1297 outb(DAC(i), dev->iobase + DAS1800_SELECT);
1298 outw(0, dev->iobase + DAS1800_DAC);
1300 } else if (board->id == DAS1800_ID_AO) {
1302 * 'ao' boards have waveform analog outputs that are not
1303 * currently supported.
1305 s->type = COMEDI_SUBD_UNUSED;
1307 s->type = COMEDI_SUBD_UNUSED;
1310 /* Digital Input subdevice */
1311 s = &dev->subdevices[2];
1312 s->type = COMEDI_SUBD_DI;
1313 s->subdev_flags = SDF_READABLE;
1316 s->range_table = &range_digital;
1317 s->insn_bits = das1800_di_insn_bits;
1319 /* Digital Output subdevice */
1320 s = &dev->subdevices[3];
1321 s->type = COMEDI_SUBD_DO;
1322 s->subdev_flags = SDF_WRITABLE;
1323 s->n_chan = (board->id == DAS1800_ID_HC) ? 8 : 4;
1325 s->range_table = &range_digital;
1326 s->insn_bits = das1800_do_insn_bits;
1328 das1800_ai_cancel(dev, dev->read_subdev);
1330 /* initialize digital out channels */
1331 outb(0, dev->iobase + DAS1800_DIGITAL);
1336 static void das1800_detach(struct comedi_device *dev)
1338 struct das1800_private *devpriv = dev->private;
1340 das1800_free_dma(dev);
1342 kfree(devpriv->fifo_buf);
1343 if (devpriv->iobase2)
1344 release_region(devpriv->iobase2, DAS1800_SIZE);
1346 comedi_legacy_detach(dev);
1349 static struct comedi_driver das1800_driver = {
1350 .driver_name = "das1800",
1351 .module = THIS_MODULE,
1352 .attach = das1800_attach,
1353 .detach = das1800_detach,
1354 .num_names = ARRAY_SIZE(das1800_boards),
1355 .board_name = &das1800_boards[0].name,
1356 .offset = sizeof(struct das1800_board),
1358 module_comedi_driver(das1800_driver);
1360 MODULE_AUTHOR("Comedi https://www.comedi.org");
1361 MODULE_DESCRIPTION("Comedi driver for DAS1800 compatible ISA boards");
1362 MODULE_LICENSE("GPL");