2 comedi/drivers/das1800.c
3 Driver for Keitley das1700/das1800 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>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
21 Description: Keithley Metrabyte DAS1800 (& compatibles)
22 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
23 Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
24 DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
25 DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
26 DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
27 DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
28 DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
29 DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
30 DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
31 DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
32 DAS-1802AO (das-1802ao)
35 The waveform analog output on the 'ao' cards is not supported.
36 If you need it, send me (Frank Hess) an email.
38 Configuration options:
39 [0] - I/O port base address
40 [1] - IRQ (optional, required for timed or externally triggered conversions)
41 [2] - DMA0 (optional, requires irq)
42 [3] - DMA1 (optional, requires irq and dma0)
46 This driver supports the following Keithley boards:
69 [1] - irq (optional, required for timed or externally triggered conversions)
70 [2] - dma0 (optional, requires irq)
71 [3] - dma1 (optional, requires irq and dma0)
73 irq can be omitted, although the cmd interface will not work without it.
75 analog input cmd triggers supported:
76 start_src: TRIG_NOW | TRIG_EXT
77 scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
78 scan_end_src: TRIG_COUNT
79 convert_src: TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
80 stop_src: TRIG_COUNT | TRIG_EXT | TRIG_NONE
82 scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
83 'burst mode' which limits the valid conversion time to 64 microseconds
84 (convert_arg <= 64000). This limitation does not apply if scan_begin_src
88 Only the DAS-1801ST has been tested by me.
89 Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
92 Make it automatically allocate irq and dma channels if they are not specified
93 Add support for analog out on 'ao' cards
94 read insn for analog out
97 #include <linux/module.h>
98 #include <linux/interrupt.h>
99 #include <linux/slab.h>
100 #include <linux/io.h>
102 #include "../comedidev.h"
104 #include "comedi_isadma.h"
105 #include "comedi_8254.h"
108 #define DAS1800_SIZE 16 /* uses 16 io addresses */
109 #define FIFO_SIZE 1024 /* 1024 sample fifo */
110 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
112 /* Registers for the das1800 */
113 #define DAS1800_FIFO 0x0
114 #define DAS1800_QRAM 0x0
115 #define DAS1800_DAC 0x0
116 #define DAS1800_SELECT 0x2
119 #define DAC(a) (0x2 + a)
120 #define DAS1800_DIGITAL 0x3
121 #define DAS1800_CONTROL_A 0x4
128 #define DAS1800_CONTROL_B 0x5
132 #define DMA_CH5_CH6 0x5
133 #define DMA_CH6_CH7 0x6
134 #define DMA_CH7_CH5 0x7
135 #define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */
144 #define DAS1800_CONTROL_C 0X6
152 #define DAS1800_STATUS 0x7
153 /* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
154 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
161 #define CVEN_MASK 0x40 /* masks CVEN on write */
163 #define DAS1800_BURST_LENGTH 0x8
164 #define DAS1800_BURST_RATE 0x9
165 #define DAS1800_QRAM_ADDRESS 0xa
166 #define DAS1800_COUNTER 0xc
168 #define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */
170 /* analog input ranges */
171 static const struct comedi_lrange range_ai_das1801 = {
184 static const struct comedi_lrange range_ai_das1802 = {
197 enum das1800_boardid {
218 /* board probe id values (hi byte of the digital input register) */
219 #define DAS1800_ID_ST_DA 0x3
220 #define DAS1800_ID_HR_DA 0x4
221 #define DAS1800_ID_AO 0x5
222 #define DAS1800_ID_HR 0x6
223 #define DAS1800_ID_ST 0x7
224 #define DAS1800_ID_HC 0x8
226 struct das1800_board {
229 int ai_speed; /* max conversion period in nanoseconds */
230 int resolution; /* bits of ai resolution */
231 int qram_len; /* length of card's channel / gain queue */
232 int do_n_chan; /* number of digital output channels */
233 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
234 int ao_n_chan; /* number of analog out channels */
235 const struct comedi_lrange *range_ai; /* available input ranges */
238 /* Warning: the maximum conversion speeds listed below are
239 * not always achievable depending on board setup (see
242 static const struct das1800_board das1800_boards[] = {
243 [BOARD_DAS1701ST] = {
244 .name = "das-1701st",
252 .range_ai = &range_ai_das1801,
254 [BOARD_DAS1701ST_DA] = {
255 .name = "das-1701st-da",
256 .id = DAS1800_ID_ST_DA,
263 .range_ai = &range_ai_das1801,
265 [BOARD_DAS1702ST] = {
266 .name = "das-1702st",
274 .range_ai = &range_ai_das1802,
276 [BOARD_DAS1702ST_DA] = {
277 .name = "das-1702st-da",
278 .id = DAS1800_ID_ST_DA,
285 .range_ai = &range_ai_das1802,
287 [BOARD_DAS1702HR] = {
288 .name = "das-1702hr",
296 .range_ai = &range_ai_das1802,
298 [BOARD_DAS1702HR_DA] = {
299 .name = "das-1702hr-da",
300 .id = DAS1800_ID_HR_DA,
307 .range_ai = &range_ai_das1802,
309 [BOARD_DAS1701AO] = {
310 .name = "das-1701ao",
318 .range_ai = &range_ai_das1801,
320 [BOARD_DAS1702AO] = {
321 .name = "das-1702ao",
329 .range_ai = &range_ai_das1802,
331 [BOARD_DAS1801ST] = {
332 .name = "das-1801st",
340 .range_ai = &range_ai_das1801,
342 [BOARD_DAS1801ST_DA] = {
343 .name = "das-1801st-da",
344 .id = DAS1800_ID_ST_DA,
351 .range_ai = &range_ai_das1801,
353 [BOARD_DAS1802ST] = {
354 .name = "das-1802st",
362 .range_ai = &range_ai_das1802,
364 [BOARD_DAS1802ST_DA] = {
365 .name = "das-1802st-da",
366 .id = DAS1800_ID_ST_DA,
373 .range_ai = &range_ai_das1802,
375 [BOARD_DAS1802HR] = {
376 .name = "das-1802hr",
384 .range_ai = &range_ai_das1802,
386 [BOARD_DAS1802HR_DA] = {
387 .name = "das-1802hr-da",
388 .id = DAS1800_ID_HR_DA,
395 .range_ai = &range_ai_das1802,
397 [BOARD_DAS1801HC] = {
398 .name = "das-1801hc",
406 .range_ai = &range_ai_das1801,
408 [BOARD_DAS1802HC] = {
409 .name = "das-1802hc",
417 .range_ai = &range_ai_das1802,
419 [BOARD_DAS1801AO] = {
420 .name = "das-1801ao",
428 .range_ai = &range_ai_das1801,
430 [BOARD_DAS1802AO] = {
431 .name = "das-1802ao",
439 .range_ai = &range_ai_das1802,
443 struct das1800_private {
444 struct comedi_isadma *dma;
445 int irq_dma_bits; /* bits for control register b */
446 /* dma bits for control register b, stored so that dma can be
447 * turned on and off */
449 uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */
450 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */
451 unsigned short ao_update_bits; /* remembers the last write to the
456 /* analog out range for 'ao' boards */
458 static const struct comedi_lrange range_ao_2 = {
466 static void das1800_ai_munge(struct comedi_device *dev,
467 struct comedi_subdevice *s,
468 void *data, unsigned int num_bytes,
469 unsigned int start_chan_index)
471 struct das1800_private *devpriv = dev->private;
472 unsigned short *array = data;
473 unsigned int num_samples = comedi_bytes_to_samples(s, num_bytes);
476 if (devpriv->ai_is_unipolar)
479 for (i = 0; i < num_samples; i++)
480 array[i] = comedi_offset_munge(s, array[i]);
483 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
484 struct comedi_subdevice *s)
486 struct das1800_private *devpriv = dev->private;
487 unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
489 insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
490 comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
493 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
494 struct comedi_subdevice *s)
496 struct comedi_cmd *cmd = &s->async->cmd;
499 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
500 dpnt = inw(dev->iobase + DAS1800_FIFO);
501 comedi_buf_write_samples(s, &dpnt, 1);
503 if (cmd->stop_src == TRIG_COUNT &&
504 s->async->scans_done >= cmd->stop_arg)
509 /* Utility function used by das1800_flush_dma() and das1800_handle_dma() */
510 static void das1800_flush_dma_channel(struct comedi_device *dev,
511 struct comedi_subdevice *s,
512 struct comedi_isadma_desc *desc)
514 unsigned int residue = comedi_isadma_disable(desc->chan);
515 unsigned int nbytes = desc->size - residue;
516 unsigned int nsamples;
518 /* figure out how many points to read */
519 nsamples = comedi_bytes_to_samples(s, nbytes);
520 nsamples = comedi_nsamples_left(s, nsamples);
522 comedi_buf_write_samples(s, desc->virt_addr, nsamples);
525 /* flushes remaining data from board when external trigger has stopped acquisition
526 * and we are using dma transfers */
527 static void das1800_flush_dma(struct comedi_device *dev,
528 struct comedi_subdevice *s)
530 struct das1800_private *devpriv = dev->private;
531 struct comedi_isadma *dma = devpriv->dma;
532 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
533 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
535 das1800_flush_dma_channel(dev, s, desc);
538 /* switch to other channel and flush it */
539 dma->cur_dma = 1 - dma->cur_dma;
540 desc = &dma->desc[dma->cur_dma];
541 das1800_flush_dma_channel(dev, s, desc);
544 /* get any remaining samples in fifo */
545 das1800_handle_fifo_not_empty(dev, s);
548 static void das1800_handle_dma(struct comedi_device *dev,
549 struct comedi_subdevice *s, unsigned int status)
551 struct das1800_private *devpriv = dev->private;
552 struct comedi_isadma *dma = devpriv->dma;
553 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
554 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
556 das1800_flush_dma_channel(dev, s, desc);
558 /* re-enable dma channel */
559 comedi_isadma_program(desc);
561 if (status & DMATC) {
562 /* clear DMATC interrupt bit */
563 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
564 /* switch dma channels for next time, if appropriate */
566 dma->cur_dma = 1 - dma->cur_dma;
570 static int das1800_ai_cancel(struct comedi_device *dev,
571 struct comedi_subdevice *s)
573 struct das1800_private *devpriv = dev->private;
574 struct comedi_isadma *dma = devpriv->dma;
575 struct comedi_isadma_desc *desc;
578 /* disable and stop conversions */
579 outb(0x0, dev->iobase + DAS1800_STATUS);
580 outb(0x0, dev->iobase + DAS1800_CONTROL_B);
581 outb(0x0, dev->iobase + DAS1800_CONTROL_A);
584 for (i = 0; i < 2; i++) {
585 desc = &dma->desc[i];
587 comedi_isadma_disable(desc->chan);
594 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
595 static void das1800_ai_handler(struct comedi_device *dev)
597 struct das1800_private *devpriv = dev->private;
598 struct comedi_subdevice *s = dev->read_subdev;
599 struct comedi_async *async = s->async;
600 struct comedi_cmd *cmd = &async->cmd;
601 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
603 /* select adc for base address + 0 */
604 outb(ADC, dev->iobase + DAS1800_SELECT);
605 /* dma buffer full */
606 if (devpriv->irq_dma_bits & DMA_ENABLED) {
607 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
608 das1800_handle_dma(dev, s, status);
609 } else if (status & FHF) { /* if fifo half full */
610 das1800_handle_fifo_half_full(dev, s);
611 } else if (status & FNE) { /* if fifo not empty */
612 das1800_handle_fifo_not_empty(dev, s);
615 /* if the card's fifo has overflowed */
617 /* clear OVF interrupt bit */
618 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
619 dev_err(dev->class_dev, "FIFO overflow\n");
620 async->events |= COMEDI_CB_ERROR;
621 comedi_handle_events(dev, s);
624 /* stop taking data if appropriate */
625 /* stop_src TRIG_EXT */
626 if (status & CT0TC) {
627 /* clear CT0TC interrupt bit */
628 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
629 /* make sure we get all remaining data from board before quitting */
630 if (devpriv->irq_dma_bits & DMA_ENABLED)
631 das1800_flush_dma(dev, s);
633 das1800_handle_fifo_not_empty(dev, s);
634 async->events |= COMEDI_CB_EOA;
635 } else if (cmd->stop_src == TRIG_COUNT &&
636 async->scans_done >= cmd->stop_arg) {
637 async->events |= COMEDI_CB_EOA;
640 comedi_handle_events(dev, s);
643 static int das1800_ai_poll(struct comedi_device *dev,
644 struct comedi_subdevice *s)
648 /* prevent race with interrupt handler */
649 spin_lock_irqsave(&dev->spinlock, flags);
650 das1800_ai_handler(dev);
651 spin_unlock_irqrestore(&dev->spinlock, flags);
653 return comedi_buf_n_bytes_ready(s);
656 static irqreturn_t das1800_interrupt(int irq, void *d)
658 struct comedi_device *dev = d;
661 if (!dev->attached) {
662 dev_err(dev->class_dev, "premature interrupt\n");
666 /* Prevent race with das1800_ai_poll() on multi processor systems.
667 * Also protects indirect addressing in das1800_ai_handler */
668 spin_lock(&dev->spinlock);
669 status = inb(dev->iobase + DAS1800_STATUS);
671 /* if interrupt was not caused by das-1800 */
672 if (!(status & INT)) {
673 spin_unlock(&dev->spinlock);
676 /* clear the interrupt status bit INT */
677 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
678 /* handle interrupt */
679 das1800_ai_handler(dev);
681 spin_unlock(&dev->spinlock);
685 /* converts requested conversion timing to timing compatible with
686 * hardware, used only when card is in 'burst mode'
688 static unsigned int burst_convert_arg(unsigned int convert_arg, int flags)
690 unsigned int micro_sec;
692 /* in burst mode, the maximum conversion time is 64 microseconds */
693 if (convert_arg > 64000)
696 /* the conversion time must be an integral number of microseconds */
697 switch (flags & CMDF_ROUND_MASK) {
698 case CMDF_ROUND_NEAREST:
700 micro_sec = (convert_arg + 500) / 1000;
702 case CMDF_ROUND_DOWN:
703 micro_sec = convert_arg / 1000;
706 micro_sec = (convert_arg - 1) / 1000 + 1;
710 /* return number of nanoseconds */
711 return micro_sec * 1000;
714 static int das1800_ai_check_chanlist(struct comedi_device *dev,
715 struct comedi_subdevice *s,
716 struct comedi_cmd *cmd)
718 unsigned int range = CR_RANGE(cmd->chanlist[0]);
719 bool unipolar0 = comedi_range_is_unipolar(s, range);
722 for (i = 1; i < cmd->chanlist_len; i++) {
723 range = CR_RANGE(cmd->chanlist[i]);
725 if (unipolar0 != comedi_range_is_unipolar(s, range)) {
726 dev_dbg(dev->class_dev,
727 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
735 static int das1800_ai_cmdtest(struct comedi_device *dev,
736 struct comedi_subdevice *s,
737 struct comedi_cmd *cmd)
739 const struct das1800_board *board = dev->board_ptr;
743 /* Step 1 : check if triggers are trivially valid */
745 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
746 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
747 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
748 err |= comedi_check_trigger_src(&cmd->convert_src,
749 TRIG_TIMER | TRIG_EXT);
750 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
751 err |= comedi_check_trigger_src(&cmd->stop_src,
752 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
757 /* Step 2a : make sure trigger sources are unique */
759 err |= comedi_check_trigger_is_unique(cmd->start_src);
760 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
761 err |= comedi_check_trigger_is_unique(cmd->convert_src);
762 err |= comedi_check_trigger_is_unique(cmd->stop_src);
764 /* Step 2b : and mutually compatible */
766 if (cmd->scan_begin_src != TRIG_FOLLOW &&
767 cmd->convert_src != TRIG_TIMER)
773 /* Step 3: check if arguments are trivially valid */
775 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
777 if (cmd->convert_src == TRIG_TIMER) {
778 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
782 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
783 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
786 switch (cmd->stop_src) {
788 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
791 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
800 /* step 4: fix up any arguments */
802 if (cmd->scan_begin_src == TRIG_FOLLOW &&
803 cmd->convert_src == TRIG_TIMER) {
804 /* we are not in burst mode */
805 arg = cmd->convert_arg;
806 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
807 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
808 } else if (cmd->convert_src == TRIG_TIMER) {
809 /* we are in burst mode */
810 arg = burst_convert_arg(cmd->convert_arg, cmd->flags);
811 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
813 if (cmd->scan_begin_src == TRIG_TIMER) {
814 arg = cmd->convert_arg * cmd->chanlist_len;
815 err |= comedi_check_trigger_arg_max(&cmd->
819 arg = cmd->scan_begin_arg;
820 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg,
822 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg,
830 /* Step 5: check channel list if it exists */
831 if (cmd->chanlist && cmd->chanlist_len > 0)
832 err |= das1800_ai_check_chanlist(dev, s, cmd);
840 /* returns appropriate bits for control register a, depending on command */
841 static int control_a_bits(const struct comedi_cmd *cmd)
845 control_a = FFEN; /* enable fifo */
846 if (cmd->stop_src == TRIG_EXT)
848 switch (cmd->start_src) {
850 control_a |= TGEN | CGSL;
862 /* returns appropriate bits for control register c, depending on command */
863 static int control_c_bits(struct comedi_subdevice *s,
864 const struct comedi_cmd *cmd)
866 unsigned int range = CR_RANGE(cmd->chanlist[0]);
867 unsigned int aref = CR_AREF(cmd->chanlist[0]);
870 /* set clock source to internal or external, select analog reference,
871 * select unipolar / bipolar
873 control_c = UQEN; /* enable upper qram addresses */
874 if (aref != AREF_DIFF)
876 if (aref == AREF_COMMON)
878 if (comedi_range_is_unipolar(s, range))
881 switch (cmd->scan_begin_src) {
882 case TRIG_FOLLOW: /* not in burst mode */
883 switch (cmd->convert_src) {
885 /* trig on cascaded counters */
889 /* trig on falling edge of external trigger */
897 /* burst mode with internal pacer clock */
898 control_c |= BMDE | IPCLK;
901 /* burst mode with external trigger */
902 control_c |= BMDE | XPCLK;
911 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
912 struct comedi_subdevice *s,
913 unsigned int maxbytes,
916 struct comedi_cmd *cmd = &s->async->cmd;
917 unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
918 unsigned int samples;
920 samples = max_samples;
922 /* for timed modes, make dma buffer fill in 'ns' time */
923 switch (cmd->scan_begin_src) {
924 case TRIG_FOLLOW: /* not in burst mode */
925 if (cmd->convert_src == TRIG_TIMER)
926 samples = ns / cmd->convert_arg;
929 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
933 /* limit samples to what is remaining in the command */
934 samples = comedi_nsamples_left(s, samples);
936 if (samples > max_samples)
937 samples = max_samples;
941 return comedi_samples_to_bytes(s, samples);
944 static void das1800_ai_setup_dma(struct comedi_device *dev,
945 struct comedi_subdevice *s)
947 struct das1800_private *devpriv = dev->private;
948 struct comedi_isadma *dma = devpriv->dma;
949 struct comedi_isadma_desc *desc;
952 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
956 desc = &dma->desc[0];
958 /* determine a dma transfer size to fill buffer in 0.3 sec */
959 bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
962 comedi_isadma_program(desc);
964 /* set up dual dma if appropriate */
965 if (devpriv->irq_dma_bits & DMA_DUAL) {
966 desc = &dma->desc[1];
968 comedi_isadma_program(desc);
972 /* programs channel/gain list into card */
973 static void program_chanlist(struct comedi_device *dev,
974 const struct comedi_cmd *cmd)
976 int i, n, chan_range;
977 unsigned long irq_flags;
978 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
979 const int range_bitshift = 8;
981 n = cmd->chanlist_len;
982 /* spinlock protects indirect addressing */
983 spin_lock_irqsave(&dev->spinlock, irq_flags);
984 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
985 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
986 /* make channel / gain list */
987 for (i = 0; i < n; i++) {
989 CR_CHAN(cmd->chanlist[i]) |
990 ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
992 outw(chan_range, dev->iobase + DAS1800_QRAM);
994 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
995 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
998 static int das1800_ai_cmd(struct comedi_device *dev,
999 struct comedi_subdevice *s)
1001 struct das1800_private *devpriv = dev->private;
1002 int control_a, control_c;
1003 struct comedi_async *async = s->async;
1004 const struct comedi_cmd *cmd = &async->cmd;
1005 unsigned int range0 = CR_RANGE(cmd->chanlist[0]);
1007 /* disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY
1008 * (because dma in handler is unsafe at hard real-time priority) */
1009 if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
1010 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1012 devpriv->irq_dma_bits |= devpriv->dma_bits;
1013 /* interrupt on end of conversion for CMDF_WAKE_EOS */
1014 if (cmd->flags & CMDF_WAKE_EOS) {
1015 /* interrupt fifo not empty */
1016 devpriv->irq_dma_bits &= ~FIMD;
1018 /* interrupt fifo half full */
1019 devpriv->irq_dma_bits |= FIMD;
1022 das1800_ai_cancel(dev, s);
1024 devpriv->ai_is_unipolar = comedi_range_is_unipolar(s, range0);
1026 /* determine proper bits for control registers */
1027 control_a = control_a_bits(cmd);
1028 control_c = control_c_bits(s, cmd);
1030 /* setup card and start */
1031 program_chanlist(dev, cmd);
1033 /* setup cascaded counters for conversion/scan frequency */
1034 if ((cmd->scan_begin_src == TRIG_FOLLOW ||
1035 cmd->scan_begin_src == TRIG_TIMER) &&
1036 cmd->convert_src == TRIG_TIMER) {
1037 comedi_8254_update_divisors(dev->pacer);
1038 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
1041 /* setup counter 0 for 'about triggering' */
1042 if (cmd->stop_src == TRIG_EXT)
1043 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
1045 das1800_ai_setup_dma(dev, s);
1046 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1047 /* set conversion rate and length for burst mode */
1048 if (control_c & BMDE) {
1049 /* program conversion period with number of microseconds minus 1 */
1050 outb(cmd->convert_arg / 1000 - 1,
1051 dev->iobase + DAS1800_BURST_RATE);
1052 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1054 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1055 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1056 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1061 static int das1800_ai_insn_read(struct comedi_device *dev,
1062 struct comedi_subdevice *s,
1063 struct comedi_insn *insn,
1066 unsigned int chan = CR_CHAN(insn->chanspec);
1067 unsigned int range = CR_RANGE(insn->chanspec);
1068 unsigned int aref = CR_AREF(insn->chanspec);
1069 bool is_unipolar = comedi_range_is_unipolar(s, range);
1073 unsigned short dpnt;
1075 unsigned long irq_flags;
1077 /* set up analog reference and unipolar / bipolar mode */
1079 if (aref != AREF_DIFF)
1081 if (aref == AREF_COMMON)
1086 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1087 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1088 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1089 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1091 chan_range = chan | ((range & 0x3) << 8);
1092 spin_lock_irqsave(&dev->spinlock, irq_flags);
1093 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1094 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1095 outw(chan_range, dev->iobase + DAS1800_QRAM);
1096 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1097 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1099 for (n = 0; n < insn->n; n++) {
1100 /* trigger conversion */
1101 outb(0, dev->iobase + DAS1800_FIFO);
1102 for (i = 0; i < timeout; i++) {
1103 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1107 dev_err(dev->class_dev, "timeout\n");
1111 dpnt = inw(dev->iobase + DAS1800_FIFO);
1113 dpnt = comedi_offset_munge(s, dpnt);
1117 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1122 static int das1800_ao_insn_write(struct comedi_device *dev,
1123 struct comedi_subdevice *s,
1124 struct comedi_insn *insn,
1127 const struct das1800_board *board = dev->board_ptr;
1128 struct das1800_private *devpriv = dev->private;
1129 int chan = CR_CHAN(insn->chanspec);
1130 /* int range = CR_RANGE(insn->chanspec); */
1131 int update_chan = board->ao_n_chan - 1;
1132 unsigned short output;
1133 unsigned long irq_flags;
1135 /* card expects two's complement data */
1136 output = data[0] - (1 << (board->resolution - 1));
1137 /* if the write is to the 'update' channel, we need to remember its value */
1138 if (chan == update_chan)
1139 devpriv->ao_update_bits = output;
1140 /* write to channel */
1141 spin_lock_irqsave(&dev->spinlock, irq_flags);
1142 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1143 outw(output, dev->iobase + DAS1800_DAC);
1144 /* now we need to write to 'update' channel to update all dac channels */
1145 if (chan != update_chan) {
1146 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1147 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1149 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1154 static int das1800_di_insn_bits(struct comedi_device *dev,
1155 struct comedi_subdevice *s,
1156 struct comedi_insn *insn,
1159 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1165 static int das1800_do_insn_bits(struct comedi_device *dev,
1166 struct comedi_subdevice *s,
1167 struct comedi_insn *insn,
1170 if (comedi_dio_update_state(s, data))
1171 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1178 static void das1800_init_dma(struct comedi_device *dev,
1179 struct comedi_devconfig *it)
1181 struct das1800_private *devpriv = dev->private;
1182 unsigned int *dma_chan;
1185 * it->options[2] is DMA channel 0
1186 * it->options[3] is DMA channel 1
1188 * Encode the DMA channels into 2 digit hexadecimal for switch.
1190 dma_chan = &it->options[2];
1192 switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1193 case 0x5: /* dma0 == 5 */
1194 devpriv->dma_bits = DMA_CH5;
1196 case 0x6: /* dma0 == 6 */
1197 devpriv->dma_bits = DMA_CH6;
1199 case 0x7: /* dma0 == 7 */
1200 devpriv->dma_bits = DMA_CH7;
1202 case 0x65: /* dma0 == 5, dma1 == 6 */
1203 devpriv->dma_bits = DMA_CH5_CH6;
1205 case 0x76: /* dma0 == 6, dma1 == 7 */
1206 devpriv->dma_bits = DMA_CH6_CH7;
1208 case 0x57: /* dma0 == 7, dma1 == 5 */
1209 devpriv->dma_bits = DMA_CH7_CH5;
1215 /* DMA can use 1 or 2 buffers, each with a separate channel */
1216 devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1217 dma_chan[0], dma_chan[1],
1218 DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1220 devpriv->dma_bits = 0;
1223 static void das1800_free_dma(struct comedi_device *dev)
1225 struct das1800_private *devpriv = dev->private;
1228 comedi_isadma_free(devpriv->dma);
1231 static int das1800_probe(struct comedi_device *dev)
1233 const struct das1800_board *board = dev->board_ptr;
1236 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1239 * The dev->board_ptr will be set by comedi_device_attach() if the
1240 * board name provided by the user matches a board->name in this
1241 * driver. If so, this function sanity checks the id to verify that
1242 * the board is correct.
1245 if (board->id == id)
1247 dev_err(dev->class_dev,
1248 "probed id does not match board id (0x%x != 0x%x)\n",
1254 * If the dev->board_ptr is not set, the user is trying to attach
1255 * an unspecified board to this driver. In this case the id is used
1256 * to 'probe' for the dev->board_ptr.
1259 case DAS1800_ID_ST_DA:
1260 /* das-1701st-da, das-1702st-da, das-1801st-da, das-1802st-da */
1261 board = &das1800_boards[BOARD_DAS1801ST_DA];
1263 case DAS1800_ID_HR_DA:
1264 /* das-1702hr-da, das-1802hr-da */
1265 board = &das1800_boards[BOARD_DAS1802HR_DA];
1268 /* das-1701ao, das-1702ao, das-1801ao, das-1802ao */
1269 board = &das1800_boards[BOARD_DAS1801AO];
1272 /* das-1702hr, das-1802hr */
1273 board = &das1800_boards[BOARD_DAS1802HR];
1276 /* das-1701st, das-1702st, das-1801st, das-1802st */
1277 board = &das1800_boards[BOARD_DAS1801ST];
1280 /* das-1801hc, das-1802hc */
1281 board = &das1800_boards[BOARD_DAS1801HC];
1284 dev_err(dev->class_dev, "invalid probe id 0x%x\n", id);
1287 dev->board_ptr = board;
1288 dev->board_name = board->name;
1289 dev_warn(dev->class_dev,
1290 "probed id 0x%0x: %s series (not recommended)\n",
1295 static int das1800_attach(struct comedi_device *dev,
1296 struct comedi_devconfig *it)
1298 const struct das1800_board *board;
1299 struct das1800_private *devpriv;
1300 struct comedi_subdevice *s;
1301 unsigned int irq = it->options[1];
1304 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1308 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1312 ret = das1800_probe(dev);
1315 board = dev->board_ptr;
1317 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
1318 if (board->ao_ability == 2) {
1319 unsigned long iobase2 = dev->iobase + IOBASE2;
1321 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1324 devpriv->iobase2 = iobase2;
1327 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1329 ret = request_irq(irq, das1800_interrupt, 0,
1330 dev->board_name, dev);
1336 devpriv->irq_dma_bits |= 0x8;
1339 devpriv->irq_dma_bits |= 0x10;
1342 devpriv->irq_dma_bits |= 0x18;
1345 devpriv->irq_dma_bits |= 0x28;
1348 devpriv->irq_dma_bits |= 0x30;
1351 devpriv->irq_dma_bits |= 0x38;
1357 /* an irq and one dma channel is required to use dma */
1358 if (dev->irq & it->options[2])
1359 das1800_init_dma(dev, it);
1361 devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, sizeof(uint16_t), GFP_KERNEL);
1362 if (!devpriv->fifo_buf)
1365 dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1366 I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1370 ret = comedi_alloc_subdevices(dev, 4);
1374 /* Analog Input subdevice */
1375 s = &dev->subdevices[0];
1376 s->type = COMEDI_SUBD_AI;
1377 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1378 if (board->id != DAS1800_ID_HC)
1379 s->subdev_flags |= SDF_COMMON;
1380 s->n_chan = board->qram_len;
1381 s->maxdata = (1 << board->resolution) - 1;
1382 s->range_table = board->range_ai;
1383 s->insn_read = das1800_ai_insn_read;
1385 dev->read_subdev = s;
1386 s->subdev_flags |= SDF_CMD_READ;
1387 s->len_chanlist = s->n_chan;
1388 s->do_cmd = das1800_ai_cmd;
1389 s->do_cmdtest = das1800_ai_cmdtest;
1390 s->poll = das1800_ai_poll;
1391 s->cancel = das1800_ai_cancel;
1392 s->munge = das1800_ai_munge;
1395 /* Analog Output subdevice */
1396 s = &dev->subdevices[1];
1397 if (board->ao_ability == 1) {
1398 s->type = COMEDI_SUBD_AO;
1399 s->subdev_flags = SDF_WRITABLE;
1400 s->n_chan = board->ao_n_chan;
1401 s->maxdata = (1 << board->resolution) - 1;
1402 s->range_table = &range_bipolar10;
1403 s->insn_write = das1800_ao_insn_write;
1405 s->type = COMEDI_SUBD_UNUSED;
1408 /* Digital Input subdevice */
1409 s = &dev->subdevices[2];
1410 s->type = COMEDI_SUBD_DI;
1411 s->subdev_flags = SDF_READABLE;
1414 s->range_table = &range_digital;
1415 s->insn_bits = das1800_di_insn_bits;
1417 /* Digital Output subdevice */
1418 s = &dev->subdevices[3];
1419 s->type = COMEDI_SUBD_DO;
1420 s->subdev_flags = SDF_WRITABLE;
1421 s->n_chan = board->do_n_chan;
1423 s->range_table = &range_digital;
1424 s->insn_bits = das1800_do_insn_bits;
1426 das1800_ai_cancel(dev, dev->read_subdev);
1428 /* initialize digital out channels */
1429 outb(0, dev->iobase + DAS1800_DIGITAL);
1431 /* initialize analog out channels */
1432 if (board->ao_ability == 1) {
1433 /* select 'update' dac channel for baseAddress + 0x0 */
1434 outb(DAC(board->ao_n_chan - 1),
1435 dev->iobase + DAS1800_SELECT);
1436 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1442 static void das1800_detach(struct comedi_device *dev)
1444 struct das1800_private *devpriv = dev->private;
1446 das1800_free_dma(dev);
1448 kfree(devpriv->fifo_buf);
1449 if (devpriv->iobase2)
1450 release_region(devpriv->iobase2, DAS1800_SIZE);
1452 comedi_legacy_detach(dev);
1455 static struct comedi_driver das1800_driver = {
1456 .driver_name = "das1800",
1457 .module = THIS_MODULE,
1458 .attach = das1800_attach,
1459 .detach = das1800_detach,
1460 .num_names = ARRAY_SIZE(das1800_boards),
1461 .board_name = &das1800_boards[0].name,
1462 .offset = sizeof(struct das1800_board),
1464 module_comedi_driver(das1800_driver);
1466 MODULE_AUTHOR("Comedi http://www.comedi.org");
1467 MODULE_DESCRIPTION("Comedi low-level driver");
1468 MODULE_LICENSE("GPL");