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 = {
194 static const struct comedi_lrange range_ai_das1802 = {
208 struct das1800_board {
210 int ai_speed; /* max conversion period in nanoseconds */
211 int resolution; /* bits of ai resolution */
212 int qram_len; /* length of card's channel / gain queue */
213 int common; /* supports AREF_COMMON flag */
214 int do_n_chan; /* number of digital output channels */
215 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
216 int ao_n_chan; /* number of analog out channels */
217 const struct comedi_lrange *range_ai; /* available input ranges */
220 /* Warning: the maximum conversion speeds listed below are
221 * not always achievable depending on board setup (see
224 static const struct das1800_board das1800_boards[] = {
226 .name = "das-1701st",
234 .range_ai = &range_ai_das1801,
237 .name = "das-1701st-da",
245 .range_ai = &range_ai_das1801,
248 .name = "das-1702st",
256 .range_ai = &range_ai_das1802,
259 .name = "das-1702st-da",
267 .range_ai = &range_ai_das1802,
270 .name = "das-1702hr",
278 .range_ai = &range_ai_das1802,
281 .name = "das-1702hr-da",
289 .range_ai = &range_ai_das1802,
292 .name = "das-1701ao",
300 .range_ai = &range_ai_das1801,
303 .name = "das-1702ao",
311 .range_ai = &range_ai_das1802,
314 .name = "das-1801st",
322 .range_ai = &range_ai_das1801,
325 .name = "das-1801st-da",
333 .range_ai = &range_ai_das1801,
336 .name = "das-1802st",
344 .range_ai = &range_ai_das1802,
347 .name = "das-1802st-da",
355 .range_ai = &range_ai_das1802,
358 .name = "das-1802hr",
366 .range_ai = &range_ai_das1802,
369 .name = "das-1802hr-da",
377 .range_ai = &range_ai_das1802,
380 .name = "das-1801hc",
388 .range_ai = &range_ai_das1801,
391 .name = "das-1802hc",
399 .range_ai = &range_ai_das1802,
402 .name = "das-1801ao",
410 .range_ai = &range_ai_das1801,
413 .name = "das-1802ao",
421 .range_ai = &range_ai_das1802,
425 struct das1800_private {
426 volatile unsigned int count; /* number of data points left to be taken */
427 unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */
428 unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */
429 int irq_dma_bits; /* bits for control register b */
430 /* dma bits for control register b, stored so that dma can be
431 * turned on and off */
433 unsigned int dma0; /* dma channels used */
435 volatile unsigned int dma_current; /* dma channel currently in use */
436 uint16_t *ai_buf0; /* pointers to dma buffers */
438 uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */
439 unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */
440 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */
441 short ao_update_bits; /* remembers the last write to the 'update' dac */
444 /* analog out range for 'ao' boards */
446 static const struct comedi_lrange range_ao_2 = {
455 static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
458 const struct das1800_board *thisboard = comedi_board(dev);
460 sample += 1 << (thisboard->resolution - 1);
464 static void munge_data(struct comedi_device *dev, uint16_t * array,
465 unsigned int num_elements)
470 /* see if card is using a unipolar or bipolar range so we can munge data correctly */
471 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
473 /* convert to unsigned type if we are in a bipolar mode */
475 for (i = 0; i < num_elements; i++)
476 array[i] = munge_bipolar_sample(dev, array[i]);
480 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
481 struct comedi_subdevice *s)
483 struct das1800_private *devpriv = dev->private;
484 int numPoints = 0; /* number of points to read */
485 struct comedi_cmd *cmd = &s->async->cmd;
487 numPoints = FIFO_SIZE / 2;
488 /* if we only need some of the points */
489 if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
490 numPoints = devpriv->count;
491 insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
492 munge_data(dev, devpriv->ai_buf0, numPoints);
493 cfc_write_array_to_buffer(s, devpriv->ai_buf0,
494 numPoints * sizeof(devpriv->ai_buf0[0]));
495 if (cmd->stop_src == TRIG_COUNT)
496 devpriv->count -= numPoints;
500 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
501 struct comedi_subdevice *s)
503 struct das1800_private *devpriv = dev->private;
506 struct comedi_cmd *cmd = &s->async->cmd;
508 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
510 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
511 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
513 dpnt = inw(dev->iobase + DAS1800_FIFO);
514 /* convert to unsigned type if we are in a bipolar mode */
517 dpnt = munge_bipolar_sample(dev, dpnt);
518 cfc_write_to_buffer(s, dpnt);
519 if (cmd->stop_src == TRIG_COUNT)
526 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
527 * Assumes dma lock is held */
528 static void das1800_flush_dma_channel(struct comedi_device *dev,
529 struct comedi_subdevice *s,
530 unsigned int channel, uint16_t *buffer)
532 struct das1800_private *devpriv = dev->private;
533 unsigned int num_bytes, num_samples;
534 struct comedi_cmd *cmd = &s->async->cmd;
536 disable_dma(channel);
538 /* clear flip-flop to make sure 2-byte registers
539 * get set correctly */
540 clear_dma_ff(channel);
542 /* figure out how many points to read */
543 num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
544 num_samples = num_bytes / sizeof(short);
546 /* if we only need some of the points */
547 if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
548 num_samples = devpriv->count;
550 munge_data(dev, buffer, num_samples);
551 cfc_write_array_to_buffer(s, buffer, num_bytes);
552 if (s->async->cmd.stop_src == TRIG_COUNT)
553 devpriv->count -= num_samples;
558 /* flushes remaining data from board when external trigger has stopped acquisition
559 * and we are using dma transfers */
560 static void das1800_flush_dma(struct comedi_device *dev,
561 struct comedi_subdevice *s)
563 struct das1800_private *devpriv = dev->private;
565 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
567 flags = claim_dma_lock();
568 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
569 devpriv->dma_current_buf);
572 /* switch to other channel and flush it */
573 if (devpriv->dma_current == devpriv->dma0) {
574 devpriv->dma_current = devpriv->dma1;
575 devpriv->dma_current_buf = devpriv->ai_buf1;
577 devpriv->dma_current = devpriv->dma0;
578 devpriv->dma_current_buf = devpriv->ai_buf0;
580 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
581 devpriv->dma_current_buf);
584 release_dma_lock(flags);
586 /* get any remaining samples in fifo */
587 das1800_handle_fifo_not_empty(dev, s);
592 static void das1800_handle_dma(struct comedi_device *dev,
593 struct comedi_subdevice *s, unsigned int status)
595 struct das1800_private *devpriv = dev->private;
597 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
599 flags = claim_dma_lock();
600 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
601 devpriv->dma_current_buf);
602 /* re-enable dma channel */
603 set_dma_addr(devpriv->dma_current,
604 virt_to_bus(devpriv->dma_current_buf));
605 set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
606 enable_dma(devpriv->dma_current);
607 release_dma_lock(flags);
609 if (status & DMATC) {
610 /* clear DMATC interrupt bit */
611 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
612 /* switch dma channels for next time, if appropriate */
614 /* read data from the other channel next time */
615 if (devpriv->dma_current == devpriv->dma0) {
616 devpriv->dma_current = devpriv->dma1;
617 devpriv->dma_current_buf = devpriv->ai_buf1;
619 devpriv->dma_current = devpriv->dma0;
620 devpriv->dma_current_buf = devpriv->ai_buf0;
628 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
630 struct das1800_private *devpriv = dev->private;
632 outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */
633 outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */
634 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */
636 disable_dma(devpriv->dma0);
638 disable_dma(devpriv->dma1);
642 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
643 static void das1800_ai_handler(struct comedi_device *dev)
645 struct das1800_private *devpriv = dev->private;
646 struct comedi_subdevice *s = &dev->subdevices[0];
647 struct comedi_async *async = s->async;
648 struct comedi_cmd *cmd = &async->cmd;
649 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
652 /* select adc for base address + 0 */
653 outb(ADC, dev->iobase + DAS1800_SELECT);
654 /* dma buffer full */
655 if (devpriv->irq_dma_bits & DMA_ENABLED) {
656 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
657 das1800_handle_dma(dev, s, status);
658 } else if (status & FHF) { /* if fifo half full */
659 das1800_handle_fifo_half_full(dev, s);
660 } else if (status & FNE) { /* if fifo not empty */
661 das1800_handle_fifo_not_empty(dev, s);
664 async->events |= COMEDI_CB_BLOCK;
665 /* if the card's fifo has overflowed */
667 /* clear OVF interrupt bit */
668 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
669 comedi_error(dev, "DAS1800 FIFO overflow");
670 das1800_cancel(dev, s);
671 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
672 comedi_event(dev, s);
675 /* stop taking data if appropriate */
676 /* stop_src TRIG_EXT */
677 if (status & CT0TC) {
678 /* clear CT0TC interrupt bit */
679 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
680 /* make sure we get all remaining data from board before quitting */
681 if (devpriv->irq_dma_bits & DMA_ENABLED)
682 das1800_flush_dma(dev, s);
684 das1800_handle_fifo_not_empty(dev, s);
685 das1800_cancel(dev, s); /* disable hardware conversions */
686 async->events |= COMEDI_CB_EOA;
687 } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { /* stop_src TRIG_COUNT */
688 das1800_cancel(dev, s); /* disable hardware conversions */
689 async->events |= COMEDI_CB_EOA;
692 comedi_event(dev, s);
697 static int das1800_ai_poll(struct comedi_device *dev,
698 struct comedi_subdevice *s)
702 /* prevent race with interrupt handler */
703 spin_lock_irqsave(&dev->spinlock, flags);
704 das1800_ai_handler(dev);
705 spin_unlock_irqrestore(&dev->spinlock, flags);
707 return s->async->buf_write_count - s->async->buf_read_count;
710 static irqreturn_t das1800_interrupt(int irq, void *d)
712 struct comedi_device *dev = d;
715 if (!dev->attached) {
716 comedi_error(dev, "premature interrupt");
720 /* Prevent race with das1800_ai_poll() on multi processor systems.
721 * Also protects indirect addressing in das1800_ai_handler */
722 spin_lock(&dev->spinlock);
723 status = inb(dev->iobase + DAS1800_STATUS);
725 /* if interrupt was not caused by das-1800 */
726 if (!(status & INT)) {
727 spin_unlock(&dev->spinlock);
730 /* clear the interrupt status bit INT */
731 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
732 /* handle interrupt */
733 das1800_ai_handler(dev);
735 spin_unlock(&dev->spinlock);
739 /* converts requested conversion timing to timing compatible with
740 * hardware, used only when card is in 'burst mode'
742 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
744 unsigned int micro_sec;
746 /* in burst mode, the maximum conversion time is 64 microseconds */
747 if (convert_arg > 64000)
750 /* the conversion time must be an integral number of microseconds */
751 switch (round_mode) {
752 case TRIG_ROUND_NEAREST:
754 micro_sec = (convert_arg + 500) / 1000;
756 case TRIG_ROUND_DOWN:
757 micro_sec = convert_arg / 1000;
760 micro_sec = (convert_arg - 1) / 1000 + 1;
764 /* return number of nanoseconds */
765 return micro_sec * 1000;
768 /* test analog input cmd */
769 static int das1800_ai_do_cmdtest(struct comedi_device *dev,
770 struct comedi_subdevice *s,
771 struct comedi_cmd *cmd)
773 const struct das1800_board *thisboard = comedi_board(dev);
774 struct das1800_private *devpriv = dev->private;
776 unsigned int tmp_arg;
780 /* Step 1 : check if triggers are trivially valid */
782 err |= cfc_check_trigger_src(&cmd->start_src, TRIG_NOW | TRIG_EXT);
783 err |= cfc_check_trigger_src(&cmd->scan_begin_src,
784 TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT);
785 err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_TIMER | TRIG_EXT);
786 err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
787 err |= cfc_check_trigger_src(&cmd->stop_src,
788 TRIG_COUNT | TRIG_EXT | TRIG_NONE);
793 /* Step 2a : make sure trigger sources are unique */
795 err |= cfc_check_trigger_is_unique(cmd->start_src);
796 err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
797 err |= cfc_check_trigger_is_unique(cmd->convert_src);
798 err |= cfc_check_trigger_is_unique(cmd->stop_src);
800 /* Step 2b : and mutually compatible */
802 if (cmd->scan_begin_src != TRIG_FOLLOW &&
803 cmd->convert_src != TRIG_TIMER)
809 /* Step 3: check if arguments are trivially valid */
811 err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
813 if (cmd->convert_src == TRIG_TIMER)
814 err |= cfc_check_trigger_arg_min(&cmd->convert_arg,
815 thisboard->ai_speed);
817 err |= cfc_check_trigger_arg_min(&cmd->chanlist_len, 1);
818 err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
820 switch (cmd->stop_src) {
822 err |= cfc_check_trigger_arg_min(&cmd->stop_arg, 1);
825 err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
834 /* step 4: fix up any arguments */
836 if (cmd->convert_src == TRIG_TIMER) {
837 /* if we are not in burst mode */
838 if (cmd->scan_begin_src == TRIG_FOLLOW) {
839 tmp_arg = cmd->convert_arg;
840 /* calculate counter values that give desired timing */
841 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
846 if (tmp_arg != cmd->convert_arg)
849 /* if we are in burst mode */
851 /* check that convert_arg is compatible */
852 tmp_arg = cmd->convert_arg;
854 burst_convert_arg(cmd->convert_arg,
855 cmd->flags & TRIG_ROUND_MASK);
856 if (tmp_arg != cmd->convert_arg)
859 if (cmd->scan_begin_src == TRIG_TIMER) {
860 /* if scans are timed faster than conversion rate allows */
861 if (cmd->convert_arg * cmd->chanlist_len >
862 cmd->scan_begin_arg) {
863 cmd->scan_begin_arg =
868 tmp_arg = cmd->scan_begin_arg;
869 /* calculate counter values that give desired timing */
870 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
873 &cmd->scan_begin_arg,
875 if (tmp_arg != cmd->scan_begin_arg)
884 /* make sure user is not trying to mix unipolar and bipolar ranges */
886 unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
887 for (i = 1; i < cmd->chanlist_len; i++) {
888 if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
890 "unipolar and bipolar ranges cannot be mixed in the chanlist");
903 /* returns appropriate bits for control register a, depending on command */
904 static int control_a_bits(const struct comedi_cmd *cmd)
908 control_a = FFEN; /* enable fifo */
909 if (cmd->stop_src == TRIG_EXT)
911 switch (cmd->start_src) {
913 control_a |= TGEN | CGSL;
925 /* returns appropriate bits for control register c, depending on command */
926 static int control_c_bits(const struct comedi_cmd *cmd)
931 /* set clock source to internal or external, select analog reference,
932 * select unipolar / bipolar
934 aref = CR_AREF(cmd->chanlist[0]);
935 control_c = UQEN; /* enable upper qram addresses */
936 if (aref != AREF_DIFF)
938 if (aref == AREF_COMMON)
940 /* if a unipolar range was selected */
941 if (CR_RANGE(cmd->chanlist[0]) & UNIPOLAR)
943 switch (cmd->scan_begin_src) {
944 case TRIG_FOLLOW: /* not in burst mode */
945 switch (cmd->convert_src) {
947 /* trig on cascaded counters */
951 /* trig on falling edge of external trigger */
959 /* burst mode with internal pacer clock */
960 control_c |= BMDE | IPCLK;
963 /* burst mode with external trigger */
964 control_c |= BMDE | XPCLK;
973 /* loads counters with divisor1, divisor2 from private structure */
974 static int das1800_set_frequency(struct comedi_device *dev)
976 struct das1800_private *devpriv = dev->private;
979 /* counter 1, mode 2 */
980 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
983 /* counter 2, mode 2 */
984 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
993 /* sets up counters */
994 static int setup_counters(struct comedi_device *dev,
995 const struct comedi_cmd *cmd)
997 struct das1800_private *devpriv = dev->private;
1000 /* setup cascaded counters for conversion/scan frequency */
1001 switch (cmd->scan_begin_src) {
1002 case TRIG_FOLLOW: /* not in burst mode */
1003 if (cmd->convert_src == TRIG_TIMER) {
1004 /* set conversion frequency */
1005 period = cmd->convert_arg;
1006 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1009 &period, cmd->flags);
1010 if (das1800_set_frequency(dev) < 0)
1014 case TRIG_TIMER: /* in burst mode */
1015 /* set scan frequency */
1016 period = cmd->scan_begin_arg;
1017 i8253_cascade_ns_to_timer(I8254_OSC_BASE_5MHZ,
1020 &period, cmd->flags);
1021 if (das1800_set_frequency(dev) < 0)
1028 /* setup counter 0 for 'about triggering' */
1029 if (cmd->stop_src == TRIG_EXT) {
1030 /* load counter 0 in mode 0 */
1031 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1037 /* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1038 static unsigned int suggest_transfer_size(const struct comedi_cmd *cmd)
1040 unsigned int size = DMA_BUF_SIZE;
1041 static const int sample_size = 2; /* size in bytes of one sample from board */
1042 unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */
1043 unsigned int max_size; /* maximum size we will allow for a transfer */
1045 /* make dma buffer fill in 0.3 seconds for timed modes */
1046 switch (cmd->scan_begin_src) {
1047 case TRIG_FOLLOW: /* not in burst mode */
1048 if (cmd->convert_src == TRIG_TIMER)
1049 size = (fill_time / cmd->convert_arg) * sample_size;
1052 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1056 size = DMA_BUF_SIZE;
1060 /* set a minimum and maximum size allowed */
1061 max_size = DMA_BUF_SIZE;
1062 /* if we are taking limited number of conversions, limit transfer size to that */
1063 if (cmd->stop_src == TRIG_COUNT &&
1064 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1065 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1067 if (size > max_size)
1069 if (size < sample_size)
1076 static void setup_dma(struct comedi_device *dev, const struct comedi_cmd *cmd)
1078 struct das1800_private *devpriv = dev->private;
1079 unsigned long lock_flags;
1080 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1082 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1085 /* determine a reasonable dma transfer size */
1086 devpriv->dma_transfer_size = suggest_transfer_size(cmd);
1087 lock_flags = claim_dma_lock();
1088 disable_dma(devpriv->dma0);
1089 /* clear flip-flop to make sure 2-byte registers for
1090 * count and address get set correctly */
1091 clear_dma_ff(devpriv->dma0);
1092 set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1093 /* set appropriate size of transfer */
1094 set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1095 devpriv->dma_current = devpriv->dma0;
1096 devpriv->dma_current_buf = devpriv->ai_buf0;
1097 enable_dma(devpriv->dma0);
1098 /* set up dual dma if appropriate */
1100 disable_dma(devpriv->dma1);
1101 /* clear flip-flop to make sure 2-byte registers for
1102 * count and address get set correctly */
1103 clear_dma_ff(devpriv->dma1);
1104 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1105 /* set appropriate size of transfer */
1106 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1107 enable_dma(devpriv->dma1);
1109 release_dma_lock(lock_flags);
1114 /* programs channel/gain list into card */
1115 static void program_chanlist(struct comedi_device *dev,
1116 const struct comedi_cmd *cmd)
1118 int i, n, chan_range;
1119 unsigned long irq_flags;
1120 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
1121 const int range_bitshift = 8;
1123 n = cmd->chanlist_len;
1124 /* spinlock protects indirect addressing */
1125 spin_lock_irqsave(&dev->spinlock, irq_flags);
1126 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1127 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
1128 /* make channel / gain list */
1129 for (i = 0; i < n; i++) {
1131 CR_CHAN(cmd->chanlist[i]) |
1132 ((CR_RANGE(cmd->chanlist[i]) & range_mask) <<
1134 outw(chan_range, dev->iobase + DAS1800_QRAM);
1136 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1137 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1142 /* analog input do_cmd */
1143 static int das1800_ai_do_cmd(struct comedi_device *dev,
1144 struct comedi_subdevice *s)
1146 struct das1800_private *devpriv = dev->private;
1148 int control_a, control_c;
1149 struct comedi_async *async = s->async;
1150 const struct comedi_cmd *cmd = &async->cmd;
1154 "no irq assigned for das-1800, cannot do hardware conversions");
1158 /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1159 * (because dma in handler is unsafe at hard real-time priority) */
1160 if (cmd->flags & (TRIG_WAKE_EOS | TRIG_RT))
1161 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1163 devpriv->irq_dma_bits |= devpriv->dma_bits;
1164 /* interrupt on end of conversion for TRIG_WAKE_EOS */
1165 if (cmd->flags & TRIG_WAKE_EOS) {
1166 /* interrupt fifo not empty */
1167 devpriv->irq_dma_bits &= ~FIMD;
1169 /* interrupt fifo half full */
1170 devpriv->irq_dma_bits |= FIMD;
1172 /* determine how many conversions we need */
1173 if (cmd->stop_src == TRIG_COUNT)
1174 devpriv->count = cmd->stop_arg * cmd->chanlist_len;
1176 das1800_cancel(dev, s);
1178 /* determine proper bits for control registers */
1179 control_a = control_a_bits(cmd);
1180 control_c = control_c_bits(cmd);
1182 /* setup card and start */
1183 program_chanlist(dev, cmd);
1184 ret = setup_counters(dev, cmd);
1186 comedi_error(dev, "Error setting up counters");
1189 setup_dma(dev, cmd);
1190 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1191 /* set conversion rate and length for burst mode */
1192 if (control_c & BMDE) {
1193 /* program conversion period with number of microseconds minus 1 */
1194 outb(cmd->convert_arg / 1000 - 1,
1195 dev->iobase + DAS1800_BURST_RATE);
1196 outb(cmd->chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1198 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1199 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1200 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1205 /* read analog input */
1206 static int das1800_ai_rinsn(struct comedi_device *dev,
1207 struct comedi_subdevice *s,
1208 struct comedi_insn *insn, unsigned int *data)
1210 const struct das1800_board *thisboard = comedi_board(dev);
1212 int chan, range, aref, chan_range;
1216 unsigned long irq_flags;
1218 /* set up analog reference and unipolar / bipolar mode */
1219 aref = CR_AREF(insn->chanspec);
1221 if (aref != AREF_DIFF)
1223 if (aref == AREF_COMMON)
1225 /* if a unipolar range was selected */
1226 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1229 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1230 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1231 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1232 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1234 chan = CR_CHAN(insn->chanspec);
1235 /* mask of unipolar/bipolar bit from range */
1236 range = CR_RANGE(insn->chanspec) & 0x3;
1237 chan_range = chan | (range << 8);
1238 spin_lock_irqsave(&dev->spinlock, irq_flags);
1239 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1240 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1241 outw(chan_range, dev->iobase + DAS1800_QRAM);
1242 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1243 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1245 for (n = 0; n < insn->n; n++) {
1246 /* trigger conversion */
1247 outb(0, dev->iobase + DAS1800_FIFO);
1248 for (i = 0; i < timeout; i++) {
1249 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1253 comedi_error(dev, "timeout");
1257 dpnt = inw(dev->iobase + DAS1800_FIFO);
1258 /* shift data to offset binary for bipolar ranges */
1259 if ((conv_flags & UB) == 0)
1260 dpnt += 1 << (thisboard->resolution - 1);
1264 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1269 /* writes to an analog output channel */
1270 static int das1800_ao_winsn(struct comedi_device *dev,
1271 struct comedi_subdevice *s,
1272 struct comedi_insn *insn, unsigned int *data)
1274 const struct das1800_board *thisboard = comedi_board(dev);
1275 struct das1800_private *devpriv = dev->private;
1276 int chan = CR_CHAN(insn->chanspec);
1277 /* int range = CR_RANGE(insn->chanspec); */
1278 int update_chan = thisboard->ao_n_chan - 1;
1280 unsigned long irq_flags;
1282 /* card expects two's complement data */
1283 output = data[0] - (1 << (thisboard->resolution - 1));
1284 /* if the write is to the 'update' channel, we need to remember its value */
1285 if (chan == update_chan)
1286 devpriv->ao_update_bits = output;
1287 /* write to channel */
1288 spin_lock_irqsave(&dev->spinlock, irq_flags);
1289 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1290 outw(output, dev->iobase + DAS1800_DAC);
1291 /* now we need to write to 'update' channel to update all dac channels */
1292 if (chan != update_chan) {
1293 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1294 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1296 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1301 /* reads from digital input channels */
1302 static int das1800_di_rbits(struct comedi_device *dev,
1303 struct comedi_subdevice *s,
1304 struct comedi_insn *insn, unsigned int *data)
1307 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1313 static int das1800_do_wbits(struct comedi_device *dev,
1314 struct comedi_subdevice *s,
1315 struct comedi_insn *insn,
1318 if (comedi_dio_update_state(s, data))
1319 outb(s->state, dev->iobase + DAS1800_DIGITAL);
1326 static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
1329 struct das1800_private *devpriv = dev->private;
1330 unsigned long flags;
1332 /* need an irq to do dma */
1333 if (dev->irq && dma0) {
1334 /* encode dma0 and dma1 into 2 digit hexadecimal for switch */
1335 switch ((dma0 & 0x7) | (dma1 << 4)) {
1336 case 0x5: /* dma0 == 5 */
1337 devpriv->dma_bits |= DMA_CH5;
1339 case 0x6: /* dma0 == 6 */
1340 devpriv->dma_bits |= DMA_CH6;
1342 case 0x7: /* dma0 == 7 */
1343 devpriv->dma_bits |= DMA_CH7;
1345 case 0x65: /* dma0 == 5, dma1 == 6 */
1346 devpriv->dma_bits |= DMA_CH5_CH6;
1348 case 0x76: /* dma0 == 6, dma1 == 7 */
1349 devpriv->dma_bits |= DMA_CH6_CH7;
1351 case 0x57: /* dma0 == 7, dma1 == 5 */
1352 devpriv->dma_bits |= DMA_CH7_CH5;
1355 dev_err(dev->class_dev,
1356 "only supports dma channels 5 through 7\n");
1357 dev_err(dev->class_dev,
1358 "Dual dma only allows the following combinations:\n");
1359 dev_err(dev->class_dev,
1360 "dma 5,6 / 6,7 / or 7,5\n");
1364 if (request_dma(dma0, dev->driver->driver_name)) {
1365 dev_err(dev->class_dev,
1366 "failed to allocate dma channel %i\n", dma0);
1369 devpriv->dma0 = dma0;
1370 devpriv->dma_current = dma0;
1372 if (request_dma(dma1, dev->driver->driver_name)) {
1373 dev_err(dev->class_dev,
1374 "failed to allocate dma channel %i\n",
1378 devpriv->dma1 = dma1;
1380 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1381 if (devpriv->ai_buf0 == NULL)
1383 devpriv->dma_current_buf = devpriv->ai_buf0;
1386 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
1387 if (devpriv->ai_buf1 == NULL)
1390 flags = claim_dma_lock();
1391 disable_dma(devpriv->dma0);
1392 set_dma_mode(devpriv->dma0, DMA_MODE_READ);
1394 disable_dma(devpriv->dma1);
1395 set_dma_mode(devpriv->dma1, DMA_MODE_READ);
1397 release_dma_lock(flags);
1402 static int das1800_probe(struct comedi_device *dev)
1407 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */
1408 board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
1412 if (board == das1801st_da || board == das1802st_da ||
1413 board == das1701st_da || board == das1702st_da) {
1414 dev_dbg(dev->class_dev, "Board model: %s\n",
1415 das1800_boards[board].name);
1419 (" Board model (probed, not recommended): das-1800st-da series\n");
1423 if (board == das1802hr_da || board == das1702hr_da) {
1424 dev_dbg(dev->class_dev, "Board model: %s\n",
1425 das1800_boards[board].name);
1429 (" Board model (probed, not recommended): das-1802hr-da\n");
1433 if (board == das1801ao || board == das1802ao ||
1434 board == das1701ao || board == das1702ao) {
1435 dev_dbg(dev->class_dev, "Board model: %s\n",
1436 das1800_boards[board].name);
1440 (" Board model (probed, not recommended): das-1800ao series\n");
1444 if (board == das1802hr || board == das1702hr) {
1445 dev_dbg(dev->class_dev, "Board model: %s\n",
1446 das1800_boards[board].name);
1450 (" Board model (probed, not recommended): das-1802hr\n");
1454 if (board == das1801st || board == das1802st ||
1455 board == das1701st || board == das1702st) {
1456 dev_dbg(dev->class_dev, "Board model: %s\n",
1457 das1800_boards[board].name);
1461 (" Board model (probed, not recommended): das-1800st series\n");
1465 if (board == das1801hc || board == das1802hc) {
1466 dev_dbg(dev->class_dev, "Board model: %s\n",
1467 das1800_boards[board].name);
1471 (" Board model (probed, not recommended): das-1800hc series\n");
1476 (" Board model: probe returned 0x%x (unknown, please report)\n",
1484 static int das1800_attach(struct comedi_device *dev,
1485 struct comedi_devconfig *it)
1487 const struct das1800_board *thisboard = comedi_board(dev);
1488 struct das1800_private *devpriv;
1489 struct comedi_subdevice *s;
1490 unsigned int irq = it->options[1];
1491 unsigned int dma0 = it->options[2];
1492 unsigned int dma1 = it->options[3];
1496 devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1500 ret = comedi_request_region(dev, it->options[0], DAS1800_SIZE);
1504 board = das1800_probe(dev);
1506 dev_err(dev->class_dev, "unable to determine board type\n");
1510 dev->board_ptr = das1800_boards + board;
1511 thisboard = comedi_board(dev);
1512 dev->board_name = thisboard->name;
1514 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
1515 if (thisboard->ao_ability == 2) {
1516 unsigned long iobase2 = dev->iobase + IOBASE2;
1518 ret = __comedi_request_region(dev, iobase2, DAS1800_SIZE);
1521 devpriv->iobase2 = iobase2;
1526 if (request_irq(irq, das1800_interrupt, 0,
1527 dev->driver->driver_name, dev)) {
1528 dev_dbg(dev->class_dev, "unable to allocate irq %u\n",
1535 /* set bits that tell card which irq to use */
1540 devpriv->irq_dma_bits |= 0x8;
1543 devpriv->irq_dma_bits |= 0x10;
1546 devpriv->irq_dma_bits |= 0x18;
1549 devpriv->irq_dma_bits |= 0x28;
1552 devpriv->irq_dma_bits |= 0x30;
1555 devpriv->irq_dma_bits |= 0x38;
1558 dev_err(dev->class_dev, "irq out of range\n");
1563 ret = das1800_init_dma(dev, dma0, dma1);
1567 if (devpriv->ai_buf0 == NULL) {
1569 kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
1570 if (devpriv->ai_buf0 == NULL)
1574 ret = comedi_alloc_subdevices(dev, 4);
1578 /* analog input subdevice */
1579 s = &dev->subdevices[0];
1580 dev->read_subdev = s;
1581 s->type = COMEDI_SUBD_AI;
1582 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
1583 if (thisboard->common)
1584 s->subdev_flags |= SDF_COMMON;
1585 s->n_chan = thisboard->qram_len;
1586 s->len_chanlist = thisboard->qram_len;
1587 s->maxdata = (1 << thisboard->resolution) - 1;
1588 s->range_table = thisboard->range_ai;
1589 s->do_cmd = das1800_ai_do_cmd;
1590 s->do_cmdtest = das1800_ai_do_cmdtest;
1591 s->insn_read = das1800_ai_rinsn;
1592 s->poll = das1800_ai_poll;
1593 s->cancel = das1800_cancel;
1596 s = &dev->subdevices[1];
1597 if (thisboard->ao_ability == 1) {
1598 s->type = COMEDI_SUBD_AO;
1599 s->subdev_flags = SDF_WRITABLE;
1600 s->n_chan = thisboard->ao_n_chan;
1601 s->maxdata = (1 << thisboard->resolution) - 1;
1602 s->range_table = &range_bipolar10;
1603 s->insn_write = das1800_ao_winsn;
1605 s->type = COMEDI_SUBD_UNUSED;
1609 s = &dev->subdevices[2];
1610 s->type = COMEDI_SUBD_DI;
1611 s->subdev_flags = SDF_READABLE;
1614 s->range_table = &range_digital;
1615 s->insn_bits = das1800_di_rbits;
1618 s = &dev->subdevices[3];
1619 s->type = COMEDI_SUBD_DO;
1620 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
1621 s->n_chan = thisboard->do_n_chan;
1623 s->range_table = &range_digital;
1624 s->insn_bits = das1800_do_wbits;
1626 das1800_cancel(dev, dev->read_subdev);
1628 /* initialize digital out channels */
1629 outb(0, dev->iobase + DAS1800_DIGITAL);
1631 /* initialize analog out channels */
1632 if (thisboard->ao_ability == 1) {
1633 /* select 'update' dac channel for baseAddress + 0x0 */
1634 outb(DAC(thisboard->ao_n_chan - 1),
1635 dev->iobase + DAS1800_SELECT);
1636 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1642 static void das1800_detach(struct comedi_device *dev)
1644 struct das1800_private *devpriv = dev->private;
1648 free_dma(devpriv->dma0);
1650 free_dma(devpriv->dma1);
1651 kfree(devpriv->ai_buf0);
1652 kfree(devpriv->ai_buf1);
1653 if (devpriv->iobase2)
1654 release_region(devpriv->iobase2, DAS1800_SIZE);
1656 comedi_legacy_detach(dev);
1659 static struct comedi_driver das1800_driver = {
1660 .driver_name = "das1800",
1661 .module = THIS_MODULE,
1662 .attach = das1800_attach,
1663 .detach = das1800_detach,
1664 .num_names = ARRAY_SIZE(das1800_boards),
1665 .board_name = &das1800_boards[0].name,
1666 .offset = sizeof(struct das1800_board),
1668 module_comedi_driver(das1800_driver);
1670 MODULE_AUTHOR("Comedi http://www.comedi.org");
1671 MODULE_DESCRIPTION("Comedi low-level driver");
1672 MODULE_LICENSE("GPL");