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.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 ************************************************************************
27 Description: Keithley Metrabyte DAS1800 (& compatibles)
28 Author: Frank Mori Hess <fmhess@users.sourceforge.net>
29 Devices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
30 DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
31 DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
32 DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
33 DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
34 DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
35 DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
36 DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
37 DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
38 DAS-1802AO (das-1802ao)
41 The waveform analog output on the 'ao' cards is not supported.
42 If you need it, send me (Frank Hess) an email.
44 Configuration options:
45 [0] - I/O port base address
46 [1] - IRQ (optional, required for timed or externally triggered conversions)
47 [2] - DMA0 (optional, requires irq)
48 [3] - DMA1 (optional, requires irq and dma0)
52 This driver supports the following Keithley boards:
75 [1] - irq (optional, required for timed or externally triggered conversions)
76 [2] - dma0 (optional, requires irq)
77 [3] - dma1 (optional, requires irq and dma0)
79 irq can be omitted, although the cmd interface will not work without it.
81 analog input cmd triggers supported:
82 start_src: TRIG_NOW | TRIG_EXT
83 scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
84 scan_end_src: TRIG_COUNT
85 convert_src: TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
86 stop_src: TRIG_COUNT | TRIG_EXT | TRIG_NONE
88 scan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
89 'burst mode' which limits the valid conversion time to 64 microseconds
90 (convert_arg <= 64000). This limitation does not apply if scan_begin_src
94 Only the DAS-1801ST has been tested by me.
95 Unipolar and bipolar ranges cannot be mixed in the channel/gain list.
98 Make it automatically allocate irq and dma channels if they are not specified
99 Add support for analog out on 'ao' cards
100 read insn for analog out
103 #include <linux/interrupt.h>
104 #include "../comedidev.h"
106 #include <linux/ioport.h>
110 #include "comedi_fc.h"
113 #define DAS1800_SIZE 16 /* uses 16 io addresses */
114 #define FIFO_SIZE 1024 /* 1024 sample fifo */
115 #define TIMER_BASE 200 /* 5 Mhz master clock */
116 #define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */
117 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
119 /* Registers for the das1800 */
120 #define DAS1800_FIFO 0x0
121 #define DAS1800_QRAM 0x0
122 #define DAS1800_DAC 0x0
123 #define DAS1800_SELECT 0x2
126 #define DAC(a) (0x2 + a)
127 #define DAS1800_DIGITAL 0x3
128 #define DAS1800_CONTROL_A 0x4
135 #define DAS1800_CONTROL_B 0x5
139 #define DMA_CH5_CH6 0x5
140 #define DMA_CH6_CH7 0x6
141 #define DMA_CH7_CH5 0x7
142 #define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */
151 #define DAS1800_CONTROL_C 0X6
159 #define DAS1800_STATUS 0x7
160 /* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
161 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
168 #define CVEN_MASK 0x40 /* masks CVEN on write */
170 #define DAS1800_BURST_LENGTH 0x8
171 #define DAS1800_BURST_RATE 0x9
172 #define DAS1800_QRAM_ADDRESS 0xa
173 #define DAS1800_COUNTER 0xc
175 #define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */
178 das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
180 das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
181 das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
184 static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
185 static int das1800_detach(struct comedi_device *dev);
186 static int das1800_probe(struct comedi_device *dev);
187 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
188 static irqreturn_t das1800_interrupt(int irq, void *d);
189 static int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s);
190 static void das1800_ai_handler(struct comedi_device *dev);
191 static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
192 unsigned int status);
193 static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s);
194 static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
195 unsigned int channel, uint16_t *buffer);
196 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
197 struct comedi_subdevice *s);
198 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
199 struct comedi_subdevice *s);
200 static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
201 struct comedi_cmd *cmd);
202 static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
203 static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
204 struct comedi_insn *insn, unsigned int *data);
205 static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
206 struct comedi_insn *insn, unsigned int *data);
207 static int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
208 struct comedi_insn *insn, unsigned int *data);
209 static int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
210 struct comedi_insn *insn, unsigned int *data);
212 static int das1800_set_frequency(struct comedi_device *dev);
213 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
214 static unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
216 /* analog input ranges */
217 static const struct comedi_lrange range_ai_das1801 = {
231 static const struct comedi_lrange range_ai_das1802 = {
245 struct das1800_board {
247 int ai_speed; /* max conversion period in nanoseconds */
248 int resolution; /* bits of ai resolution */
249 int qram_len; /* length of card's channel / gain queue */
250 int common; /* supports AREF_COMMON flag */
251 int do_n_chan; /* number of digital output channels */
252 int ao_ability; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
253 int ao_n_chan; /* number of analog out channels */
254 const struct comedi_lrange *range_ai; /* available input ranges */
257 /* Warning: the maximum conversion speeds listed below are
258 * not always achievable depending on board setup (see
261 static const struct das1800_board das1800_boards[] = {
263 .name = "das-1701st",
271 .range_ai = &range_ai_das1801,
274 .name = "das-1701st-da",
282 .range_ai = &range_ai_das1801,
285 .name = "das-1702st",
293 .range_ai = &range_ai_das1802,
296 .name = "das-1702st-da",
304 .range_ai = &range_ai_das1802,
307 .name = "das-1702hr",
315 .range_ai = &range_ai_das1802,
318 .name = "das-1702hr-da",
326 .range_ai = &range_ai_das1802,
329 .name = "das-1701ao",
337 .range_ai = &range_ai_das1801,
340 .name = "das-1702ao",
348 .range_ai = &range_ai_das1802,
351 .name = "das-1801st",
359 .range_ai = &range_ai_das1801,
362 .name = "das-1801st-da",
370 .range_ai = &range_ai_das1801,
373 .name = "das-1802st",
381 .range_ai = &range_ai_das1802,
384 .name = "das-1802st-da",
392 .range_ai = &range_ai_das1802,
395 .name = "das-1802hr",
403 .range_ai = &range_ai_das1802,
406 .name = "das-1802hr-da",
414 .range_ai = &range_ai_das1802,
417 .name = "das-1801hc",
425 .range_ai = &range_ai_das1801,
428 .name = "das-1802hc",
436 .range_ai = &range_ai_das1802,
439 .name = "das-1801ao",
447 .range_ai = &range_ai_das1801,
450 .name = "das-1802ao",
458 .range_ai = &range_ai_das1802,
463 * Useful for shorthand access to the particular board structure
465 #define thisboard ((const struct das1800_board *)dev->board_ptr)
467 struct das1800_private {
468 volatile unsigned int count; /* number of data points left to be taken */
469 unsigned int divisor1; /* value to load into board's counter 1 for timed conversions */
470 unsigned int divisor2; /* value to load into board's counter 2 for timed conversions */
471 int do_bits; /* digital output bits */
472 int irq_dma_bits; /* bits for control register b */
473 /* dma bits for control register b, stored so that dma can be
474 * turned on and off */
476 unsigned int dma0; /* dma channels used */
478 volatile unsigned int dma_current; /* dma channel currently in use */
479 uint16_t *ai_buf0; /* pointers to dma buffers */
481 uint16_t *dma_current_buf; /* pointer to dma buffer currently being used */
482 unsigned int dma_transfer_size; /* size of transfer currently used, in bytes */
483 unsigned long iobase2; /* secondary io address used for analog out on 'ao' boards */
484 short ao_update_bits; /* remembers the last write to the 'update' dac */
487 #define devpriv ((struct das1800_private *)dev->private)
489 /* analog out range for boards with basic analog out */
490 static const struct comedi_lrange range_ao_1 = {
497 /* analog out range for 'ao' boards */
499 static const struct comedi_lrange range_ao_2 = {
508 static struct comedi_driver driver_das1800 = {
509 .driver_name = "das1800",
510 .module = THIS_MODULE,
511 .attach = das1800_attach,
512 .detach = das1800_detach,
513 .num_names = ARRAY_SIZE(das1800_boards),
514 .board_name = &das1800_boards[0].name,
515 .offset = sizeof(struct das1800_board),
519 * A convenient macro that defines init_module() and cleanup_module(),
522 COMEDI_INITCLEANUP(driver_das1800);
524 static int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
529 /* need an irq to do dma */
530 if (dev->irq && dma0) {
531 /* encode dma0 and dma1 into 2 digit hexadecimal for switch */
532 switch ((dma0 & 0x7) | (dma1 << 4)) {
533 case 0x5: /* dma0 == 5 */
534 devpriv->dma_bits |= DMA_CH5;
536 case 0x6: /* dma0 == 6 */
537 devpriv->dma_bits |= DMA_CH6;
539 case 0x7: /* dma0 == 7 */
540 devpriv->dma_bits |= DMA_CH7;
542 case 0x65: /* dma0 == 5, dma1 == 6 */
543 devpriv->dma_bits |= DMA_CH5_CH6;
545 case 0x76: /* dma0 == 6, dma1 == 7 */
546 devpriv->dma_bits |= DMA_CH6_CH7;
548 case 0x57: /* dma0 == 7, dma1 == 5 */
549 devpriv->dma_bits |= DMA_CH7_CH5;
552 printk(" only supports dma channels 5 through 7\n"
553 " Dual dma only allows the following combinations:\n"
554 " dma 5,6 / 6,7 / or 7,5\n");
558 if (request_dma(dma0, driver_das1800.driver_name)) {
559 printk(" failed to allocate dma channel %i\n", dma0);
562 devpriv->dma0 = dma0;
563 devpriv->dma_current = dma0;
565 if (request_dma(dma1, driver_das1800.driver_name)) {
566 printk(" failed to allocate dma channel %i\n",
570 devpriv->dma1 = dma1;
572 devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
573 if (devpriv->ai_buf0 == NULL)
575 devpriv->dma_current_buf = devpriv->ai_buf0;
578 kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
579 if (devpriv->ai_buf1 == NULL)
582 flags = claim_dma_lock();
583 disable_dma(devpriv->dma0);
584 set_dma_mode(devpriv->dma0, DMA_MODE_READ);
586 disable_dma(devpriv->dma1);
587 set_dma_mode(devpriv->dma1, DMA_MODE_READ);
589 release_dma_lock(flags);
594 static int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
596 struct comedi_subdevice *s;
597 unsigned long iobase = it->options[0];
598 unsigned int irq = it->options[1];
599 unsigned int dma0 = it->options[2];
600 unsigned int dma1 = it->options[3];
601 unsigned long iobase2;
605 /* allocate and initialize dev->private */
606 if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
609 printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
612 printk(", irq %u", irq);
614 printk(", dma %u", dma0);
616 printk(" and %u", dma1);
622 printk(" io base address required\n");
626 /* check if io addresses are available */
627 if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
628 printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1);
631 dev->iobase = iobase;
633 board = das1800_probe(dev);
635 printk(" unable to determine board type\n");
639 dev->board_ptr = das1800_boards + board;
640 dev->board_name = thisboard->name;
642 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
643 if (thisboard->ao_ability == 2) {
644 iobase2 = iobase + IOBASE2;
645 if (!request_region(iobase2, DAS1800_SIZE,
646 driver_das1800.driver_name)) {
647 printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1);
650 devpriv->iobase2 = iobase2;
655 if (request_irq(irq, das1800_interrupt, 0,
656 driver_das1800.driver_name, dev)) {
657 printk(" unable to allocate irq %u\n", irq);
663 /* set bits that tell card which irq to use */
668 devpriv->irq_dma_bits |= 0x8;
671 devpriv->irq_dma_bits |= 0x10;
674 devpriv->irq_dma_bits |= 0x18;
677 devpriv->irq_dma_bits |= 0x28;
680 devpriv->irq_dma_bits |= 0x30;
683 devpriv->irq_dma_bits |= 0x38;
686 printk(" irq out of range\n");
691 retval = das1800_init_dma(dev, dma0, dma1);
695 if (devpriv->ai_buf0 == NULL) {
697 kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
698 if (devpriv->ai_buf0 == NULL)
702 if (alloc_subdevices(dev, 4) < 0)
705 /* analog input subdevice */
706 s = dev->subdevices + 0;
707 dev->read_subdev = s;
708 s->type = COMEDI_SUBD_AI;
709 s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
710 if (thisboard->common)
711 s->subdev_flags |= SDF_COMMON;
712 s->n_chan = thisboard->qram_len;
713 s->len_chanlist = thisboard->qram_len;
714 s->maxdata = (1 << thisboard->resolution) - 1;
715 s->range_table = thisboard->range_ai;
716 s->do_cmd = das1800_ai_do_cmd;
717 s->do_cmdtest = das1800_ai_do_cmdtest;
718 s->insn_read = das1800_ai_rinsn;
719 s->poll = das1800_ai_poll;
720 s->cancel = das1800_cancel;
723 s = dev->subdevices + 1;
724 if (thisboard->ao_ability == 1) {
725 s->type = COMEDI_SUBD_AO;
726 s->subdev_flags = SDF_WRITABLE;
727 s->n_chan = thisboard->ao_n_chan;
728 s->maxdata = (1 << thisboard->resolution) - 1;
729 s->range_table = &range_ao_1;
730 s->insn_write = das1800_ao_winsn;
732 s->type = COMEDI_SUBD_UNUSED;
736 s = dev->subdevices + 2;
737 s->type = COMEDI_SUBD_DI;
738 s->subdev_flags = SDF_READABLE;
741 s->range_table = &range_digital;
742 s->insn_bits = das1800_di_rbits;
745 s = dev->subdevices + 3;
746 s->type = COMEDI_SUBD_DO;
747 s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
748 s->n_chan = thisboard->do_n_chan;
750 s->range_table = &range_digital;
751 s->insn_bits = das1800_do_wbits;
753 das1800_cancel(dev, dev->read_subdev);
755 /* initialize digital out channels */
756 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
758 /* initialize analog out channels */
759 if (thisboard->ao_ability == 1) {
760 /* select 'update' dac channel for baseAddress + 0x0 */
761 outb(DAC(thisboard->ao_n_chan - 1),
762 dev->iobase + DAS1800_SELECT);
763 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
769 static int das1800_detach(struct comedi_device *dev)
771 /* only free stuff if it has been allocated by _attach */
773 release_region(dev->iobase, DAS1800_SIZE);
775 free_irq(dev->irq, dev);
777 if (devpriv->iobase2)
778 release_region(devpriv->iobase2, DAS1800_SIZE);
780 free_dma(devpriv->dma0);
782 free_dma(devpriv->dma1);
783 if (devpriv->ai_buf0)
784 kfree(devpriv->ai_buf0);
785 if (devpriv->ai_buf1)
786 kfree(devpriv->ai_buf1);
789 printk("comedi%d: %s: remove\n", dev->minor,
790 driver_das1800.driver_name);
795 /* probes and checks das-1800 series board type
797 static int das1800_probe(struct comedi_device *dev)
802 id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf; /* get id bits */
803 board = ((struct das1800_board *) dev->board_ptr) - das1800_boards;
807 if (board == das1801st_da || board == das1802st_da ||
808 board == das1701st_da || board == das1702st_da) {
809 printk(" Board model: %s\n",
810 das1800_boards[board].name);
813 printk(" Board model (probed, not recommended): das-1800st-da series\n");
817 if (board == das1802hr_da || board == das1702hr_da) {
818 printk(" Board model: %s\n",
819 das1800_boards[board].name);
822 printk(" Board model (probed, not recommended): das-1802hr-da\n");
826 if (board == das1801ao || board == das1802ao ||
827 board == das1701ao || board == das1702ao) {
828 printk(" Board model: %s\n",
829 das1800_boards[board].name);
832 printk(" Board model (probed, not recommended): das-1800ao series\n");
836 if (board == das1802hr || board == das1702hr) {
837 printk(" Board model: %s\n",
838 das1800_boards[board].name);
841 printk(" Board model (probed, not recommended): das-1802hr\n");
845 if (board == das1801st || board == das1802st ||
846 board == das1701st || board == das1702st) {
847 printk(" Board model: %s\n",
848 das1800_boards[board].name);
851 printk(" Board model (probed, not recommended): das-1800st series\n");
855 if (board == das1801hc || board == das1802hc) {
856 printk(" Board model: %s\n",
857 das1800_boards[board].name);
860 printk(" Board model (probed, not recommended): das-1800hc series\n");
864 printk(" Board model: probe returned 0x%x (unknown, please report)\n", id);
871 static int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
875 /* prevent race with interrupt handler */
876 spin_lock_irqsave(&dev->spinlock, flags);
877 das1800_ai_handler(dev);
878 spin_unlock_irqrestore(&dev->spinlock, flags);
880 return s->async->buf_write_count - s->async->buf_read_count;
883 static irqreturn_t das1800_interrupt(int irq, void *d)
885 struct comedi_device *dev = d;
888 if (dev->attached == 0) {
889 comedi_error(dev, "premature interrupt");
893 /* Prevent race with das1800_ai_poll() on multi processor systems.
894 * Also protects indirect addressing in das1800_ai_handler */
895 spin_lock(&dev->spinlock);
896 status = inb(dev->iobase + DAS1800_STATUS);
898 /* if interrupt was not caused by das-1800 */
899 if (!(status & INT)) {
900 spin_unlock(&dev->spinlock);
903 /* clear the interrupt status bit INT */
904 outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
905 /* handle interrupt */
906 das1800_ai_handler(dev);
908 spin_unlock(&dev->spinlock);
912 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
913 static void das1800_ai_handler(struct comedi_device *dev)
915 struct comedi_subdevice *s = dev->subdevices + 0; /* analog input subdevice */
916 struct comedi_async *async = s->async;
917 struct comedi_cmd *cmd = &async->cmd;
918 unsigned int status = inb(dev->iobase + DAS1800_STATUS);
921 /* select adc for base address + 0 */
922 outb(ADC, dev->iobase + DAS1800_SELECT);
923 /* dma buffer full */
924 if (devpriv->irq_dma_bits & DMA_ENABLED) {
925 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
926 das1800_handle_dma(dev, s, status);
927 } else if (status & FHF) { /* if fifo half full */
928 das1800_handle_fifo_half_full(dev, s);
929 } else if (status & FNE) { /* if fifo not empty */
930 das1800_handle_fifo_not_empty(dev, s);
933 async->events |= COMEDI_CB_BLOCK;
934 /* if the card's fifo has overflowed */
936 /* clear OVF interrupt bit */
937 outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
938 comedi_error(dev, "DAS1800 FIFO overflow");
939 das1800_cancel(dev, s);
940 async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
941 comedi_event(dev, s);
944 /* stop taking data if appropriate */
945 /* stop_src TRIG_EXT */
946 if (status & CT0TC) {
947 /* clear CT0TC interrupt bit */
948 outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
949 /* make sure we get all remaining data from board before quitting */
950 if (devpriv->irq_dma_bits & DMA_ENABLED)
951 das1800_flush_dma(dev, s);
953 das1800_handle_fifo_not_empty(dev, s);
954 das1800_cancel(dev, s); /* disable hardware conversions */
955 async->events |= COMEDI_CB_EOA;
956 } else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) { /* stop_src TRIG_COUNT */
957 das1800_cancel(dev, s); /* disable hardware conversions */
958 async->events |= COMEDI_CB_EOA;
961 comedi_event(dev, s);
966 static void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
970 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
972 flags = claim_dma_lock();
973 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
974 devpriv->dma_current_buf);
975 /* re-enable dma channel */
976 set_dma_addr(devpriv->dma_current,
977 virt_to_bus(devpriv->dma_current_buf));
978 set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
979 enable_dma(devpriv->dma_current);
980 release_dma_lock(flags);
982 if (status & DMATC) {
983 /* clear DMATC interrupt bit */
984 outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
985 /* switch dma channels for next time, if appropriate */
987 /* read data from the other channel next time */
988 if (devpriv->dma_current == devpriv->dma0) {
989 devpriv->dma_current = devpriv->dma1;
990 devpriv->dma_current_buf = devpriv->ai_buf1;
992 devpriv->dma_current = devpriv->dma0;
993 devpriv->dma_current_buf = devpriv->ai_buf0;
1001 static inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
1004 sample += 1 << (thisboard->resolution - 1);
1008 static void munge_data(struct comedi_device *dev, uint16_t *array,
1009 unsigned int num_elements)
1014 /* see if card is using a unipolar or bipolar range so we can munge data correctly */
1015 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1017 /* convert to unsigned type if we are in a bipolar mode */
1019 for (i = 0; i < num_elements; i++) {
1020 array[i] = munge_bipolar_sample(dev, array[i]);
1025 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1026 * Assumes dma lock is held */
1027 static void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
1028 unsigned int channel, uint16_t *buffer)
1030 unsigned int num_bytes, num_samples;
1031 struct comedi_cmd *cmd = &s->async->cmd;
1033 disable_dma(channel);
1035 /* clear flip-flop to make sure 2-byte registers
1036 * get set correctly */
1037 clear_dma_ff(channel);
1039 /* figure out how many points to read */
1040 num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1041 num_samples = num_bytes / sizeof(short);
1043 /* if we only need some of the points */
1044 if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1045 num_samples = devpriv->count;
1047 munge_data(dev, buffer, num_samples);
1048 cfc_write_array_to_buffer(s, buffer, num_bytes);
1049 if (s->async->cmd.stop_src == TRIG_COUNT)
1050 devpriv->count -= num_samples;
1055 /* flushes remaining data from board when external trigger has stopped aquisition
1056 * and we are using dma transfers */
1057 static void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1059 unsigned long flags;
1060 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1062 flags = claim_dma_lock();
1063 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1064 devpriv->dma_current_buf);
1067 /* switch to other channel and flush it */
1068 if (devpriv->dma_current == devpriv->dma0) {
1069 devpriv->dma_current = devpriv->dma1;
1070 devpriv->dma_current_buf = devpriv->ai_buf1;
1072 devpriv->dma_current = devpriv->dma0;
1073 devpriv->dma_current_buf = devpriv->ai_buf0;
1075 das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1076 devpriv->dma_current_buf);
1079 release_dma_lock(flags);
1081 /* get any remaining samples in fifo */
1082 das1800_handle_fifo_not_empty(dev, s);
1087 static void das1800_handle_fifo_half_full(struct comedi_device *dev,
1088 struct comedi_subdevice *s)
1090 int numPoints = 0; /* number of points to read */
1091 struct comedi_cmd *cmd = &s->async->cmd;
1093 numPoints = FIFO_SIZE / 2;
1094 /* if we only need some of the points */
1095 if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1096 numPoints = devpriv->count;
1097 insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1098 munge_data(dev, devpriv->ai_buf0, numPoints);
1099 cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1100 numPoints * sizeof(devpriv->ai_buf0[0]));
1101 if (cmd->stop_src == TRIG_COUNT)
1102 devpriv->count -= numPoints;
1106 static void das1800_handle_fifo_not_empty(struct comedi_device *dev,
1107 struct comedi_subdevice *s)
1111 struct comedi_cmd *cmd = &s->async->cmd;
1113 unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1115 while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1116 if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1118 dpnt = inw(dev->iobase + DAS1800_FIFO);
1119 /* convert to unsigned type if we are in a bipolar mode */
1121 dpnt = munge_bipolar_sample(dev, dpnt);
1122 cfc_write_to_buffer(s, dpnt);
1123 if (cmd->stop_src == TRIG_COUNT)
1130 static int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1132 outb(0x0, dev->iobase + DAS1800_STATUS); /* disable conversions */
1133 outb(0x0, dev->iobase + DAS1800_CONTROL_B); /* disable interrupts and dma */
1134 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* disable and clear fifo and stop triggering */
1136 disable_dma(devpriv->dma0);
1138 disable_dma(devpriv->dma1);
1142 /* test analog input cmd */
1143 static int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1144 struct comedi_cmd *cmd)
1148 unsigned int tmp_arg;
1152 /* step 1: make sure trigger sources are trivially valid */
1154 tmp = cmd->start_src;
1155 cmd->start_src &= TRIG_NOW | TRIG_EXT;
1156 if (!cmd->start_src || tmp != cmd->start_src)
1159 tmp = cmd->scan_begin_src;
1160 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1161 if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1164 tmp = cmd->convert_src;
1165 cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1166 if (!cmd->convert_src || tmp != cmd->convert_src)
1169 tmp = cmd->scan_end_src;
1170 cmd->scan_end_src &= TRIG_COUNT;
1171 if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1174 tmp = cmd->stop_src;
1175 cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1176 if (!cmd->stop_src || tmp != cmd->stop_src)
1182 /* step 2: make sure trigger sources are unique and mutually compatible */
1184 /* uniqueness check */
1185 if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1187 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1188 cmd->scan_begin_src != TRIG_TIMER &&
1189 cmd->scan_begin_src != TRIG_EXT)
1191 if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1193 if (cmd->stop_src != TRIG_COUNT &&
1194 cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1196 /* compatibility check */
1197 if (cmd->scan_begin_src != TRIG_FOLLOW &&
1198 cmd->convert_src != TRIG_TIMER)
1204 /* step 3: make sure arguments are trivially compatible */
1206 if (cmd->start_arg != 0) {
1210 if (cmd->convert_src == TRIG_TIMER) {
1211 if (cmd->convert_arg < thisboard->ai_speed) {
1212 cmd->convert_arg = thisboard->ai_speed;
1216 if (!cmd->chanlist_len) {
1217 cmd->chanlist_len = 1;
1220 if (cmd->scan_end_arg != cmd->chanlist_len) {
1221 cmd->scan_end_arg = cmd->chanlist_len;
1225 switch (cmd->stop_src) {
1227 if (!cmd->stop_arg) {
1233 if (cmd->stop_arg != 0) {
1245 /* step 4: fix up any arguments */
1247 if (cmd->convert_src == TRIG_TIMER) {
1248 /* if we are not in burst mode */
1249 if (cmd->scan_begin_src == TRIG_FOLLOW) {
1250 tmp_arg = cmd->convert_arg;
1251 /* calculate counter values that give desired timing */
1252 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1253 &(devpriv->divisor1), &(devpriv->divisor2),
1254 &(cmd->convert_arg),
1255 cmd->flags & TRIG_ROUND_MASK);
1256 if (tmp_arg != cmd->convert_arg)
1259 /* if we are in burst mode */
1261 /* check that convert_arg is compatible */
1262 tmp_arg = cmd->convert_arg;
1264 burst_convert_arg(cmd->convert_arg,
1265 cmd->flags & TRIG_ROUND_MASK);
1266 if (tmp_arg != cmd->convert_arg)
1269 if (cmd->scan_begin_src == TRIG_TIMER) {
1270 /* if scans are timed faster than conversion rate allows */
1271 if (cmd->convert_arg * cmd->chanlist_len >
1272 cmd->scan_begin_arg) {
1273 cmd->scan_begin_arg =
1278 tmp_arg = cmd->scan_begin_arg;
1279 /* calculate counter values that give desired timing */
1280 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1281 &(devpriv->divisor1),
1282 &(devpriv->divisor2),
1283 &(cmd->scan_begin_arg),
1284 cmd->flags & TRIG_ROUND_MASK);
1285 if (tmp_arg != cmd->scan_begin_arg)
1294 /* make sure user is not trying to mix unipolar and bipolar ranges */
1295 if (cmd->chanlist) {
1296 unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1297 for (i = 1; i < cmd->chanlist_len; i++) {
1298 if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1300 "unipolar and bipolar ranges cannot be mixed in the chanlist");
1313 /* analog input cmd interface */
1315 /* first, some utility functions used in the main ai_do_cmd() */
1317 /* returns appropriate bits for control register a, depending on command */
1318 static int control_a_bits(struct comedi_cmd cmd)
1322 control_a = FFEN; /* enable fifo */
1323 if (cmd.stop_src == TRIG_EXT) {
1326 switch (cmd.start_src) {
1328 control_a |= TGEN | CGSL;
1340 /* returns appropriate bits for control register c, depending on command */
1341 static int control_c_bits(struct comedi_cmd cmd)
1346 /* set clock source to internal or external, select analog reference,
1347 * select unipolar / bipolar
1349 aref = CR_AREF(cmd.chanlist[0]);
1350 control_c = UQEN; /* enable upper qram addresses */
1351 if (aref != AREF_DIFF)
1353 if (aref == AREF_COMMON)
1355 /* if a unipolar range was selected */
1356 if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1358 switch (cmd.scan_begin_src) {
1359 case TRIG_FOLLOW: /* not in burst mode */
1360 switch (cmd.convert_src) {
1362 /* trig on cascaded counters */
1366 /* trig on falling edge of external trigger */
1374 /* burst mode with internal pacer clock */
1375 control_c |= BMDE | IPCLK;
1378 /* burst mode with external trigger */
1379 control_c |= BMDE | XPCLK;
1388 /* sets up counters */
1389 static int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
1391 /* setup cascaded counters for conversion/scan frequency */
1392 switch (cmd.scan_begin_src) {
1393 case TRIG_FOLLOW: /* not in burst mode */
1394 if (cmd.convert_src == TRIG_TIMER) {
1395 /* set conversion frequency */
1396 i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1397 &(devpriv->divisor1), &(devpriv->divisor2),
1399 cmd.flags & TRIG_ROUND_MASK);
1400 if (das1800_set_frequency(dev) < 0) {
1405 case TRIG_TIMER: /* in burst mode */
1406 /* set scan frequency */
1407 i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1408 &(devpriv->divisor2), &(cmd.scan_begin_arg),
1409 cmd.flags & TRIG_ROUND_MASK);
1410 if (das1800_set_frequency(dev) < 0) {
1418 /* setup counter 0 for 'about triggering' */
1419 if (cmd.stop_src == TRIG_EXT) {
1420 /* load counter 0 in mode 0 */
1421 i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1428 static void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
1430 unsigned long lock_flags;
1431 const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1433 if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1436 /* determine a reasonable dma transfer size */
1437 devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1438 lock_flags = claim_dma_lock();
1439 disable_dma(devpriv->dma0);
1440 /* clear flip-flop to make sure 2-byte registers for
1441 * count and address get set correctly */
1442 clear_dma_ff(devpriv->dma0);
1443 set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1444 /* set appropriate size of transfer */
1445 set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1446 devpriv->dma_current = devpriv->dma0;
1447 devpriv->dma_current_buf = devpriv->ai_buf0;
1448 enable_dma(devpriv->dma0);
1449 /* set up dual dma if appropriate */
1451 disable_dma(devpriv->dma1);
1452 /* clear flip-flop to make sure 2-byte registers for
1453 * count and address get set correctly */
1454 clear_dma_ff(devpriv->dma1);
1455 set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1456 /* set appropriate size of transfer */
1457 set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1458 enable_dma(devpriv->dma1);
1460 release_dma_lock(lock_flags);
1465 /* programs channel/gain list into card */
1466 static void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
1468 int i, n, chan_range;
1469 unsigned long irq_flags;
1470 const int range_mask = 0x3; /* masks unipolar/bipolar bit off range */
1471 const int range_bitshift = 8;
1473 n = cmd.chanlist_len;
1474 /* spinlock protects indirect addressing */
1475 spin_lock_irqsave(&dev->spinlock, irq_flags);
1476 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1477 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*set QRAM address start */
1478 /* make channel / gain list */
1479 for (i = 0; i < n; i++) {
1481 CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd.
1482 chanlist[i]) & range_mask) <<
1484 outw(chan_range, dev->iobase + DAS1800_QRAM);
1486 outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1487 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1492 /* analog input do_cmd */
1493 static int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1496 int control_a, control_c;
1497 struct comedi_async *async = s->async;
1498 struct comedi_cmd cmd = async->cmd;
1502 "no irq assigned for das-1800, cannot do hardware conversions");
1506 /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1507 * (because dma in handler is unsafe at hard real-time priority) */
1508 if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1509 devpriv->irq_dma_bits &= ~DMA_ENABLED;
1511 devpriv->irq_dma_bits |= devpriv->dma_bits;
1513 /* interrupt on end of conversion for TRIG_WAKE_EOS */
1514 if (cmd.flags & TRIG_WAKE_EOS) {
1515 /* interrupt fifo not empty */
1516 devpriv->irq_dma_bits &= ~FIMD;
1518 /* interrupt fifo half full */
1519 devpriv->irq_dma_bits |= FIMD;
1521 /* determine how many conversions we need */
1522 if (cmd.stop_src == TRIG_COUNT) {
1523 devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1526 das1800_cancel(dev, s);
1528 /* determine proper bits for control registers */
1529 control_a = control_a_bits(cmd);
1530 control_c = control_c_bits(cmd);
1532 /* setup card and start */
1533 program_chanlist(dev, cmd);
1534 ret = setup_counters(dev, cmd);
1536 comedi_error(dev, "Error setting up counters");
1539 setup_dma(dev, cmd);
1540 outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1541 /* set conversion rate and length for burst mode */
1542 if (control_c & BMDE) {
1543 /* program conversion period with number of microseconds minus 1 */
1544 outb(cmd.convert_arg / 1000 - 1,
1545 dev->iobase + DAS1800_BURST_RATE);
1546 outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1548 outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B); /* enable irq/dma */
1549 outb(control_a, dev->iobase + DAS1800_CONTROL_A); /* enable fifo and triggering */
1550 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1555 /* read analog input */
1556 static int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1557 struct comedi_insn *insn, unsigned int *data)
1560 int chan, range, aref, chan_range;
1564 unsigned long irq_flags;
1566 /* set up analog reference and unipolar / bipolar mode */
1567 aref = CR_AREF(insn->chanspec);
1569 if (aref != AREF_DIFF)
1571 if (aref == AREF_COMMON)
1573 /* if a unipolar range was selected */
1574 if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1577 outb(conv_flags, dev->iobase + DAS1800_CONTROL_C); /* software conversion enabled */
1578 outb(CVEN, dev->iobase + DAS1800_STATUS); /* enable conversions */
1579 outb(0x0, dev->iobase + DAS1800_CONTROL_A); /* reset fifo */
1580 outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1582 chan = CR_CHAN(insn->chanspec);
1583 /* mask of unipolar/bipolar bit from range */
1584 range = CR_RANGE(insn->chanspec) & 0x3;
1585 chan_range = chan | (range << 8);
1586 spin_lock_irqsave(&dev->spinlock, irq_flags);
1587 outb(QRAM, dev->iobase + DAS1800_SELECT); /* select QRAM for baseAddress + 0x0 */
1588 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /* set QRAM address start */
1589 outw(chan_range, dev->iobase + DAS1800_QRAM);
1590 outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS); /*finish write to QRAM */
1591 outb(ADC, dev->iobase + DAS1800_SELECT); /* select ADC for baseAddress + 0x0 */
1593 for (n = 0; n < insn->n; n++) {
1594 /* trigger conversion */
1595 outb(0, dev->iobase + DAS1800_FIFO);
1596 for (i = 0; i < timeout; i++) {
1597 if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1601 comedi_error(dev, "timeout");
1604 dpnt = inw(dev->iobase + DAS1800_FIFO);
1605 /* shift data to offset binary for bipolar ranges */
1606 if ((conv_flags & UB) == 0)
1607 dpnt += 1 << (thisboard->resolution - 1);
1610 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1615 /* writes to an analog output channel */
1616 static int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
1617 struct comedi_insn *insn, unsigned int *data)
1619 int chan = CR_CHAN(insn->chanspec);
1620 /* int range = CR_RANGE(insn->chanspec); */
1621 int update_chan = thisboard->ao_n_chan - 1;
1623 unsigned long irq_flags;
1625 /* card expects two's complement data */
1626 output = data[0] - (1 << (thisboard->resolution - 1));
1627 /* if the write is to the 'update' channel, we need to remember its value */
1628 if (chan == update_chan)
1629 devpriv->ao_update_bits = output;
1630 /* write to channel */
1631 spin_lock_irqsave(&dev->spinlock, irq_flags);
1632 outb(DAC(chan), dev->iobase + DAS1800_SELECT); /* select dac channel for baseAddress + 0x0 */
1633 outw(output, dev->iobase + DAS1800_DAC);
1634 /* now we need to write to 'update' channel to update all dac channels */
1635 if (chan != update_chan) {
1636 outb(DAC(update_chan), dev->iobase + DAS1800_SELECT); /* select 'update' channel for baseAddress + 0x0 */
1637 outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1639 spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1644 /* reads from digital input channels */
1645 static int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
1646 struct comedi_insn *insn, unsigned int *data)
1649 data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1655 /* writes to digital output channels */
1656 static int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
1657 struct comedi_insn *insn, unsigned int *data)
1661 /* only set bits that have been masked */
1662 data[0] &= (1 << s->n_chan) - 1;
1663 wbits = devpriv->do_bits;
1665 wbits |= data[0] & data[1];
1666 devpriv->do_bits = wbits;
1668 outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1670 data[1] = devpriv->do_bits;
1675 /* loads counters with divisor1, divisor2 from private structure */
1676 static int das1800_set_frequency(struct comedi_device *dev)
1680 /* counter 1, mode 2 */
1681 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1684 /* counter 2, mode 2 */
1685 if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1694 /* converts requested conversion timing to timing compatible with
1695 * hardware, used only when card is in 'burst mode'
1697 static unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1699 unsigned int micro_sec;
1701 /* in burst mode, the maximum conversion time is 64 microseconds */
1702 if (convert_arg > 64000)
1703 convert_arg = 64000;
1705 /* the conversion time must be an integral number of microseconds */
1706 switch (round_mode) {
1707 case TRIG_ROUND_NEAREST:
1709 micro_sec = (convert_arg + 500) / 1000;
1711 case TRIG_ROUND_DOWN:
1712 micro_sec = convert_arg / 1000;
1715 micro_sec = (convert_arg - 1) / 1000 + 1;
1719 /* return number of nanoseconds */
1720 return micro_sec * 1000;
1723 /* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1724 static unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
1726 unsigned int size = DMA_BUF_SIZE;
1727 static const int sample_size = 2; /* size in bytes of one sample from board */
1728 unsigned int fill_time = 300000000; /* target time in nanoseconds for filling dma buffer */
1729 unsigned int max_size; /* maximum size we will allow for a transfer */
1731 /* make dma buffer fill in 0.3 seconds for timed modes */
1732 switch (cmd->scan_begin_src) {
1733 case TRIG_FOLLOW: /* not in burst mode */
1734 if (cmd->convert_src == TRIG_TIMER)
1735 size = (fill_time / cmd->convert_arg) * sample_size;
1738 size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1742 size = DMA_BUF_SIZE;
1746 /* set a minimum and maximum size allowed */
1747 max_size = DMA_BUF_SIZE;
1748 /* if we are taking limited number of conversions, limit transfer size to that */
1749 if (cmd->stop_src == TRIG_COUNT &&
1750 cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1751 max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1753 if (size > max_size)
1755 if (size < sample_size)