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 *thisboard = dev->board_ptr;
449 sample += 1 << (thisboard->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 outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */
571 outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */
572 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */
574 for (i = 0; i < 2; i++) {
575 desc = &dma->desc[i];
577 comedi_isadma_disable(desc->chan);
583 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
584 static void das1800_ai_handler(struct comedi_device *dev)
586 struct das1800_private *devpriv = dev->private;
587 struct comedi_subdevice *s = dev->read_subdev;
588 struct comedi_async *async = s->async;
589 struct comedi_cmd *cmd = &async->cmd;
590 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
592 /* select adc for base address + 0 */
593 outb(ADC, dev->iobase + DAS1800_SELECT);
594 /* dma buffer full */
595 if (devpriv->irq_dma_bits & DMA_ENABLED) {
596 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
597 das1800_handle_dma(dev, s, status);
598 } else if (status & FHF) { /* if fifo half full */
599 das1800_handle_fifo_half_full(dev, s);
600 } else if (status & FNE) { /* if fifo not empty */
601 das1800_handle_fifo_not_empty(dev, s);
604 /* if the card's fifo has overflowed */
606 /* clear OVF interrupt bit */
607 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
608 dev_err(dev->class_dev, "FIFO overflow\n");
609 async->events |= COMEDI_CB_ERROR;
610 comedi_handle_events(dev, s);
613 /* stop taking data if appropriate */
614 /* stop_src TRIG_EXT */
615 if (status & CT0TC) {
616 /* clear CT0TC interrupt bit */
617 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
618 /* make sure we get all remaining data from board before quitting */
619 if (devpriv->irq_dma_bits & DMA_ENABLED)
620 das1800_flush_dma(dev, s);
622 das1800_handle_fifo_not_empty(dev, s);
623 async->events |= COMEDI_CB_EOA;
624 } else if (cmd->stop_src == TRIG_COUNT &&
625 async->scans_done >= cmd->stop_arg) {
626 async->events |= COMEDI_CB_EOA;
629 comedi_handle_events(dev, s);
632 static int das1800_ai_poll(struct comedi_device *dev,
633 struct comedi_subdevice *s)
637 /* prevent race with interrupt handler */
638 spin_lock_irqsave(&dev->spinlock, flags);
639 das1800_ai_handler(dev);
640 spin_unlock_irqrestore(&dev->spinlock, flags);
642 return comedi_buf_n_bytes_ready(s);
645 static irqreturn_t das1800_interrupt(int irq, void *d)
647 struct comedi_device *dev = d;
650 if (!dev->attached) {
651 dev_err(dev->class_dev, "premature interrupt\n");
655 /* Prevent race with das1800_ai_poll() on multi processor systems.
656 * Also protects indirect addressing in das1800_ai_handler */
657 spin_lock(&dev->spinlock);
658 status = inb(dev->iobase + DAS1800_STATUS);
660 /* if interrupt was not caused by das-1800 */
661 if (!(status & INT)) {
662 spin_unlock(&dev->spinlock);
665 /* clear the interrupt status bit INT */
666 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
667 /* handle interrupt */
668 das1800_ai_handler(dev);
670 spin_unlock(&dev->spinlock);
674 /* converts requested conversion timing to timing compatible with
675 * hardware, used only when card is in 'burst mode'
677 static unsigned int burst_convert_arg(unsigned int convert_arg, int flags)
679 unsigned int micro_sec;
681 /* in burst mode, the maximum conversion time is 64 microseconds */
682 if (convert_arg > 64000)
685 /* the conversion time must be an integral number of microseconds */
686 switch (flags & CMDF_ROUND_MASK) {
687 case CMDF_ROUND_NEAREST:
689 micro_sec = (convert_arg + 500) / 1000;
691 case CMDF_ROUND_DOWN:
692 micro_sec = convert_arg / 1000;
695 micro_sec = (convert_arg - 1) / 1000 + 1;
699 /* return number of nanoseconds */
700 return micro_sec * 1000;
703 static int das1800_ai_check_chanlist(struct comedi_device *dev,
704 struct comedi_subdevice *s,
705 struct comedi_cmd *cmd)
707 unsigned int unipolar0 = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
710 for (i = 1; i < cmd->chanlist_len; i++) {
711 unsigned int unipolar = CR_RANGE(cmd->chanlist[i]) & UNIPOLAR;
713 if (unipolar != unipolar0) {
714 dev_dbg(dev->class_dev,
715 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
723 /* test analog input cmd */
724 static int das1800_ai_do_cmdtest(struct comedi_device *dev,
725 struct comedi_subdevice *s,
726 struct comedi_cmd *cmd)
728 const struct das1800_board *thisboard = dev->board_ptr;
732 /* Step 1 : check if triggers are trivially valid */
734 err |= comedi_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
735 err |= comedi_check_trigger_src(&cmd->scan_begin_src,
736 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
737 err |= comedi_check_trigger_src(&cmd->convert_src,
738 TRIG_TIMER | TRIG_EXT);
739 err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
740 err |= comedi_check_trigger_src(&cmd->stop_src,
741 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
746 /* Step 2a : make sure trigger sources are unique */
748 err |= comedi_check_trigger_is_unique(cmd->start_src);
749 err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
750 err |= comedi_check_trigger_is_unique(cmd->convert_src);
751 err |= comedi_check_trigger_is_unique(cmd->stop_src);
753 /* Step 2b : and mutually compatible */
755 if (cmd->scan_begin_src != TRIG_FOLLOW &&
756 cmd->convert_src != TRIG_TIMER)
762 /* Step 3: check if arguments are trivially valid */
764 err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
766 if (cmd->convert_src == TRIG_TIMER) {
767 err |= comedi_check_trigger_arg_min(&cmd->convert_arg,
768 thisboard->ai_speed);
771 err |= comedi_check_trigger_arg_min(&cmd->chanlist_len, 1);
772 err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
775 switch (cmd->stop_src) {
777 err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
780 err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
789 /* step 4: fix up any arguments */
791 if (cmd->scan_begin_src == TRIG_FOLLOW &&
792 cmd->convert_src == TRIG_TIMER) {
793 /* we are not in burst mode */
794 arg = cmd->convert_arg;
795 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
796 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
797 } else if (cmd->convert_src == TRIG_TIMER) {
798 /* we are in burst mode */
799 arg = burst_convert_arg(cmd->convert_arg, cmd->flags);
800 err |= comedi_check_trigger_arg_is(&cmd->convert_arg, arg);
802 if (cmd->scan_begin_src == TRIG_TIMER) {
803 arg = cmd->convert_arg * cmd->chanlist_len;
804 err |= comedi_check_trigger_arg_max(&cmd->
808 arg = cmd->scan_begin_arg;
809 comedi_8254_cascade_ns_to_timer(dev->pacer, &arg,
811 err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg,
819 /* Step 5: check channel list if it exists */
820 if (cmd->chanlist && cmd->chanlist_len > 0)
821 err |= das1800_ai_check_chanlist(dev, s, cmd);
829 /* returns appropriate bits for control register a, depending on command */
830 static int control_a_bits(const struct comedi_cmd *cmd)
834 control_a = FFEN; /* enable fifo */
835 if (cmd->stop_src == TRIG_EXT)
837 switch (cmd->start_src) {
839 control_a |= TGEN | CGSL;
851 /* returns appropriate bits for control register c, depending on command */
852 static int control_c_bits(const struct comedi_cmd *cmd)
857 /* set clock source to internal or external, select analog reference,
858 * select unipolar / bipolar
860 aref = CR_AREF(cmd->chanlist[0]);
861 control_c = UQEN; /* enable upper qram addresses */
862 if (aref != AREF_DIFF)
864 if (aref == AREF_COMMON)
866 /* if a unipolar range was selected */
867 if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
869 switch (cmd->scan_begin_src) {
870 case TRIG_FOLLOW: /* not in burst mode */
871 switch (cmd->convert_src) {
873 /* trig on cascaded counters */
877 /* trig on falling edge of external trigger */
885 /* burst mode with internal pacer clock */
886 control_c |= BMDE | IPCLK;
889 /* burst mode with external trigger */
890 control_c |= BMDE | XPCLK;
899 static unsigned int das1800_ai_transfer_size(struct comedi_device *dev,
900 struct comedi_subdevice *s,
901 unsigned int maxbytes,
904 struct comedi_cmd *cmd = &s->async->cmd;
905 unsigned int max_samples = comedi_bytes_to_samples(s, maxbytes);
906 unsigned int samples;
908 samples = max_samples;
910 /* for timed modes, make dma buffer fill in 'ns' time */
911 switch (cmd->scan_begin_src) {
912 case TRIG_FOLLOW: /* not in burst mode */
913 if (cmd->convert_src == TRIG_TIMER)
914 samples = ns / cmd->convert_arg;
917 samples = ns / (cmd->scan_begin_arg * cmd->chanlist_len);
921 /* limit samples to what is remaining in the command */
922 samples = comedi_nsamples_left(s, samples);
924 if (samples > max_samples)
925 samples = max_samples;
929 return comedi_samples_to_bytes(s, samples);
932 static void das1800_ai_setup_dma(struct comedi_device *dev,
933 struct comedi_subdevice *s)
935 struct das1800_private *devpriv = dev->private;
936 struct comedi_isadma *dma = devpriv->dma;
937 struct comedi_isadma_desc *desc = &dma->desc[0];
940 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
945 /* determine a dma transfer size to fill buffer in 0.3 sec */
946 bytes = das1800_ai_transfer_size(dev, s, desc->maxsize, 300000000);
949 comedi_isadma_program(desc);
951 /* set up dual dma if appropriate */
952 if (devpriv->irq_dma_bits & DMA_DUAL) {
953 desc = &dma->desc[1];
955 comedi_isadma_program(desc);
959 /* programs channel/gain list into card */
960 static void program_chanlist(struct comedi_device *dev,
961 const struct comedi_cmd *cmd)
963 int i, n, chan_range;
964 unsigned long irq_flags;
965 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
966 const int range_bitshift = 8;
968 n = cmd->chanlist_len;
969 /* spinlock protects indirect addressing */
970 spin_lock_irqsave(&dev->spinlock, irq_flags);
971 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
972 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
973 /* make channel / gain list */
974 for (i = 0; i < n; i++) {
976 CR_CHAN(cmd->chanlist[i]) |
977 ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
979 outw(chan_range, dev->iobase + DAS1800_QRAM);
981 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
982 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
985 /* analog input do_cmd */
986 static int das1800_ai_do_cmd(struct comedi_device *dev,
987 struct comedi_subdevice *s)
989 struct das1800_private *devpriv = dev->private;
990 int control_a, control_c;
991 struct comedi_async *async = s->async;
992 const struct comedi_cmd *cmd = &async->cmd;
994 /* disable dma on CMDF_WAKE_EOS, or CMDF_PRIORITY
995 * (because dma in handler is unsafe at hard real-time priority) */
996 if (cmd->flags & (CMDF_WAKE_EOS | CMDF_PRIORITY))
997 devpriv->irq_dma_bits &= ~DMA_ENABLED;
999 devpriv->irq_dma_bits |= devpriv->dma_bits;
1000 /* interrupt on end of conversion for CMDF_WAKE_EOS */
1001 if (cmd->flags & CMDF_WAKE_EOS) {
1002 /* interrupt fifo not empty */
1003 devpriv->irq_dma_bits &= ~FIMD;
1005 /* interrupt fifo half full */
1006 devpriv->irq_dma_bits |= FIMD;
1009 das1800_cancel(dev, s);
1011 /* determine proper bits for control registers */
1012 control_a = control_a_bits(cmd);
1013 control_c = control_c_bits(cmd);
1015 /* setup card and start */
1016 program_chanlist(dev, cmd);
1018 /* setup cascaded counters for conversion/scan frequency */
1019 if ((cmd->scan_begin_src == TRIG_FOLLOW ||
1020 cmd->scan_begin_src == TRIG_TIMER) &&
1021 cmd->convert_src == TRIG_TIMER) {
1022 comedi_8254_update_divisors(dev->pacer);
1023 comedi_8254_pacer_enable(dev->pacer, 1, 2, true);
1026 /* setup counter 0 for 'about triggering' */
1027 if (cmd->stop_src == TRIG_EXT)
1028 comedi_8254_load(dev->pacer, 0, 1, I8254_MODE0 | I8254_BINARY);
1030 das1800_ai_setup_dma(dev, s);
1031 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1032 /* set conversion rate and length for burst mode */
1033 if (control_c & BMDE) {
1034 /* program conversion period with number of microseconds minus 1 */
1035 outb(cmd->convert_arg / 1000 - 1,
1036 dev->iobase + DAS1800_BURST_RATE);
1037 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1039 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1040 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1041 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1046 /* read analog input */
1047 static int das1800_ai_rinsn(struct comedi_device *dev,
1048 struct comedi_subdevice *s,
1049 struct comedi_insn *insn, unsigned int *data)
1051 const struct das1800_board *thisboard = dev->board_ptr;
1053 int chan, range, aref, chan_range;
1055 unsigned short dpnt;
1057 unsigned long irq_flags;
1059 /* set up analog reference and unipolar / bipolar mode */
1060 aref = CR_AREF(insn->chanspec);
1062 if (aref != AREF_DIFF)
1064 if (aref == AREF_COMMON)
1066 /* if a unipolar range was selected */
1067 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1070 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1071 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1072 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1073 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1075 chan = CR_CHAN(insn->chanspec);
1076 /* mask of unipolar/bipolar bit from range */
1077 range = CR_RANGE(insn->chanspec) & 0x3;
1078 chan_range = chan | (range << 8);
1079 spin_lock_irqsave(&dev->spinlock, irq_flags);
1080 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1081 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1082 outw(chan_range, dev->iobase + DAS1800_QRAM);
1083 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1084 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1086 for (n = 0; n < insn->n; n++) {
1087 /* trigger conversion */
1088 outb(0, dev->iobase + DAS1800_FIFO);
1089 for (i = 0; i < timeout; i++) {
1090 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1094 dev_err(dev->class_dev, "timeout\n");
1098 dpnt = inw(dev->iobase + DAS1800_FIFO);
1099 /* shift data to offset binary for bipolar ranges */
1100 if ((conv_flags & UB) == 0)
1101 dpnt += 1 << (thisboard->resolution - 1);
1105 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1110 /* writes to an analog output channel */
1111 static int das1800_ao_winsn(struct comedi_device *dev,
1112 struct comedi_subdevice *s,
1113 struct comedi_insn *insn, unsigned int *data)
1115 const struct das1800_board *thisboard = dev->board_ptr;
1116 struct das1800_private *devpriv = dev->private;
1117 int chan = CR_CHAN(insn->chanspec);
1118 /* int range = CR_RANGE(insn->chanspec); */
1119 int update_chan = thisboard->ao_n_chan - 1;
1120 unsigned short output;
1121 unsigned long irq_flags;
1123 /* card expects two's complement data */
1124 output = data[0] - (1 << (thisboard->resolution - 1));
1125 /* if the write is to the 'update' channel, we need to remember its value */
1126 if (chan == update_chan)
1127 devpriv->ao_update_bits = output;
1128 /* write to channel */
1129 spin_lock_irqsave(&dev->spinlock, irq_flags);
1130 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1131 outw(output, dev->iobase + DAS1800_DAC);
1132 /* now we need to write to 'update' channel to update all dac channels */
1133 if (chan != update_chan) {
1134 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1135 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1137 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1142 /* reads from digital input channels */
1143 static int das1800_di_rbits(struct comedi_device *dev,
1144 struct comedi_subdevice *s,
1145 struct comedi_insn *insn, unsigned int *data)
1147 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1153 static int das1800_do_wbits(struct comedi_device *dev,
1154 struct comedi_subdevice *s,
1155 struct comedi_insn *insn,
1158 if (comedi_dio_update_state(s, data))
1159 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1166 static void das1800_init_dma(struct comedi_device *dev,
1167 struct comedi_devconfig *it)
1169 struct das1800_private *devpriv = dev->private;
1170 unsigned int *dma_chan;
1173 * it->options[2] is DMA channel 0
1174 * it->options[3] is DMA channel 1
1176 * Encode the DMA channels into 2 digit hexadecimal for switch.
1178 dma_chan = &it->options[2];
1180 switch ((dma_chan[0] & 0x7) | (dma_chan[1] << 4)) {
1181 case 0x5: /* dma0 == 5 */
1182 devpriv->dma_bits = DMA_CH5;
1184 case 0x6: /* dma0 == 6 */
1185 devpriv->dma_bits = DMA_CH6;
1187 case 0x7: /* dma0 == 7 */
1188 devpriv->dma_bits = DMA_CH7;
1190 case 0x65: /* dma0 == 5, dma1 == 6 */
1191 devpriv->dma_bits = DMA_CH5_CH6;
1193 case 0x76: /* dma0 == 6, dma1 == 7 */
1194 devpriv->dma_bits = DMA_CH6_CH7;
1196 case 0x57: /* dma0 == 7, dma1 == 5 */
1197 devpriv->dma_bits = DMA_CH7_CH5;
1203 /* DMA can use 1 or 2 buffers, each with a separate channel */
1204 devpriv->dma = comedi_isadma_alloc(dev, dma_chan[1] ? 2 : 1,
1205 dma_chan[0], dma_chan[1],
1206 DMA_BUF_SIZE, COMEDI_ISADMA_READ);
1208 devpriv->dma_bits = 0;
1211 static void das1800_free_dma(struct comedi_device *dev)
1213 struct das1800_private *devpriv = dev->private;
1216 comedi_isadma_free(devpriv->dma);
1219 static int das1800_probe(struct comedi_device *dev)
1221 const struct das1800_board *board = dev->board_ptr;
1225 /* calc the offset to the boardinfo that was found by the core */
1226 index = board - das1800_boards;
1228 /* verify that the board id matches the boardinfo */
1229 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;
1232 if (index == das1801st_da || index == das1802st_da ||
1233 index == das1701st_da || index == das1702st_da)
1238 if (index == das1802hr_da || index == das1702hr_da)
1243 if (index == das1801ao || index == das1802ao ||
1244 index == das1701ao || index == das1702ao)
1249 if (index == das1802hr || index == das1702hr)
1254 if (index == das1801st || index == das1802st ||
1255 index == das1701st || index == das1702st)
1260 if (index == das1801hc || index == das1802hc)
1265 dev_err(dev->class_dev,
1266 "Board model: probe returned 0x%x (unknown, please report)\n",
1270 dev_err(dev->class_dev,
1271 "Board model (probed, not recommended): %s series\n",
1272 das1800_boards[index].name);
1277 static int das1800_attach(struct comedi_device *dev,
1278 struct comedi_devconfig *it)
1280 const struct das1800_board *thisboard;
1281 struct das1800_private *devpriv;
1282 struct comedi_subdevice *s;
1283 unsigned int irq = it->options[1];
1287 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1291 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1295 board = das1800_probe(dev);
1297 dev_err(dev->class_dev, "unable to determine board type\n");
1301 dev->board_ptr = das1800_boards + board;
1302 thisboard = dev->board_ptr;
1303 dev->board_name = thisboard->name;
1305 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
1306 if (thisboard->ao_ability == 2) {
1307 unsigned long iobase2 = dev->iobase + IOBASE2;
1309 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1312 devpriv->iobase2 = iobase2;
1315 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1317 ret = request_irq(irq, das1800_interrupt, 0,
1318 dev->board_name, dev);
1324 devpriv->irq_dma_bits |= 0x8;
1327 devpriv->irq_dma_bits |= 0x10;
1330 devpriv->irq_dma_bits |= 0x18;
1333 devpriv->irq_dma_bits |= 0x28;
1336 devpriv->irq_dma_bits |= 0x30;
1339 devpriv->irq_dma_bits |= 0x38;
1345 /* an irq and one dma channel is required to use dma */
1346 if (dev->irq & it->options[2])
1347 das1800_init_dma(dev, it);
1349 devpriv->fifo_buf = kmalloc_array(FIFO_SIZE, sizeof(uint16_t), GFP_KERNEL);
1350 if (!devpriv->fifo_buf)
1353 dev->pacer = comedi_8254_init(dev->iobase + DAS1800_COUNTER,
1354 I8254_OSC_BASE_5MHZ, I8254_IO8, 0);
1358 ret = comedi_alloc_subdevices(dev, 4);
1362 /* analog input subdevice */
1363 s = &dev->subdevices[0];
1364 s->type = COMEDI_SUBD_AI;
1365 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1366 if (thisboard->common)
1367 s->subdev_flags |= SDF_COMMON;
1368 s->n_chan = thisboard->qram_len;
1369 s->maxdata = (1 << thisboard->resolution) - 1;
1370 s->range_table = thisboard->range_ai;
1371 s->insn_read = das1800_ai_rinsn;
1373 dev->read_subdev = s;
1374 s->subdev_flags |= SDF_CMD_READ;
1375 s->len_chanlist = s->n_chan;
1376 s->do_cmd = das1800_ai_do_cmd;
1377 s->do_cmdtest = das1800_ai_do_cmdtest;
1378 s->poll = das1800_ai_poll;
1379 s->cancel = das1800_cancel;
1383 s = &dev->subdevices[1];
1384 if (thisboard->ao_ability == 1) {
1385 s->type = COMEDI_SUBD_AO;
1386 s->subdev_flags = SDF_WRITABLE;
1387 s->n_chan = thisboard->ao_n_chan;
1388 s->maxdata = (1 << thisboard->resolution) - 1;
1389 s->range_table = &range_bipolar10;
1390 s->insn_write = das1800_ao_winsn;
1392 s->type = COMEDI_SUBD_UNUSED;
1396 s = &dev->subdevices[2];
1397 s->type = COMEDI_SUBD_DI;
1398 s->subdev_flags = SDF_READABLE;
1401 s->range_table = &range_digital;
1402 s->insn_bits = das1800_di_rbits;
1405 s = &dev->subdevices[3];
1406 s->type = COMEDI_SUBD_DO;
1407 s->subdev_flags = SDF_WRITABLE;
1408 s->n_chan = thisboard->do_n_chan;
1410 s->range_table = &range_digital;
1411 s->insn_bits = das1800_do_wbits;
1413 das1800_cancel(dev, dev->read_subdev);
1415 /* initialize digital out channels */
1416 outb(0, dev->iobase + DAS1800_DIGITAL);
1418 /* initialize analog out channels */
1419 if (thisboard->ao_ability == 1) {
1420 /* select 'update' dac channel for baseAddress + 0x0 */
1421 outb(DAC(thisboard->ao_n_chan - 1),
1422 dev->iobase + DAS1800_SELECT);
1423 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1429 static void das1800_detach(struct comedi_device *dev)
1431 struct das1800_private *devpriv = dev->private;
1433 das1800_free_dma(dev);
1435 kfree(devpriv->fifo_buf);
1436 if (devpriv->iobase2)
1437 release_region(devpriv->iobase2, DAS1800_SIZE);
1439 comedi_legacy_detach(dev);
1442 static struct comedi_driver das1800_driver = {
1443 .driver_name = "das1800",
1444 .module = THIS_MODULE,
1445 .attach = das1800_attach,
1446 .detach = das1800_detach,
1447 .num_names = ARRAY_SIZE(das1800_boards),
1448 .board_name = &das1800_boards[0].name,
1449 .offset = sizeof(struct das1800_board),
1451 module_comedi_driver(das1800_driver);
1453 MODULE_AUTHOR("Comedi http://www.comedi.org");
1454 MODULE_DESCRIPTION("Comedi low-level driver");
1455 MODULE_LICENSE("GPL");