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 UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */
111 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
113 /* Registers for the das1800 */
114 #define DAS1800_FIFO 0x0
115 #define DAS1800_QRAM 0x0
116 #define DAS1800_DAC 0x0
117 #define DAS1800_SELECT 0x2
120 #define DAC(a) (0x2 + a)
121 #define DAS1800_DIGITAL 0x3
122 #define DAS1800_CONTROL_A 0x4
129 #define DAS1800_CONTROL_B 0x5
133 #define DMA_CH5_CH6 0x5
134 #define DMA_CH6_CH7 0x6
135 #define DMA_CH7_CH5 0x7
136 #define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */
145 #define DAS1800_CONTROL_C 0X6
153 #define DAS1800_STATUS 0x7
154 /* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
155 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
162 #define CVEN_MASK 0x40 /* masks CVEN on write */
164 #define DAS1800_BURST_LENGTH 0x8
165 #define DAS1800_BURST_RATE 0x9
166 #define DAS1800_QRAM_ADDRESS 0xa
167 #define DAS1800_COUNTER 0xc
169 #define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */
172 das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
174 das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
175 das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
178 /* analog input ranges */
179 static const struct comedi_lrange range_ai_das1801 = {
192 static const struct comedi_lrange range_ai_das1802 = {
205 struct das1800_board {
207 int ai_speed; /* max conversion period in nanoseconds */
208 int resolution; /* bits of ai resolution */
209 int qram_len; /* length of card's channel / gain queue */
210 int common; /* supports AREF_COMMON flag */
211 int do_n_chan; /* number of digital output channels */
212 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
213 int ao_n_chan; /* number of analog out channels */
214 const struct comedi_lrange *range_ai; /* available input ranges */
217 /* Warning: the maximum conversion speeds listed below are
218 * not always achievable depending on board setup (see
221 static const struct das1800_board das1800_boards[] = {
223 .name = "das-1701st",
231 .range_ai = &range_ai_das1801,
234 .name = "das-1701st-da",
242 .range_ai = &range_ai_das1801,
245 .name = "das-1702st",
253 .range_ai = &range_ai_das1802,
256 .name = "das-1702st-da",
264 .range_ai = &range_ai_das1802,
267 .name = "das-1702hr",
275 .range_ai = &range_ai_das1802,
278 .name = "das-1702hr-da",
286 .range_ai = &range_ai_das1802,
289 .name = "das-1701ao",
297 .range_ai = &range_ai_das1801,
300 .name = "das-1702ao",
308 .range_ai = &range_ai_das1802,
311 .name = "das-1801st",
319 .range_ai = &range_ai_das1801,
322 .name = "das-1801st-da",
330 .range_ai = &range_ai_das1801,
333 .name = "das-1802st",
341 .range_ai = &range_ai_das1802,
344 .name = "das-1802st-da",
352 .range_ai = &range_ai_das1802,
355 .name = "das-1802hr",
363 .range_ai = &range_ai_das1802,
366 .name = "das-1802hr-da",
374 .range_ai = &range_ai_das1802,
377 .name = "das-1801hc",
385 .range_ai = &range_ai_das1801,
388 .name = "das-1802hc",
396 .range_ai = &range_ai_das1802,
399 .name = "das-1801ao",
407 .range_ai = &range_ai_das1801,
410 .name = "das-1802ao",
418 .range_ai = &range_ai_das1802,
422 struct das1800_private {
423 struct comedi_isadma *dma;
424 int irq_dma_bits; /* bits for control register b */
425 /* dma bits for control register b, stored so that dma can be
426 * turned on and off */
428 uint16_t *fifo_buf; /* bounce buffer for analog input FIFO */
429 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */
430 unsigned short ao_update_bits; /* remembers the last write to the
434 /* analog out range for 'ao' boards */
436 static const struct comedi_lrange range_ao_2 = {
444 static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
447 const struct das1800_board *board = dev->board_ptr;
449 sample += 1 << (board->resolution - 1);
453 static void munge_data(struct comedi_device *dev, uint16_t *array,
454 unsigned int num_elements)
459 /* see if card is using a unipolar or bipolar range so we can munge data correctly */
460 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
462 /* convert to unsigned type if we are in a bipolar mode */
464 for (i = 0; i < num_elements; i++)
465 array[i] = munge_bipolar_sample(dev, array[i]);
469 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
470 struct comedi_subdevice *s)
472 struct das1800_private *devpriv = dev->private;
473 unsigned int nsamples = comedi_nsamples_left(s, FIFO_SIZE / 2);
475 insw(dev->iobase + DAS1800_FIFO, devpriv->fifo_buf, nsamples);
476 munge_data(dev, devpriv->fifo_buf, nsamples);
477 comedi_buf_write_samples(s, devpriv->fifo_buf, nsamples);
480 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
481 struct comedi_subdevice *s)
483 struct comedi_cmd *cmd = &s->async->cmd;
487 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
489 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
490 dpnt = inw(dev->iobase + DAS1800_FIFO);
491 /* convert to unsigned type */
492 dpnt = munge_bipolar_sample(dev, dpnt);
493 comedi_buf_write_samples(s, &dpnt, 1);
495 if (cmd->stop_src == TRIG_COUNT &&
496 s->async->scans_done >= cmd->stop_arg)
501 /* Utility function used by das1800_flush_dma() and das1800_handle_dma() */
502 static void das1800_flush_dma_channel(struct comedi_device *dev,
503 struct comedi_subdevice *s,
504 struct comedi_isadma_desc *desc)
506 unsigned int residue = comedi_isadma_disable(desc->chan);
507 unsigned int nbytes = desc->size - residue;
508 unsigned int nsamples;
510 /* figure out how many points to read */
511 nsamples = comedi_bytes_to_samples(s, nbytes);
512 nsamples = comedi_nsamples_left(s, nsamples);
514 munge_data(dev, desc->virt_addr, nsamples);
515 comedi_buf_write_samples(s, desc->virt_addr, nsamples);
518 /* flushes remaining data from board when external trigger has stopped acquisition
519 * and we are using dma transfers */
520 static void das1800_flush_dma(struct comedi_device *dev,
521 struct comedi_subdevice *s)
523 struct das1800_private *devpriv = dev->private;
524 struct comedi_isadma *dma = devpriv->dma;
525 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
526 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
528 das1800_flush_dma_channel(dev, s, desc);
531 /* switch to other channel and flush it */
532 dma->cur_dma = 1 - dma->cur_dma;
533 desc = &dma->desc[dma->cur_dma];
534 das1800_flush_dma_channel(dev, s, desc);
537 /* get any remaining samples in fifo */
538 das1800_handle_fifo_not_empty(dev, s);
541 static void das1800_handle_dma(struct comedi_device *dev,
542 struct comedi_subdevice *s, unsigned int status)
544 struct das1800_private *devpriv = dev->private;
545 struct comedi_isadma *dma = devpriv->dma;
546 struct comedi_isadma_desc *desc = &dma->desc[dma->cur_dma];
547 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
549 das1800_flush_dma_channel(dev, s, desc);
551 /* re-enable dma channel */
552 comedi_isadma_program(desc);
554 if (status & DMATC) {
555 /* clear DMATC interrupt bit */
556 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
557 /* switch dma channels for next time, if appropriate */
559 dma->cur_dma = 1 - dma->cur_dma;
563 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
565 struct das1800_private *devpriv = dev->private;
566 struct comedi_isadma *dma = devpriv->dma;
567 struct comedi_isadma_desc *desc;
570 /* disable and stop conversions */
571 outb(0x0, dev->iobase + DAS1800_STATUS);
572 outb(0x0, dev->iobase + DAS1800_CONTROL_B);
573 outb(0x0, dev->iobase + DAS1800_CONTROL_A);
576 for (i = 0; i < 2; i++) {
577 desc = &dma->desc[i];
579 comedi_isadma_disable(desc->chan);
586 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
587 static void das1800_ai_handler(struct comedi_device *dev)
589 struct das1800_private *devpriv = dev->private;
590 struct comedi_subdevice *s = dev->read_subdev;
591 struct comedi_async *async = s->async;
592 struct comedi_cmd *cmd = &async->cmd;
593 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
595 /* select adc for base address + 0 */
596 outb(ADC, dev->iobase + DAS1800_SELECT);
597 /* dma buffer full */
598 if (devpriv->irq_dma_bits & DMA_ENABLED) {
599 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
600 das1800_handle_dma(dev, s, status);
601 } else if (status & FHF) { /* if fifo half full */
602 das1800_handle_fifo_half_full(dev, s);
603 } else if (status & FNE) { /* if fifo not empty */
604 das1800_handle_fifo_not_empty(dev, s);
607 /* if the card's fifo has overflowed */
609 /* clear OVF interrupt bit */
610 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
611 dev_err(dev->class_dev, "FIFO overflow\n");
612 async->events |= COMEDI_CB_ERROR;
613 comedi_handle_events(dev, s);
616 /* stop taking data if appropriate */
617 /* stop_src TRIG_EXT */
618 if (status & CT0TC) {
619 /* clear CT0TC interrupt bit */
620 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
621 /* make sure we get all remaining data from board before quitting */
622 if (devpriv->irq_dma_bits & DMA_ENABLED)
623 das1800_flush_dma(dev, s);
625 das1800_handle_fifo_not_empty(dev, s);
626 async->events |= COMEDI_CB_EOA;
627 } else if (cmd->stop_src == TRIG_COUNT &&
628 async->scans_done >= cmd->stop_arg) {
629 async->events |= COMEDI_CB_EOA;
632 comedi_handle_events(dev, s);
635 static int das1800_ai_poll(struct comedi_device *dev,
636 struct comedi_subdevice *s)
640 /* prevent race with interrupt handler */
641 spin_lock_irqsave(&dev->spinlock, flags);
642 das1800_ai_handler(dev);
643 spin_unlock_irqrestore(&dev->spinlock, flags);
645 return comedi_buf_n_bytes_ready(s);
648 static irqreturn_t das1800_interrupt(int irq, void *d)
650 struct comedi_device *dev = d;
653 if (!dev->attached) {
654 dev_err(dev->class_dev, "premature interrupt\n");
658 /* Prevent race with das1800_ai_poll() on multi processor systems.
659 * Also protects indirect addressing in das1800_ai_handler */
660 spin_lock(&dev->spinlock);
661 status = inb(dev->iobase + DAS1800_STATUS);
663 /* if interrupt was not caused by das-1800 */
664 if (!(status & INT)) {
665 spin_unlock(&dev->spinlock);
668 /* clear the interrupt status bit INT */
669 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
670 /* handle interrupt */
671 das1800_ai_handler(dev);
673 spin_unlock(&dev->spinlock);
677 /* converts requested conversion timing to timing compatible with
678 * hardware, used only when card is in 'burst mode'
680 static unsigned int burst_convert_arg(unsigned int convert_arg, int flags)
682 unsigned int micro_sec;
684 /* in burst mode, the maximum conversion time is 64 microseconds */
685 if (convert_arg > 64000)
688 /* the conversion time must be an integral number of microseconds */
689 switch (flags & CMDF_ROUND_MASK) {
690 case CMDF_ROUND_NEAREST:
692 micro_sec = (convert_arg + 500) / 1000;
694 case CMDF_ROUND_DOWN:
695 micro_sec = convert_arg / 1000;
698 micro_sec = (convert_arg - 1) / 1000 + 1;
702 /* return number of nanoseconds */
703 return micro_sec * 1000;
706 static int das1800_ai_check_chanlist(struct comedi_device *dev,
707 struct comedi_subdevice *s,
708 struct comedi_cmd *cmd)
710 unsigned int unipolar0 = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
713 for (i = 1; i < cmd->chanlist_len; i++) {
714 unsigned int unipolar = CR_RANGE(cmd->chanlist[i]) & UNIPOLAR;
716 if (unipolar != unipolar0) {
717 dev_dbg(dev->class_dev,
718 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
726 /* test analog input cmd */
727 static int das1800_ai_do_cmdtest(struct comedi_device *dev,
728 struct comedi_subdevice *s,
729 struct comedi_cmd *cmd)
731 const struct das1800_board *board = dev->board_ptr;
735 /* Step 1 : check if triggers are trivially valid */
737 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
738 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
739 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
740 err |= comedi_check_trigger_src(&cmd->convert_src,
741 TRIG_TIMER | TRIG_EXT);
742 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
743 err |= comedi_check_trigger_src(&cmd->stop_src,
744 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
749 /* Step 2a : make sure trigger sources are unique */
751 err |= comedi_check_trigger_is_unique(cmd->start_src);
752 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
753 err |= comedi_check_trigger_is_unique(cmd->convert_src);
754 err |= comedi_check_trigger_is_unique(cmd->stop_src);
756 /* Step 2b : and mutually compatible */
758 if (cmd->scan_begin_src != TRIG_FOLLOW &&
759 cmd->convert_src != TRIG_TIMER)
765 /* Step 3: check if arguments are trivially valid */
767 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
769 if (cmd->convert_src == TRIG_TIMER) {
770 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
774 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
775 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
778 switch (cmd->stop_src) {
780 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
783 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
792 /* step 4: fix up any arguments */
794 if (cmd->scan_begin_src == TRIG_FOLLOW &&
795 cmd->convert_src == TRIG_TIMER) {
796 /* we are not in burst mode */
797 arg = cmd->convert_arg;
798 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
799 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
800 } else if (cmd->convert_src == TRIG_TIMER) {
801 /* we are in burst mode */
802 arg = burst_convert_arg(cmd->convert_arg, cmd->flags);
803 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
805 if (cmd->scan_begin_src == TRIG_TIMER) {
806 arg = cmd->convert_arg * cmd->chanlist_len;
807 err |= comedi_check_trigger_arg_max(&cmd->
811 arg = cmd->scan_begin_arg;
812 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg,
814 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg,
822 /* Step 5: check channel list if it exists */
823 if (cmd->chanlist && cmd->chanlist_len > 0)
824 err |= das1800_ai_check_chanlist(dev, s, cmd);
832 /* returns appropriate bits for control register a, depending on command */
833 static int control_a_bits(const struct comedi_cmd *cmd)
837 control_a = FFEN; /* enable fifo */
838 if (cmd->stop_src == TRIG_EXT)
840 switch (cmd->start_src) {
842 control_a |= TGEN | CGSL;
854 /* returns appropriate bits for control register c, depending on command */
855 static int control_c_bits(const struct comedi_cmd *cmd)
860 /* set clock source to internal or external, select analog reference,
861 * select unipolar / bipolar
863 aref = CR_AREF(cmd->chanlist[0]);
864 control_c = UQEN; /* enable upper qram addresses */
865 if (aref != AREF_DIFF)
867 if (aref == AREF_COMMON)
869 /* if a unipolar range was selected */
870 if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
872 switch (cmd->scan_begin_src) {
873 case TRIG_FOLLOW: /* not in burst mode */
874 switch (cmd->convert_src) {
876 /* trig on cascaded counters */
880 /* trig on falling edge of external trigger */
888 /* burst mode with internal pacer clock */
889 control_c |= BMDE | IPCLK;
892 /* burst mode with external trigger */
893 control_c |= BMDE | XPCLK;
902 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
903 struct comedi_subdevice *s,
904 unsigned int maxbytes,
907 struct comedi_cmd *cmd = &s->async->cmd;
908 unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
909 unsigned int samples;
911 samples = max_samples;
913 /* for timed modes, make dma buffer fill in 'ns' time */
914 switch (cmd->scan_begin_src) {
915 case TRIG_FOLLOW: /* not in burst mode */
916 if (cmd->convert_src == TRIG_TIMER)
917 samples = ns / cmd->convert_arg;
920 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
924 /* limit samples to what is remaining in the command */
925 samples = comedi_nsamples_left(s, samples);
927 if (samples > max_samples)
928 samples = max_samples;
932 return comedi_samples_to_bytes(s, samples);
935 static void das1800_ai_setup_dma(struct comedi_device *dev,
936 struct comedi_subdevice *s)
938 struct das1800_private *devpriv = dev->private;
939 struct comedi_isadma *dma = devpriv->dma;
940 struct comedi_isadma_desc *desc;
943 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
947 desc = &dma->desc[0];
949 /* determine a dma transfer size to fill buffer in 0.3 sec */
950 bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
953 comedi_isadma_program(desc);
955 /* set up dual dma if appropriate */
956 if (devpriv->irq_dma_bits & DMA_DUAL) {
957 desc = &dma->desc[1];
959 comedi_isadma_program(desc);
963 /* programs channel/gain list into card */
964 static void program_chanlist(struct comedi_device *dev,
965 const struct comedi_cmd *cmd)
967 int i, n, chan_range;
968 unsigned long irq_flags;
969 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
970 const int range_bitshift = 8;
972 n = cmd->chanlist_len;
973 /* spinlock protects indirect addressing */
974 spin_lock_irqsave(&dev->spinlock, irq_flags);
975 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
976 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
977 /* make channel / gain list */
978 for (i = 0; i < n; i++) {
980 CR_CHAN(cmd->chanlist[i]) |
981 ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
983 outw(chan_range, dev->iobase + DAS1800_QRAM);
985 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
986 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
989 /* analog input do_cmd */
990 static int das1800_ai_do_cmd(struct comedi_device *dev,
991 struct comedi_subdevice *s)
993 struct das1800_private *devpriv = dev->private;
994 int control_a, control_c;
995 struct comedi_async *async = s->async;
996 const struct comedi_cmd *cmd = &async->cmd;
998 /* disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY
999 * (because dma in handler is unsafe at hard real-time priority) */
1000 if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
1001 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1003 devpriv->irq_dma_bits |= devpriv->dma_bits;
1004 /* interrupt on end of conversion for CMDF_WAKE_EOS */
1005 if (cmd->flags & CMDF_WAKE_EOS) {
1006 /* interrupt fifo not empty */
1007 devpriv->irq_dma_bits &= ~FIMD;
1009 /* interrupt fifo half full */
1010 devpriv->irq_dma_bits |= FIMD;
1013 das1800_cancel(dev, s);
1015 /* determine proper bits for control registers */
1016 control_a = control_a_bits(cmd);
1017 control_c = control_c_bits(cmd);
1019 /* setup card and start */
1020 program_chanlist(dev, cmd);
1022 /* setup cascaded counters for conversion/scan frequency */
1023 if ((cmd->scan_begin_src == TRIG_FOLLOW ||
1024 cmd->scan_begin_src == TRIG_TIMER) &&
1025 cmd->convert_src == TRIG_TIMER) {
1026 comedi_8254_update_divisors(dev->pacer);
1027 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
1030 /* setup counter 0 for 'about triggering' */
1031 if (cmd->stop_src == TRIG_EXT)
1032 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
1034 das1800_ai_setup_dma(dev, s);
1035 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1036 /* set conversion rate and length for burst mode */
1037 if (control_c & BMDE) {
1038 /* program conversion period with number of microseconds minus 1 */
1039 outb(cmd->convert_arg / 1000 - 1,
1040 dev->iobase + DAS1800_BURST_RATE);
1041 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1043 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1044 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1045 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1050 /* read analog input */
1051 static int das1800_ai_rinsn(struct comedi_device *dev,
1052 struct comedi_subdevice *s,
1053 struct comedi_insn *insn, unsigned int *data)
1055 const struct das1800_board *board = dev->board_ptr;
1057 int chan, range, aref, chan_range;
1059 unsigned short dpnt;
1061 unsigned long irq_flags;
1063 /* set up analog reference and unipolar / bipolar mode */
1064 aref = CR_AREF(insn->chanspec);
1066 if (aref != AREF_DIFF)
1068 if (aref == AREF_COMMON)
1070 /* if a unipolar range was selected */
1071 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1074 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1075 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1076 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1077 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1079 chan = CR_CHAN(insn->chanspec);
1080 /* mask of unipolar/bipolar bit from range */
1081 range = CR_RANGE(insn->chanspec) & 0x3;
1082 chan_range = chan | (range << 8);
1083 spin_lock_irqsave(&dev->spinlock, irq_flags);
1084 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1085 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1086 outw(chan_range, dev->iobase + DAS1800_QRAM);
1087 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1088 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1090 for (n = 0; n < insn->n; n++) {
1091 /* trigger conversion */
1092 outb(0, dev->iobase + DAS1800_FIFO);
1093 for (i = 0; i < timeout; i++) {
1094 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1098 dev_err(dev->class_dev, "timeout\n");
1102 dpnt = inw(dev->iobase + DAS1800_FIFO);
1103 /* shift data to offset binary for bipolar ranges */
1104 if ((conv_flags & UB) == 0)
1105 dpnt += 1 << (board->resolution - 1);
1109 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1114 /* writes to an analog output channel */
1115 static int das1800_ao_winsn(struct comedi_device *dev,
1116 struct comedi_subdevice *s,
1117 struct comedi_insn *insn, unsigned int *data)
1119 const struct das1800_board *board = dev->board_ptr;
1120 struct das1800_private *devpriv = dev->private;
1121 int chan = CR_CHAN(insn->chanspec);
1122 /* int range = CR_RANGE(insn->chanspec); */
1123 int update_chan = board->ao_n_chan - 1;
1124 unsigned short output;
1125 unsigned long irq_flags;
1127 /* card expects two's complement data */
1128 output = data[0] - (1 << (board->resolution - 1));
1129 /* if the write is to the 'update' channel, we need to remember its value */
1130 if (chan == update_chan)
1131 devpriv->ao_update_bits = output;
1132 /* write to channel */
1133 spin_lock_irqsave(&dev->spinlock, irq_flags);
1134 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1135 outw(output, dev->iobase + DAS1800_DAC);
1136 /* now we need to write to 'update' channel to update all dac channels */
1137 if (chan != update_chan) {
1138 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1139 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1141 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1146 /* reads from digital input channels */
1147 static int das1800_di_rbits(struct comedi_device *dev,
1148 struct comedi_subdevice *s,
1149 struct comedi_insn *insn, unsigned int *data)
1151 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1157 static int das1800_do_wbits(struct comedi_device *dev,
1158 struct comedi_subdevice *s,
1159 struct comedi_insn *insn,
1162 if (comedi_dio_update_state(s, data))
1163 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1170 static void das1800_init_dma(struct comedi_device *dev,
1171 struct comedi_devconfig *it)
1173 struct das1800_private *devpriv = dev->private;
1174 unsigned int *dma_chan;
1177 * it->options[2] is DMA channel 0
1178 * it->options[3] is DMA channel 1
1180 * Encode the DMA channels into 2 digit hexadecimal for switch.
1182 dma_chan = &it->options[2];
1184 switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1185 case 0x5: /* dma0 == 5 */
1186 devpriv->dma_bits = DMA_CH5;
1188 case 0x6: /* dma0 == 6 */
1189 devpriv->dma_bits = DMA_CH6;
1191 case 0x7: /* dma0 == 7 */
1192 devpriv->dma_bits = DMA_CH7;
1194 case 0x65: /* dma0 == 5, dma1 == 6 */
1195 devpriv->dma_bits = DMA_CH5_CH6;
1197 case 0x76: /* dma0 == 6, dma1 == 7 */
1198 devpriv->dma_bits = DMA_CH6_CH7;
1200 case 0x57: /* dma0 == 7, dma1 == 5 */
1201 devpriv->dma_bits = DMA_CH7_CH5;
1207 /* DMA can use 1 or 2 buffers, each with a separate channel */
1208 devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1209 dma_chan[0], dma_chan[1],
1210 DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1212 devpriv->dma_bits = 0;
1215 static void das1800_free_dma(struct comedi_device *dev)
1217 struct das1800_private *devpriv = dev->private;
1220 comedi_isadma_free(devpriv->dma);
1223 static const struct das1800_board *das1800_probe(struct comedi_device *dev)
1225 const struct das1800_board *board = dev->board_ptr;
1226 int index = board ? board - das1800_boards : -EINVAL;
1230 * The dev->board_ptr will be set by comedi_device_attach() if the
1231 * board name provided by the user matches a board->name in this
1232 * driver. If so, this function sanity checks the id to verify that
1233 * the board is correct.
1235 * If the dev->board_ptr is not set, the user is trying to attach
1236 * an unspecified board to this driver. In this case the id is used
1237 * to 'probe' for the correct dev->board_ptr.
1239 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1242 if (index == das1801st_da || index == das1802st_da ||
1243 index == das1701st_da || index == das1702st_da)
1248 if (index == das1802hr_da || index == das1702hr_da)
1253 if (index == das1801ao || index == das1802ao ||
1254 index == das1701ao || index == das1702ao)
1259 if (index == das1802hr || index == das1702hr)
1264 if (index == das1801st || index == das1802st ||
1265 index == das1701st || index == das1702st)
1270 if (index == das1801hc || index == das1802hc)
1275 dev_err(dev->class_dev,
1276 "Board model: probe returned 0x%x (unknown, please report)\n",
1280 dev_err(dev->class_dev,
1281 "Board model (probed, not recommended): %s series\n",
1282 das1800_boards[index].name);
1284 return &das1800_boards[index];
1287 static int das1800_attach(struct comedi_device *dev,
1288 struct comedi_devconfig *it)
1290 const struct das1800_board *board;
1291 struct das1800_private *devpriv;
1292 struct comedi_subdevice *s;
1293 unsigned int irq = it->options[1];
1296 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1300 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1304 board = das1800_probe(dev);
1306 dev_err(dev->class_dev, "unable to determine board type\n");
1309 dev->board_ptr = board;
1310 dev->board_name = board->name;
1312 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
1313 if (board->ao_ability == 2) {
1314 unsigned long iobase2 = dev->iobase + IOBASE2;
1316 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1319 devpriv->iobase2 = iobase2;
1322 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1324 ret = request_irq(irq, das1800_interrupt, 0,
1325 dev->board_name, dev);
1331 devpriv->irq_dma_bits |= 0x8;
1334 devpriv->irq_dma_bits |= 0x10;
1337 devpriv->irq_dma_bits |= 0x18;
1340 devpriv->irq_dma_bits |= 0x28;
1343 devpriv->irq_dma_bits |= 0x30;
1346 devpriv->irq_dma_bits |= 0x38;
1352 /* an irq and one dma channel is required to use dma */
1353 if (dev->irq & it->options[2])
1354 das1800_init_dma(dev, it);
1356 devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, sizeof(uint16_t), GFP_KERNEL);
1357 if (!devpriv->fifo_buf)
1360 dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1361 I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1365 ret = comedi_alloc_subdevices(dev, 4);
1369 /* analog input subdevice */
1370 s = &dev->subdevices[0];
1371 s->type = COMEDI_SUBD_AI;
1372 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1374 s->subdev_flags |= SDF_COMMON;
1375 s->n_chan = board->qram_len;
1376 s->maxdata = (1 << board->resolution) - 1;
1377 s->range_table = board->range_ai;
1378 s->insn_read = das1800_ai_rinsn;
1380 dev->read_subdev = s;
1381 s->subdev_flags |= SDF_CMD_READ;
1382 s->len_chanlist = s->n_chan;
1383 s->do_cmd = das1800_ai_do_cmd;
1384 s->do_cmdtest = das1800_ai_do_cmdtest;
1385 s->poll = das1800_ai_poll;
1386 s->cancel = das1800_cancel;
1390 s = &dev->subdevices[1];
1391 if (board->ao_ability == 1) {
1392 s->type = COMEDI_SUBD_AO;
1393 s->subdev_flags = SDF_WRITABLE;
1394 s->n_chan = board->ao_n_chan;
1395 s->maxdata = (1 << board->resolution) - 1;
1396 s->range_table = &range_bipolar10;
1397 s->insn_write = das1800_ao_winsn;
1399 s->type = COMEDI_SUBD_UNUSED;
1403 s = &dev->subdevices[2];
1404 s->type = COMEDI_SUBD_DI;
1405 s->subdev_flags = SDF_READABLE;
1408 s->range_table = &range_digital;
1409 s->insn_bits = das1800_di_rbits;
1412 s = &dev->subdevices[3];
1413 s->type = COMEDI_SUBD_DO;
1414 s->subdev_flags = SDF_WRITABLE;
1415 s->n_chan = board->do_n_chan;
1417 s->range_table = &range_digital;
1418 s->insn_bits = das1800_do_wbits;
1420 das1800_cancel(dev, dev->read_subdev);
1422 /* initialize digital out channels */
1423 outb(0, dev->iobase + DAS1800_DIGITAL);
1425 /* initialize analog out channels */
1426 if (board->ao_ability == 1) {
1427 /* select 'update' dac channel for baseAddress + 0x0 */
1428 outb(DAC(board->ao_n_chan - 1),
1429 dev->iobase + DAS1800_SELECT);
1430 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1436 static void das1800_detach(struct comedi_device *dev)
1438 struct das1800_private *devpriv = dev->private;
1440 das1800_free_dma(dev);
1442 kfree(devpriv->fifo_buf);
1443 if (devpriv->iobase2)
1444 release_region(devpriv->iobase2, DAS1800_SIZE);
1446 comedi_legacy_detach(dev);
1449 static struct comedi_driver das1800_driver = {
1450 .driver_name = "das1800",
1451 .module = THIS_MODULE,
1452 .attach = das1800_attach,
1453 .detach = das1800_detach,
1454 .num_names = ARRAY_SIZE(das1800_boards),
1455 .board_name = &das1800_boards[0].name,
1456 .offset = sizeof(struct das1800_board),
1458 module_comedi_driver(das1800_driver);
1460 MODULE_AUTHOR("Comedi http://www.comedi.org");
1461 MODULE_DESCRIPTION("Comedi low-level driver");
1462 MODULE_LICENSE("GPL");