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>
101 #include "../comedidev.h"
106 #include "comedi_fc.h"
109 #define DAS1800_SIZE 16 /* uses 16 io addresses */
110 #define FIFO_SIZE 1024 /* 1024 sample fifo */
111 #define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */
112 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
114 /* Registers for the das1800 */
115 #define DAS1800_FIFO 0x0
116 #define DAS1800_QRAM 0x0
117 #define DAS1800_DAC 0x0
118 #define DAS1800_SELECT 0x2
121 #define DAC(a) (0x2 + a)
122 #define DAS1800_DIGITAL 0x3
123 #define DAS1800_CONTROL_A 0x4
130 #define DAS1800_CONTROL_B 0x5
134 #define DMA_CH5_CH6 0x5
135 #define DMA_CH6_CH7 0x6
136 #define DMA_CH7_CH5 0x7
137 #define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */
146 #define DAS1800_CONTROL_C 0X6
154 #define DAS1800_STATUS 0x7
155 /* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
156 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
163 #define CVEN_MASK 0x40 /* masks CVEN on write */
165 #define DAS1800_BURST_LENGTH 0x8
166 #define DAS1800_BURST_RATE 0x9
167 #define DAS1800_QRAM_ADDRESS 0xa
168 #define DAS1800_COUNTER 0xc
170 #define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */
173 das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
175 das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
176 das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
179 /* analog input ranges */
180 static const struct comedi_lrange range_ai_das1801 = {
193 static const struct comedi_lrange range_ai_das1802 = {
206 struct das1800_board {
208 int ai_speed; /* max conversion period in nanoseconds */
209 int resolution; /* bits of ai resolution */
210 int qram_len; /* length of card's channel / gain queue */
211 int common; /* supports AREF_COMMON flag */
212 int do_n_chan; /* number of digital output channels */
213 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
214 int ao_n_chan; /* number of analog out channels */
215 const struct comedi_lrange *range_ai; /* available input ranges */
218 /* Warning: the maximum conversion speeds listed below are
219 * not always achievable depending on board setup (see
222 static const struct das1800_board das1800_boards[] = {
224 .name = "das-1701st",
232 .range_ai = &range_ai_das1801,
235 .name = "das-1701st-da",
243 .range_ai = &range_ai_das1801,
246 .name = "das-1702st",
254 .range_ai = &range_ai_das1802,
257 .name = "das-1702st-da",
265 .range_ai = &range_ai_das1802,
268 .name = "das-1702hr",
276 .range_ai = &range_ai_das1802,
279 .name = "das-1702hr-da",
287 .range_ai = &range_ai_das1802,
290 .name = "das-1701ao",
298 .range_ai = &range_ai_das1801,
301 .name = "das-1702ao",
309 .range_ai = &range_ai_das1802,
312 .name = "das-1801st",
320 .range_ai = &range_ai_das1801,
323 .name = "das-1801st-da",
331 .range_ai = &range_ai_das1801,
334 .name = "das-1802st",
342 .range_ai = &range_ai_das1802,
345 .name = "das-1802st-da",
353 .range_ai = &range_ai_das1802,
356 .name = "das-1802hr",
364 .range_ai = &range_ai_das1802,
367 .name = "das-1802hr-da",
375 .range_ai = &range_ai_das1802,
378 .name = "das-1801hc",
386 .range_ai = &range_ai_das1801,
389 .name = "das-1802hc",
397 .range_ai = &range_ai_das1802,
400 .name = "das-1801ao",
408 .range_ai = &range_ai_das1801,
411 .name = "das-1802ao",
419 .range_ai = &range_ai_das1802,
423 struct das1800_private {
424 volatile unsigned int count; /* number of data points left to be taken */
425 unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */
426 unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */
427 int irq_dma_bits; /* bits for control register b */
428 /* dma bits for control register b, stored so that dma can be
429 * turned on and off */
431 unsigned int dma0; /* dma channels used */
433 volatile unsigned int dma_current; /* dma channel currently in use */
434 uint16_t *ai_buf0; /* pointers to dma buffers */
436 uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */
437 unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */
438 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */
439 unsigned short ao_update_bits; /* remembers the last write to the
443 /* analog out range for 'ao' boards */
445 static const struct comedi_lrange range_ao_2 = {
453 static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
456 const struct das1800_board *thisboard = comedi_board(dev);
458 sample += 1 << (thisboard->resolution - 1);
462 static void munge_data(struct comedi_device *dev, uint16_t *array,
463 unsigned int num_elements)
468 /* see if card is using a unipolar or bipolar range so we can munge data correctly */
469 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
471 /* convert to unsigned type if we are in a bipolar mode */
473 for (i = 0; i < num_elements; i++)
474 array[i] = munge_bipolar_sample(dev, array[i]);
478 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
479 struct comedi_subdevice *s)
481 struct das1800_private *devpriv = dev->private;
482 int numPoints = 0; /* number of points to read */
483 struct comedi_cmd *cmd = &s->async->cmd;
485 numPoints = FIFO_SIZE / 2;
486 /* if we only need some of the points */
487 if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
488 numPoints = devpriv->count;
489 insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
490 munge_data(dev, devpriv->ai_buf0, numPoints);
491 cfc_write_array_to_buffer(s, devpriv->ai_buf0,
492 numPoints * sizeof(devpriv->ai_buf0[0]));
493 if (cmd->stop_src == TRIG_COUNT)
494 devpriv->count -= numPoints;
498 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
499 struct comedi_subdevice *s)
501 struct das1800_private *devpriv = dev->private;
504 struct comedi_cmd *cmd = &s->async->cmd;
506 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
508 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
509 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
511 dpnt = inw(dev->iobase + DAS1800_FIFO);
512 /* convert to unsigned type if we are in a bipolar mode */
515 dpnt = munge_bipolar_sample(dev, dpnt);
516 cfc_write_to_buffer(s, dpnt);
517 if (cmd->stop_src == TRIG_COUNT)
524 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
525 * Assumes dma lock is held */
526 static void das1800_flush_dma_channel(struct comedi_device *dev,
527 struct comedi_subdevice *s,
528 unsigned int channel, uint16_t *buffer)
530 struct das1800_private *devpriv = dev->private;
531 unsigned int num_bytes, num_samples;
532 struct comedi_cmd *cmd = &s->async->cmd;
534 disable_dma(channel);
536 /* clear flip-flop to make sure 2-byte registers
537 * get set correctly */
538 clear_dma_ff(channel);
540 /* figure out how many points to read */
541 num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
542 num_samples = num_bytes / sizeof(short);
544 /* if we only need some of the points */
545 if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
546 num_samples = devpriv->count;
548 munge_data(dev, buffer, num_samples);
549 cfc_write_array_to_buffer(s, buffer, num_bytes);
550 if (s->async->cmd.stop_src == TRIG_COUNT)
551 devpriv->count -= num_samples;
556 /* flushes remaining data from board when external trigger has stopped acquisition
557 * and we are using dma transfers */
558 static void das1800_flush_dma(struct comedi_device *dev,
559 struct comedi_subdevice *s)
561 struct das1800_private *devpriv = dev->private;
563 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
565 flags = claim_dma_lock();
566 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
567 devpriv->dma_current_buf);
570 /* switch to other channel and flush it */
571 if (devpriv->dma_current == devpriv->dma0) {
572 devpriv->dma_current = devpriv->dma1;
573 devpriv->dma_current_buf = devpriv->ai_buf1;
575 devpriv->dma_current = devpriv->dma0;
576 devpriv->dma_current_buf = devpriv->ai_buf0;
578 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
579 devpriv->dma_current_buf);
582 release_dma_lock(flags);
584 /* get any remaining samples in fifo */
585 das1800_handle_fifo_not_empty(dev, s);
590 static void das1800_handle_dma(struct comedi_device *dev,
591 struct comedi_subdevice *s, unsigned int status)
593 struct das1800_private *devpriv = dev->private;
595 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
597 flags = claim_dma_lock();
598 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
599 devpriv->dma_current_buf);
600 /* re-enable dma channel */
601 set_dma_addr(devpriv->dma_current,
602 virt_to_bus(devpriv->dma_current_buf));
603 set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
604 enable_dma(devpriv->dma_current);
605 release_dma_lock(flags);
607 if (status & DMATC) {
608 /* clear DMATC interrupt bit */
609 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
610 /* switch dma channels for next time, if appropriate */
612 /* read data from the other channel next time */
613 if (devpriv->dma_current == devpriv->dma0) {
614 devpriv->dma_current = devpriv->dma1;
615 devpriv->dma_current_buf = devpriv->ai_buf1;
617 devpriv->dma_current = devpriv->dma0;
618 devpriv->dma_current_buf = devpriv->ai_buf0;
626 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
628 struct das1800_private *devpriv = dev->private;
630 outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */
631 outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */
632 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */
634 disable_dma(devpriv->dma0);
636 disable_dma(devpriv->dma1);
640 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
641 static void das1800_ai_handler(struct comedi_device *dev)
643 struct das1800_private *devpriv = dev->private;
644 struct comedi_subdevice *s = dev->read_subdev;
645 struct comedi_async *async = s->async;
646 struct comedi_cmd *cmd = &async->cmd;
647 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
649 /* select adc for base address + 0 */
650 outb(ADC, dev->iobase + DAS1800_SELECT);
651 /* dma buffer full */
652 if (devpriv->irq_dma_bits & DMA_ENABLED) {
653 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
654 das1800_handle_dma(dev, s, status);
655 } else if (status & FHF) { /* if fifo half full */
656 das1800_handle_fifo_half_full(dev, s);
657 } else if (status & FNE) { /* if fifo not empty */
658 das1800_handle_fifo_not_empty(dev, s);
661 async->events |= COMEDI_CB_BLOCK;
662 /* if the card's fifo has overflowed */
664 /* clear OVF interrupt bit */
665 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
666 comedi_error(dev, "DAS1800 FIFO overflow");
667 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
668 cfc_handle_events(dev, s);
671 /* stop taking data if appropriate */
672 /* stop_src TRIG_EXT */
673 if (status & CT0TC) {
674 /* clear CT0TC interrupt bit */
675 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
676 /* make sure we get all remaining data from board before quitting */
677 if (devpriv->irq_dma_bits & DMA_ENABLED)
678 das1800_flush_dma(dev, s);
680 das1800_handle_fifo_not_empty(dev, s);
681 async->events |= COMEDI_CB_EOA;
682 } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { /* stop_src TRIG_COUNT */
683 async->events |= COMEDI_CB_EOA;
686 cfc_handle_events(dev, s);
689 static int das1800_ai_poll(struct comedi_device *dev,
690 struct comedi_subdevice *s)
694 /* prevent race with interrupt handler */
695 spin_lock_irqsave(&dev->spinlock, flags);
696 das1800_ai_handler(dev);
697 spin_unlock_irqrestore(&dev->spinlock, flags);
699 return s->async->buf_write_count - s->async->buf_read_count;
702 static irqreturn_t das1800_interrupt(int irq, void *d)
704 struct comedi_device *dev = d;
707 if (!dev->attached) {
708 comedi_error(dev, "premature interrupt");
712 /* Prevent race with das1800_ai_poll() on multi processor systems.
713 * Also protects indirect addressing in das1800_ai_handler */
714 spin_lock(&dev->spinlock);
715 status = inb(dev->iobase + DAS1800_STATUS);
717 /* if interrupt was not caused by das-1800 */
718 if (!(status & INT)) {
719 spin_unlock(&dev->spinlock);
722 /* clear the interrupt status bit INT */
723 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
724 /* handle interrupt */
725 das1800_ai_handler(dev);
727 spin_unlock(&dev->spinlock);
731 /* converts requested conversion timing to timing compatible with
732 * hardware, used only when card is in 'burst mode'
734 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
736 unsigned int micro_sec;
738 /* in burst mode, the maximum conversion time is 64 microseconds */
739 if (convert_arg > 64000)
742 /* the conversion time must be an integral number of microseconds */
743 switch (round_mode) {
744 case TRIG_ROUND_NEAREST:
746 micro_sec = (convert_arg + 500) / 1000;
748 case TRIG_ROUND_DOWN:
749 micro_sec = convert_arg / 1000;
752 micro_sec = (convert_arg - 1) / 1000 + 1;
756 /* return number of nanoseconds */
757 return micro_sec * 1000;
760 static int das1800_ai_check_chanlist(struct comedi_device *dev,
761 struct comedi_subdevice *s,
762 struct comedi_cmd *cmd)
764 unsigned int unipolar0 = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
767 for (i = 1; i < cmd->chanlist_len; i++) {
768 unsigned int unipolar = CR_RANGE(cmd->chanlist[i]) & UNIPOLAR;
770 if (unipolar != unipolar0) {
771 dev_dbg(dev->class_dev,
772 "unipolar and bipolar ranges cannot be mixed in the chanlist\n");
780 /* test analog input cmd */
781 static int das1800_ai_do_cmdtest(struct comedi_device *dev,
782 struct comedi_subdevice *s,
783 struct comedi_cmd *cmd)
785 const struct das1800_board *thisboard = comedi_board(dev);
786 struct das1800_private *devpriv = dev->private;
788 unsigned int tmp_arg;
790 /* Step 1 : check if triggers are trivially valid */
792 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
793 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
794 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
795 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
796 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
797 err |= cfc_check_trigger_src(&cmd->stop_src,
798 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
803 /* Step 2a : make sure trigger sources are unique */
805 err |= cfc_check_trigger_is_unique(cmd->start_src);
806 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
807 err |= cfc_check_trigger_is_unique(cmd->convert_src);
808 err |= cfc_check_trigger_is_unique(cmd->stop_src);
810 /* Step 2b : and mutually compatible */
812 if (cmd->scan_begin_src != TRIG_FOLLOW &&
813 cmd->convert_src != TRIG_TIMER)
819 /* Step 3: check if arguments are trivially valid */
821 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
823 if (cmd->convert_src == TRIG_TIMER)
824 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
825 thisboard->ai_speed);
827 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
828 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
830 switch (cmd->stop_src) {
832 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
835 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
844 /* step 4: fix up any arguments */
846 if (cmd->convert_src == TRIG_TIMER) {
847 /* if we are not in burst mode */
848 if (cmd->scan_begin_src == TRIG_FOLLOW) {
849 tmp_arg = cmd->convert_arg;
850 /* calculate counter values that give desired timing */
851 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
856 if (tmp_arg != cmd->convert_arg)
859 /* if we are in burst mode */
861 /* check that convert_arg is compatible */
862 tmp_arg = cmd->convert_arg;
864 burst_convert_arg(cmd->convert_arg,
865 cmd->flags & TRIG_ROUND_MASK);
866 if (tmp_arg != cmd->convert_arg)
869 if (cmd->scan_begin_src == TRIG_TIMER) {
870 /* if scans are timed faster than conversion rate allows */
871 if (cmd->convert_arg * cmd->chanlist_len >
872 cmd->scan_begin_arg) {
873 cmd->scan_begin_arg =
878 tmp_arg = cmd->scan_begin_arg;
879 /* calculate counter values that give desired timing */
880 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
883 &cmd->scan_begin_arg,
885 if (tmp_arg != cmd->scan_begin_arg)
894 /* Step 5: check channel list if it exists */
895 if (cmd->chanlist && cmd->chanlist_len > 0)
896 err |= das1800_ai_check_chanlist(dev, s, cmd);
904 /* returns appropriate bits for control register a, depending on command */
905 static int control_a_bits(const struct comedi_cmd *cmd)
909 control_a = FFEN; /* enable fifo */
910 if (cmd->stop_src == TRIG_EXT)
912 switch (cmd->start_src) {
914 control_a |= TGEN | CGSL;
926 /* returns appropriate bits for control register c, depending on command */
927 static int control_c_bits(const struct comedi_cmd *cmd)
932 /* set clock source to internal or external, select analog reference,
933 * select unipolar / bipolar
935 aref = CR_AREF(cmd->chanlist[0]);
936 control_c = UQEN; /* enable upper qram addresses */
937 if (aref != AREF_DIFF)
939 if (aref == AREF_COMMON)
941 /* if a unipolar range was selected */
942 if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
944 switch (cmd->scan_begin_src) {
945 case TRIG_FOLLOW: /* not in burst mode */
946 switch (cmd->convert_src) {
948 /* trig on cascaded counters */
952 /* trig on falling edge of external trigger */
960 /* burst mode with internal pacer clock */
961 control_c |= BMDE | IPCLK;
964 /* burst mode with external trigger */
965 control_c |= BMDE | XPCLK;
974 /* loads counters with divisor1, divisor2 from private structure */
975 static int das1800_set_frequency(struct comedi_device *dev)
977 struct das1800_private *devpriv = dev->private;
980 /* counter 1, mode 2 */
981 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
984 /* counter 2, mode 2 */
985 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
994 /* sets up counters */
995 static int setup_counters(struct comedi_device *dev,
996 const struct comedi_cmd *cmd)
998 struct das1800_private *devpriv = dev->private;
1001 /* setup cascaded counters for conversion/scan frequency */
1002 switch (cmd->scan_begin_src) {
1003 case TRIG_FOLLOW: /* not in burst mode */
1004 if (cmd->convert_src == TRIG_TIMER) {
1005 /* set conversion frequency */
1006 period = cmd->convert_arg;
1007 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1010 &period, cmd->flags);
1011 if (das1800_set_frequency(dev) < 0)
1015 case TRIG_TIMER: /* in burst mode */
1016 /* set scan frequency */
1017 period = cmd->scan_begin_arg;
1018 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1021 &period, cmd->flags);
1022 if (das1800_set_frequency(dev) < 0)
1029 /* setup counter 0 for 'about triggering' */
1030 if (cmd->stop_src == TRIG_EXT) {
1031 /* load counter 0 in mode 0 */
1032 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1038 /* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1039 static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
1041 unsigned int size = DMA_BUF_SIZE;
1042 static const int sample_size = 2; /* size in bytes of one sample from board */
1043 unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */
1044 unsigned int max_size; /* maximum size we will allow for a transfer */
1046 /* make dma buffer fill in 0.3 seconds for timed modes */
1047 switch (cmd->scan_begin_src) {
1048 case TRIG_FOLLOW: /* not in burst mode */
1049 if (cmd->convert_src == TRIG_TIMER)
1050 size = (fill_time / cmd->convert_arg) * sample_size;
1053 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1057 size = DMA_BUF_SIZE;
1061 /* set a minimum and maximum size allowed */
1062 max_size = DMA_BUF_SIZE;
1063 /* if we are taking limited number of conversions, limit transfer size to that */
1064 if (cmd->stop_src == TRIG_COUNT &&
1065 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1066 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1068 if (size > max_size)
1070 if (size < sample_size)
1077 static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
1079 struct das1800_private *devpriv = dev->private;
1080 unsigned long lock_flags;
1081 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1083 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1086 /* determine a reasonable dma transfer size */
1087 devpriv->dma_transfer_size = suggest_transfer_size(cmd);
1088 lock_flags = claim_dma_lock();
1089 disable_dma(devpriv->dma0);
1090 /* clear flip-flop to make sure 2-byte registers for
1091 * count and address get set correctly */
1092 clear_dma_ff(devpriv->dma0);
1093 set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1094 /* set appropriate size of transfer */
1095 set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1096 devpriv->dma_current = devpriv->dma0;
1097 devpriv->dma_current_buf = devpriv->ai_buf0;
1098 enable_dma(devpriv->dma0);
1099 /* set up dual dma if appropriate */
1101 disable_dma(devpriv->dma1);
1102 /* clear flip-flop to make sure 2-byte registers for
1103 * count and address get set correctly */
1104 clear_dma_ff(devpriv->dma1);
1105 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1106 /* set appropriate size of transfer */
1107 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1108 enable_dma(devpriv->dma1);
1110 release_dma_lock(lock_flags);
1115 /* programs channel/gain list into card */
1116 static void program_chanlist(struct comedi_device *dev,
1117 const struct comedi_cmd *cmd)
1119 int i, n, chan_range;
1120 unsigned long irq_flags;
1121 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
1122 const int range_bitshift = 8;
1124 n = cmd->chanlist_len;
1125 /* spinlock protects indirect addressing */
1126 spin_lock_irqsave(&dev->spinlock, irq_flags);
1127 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1128 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
1129 /* make channel / gain list */
1130 for (i = 0; i < n; i++) {
1132 CR_CHAN(cmd->chanlist[i]) |
1133 ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
1135 outw(chan_range, dev->iobase + DAS1800_QRAM);
1137 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1138 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1143 /* analog input do_cmd */
1144 static int das1800_ai_do_cmd(struct comedi_device *dev,
1145 struct comedi_subdevice *s)
1147 struct das1800_private *devpriv = dev->private;
1149 int control_a, control_c;
1150 struct comedi_async *async = s->async;
1151 const struct comedi_cmd *cmd = &async->cmd;
1153 /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1154 * (because dma in handler is unsafe at hard real-time priority) */
1155 if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT))
1156 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1158 devpriv->irq_dma_bits |= devpriv->dma_bits;
1159 /* interrupt on end of conversion for TRIG_WAKE_EOS */
1160 if (cmd->flags & TRIG_WAKE_EOS) {
1161 /* interrupt fifo not empty */
1162 devpriv->irq_dma_bits &= ~FIMD;
1164 /* interrupt fifo half full */
1165 devpriv->irq_dma_bits |= FIMD;
1167 /* determine how many conversions we need */
1168 if (cmd->stop_src == TRIG_COUNT)
1169 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
1171 das1800_cancel(dev, s);
1173 /* determine proper bits for control registers */
1174 control_a = control_a_bits(cmd);
1175 control_c = control_c_bits(cmd);
1177 /* setup card and start */
1178 program_chanlist(dev, cmd);
1179 ret = setup_counters(dev, cmd);
1181 comedi_error(dev, "Error setting up counters");
1184 setup_dma(dev, cmd);
1185 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1186 /* set conversion rate and length for burst mode */
1187 if (control_c & BMDE) {
1188 /* program conversion period with number of microseconds minus 1 */
1189 outb(cmd->convert_arg / 1000 - 1,
1190 dev->iobase + DAS1800_BURST_RATE);
1191 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1193 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1194 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1195 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1200 /* read analog input */
1201 static int das1800_ai_rinsn(struct comedi_device *dev,
1202 struct comedi_subdevice *s,
1203 struct comedi_insn *insn, unsigned int *data)
1205 const struct das1800_board *thisboard = comedi_board(dev);
1207 int chan, range, aref, chan_range;
1209 unsigned short dpnt;
1211 unsigned long irq_flags;
1213 /* set up analog reference and unipolar / bipolar mode */
1214 aref = CR_AREF(insn->chanspec);
1216 if (aref != AREF_DIFF)
1218 if (aref == AREF_COMMON)
1220 /* if a unipolar range was selected */
1221 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1224 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1225 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1226 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1227 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1229 chan = CR_CHAN(insn->chanspec);
1230 /* mask of unipolar/bipolar bit from range */
1231 range = CR_RANGE(insn->chanspec) & 0x3;
1232 chan_range = chan | (range << 8);
1233 spin_lock_irqsave(&dev->spinlock, irq_flags);
1234 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1235 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1236 outw(chan_range, dev->iobase + DAS1800_QRAM);
1237 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1238 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1240 for (n = 0; n < insn->n; n++) {
1241 /* trigger conversion */
1242 outb(0, dev->iobase + DAS1800_FIFO);
1243 for (i = 0; i < timeout; i++) {
1244 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1248 comedi_error(dev, "timeout");
1252 dpnt = inw(dev->iobase + DAS1800_FIFO);
1253 /* shift data to offset binary for bipolar ranges */
1254 if ((conv_flags & UB) == 0)
1255 dpnt += 1 << (thisboard->resolution - 1);
1259 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1264 /* writes to an analog output channel */
1265 static int das1800_ao_winsn(struct comedi_device *dev,
1266 struct comedi_subdevice *s,
1267 struct comedi_insn *insn, unsigned int *data)
1269 const struct das1800_board *thisboard = comedi_board(dev);
1270 struct das1800_private *devpriv = dev->private;
1271 int chan = CR_CHAN(insn->chanspec);
1272 /* int range = CR_RANGE(insn->chanspec); */
1273 int update_chan = thisboard->ao_n_chan - 1;
1274 unsigned short output;
1275 unsigned long irq_flags;
1277 /* card expects two's complement data */
1278 output = data[0] - (1 << (thisboard->resolution - 1));
1279 /* if the write is to the 'update' channel, we need to remember its value */
1280 if (chan == update_chan)
1281 devpriv->ao_update_bits = output;
1282 /* write to channel */
1283 spin_lock_irqsave(&dev->spinlock, irq_flags);
1284 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1285 outw(output, dev->iobase + DAS1800_DAC);
1286 /* now we need to write to 'update' channel to update all dac channels */
1287 if (chan != update_chan) {
1288 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1289 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1291 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1296 /* reads from digital input channels */
1297 static int das1800_di_rbits(struct comedi_device *dev,
1298 struct comedi_subdevice *s,
1299 struct comedi_insn *insn, unsigned int *data)
1302 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1308 static int das1800_do_wbits(struct comedi_device *dev,
1309 struct comedi_subdevice *s,
1310 struct comedi_insn *insn,
1313 if (comedi_dio_update_state(s, data))
1314 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1321 static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
1324 struct das1800_private *devpriv = dev->private;
1325 unsigned long flags;
1327 /* need an irq to do dma */
1328 if (dev->irq && dma0) {
1329 /* encode dma0 and dma1 into 2 digit hexadecimal for switch */
1330 switch ((dma0 & 0x7) | (dma1 << 4)) {
1331 case 0x5: /* dma0 == 5 */
1332 devpriv->dma_bits |= DMA_CH5;
1334 case 0x6: /* dma0 == 6 */
1335 devpriv->dma_bits |= DMA_CH6;
1337 case 0x7: /* dma0 == 7 */
1338 devpriv->dma_bits |= DMA_CH7;
1340 case 0x65: /* dma0 == 5, dma1 == 6 */
1341 devpriv->dma_bits |= DMA_CH5_CH6;
1343 case 0x76: /* dma0 == 6, dma1 == 7 */
1344 devpriv->dma_bits |= DMA_CH6_CH7;
1346 case 0x57: /* dma0 == 7, dma1 == 5 */
1347 devpriv->dma_bits |= DMA_CH7_CH5;
1350 dev_err(dev->class_dev,
1351 "only supports dma channels 5 through 7\n");
1352 dev_err(dev->class_dev,
1353 "Dual dma only allows the following combinations:\n");
1354 dev_err(dev->class_dev,
1355 "dma 5,6 / 6,7 / or 7,5\n");
1359 if (request_dma(dma0, dev->driver->driver_name)) {
1360 dev_err(dev->class_dev,
1361 "failed to allocate dma channel %i\n", dma0);
1364 devpriv->dma0 = dma0;
1365 devpriv->dma_current = dma0;
1367 if (request_dma(dma1, dev->driver->driver_name)) {
1368 dev_err(dev->class_dev,
1369 "failed to allocate dma channel %i\n",
1373 devpriv->dma1 = dma1;
1375 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1376 if (devpriv->ai_buf0 == NULL)
1378 devpriv->dma_current_buf = devpriv->ai_buf0;
1381 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1382 if (devpriv->ai_buf1 == NULL)
1385 flags = claim_dma_lock();
1386 disable_dma(devpriv->dma0);
1387 set_dma_mode(devpriv->dma0, DMA_MODE_READ);
1389 disable_dma(devpriv->dma1);
1390 set_dma_mode(devpriv->dma1, DMA_MODE_READ);
1392 release_dma_lock(flags);
1397 static int das1800_probe(struct comedi_device *dev)
1402 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */
1403 board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
1407 if (board == das1801st_da || board == das1802st_da ||
1408 board == das1701st_da || board == das1702st_da) {
1409 dev_dbg(dev->class_dev, "Board model: %s\n",
1410 das1800_boards[board].name);
1414 (" Board model (probed, not recommended): das-1800st-da series\n");
1418 if (board == das1802hr_da || board == das1702hr_da) {
1419 dev_dbg(dev->class_dev, "Board model: %s\n",
1420 das1800_boards[board].name);
1424 (" Board model (probed, not recommended): das-1802hr-da\n");
1428 if (board == das1801ao || board == das1802ao ||
1429 board == das1701ao || board == das1702ao) {
1430 dev_dbg(dev->class_dev, "Board model: %s\n",
1431 das1800_boards[board].name);
1435 (" Board model (probed, not recommended): das-1800ao series\n");
1439 if (board == das1802hr || board == das1702hr) {
1440 dev_dbg(dev->class_dev, "Board model: %s\n",
1441 das1800_boards[board].name);
1445 (" Board model (probed, not recommended): das-1802hr\n");
1449 if (board == das1801st || board == das1802st ||
1450 board == das1701st || board == das1702st) {
1451 dev_dbg(dev->class_dev, "Board model: %s\n",
1452 das1800_boards[board].name);
1456 (" Board model (probed, not recommended): das-1800st series\n");
1460 if (board == das1801hc || board == das1802hc) {
1461 dev_dbg(dev->class_dev, "Board model: %s\n",
1462 das1800_boards[board].name);
1466 (" Board model (probed, not recommended): das-1800hc series\n");
1471 (" Board model: probe returned 0x%x (unknown, please report)\n",
1479 static int das1800_attach(struct comedi_device *dev,
1480 struct comedi_devconfig *it)
1482 const struct das1800_board *thisboard;
1483 struct das1800_private *devpriv;
1484 struct comedi_subdevice *s;
1485 unsigned int irq = it->options[1];
1486 unsigned int dma0 = it->options[2];
1487 unsigned int dma1 = it->options[3];
1491 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1495 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1499 board = das1800_probe(dev);
1501 dev_err(dev->class_dev, "unable to determine board type\n");
1505 dev->board_ptr = das1800_boards + board;
1506 thisboard = comedi_board(dev);
1507 dev->board_name = thisboard->name;
1509 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
1510 if (thisboard->ao_ability == 2) {
1511 unsigned long iobase2 = dev->iobase + IOBASE2;
1513 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1516 devpriv->iobase2 = iobase2;
1519 if (irq == 3 || irq == 5 || irq == 7 || irq == 10 || irq == 11 ||
1521 ret = request_irq(irq, das1800_interrupt, 0,
1522 dev->board_name, dev);
1528 devpriv->irq_dma_bits |= 0x8;
1531 devpriv->irq_dma_bits |= 0x10;
1534 devpriv->irq_dma_bits |= 0x18;
1537 devpriv->irq_dma_bits |= 0x28;
1540 devpriv->irq_dma_bits |= 0x30;
1543 devpriv->irq_dma_bits |= 0x38;
1549 ret = das1800_init_dma(dev, dma0, dma1);
1553 if (devpriv->ai_buf0 == NULL) {
1555 kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
1556 if (devpriv->ai_buf0 == NULL)
1560 ret = comedi_alloc_subdevices(dev, 4);
1564 /* analog input subdevice */
1565 s = &dev->subdevices[0];
1566 s->type = COMEDI_SUBD_AI;
1567 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
1568 if (thisboard->common)
1569 s->subdev_flags |= SDF_COMMON;
1570 s->n_chan = thisboard->qram_len;
1571 s->maxdata = (1 << thisboard->resolution) - 1;
1572 s->range_table = thisboard->range_ai;
1573 s->insn_read = das1800_ai_rinsn;
1575 dev->read_subdev = s;
1576 s->subdev_flags |= SDF_CMD_READ;
1577 s->len_chanlist = s->n_chan;
1578 s->do_cmd = das1800_ai_do_cmd;
1579 s->do_cmdtest = das1800_ai_do_cmdtest;
1580 s->poll = das1800_ai_poll;
1581 s->cancel = das1800_cancel;
1585 s = &dev->subdevices[1];
1586 if (thisboard->ao_ability == 1) {
1587 s->type = COMEDI_SUBD_AO;
1588 s->subdev_flags = SDF_WRITABLE;
1589 s->n_chan = thisboard->ao_n_chan;
1590 s->maxdata = (1 << thisboard->resolution) - 1;
1591 s->range_table = &range_bipolar10;
1592 s->insn_write = das1800_ao_winsn;
1594 s->type = COMEDI_SUBD_UNUSED;
1598 s = &dev->subdevices[2];
1599 s->type = COMEDI_SUBD_DI;
1600 s->subdev_flags = SDF_READABLE;
1603 s->range_table = &range_digital;
1604 s->insn_bits = das1800_di_rbits;
1607 s = &dev->subdevices[3];
1608 s->type = COMEDI_SUBD_DO;
1609 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1610 s->n_chan = thisboard->do_n_chan;
1612 s->range_table = &range_digital;
1613 s->insn_bits = das1800_do_wbits;
1615 das1800_cancel(dev, dev->read_subdev);
1617 /* initialize digital out channels */
1618 outb(0, dev->iobase + DAS1800_DIGITAL);
1620 /* initialize analog out channels */
1621 if (thisboard->ao_ability == 1) {
1622 /* select 'update' dac channel for baseAddress + 0x0 */
1623 outb(DAC(thisboard->ao_n_chan - 1),
1624 dev->iobase + DAS1800_SELECT);
1625 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1631 static void das1800_detach(struct comedi_device *dev)
1633 struct das1800_private *devpriv = dev->private;
1637 free_dma(devpriv->dma0);
1639 free_dma(devpriv->dma1);
1640 kfree(devpriv->ai_buf0);
1641 kfree(devpriv->ai_buf1);
1642 if (devpriv->iobase2)
1643 release_region(devpriv->iobase2, DAS1800_SIZE);
1645 comedi_legacy_detach(dev);
1648 static struct comedi_driver das1800_driver = {
1649 .driver_name = "das1800",
1650 .module = THIS_MODULE,
1651 .attach = das1800_attach,
1652 .detach = das1800_detach,
1653 .num_names = ARRAY_SIZE(das1800_boards),
1654 .board_name = &das1800_boards[0].name,
1655 .offset = sizeof(struct das1800_board),
1657 module_comedi_driver(das1800_driver);
1659 MODULE_AUTHOR("Comedi http://www.comedi.org");
1660 MODULE_DESCRIPTION("Comedi low-level driver");
1661 MODULE_LICENSE("GPL");