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 <linux/slab.h>
105 #include "../comedidev.h"
107 #include <linux/ioport.h>
111 #include "comedi_fc.h"
114 #define DAS1800_SIZE 16 /* uses 16 io addresses */
115 #define FIFO_SIZE 1024 /* 1024 sample fifo */
116 #define TIMER_BASE 200 /* 5 Mhz master clock */
117 #define UNIPOLAR 0x4 /* bit that determines whether input range is uni/bipolar */
118 #define DMA_BUF_SIZE 0x1ff00 /* size in bytes of dma buffers */
120 /* Registers for the das1800 */
121 #define DAS1800_FIFO 0x0
122 #define DAS1800_QRAM 0x0
123 #define DAS1800_DAC 0x0
124 #define DAS1800_SELECT 0x2
127 #define DAC(a) (0x2 + a)
128 #define DAS1800_DIGITAL 0x3
129 #define DAS1800_CONTROL_A 0x4
136 #define DAS1800_CONTROL_B 0x5
140 #define DMA_CH5_CH6 0x5
141 #define DMA_CH6_CH7 0x6
142 #define DMA_CH7_CH5 0x7
143 #define DMA_ENABLED 0x3 /* mask used to determine if dma is enabled */
152 #define DAS1800_CONTROL_C 0X6
160 #define DAS1800_STATUS 0x7
161 /* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
162 #define CLEAR_INTR_MASK (CVEN_MASK | 0x1f)
169 #define CVEN_MASK 0x40 /* masks CVEN on write */
171 #define DAS1800_BURST_LENGTH 0x8
172 #define DAS1800_BURST_RATE 0x9
173 #define DAS1800_QRAM_ADDRESS 0xa
174 #define DAS1800_COUNTER 0xc
176 #define IOBASE2 0x400 /* offset of additional ioports used on 'ao' cards */
179 das1701st
, das1701st_da
, das1702st
, das1702st_da
, das1702hr
,
181 das1701ao
, das1702ao
, das1801st
, das1801st_da
, das1802st
, das1802st_da
,
182 das1802hr
, das1802hr_da
, das1801hc
, das1802hc
, das1801ao
, das1802ao
185 static int das1800_attach(struct comedi_device
*dev
,
186 struct comedi_devconfig
*it
);
187 static int das1800_detach(struct comedi_device
*dev
);
188 static int das1800_probe(struct comedi_device
*dev
);
189 static int das1800_cancel(struct comedi_device
*dev
,
190 struct comedi_subdevice
*s
);
191 static irqreturn_t
das1800_interrupt(int irq
, void *d
);
192 static int das1800_ai_poll(struct comedi_device
*dev
,
193 struct comedi_subdevice
*s
);
194 static void das1800_ai_handler(struct comedi_device
*dev
);
195 static void das1800_handle_dma(struct comedi_device
*dev
,
196 struct comedi_subdevice
*s
, unsigned int status
);
197 static void das1800_flush_dma(struct comedi_device
*dev
,
198 struct comedi_subdevice
*s
);
199 static void das1800_flush_dma_channel(struct comedi_device
*dev
,
200 struct comedi_subdevice
*s
,
201 unsigned int channel
, uint16_t * buffer
);
202 static void das1800_handle_fifo_half_full(struct comedi_device
*dev
,
203 struct comedi_subdevice
*s
);
204 static void das1800_handle_fifo_not_empty(struct comedi_device
*dev
,
205 struct comedi_subdevice
*s
);
206 static int das1800_ai_do_cmdtest(struct comedi_device
*dev
,
207 struct comedi_subdevice
*s
,
208 struct comedi_cmd
*cmd
);
209 static int das1800_ai_do_cmd(struct comedi_device
*dev
,
210 struct comedi_subdevice
*s
);
211 static int das1800_ai_rinsn(struct comedi_device
*dev
,
212 struct comedi_subdevice
*s
,
213 struct comedi_insn
*insn
, unsigned int *data
);
214 static int das1800_ao_winsn(struct comedi_device
*dev
,
215 struct comedi_subdevice
*s
,
216 struct comedi_insn
*insn
, unsigned int *data
);
217 static int das1800_di_rbits(struct comedi_device
*dev
,
218 struct comedi_subdevice
*s
,
219 struct comedi_insn
*insn
, unsigned int *data
);
220 static int das1800_do_wbits(struct comedi_device
*dev
,
221 struct comedi_subdevice
*s
,
222 struct comedi_insn
*insn
, unsigned int *data
);
224 static int das1800_set_frequency(struct comedi_device
*dev
);
225 static unsigned int burst_convert_arg(unsigned int convert_arg
, int round_mode
);
226 static unsigned int suggest_transfer_size(struct comedi_cmd
*cmd
);
228 /* analog input ranges */
229 static const struct comedi_lrange range_ai_das1801
= {
243 static const struct comedi_lrange range_ai_das1802
= {
257 struct das1800_board
{
259 int ai_speed
; /* max conversion period in nanoseconds */
260 int resolution
; /* bits of ai resolution */
261 int qram_len
; /* length of card's channel / gain queue */
262 int common
; /* supports AREF_COMMON flag */
263 int do_n_chan
; /* number of digital output channels */
264 int ao_ability
; /* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
265 int ao_n_chan
; /* number of analog out channels */
266 const struct comedi_lrange
*range_ai
; /* available input ranges */
269 /* Warning: the maximum conversion speeds listed below are
270 * not always achievable depending on board setup (see
273 static const struct das1800_board das1800_boards
[] = {
275 .name
= "das-1701st",
283 .range_ai
= &range_ai_das1801
,
286 .name
= "das-1701st-da",
294 .range_ai
= &range_ai_das1801
,
297 .name
= "das-1702st",
305 .range_ai
= &range_ai_das1802
,
308 .name
= "das-1702st-da",
316 .range_ai
= &range_ai_das1802
,
319 .name
= "das-1702hr",
327 .range_ai
= &range_ai_das1802
,
330 .name
= "das-1702hr-da",
338 .range_ai
= &range_ai_das1802
,
341 .name
= "das-1701ao",
349 .range_ai
= &range_ai_das1801
,
352 .name
= "das-1702ao",
360 .range_ai
= &range_ai_das1802
,
363 .name
= "das-1801st",
371 .range_ai
= &range_ai_das1801
,
374 .name
= "das-1801st-da",
382 .range_ai
= &range_ai_das1801
,
385 .name
= "das-1802st",
393 .range_ai
= &range_ai_das1802
,
396 .name
= "das-1802st-da",
404 .range_ai
= &range_ai_das1802
,
407 .name
= "das-1802hr",
415 .range_ai
= &range_ai_das1802
,
418 .name
= "das-1802hr-da",
426 .range_ai
= &range_ai_das1802
,
429 .name
= "das-1801hc",
437 .range_ai
= &range_ai_das1801
,
440 .name
= "das-1802hc",
448 .range_ai
= &range_ai_das1802
,
451 .name
= "das-1801ao",
459 .range_ai
= &range_ai_das1801
,
462 .name
= "das-1802ao",
470 .range_ai
= &range_ai_das1802
,
475 * Useful for shorthand access to the particular board structure
477 #define thisboard ((const struct das1800_board *)dev->board_ptr)
479 struct das1800_private
{
480 volatile unsigned int count
; /* number of data points left to be taken */
481 unsigned int divisor1
; /* value to load into board's counter 1 for timed conversions */
482 unsigned int divisor2
; /* value to load into board's counter 2 for timed conversions */
483 int do_bits
; /* digital output bits */
484 int irq_dma_bits
; /* bits for control register b */
485 /* dma bits for control register b, stored so that dma can be
486 * turned on and off */
488 unsigned int dma0
; /* dma channels used */
490 volatile unsigned int dma_current
; /* dma channel currently in use */
491 uint16_t *ai_buf0
; /* pointers to dma buffers */
493 uint16_t *dma_current_buf
; /* pointer to dma buffer currently being used */
494 unsigned int dma_transfer_size
; /* size of transfer currently used, in bytes */
495 unsigned long iobase2
; /* secondary io address used for analog out on 'ao' boards */
496 short ao_update_bits
; /* remembers the last write to the 'update' dac */
499 #define devpriv ((struct das1800_private *)dev->private)
501 /* analog out range for boards with basic analog out */
502 static const struct comedi_lrange range_ao_1
= {
509 /* analog out range for 'ao' boards */
511 static const struct comedi_lrange range_ao_2 = {
520 static struct comedi_driver driver_das1800
= {
521 .driver_name
= "das1800",
522 .module
= THIS_MODULE
,
523 .attach
= das1800_attach
,
524 .detach
= das1800_detach
,
525 .num_names
= ARRAY_SIZE(das1800_boards
),
526 .board_name
= &das1800_boards
[0].name
,
527 .offset
= sizeof(struct das1800_board
),
531 * A convenient macro that defines init_module() and cleanup_module(),
534 static int __init
driver_das1800_init_module(void)
536 return comedi_driver_register(&driver_das1800
);
539 static void __exit
driver_das1800_cleanup_module(void)
541 comedi_driver_unregister(&driver_das1800
);
544 module_init(driver_das1800_init_module
);
545 module_exit(driver_das1800_cleanup_module
);
547 static int das1800_init_dma(struct comedi_device
*dev
, unsigned int dma0
,
552 /* need an irq to do dma */
553 if (dev
->irq
&& dma0
) {
554 /* encode dma0 and dma1 into 2 digit hexadecimal for switch */
555 switch ((dma0
& 0x7) | (dma1
<< 4)) {
556 case 0x5: /* dma0 == 5 */
557 devpriv
->dma_bits
|= DMA_CH5
;
559 case 0x6: /* dma0 == 6 */
560 devpriv
->dma_bits
|= DMA_CH6
;
562 case 0x7: /* dma0 == 7 */
563 devpriv
->dma_bits
|= DMA_CH7
;
565 case 0x65: /* dma0 == 5, dma1 == 6 */
566 devpriv
->dma_bits
|= DMA_CH5_CH6
;
568 case 0x76: /* dma0 == 6, dma1 == 7 */
569 devpriv
->dma_bits
|= DMA_CH6_CH7
;
571 case 0x57: /* dma0 == 7, dma1 == 5 */
572 devpriv
->dma_bits
|= DMA_CH7_CH5
;
575 printk(" only supports dma channels 5 through 7\n"
576 " Dual dma only allows the following combinations:\n"
577 " dma 5,6 / 6,7 / or 7,5\n");
581 if (request_dma(dma0
, driver_das1800
.driver_name
)) {
582 printk(" failed to allocate dma channel %i\n", dma0
);
585 devpriv
->dma0
= dma0
;
586 devpriv
->dma_current
= dma0
;
588 if (request_dma(dma1
, driver_das1800
.driver_name
)) {
589 printk(" failed to allocate dma channel %i\n",
593 devpriv
->dma1
= dma1
;
595 devpriv
->ai_buf0
= kmalloc(DMA_BUF_SIZE
, GFP_KERNEL
| GFP_DMA
);
596 if (devpriv
->ai_buf0
== NULL
)
598 devpriv
->dma_current_buf
= devpriv
->ai_buf0
;
601 kmalloc(DMA_BUF_SIZE
, GFP_KERNEL
| GFP_DMA
);
602 if (devpriv
->ai_buf1
== NULL
)
605 flags
= claim_dma_lock();
606 disable_dma(devpriv
->dma0
);
607 set_dma_mode(devpriv
->dma0
, DMA_MODE_READ
);
609 disable_dma(devpriv
->dma1
);
610 set_dma_mode(devpriv
->dma1
, DMA_MODE_READ
);
612 release_dma_lock(flags
);
617 static int das1800_attach(struct comedi_device
*dev
,
618 struct comedi_devconfig
*it
)
620 struct comedi_subdevice
*s
;
621 unsigned long iobase
= it
->options
[0];
622 unsigned int irq
= it
->options
[1];
623 unsigned int dma0
= it
->options
[2];
624 unsigned int dma1
= it
->options
[3];
625 unsigned long iobase2
;
629 /* allocate and initialize dev->private */
630 if (alloc_private(dev
, sizeof(struct das1800_private
)) < 0)
633 printk("comedi%d: %s: io 0x%lx", dev
->minor
, driver_das1800
.driver_name
,
636 printk(", irq %u", irq
);
638 printk(", dma %u", dma0
);
640 printk(" and %u", dma1
);
646 printk(" io base address required\n");
650 /* check if io addresses are available */
651 if (!request_region(iobase
, DAS1800_SIZE
, driver_das1800
.driver_name
)) {
653 (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
654 iobase
, iobase
+ DAS1800_SIZE
- 1);
657 dev
->iobase
= iobase
;
659 board
= das1800_probe(dev
);
661 printk(" unable to determine board type\n");
665 dev
->board_ptr
= das1800_boards
+ board
;
666 dev
->board_name
= thisboard
->name
;
668 /* if it is an 'ao' board with fancy analog out then we need extra io ports */
669 if (thisboard
->ao_ability
== 2) {
670 iobase2
= iobase
+ IOBASE2
;
671 if (!request_region(iobase2
, DAS1800_SIZE
,
672 driver_das1800
.driver_name
)) {
674 (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
675 iobase2
, iobase2
+ DAS1800_SIZE
- 1);
678 devpriv
->iobase2
= iobase2
;
683 if (request_irq(irq
, das1800_interrupt
, 0,
684 driver_das1800
.driver_name
, dev
)) {
685 printk(" unable to allocate irq %u\n", irq
);
691 /* set bits that tell card which irq to use */
696 devpriv
->irq_dma_bits
|= 0x8;
699 devpriv
->irq_dma_bits
|= 0x10;
702 devpriv
->irq_dma_bits
|= 0x18;
705 devpriv
->irq_dma_bits
|= 0x28;
708 devpriv
->irq_dma_bits
|= 0x30;
711 devpriv
->irq_dma_bits
|= 0x38;
714 printk(" irq out of range\n");
719 retval
= das1800_init_dma(dev
, dma0
, dma1
);
723 if (devpriv
->ai_buf0
== NULL
) {
725 kmalloc(FIFO_SIZE
* sizeof(uint16_t), GFP_KERNEL
);
726 if (devpriv
->ai_buf0
== NULL
)
730 if (alloc_subdevices(dev
, 4) < 0)
733 /* analog input subdevice */
734 s
= dev
->subdevices
+ 0;
735 dev
->read_subdev
= s
;
736 s
->type
= COMEDI_SUBD_AI
;
737 s
->subdev_flags
= SDF_READABLE
| SDF_DIFF
| SDF_GROUND
| SDF_CMD_READ
;
738 if (thisboard
->common
)
739 s
->subdev_flags
|= SDF_COMMON
;
740 s
->n_chan
= thisboard
->qram_len
;
741 s
->len_chanlist
= thisboard
->qram_len
;
742 s
->maxdata
= (1 << thisboard
->resolution
) - 1;
743 s
->range_table
= thisboard
->range_ai
;
744 s
->do_cmd
= das1800_ai_do_cmd
;
745 s
->do_cmdtest
= das1800_ai_do_cmdtest
;
746 s
->insn_read
= das1800_ai_rinsn
;
747 s
->poll
= das1800_ai_poll
;
748 s
->cancel
= das1800_cancel
;
751 s
= dev
->subdevices
+ 1;
752 if (thisboard
->ao_ability
== 1) {
753 s
->type
= COMEDI_SUBD_AO
;
754 s
->subdev_flags
= SDF_WRITABLE
;
755 s
->n_chan
= thisboard
->ao_n_chan
;
756 s
->maxdata
= (1 << thisboard
->resolution
) - 1;
757 s
->range_table
= &range_ao_1
;
758 s
->insn_write
= das1800_ao_winsn
;
760 s
->type
= COMEDI_SUBD_UNUSED
;
764 s
= dev
->subdevices
+ 2;
765 s
->type
= COMEDI_SUBD_DI
;
766 s
->subdev_flags
= SDF_READABLE
;
769 s
->range_table
= &range_digital
;
770 s
->insn_bits
= das1800_di_rbits
;
773 s
= dev
->subdevices
+ 3;
774 s
->type
= COMEDI_SUBD_DO
;
775 s
->subdev_flags
= SDF_WRITABLE
| SDF_READABLE
;
776 s
->n_chan
= thisboard
->do_n_chan
;
778 s
->range_table
= &range_digital
;
779 s
->insn_bits
= das1800_do_wbits
;
781 das1800_cancel(dev
, dev
->read_subdev
);
783 /* initialize digital out channels */
784 outb(devpriv
->do_bits
, dev
->iobase
+ DAS1800_DIGITAL
);
786 /* initialize analog out channels */
787 if (thisboard
->ao_ability
== 1) {
788 /* select 'update' dac channel for baseAddress + 0x0 */
789 outb(DAC(thisboard
->ao_n_chan
- 1),
790 dev
->iobase
+ DAS1800_SELECT
);
791 outw(devpriv
->ao_update_bits
, dev
->iobase
+ DAS1800_DAC
);
797 static int das1800_detach(struct comedi_device
*dev
)
799 /* only free stuff if it has been allocated by _attach */
801 release_region(dev
->iobase
, DAS1800_SIZE
);
803 free_irq(dev
->irq
, dev
);
805 if (devpriv
->iobase2
)
806 release_region(devpriv
->iobase2
, DAS1800_SIZE
);
808 free_dma(devpriv
->dma0
);
810 free_dma(devpriv
->dma1
);
811 kfree(devpriv
->ai_buf0
);
812 kfree(devpriv
->ai_buf1
);
815 printk("comedi%d: %s: remove\n", dev
->minor
,
816 driver_das1800
.driver_name
);
821 /* probes and checks das-1800 series board type
823 static int das1800_probe(struct comedi_device
*dev
)
828 id
= (inb(dev
->iobase
+ DAS1800_DIGITAL
) >> 4) & 0xf; /* get id bits */
829 board
= ((struct das1800_board
*)dev
->board_ptr
) - das1800_boards
;
833 if (board
== das1801st_da
|| board
== das1802st_da
||
834 board
== das1701st_da
|| board
== das1702st_da
) {
835 printk(" Board model: %s\n",
836 das1800_boards
[board
].name
);
840 (" Board model (probed, not recommended): das-1800st-da series\n");
844 if (board
== das1802hr_da
|| board
== das1702hr_da
) {
845 printk(" Board model: %s\n",
846 das1800_boards
[board
].name
);
850 (" Board model (probed, not recommended): das-1802hr-da\n");
854 if (board
== das1801ao
|| board
== das1802ao
||
855 board
== das1701ao
|| board
== das1702ao
) {
856 printk(" Board model: %s\n",
857 das1800_boards
[board
].name
);
861 (" Board model (probed, not recommended): das-1800ao series\n");
865 if (board
== das1802hr
|| board
== das1702hr
) {
866 printk(" Board model: %s\n",
867 das1800_boards
[board
].name
);
870 printk(" Board model (probed, not recommended): das-1802hr\n");
874 if (board
== das1801st
|| board
== das1802st
||
875 board
== das1701st
|| board
== das1702st
) {
876 printk(" Board model: %s\n",
877 das1800_boards
[board
].name
);
881 (" Board model (probed, not recommended): das-1800st series\n");
885 if (board
== das1801hc
|| board
== das1802hc
) {
886 printk(" Board model: %s\n",
887 das1800_boards
[board
].name
);
891 (" Board model (probed, not recommended): das-1800hc series\n");
896 (" Board model: probe returned 0x%x (unknown, please report)\n",
904 static int das1800_ai_poll(struct comedi_device
*dev
,
905 struct comedi_subdevice
*s
)
909 /* prevent race with interrupt handler */
910 spin_lock_irqsave(&dev
->spinlock
, flags
);
911 das1800_ai_handler(dev
);
912 spin_unlock_irqrestore(&dev
->spinlock
, flags
);
914 return s
->async
->buf_write_count
- s
->async
->buf_read_count
;
917 static irqreturn_t
das1800_interrupt(int irq
, void *d
)
919 struct comedi_device
*dev
= d
;
922 if (dev
->attached
== 0) {
923 comedi_error(dev
, "premature interrupt");
927 /* Prevent race with das1800_ai_poll() on multi processor systems.
928 * Also protects indirect addressing in das1800_ai_handler */
929 spin_lock(&dev
->spinlock
);
930 status
= inb(dev
->iobase
+ DAS1800_STATUS
);
932 /* if interrupt was not caused by das-1800 */
933 if (!(status
& INT
)) {
934 spin_unlock(&dev
->spinlock
);
937 /* clear the interrupt status bit INT */
938 outb(CLEAR_INTR_MASK
& ~INT
, dev
->iobase
+ DAS1800_STATUS
);
939 /* handle interrupt */
940 das1800_ai_handler(dev
);
942 spin_unlock(&dev
->spinlock
);
946 /* the guts of the interrupt handler, that is shared with das1800_ai_poll */
947 static void das1800_ai_handler(struct comedi_device
*dev
)
949 struct comedi_subdevice
*s
= dev
->subdevices
+ 0; /* analog input subdevice */
950 struct comedi_async
*async
= s
->async
;
951 struct comedi_cmd
*cmd
= &async
->cmd
;
952 unsigned int status
= inb(dev
->iobase
+ DAS1800_STATUS
);
955 /* select adc for base address + 0 */
956 outb(ADC
, dev
->iobase
+ DAS1800_SELECT
);
957 /* dma buffer full */
958 if (devpriv
->irq_dma_bits
& DMA_ENABLED
) {
959 /* look for data from dma transfer even if dma terminal count hasn't happened yet */
960 das1800_handle_dma(dev
, s
, status
);
961 } else if (status
& FHF
) { /* if fifo half full */
962 das1800_handle_fifo_half_full(dev
, s
);
963 } else if (status
& FNE
) { /* if fifo not empty */
964 das1800_handle_fifo_not_empty(dev
, s
);
967 async
->events
|= COMEDI_CB_BLOCK
;
968 /* if the card's fifo has overflowed */
970 /* clear OVF interrupt bit */
971 outb(CLEAR_INTR_MASK
& ~OVF
, dev
->iobase
+ DAS1800_STATUS
);
972 comedi_error(dev
, "DAS1800 FIFO overflow");
973 das1800_cancel(dev
, s
);
974 async
->events
|= COMEDI_CB_ERROR
| COMEDI_CB_EOA
;
975 comedi_event(dev
, s
);
978 /* stop taking data if appropriate */
979 /* stop_src TRIG_EXT */
980 if (status
& CT0TC
) {
981 /* clear CT0TC interrupt bit */
982 outb(CLEAR_INTR_MASK
& ~CT0TC
, dev
->iobase
+ DAS1800_STATUS
);
983 /* make sure we get all remaining data from board before quitting */
984 if (devpriv
->irq_dma_bits
& DMA_ENABLED
)
985 das1800_flush_dma(dev
, s
);
987 das1800_handle_fifo_not_empty(dev
, s
);
988 das1800_cancel(dev
, s
); /* disable hardware conversions */
989 async
->events
|= COMEDI_CB_EOA
;
990 } else if (cmd
->stop_src
== TRIG_COUNT
&& devpriv
->count
== 0) { /* stop_src TRIG_COUNT */
991 das1800_cancel(dev
, s
); /* disable hardware conversions */
992 async
->events
|= COMEDI_CB_EOA
;
995 comedi_event(dev
, s
);
1000 static void das1800_handle_dma(struct comedi_device
*dev
,
1001 struct comedi_subdevice
*s
, unsigned int status
)
1003 unsigned long flags
;
1004 const int dual_dma
= devpriv
->irq_dma_bits
& DMA_DUAL
;
1006 flags
= claim_dma_lock();
1007 das1800_flush_dma_channel(dev
, s
, devpriv
->dma_current
,
1008 devpriv
->dma_current_buf
);
1009 /* re-enable dma channel */
1010 set_dma_addr(devpriv
->dma_current
,
1011 virt_to_bus(devpriv
->dma_current_buf
));
1012 set_dma_count(devpriv
->dma_current
, devpriv
->dma_transfer_size
);
1013 enable_dma(devpriv
->dma_current
);
1014 release_dma_lock(flags
);
1016 if (status
& DMATC
) {
1017 /* clear DMATC interrupt bit */
1018 outb(CLEAR_INTR_MASK
& ~DMATC
, dev
->iobase
+ DAS1800_STATUS
);
1019 /* switch dma channels for next time, if appropriate */
1021 /* read data from the other channel next time */
1022 if (devpriv
->dma_current
== devpriv
->dma0
) {
1023 devpriv
->dma_current
= devpriv
->dma1
;
1024 devpriv
->dma_current_buf
= devpriv
->ai_buf1
;
1026 devpriv
->dma_current
= devpriv
->dma0
;
1027 devpriv
->dma_current_buf
= devpriv
->ai_buf0
;
1035 static inline uint16_t munge_bipolar_sample(const struct comedi_device
*dev
,
1038 sample
+= 1 << (thisboard
->resolution
- 1);
1042 static void munge_data(struct comedi_device
*dev
, uint16_t * array
,
1043 unsigned int num_elements
)
1048 /* see if card is using a unipolar or bipolar range so we can munge data correctly */
1049 unipolar
= inb(dev
->iobase
+ DAS1800_CONTROL_C
) & UB
;
1051 /* convert to unsigned type if we are in a bipolar mode */
1053 for (i
= 0; i
< num_elements
; i
++) {
1054 array
[i
] = munge_bipolar_sample(dev
, array
[i
]);
1059 /* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1060 * Assumes dma lock is held */
1061 static void das1800_flush_dma_channel(struct comedi_device
*dev
,
1062 struct comedi_subdevice
*s
,
1063 unsigned int channel
, uint16_t * buffer
)
1065 unsigned int num_bytes
, num_samples
;
1066 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
1068 disable_dma(channel
);
1070 /* clear flip-flop to make sure 2-byte registers
1071 * get set correctly */
1072 clear_dma_ff(channel
);
1074 /* figure out how many points to read */
1075 num_bytes
= devpriv
->dma_transfer_size
- get_dma_residue(channel
);
1076 num_samples
= num_bytes
/ sizeof(short);
1078 /* if we only need some of the points */
1079 if (cmd
->stop_src
== TRIG_COUNT
&& devpriv
->count
< num_samples
)
1080 num_samples
= devpriv
->count
;
1082 munge_data(dev
, buffer
, num_samples
);
1083 cfc_write_array_to_buffer(s
, buffer
, num_bytes
);
1084 if (s
->async
->cmd
.stop_src
== TRIG_COUNT
)
1085 devpriv
->count
-= num_samples
;
1090 /* flushes remaining data from board when external trigger has stopped aquisition
1091 * and we are using dma transfers */
1092 static void das1800_flush_dma(struct comedi_device
*dev
,
1093 struct comedi_subdevice
*s
)
1095 unsigned long flags
;
1096 const int dual_dma
= devpriv
->irq_dma_bits
& DMA_DUAL
;
1098 flags
= claim_dma_lock();
1099 das1800_flush_dma_channel(dev
, s
, devpriv
->dma_current
,
1100 devpriv
->dma_current_buf
);
1103 /* switch to other channel and flush it */
1104 if (devpriv
->dma_current
== devpriv
->dma0
) {
1105 devpriv
->dma_current
= devpriv
->dma1
;
1106 devpriv
->dma_current_buf
= devpriv
->ai_buf1
;
1108 devpriv
->dma_current
= devpriv
->dma0
;
1109 devpriv
->dma_current_buf
= devpriv
->ai_buf0
;
1111 das1800_flush_dma_channel(dev
, s
, devpriv
->dma_current
,
1112 devpriv
->dma_current_buf
);
1115 release_dma_lock(flags
);
1117 /* get any remaining samples in fifo */
1118 das1800_handle_fifo_not_empty(dev
, s
);
1123 static void das1800_handle_fifo_half_full(struct comedi_device
*dev
,
1124 struct comedi_subdevice
*s
)
1126 int numPoints
= 0; /* number of points to read */
1127 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
1129 numPoints
= FIFO_SIZE
/ 2;
1130 /* if we only need some of the points */
1131 if (cmd
->stop_src
== TRIG_COUNT
&& devpriv
->count
< numPoints
)
1132 numPoints
= devpriv
->count
;
1133 insw(dev
->iobase
+ DAS1800_FIFO
, devpriv
->ai_buf0
, numPoints
);
1134 munge_data(dev
, devpriv
->ai_buf0
, numPoints
);
1135 cfc_write_array_to_buffer(s
, devpriv
->ai_buf0
,
1136 numPoints
* sizeof(devpriv
->ai_buf0
[0]));
1137 if (cmd
->stop_src
== TRIG_COUNT
)
1138 devpriv
->count
-= numPoints
;
1142 static void das1800_handle_fifo_not_empty(struct comedi_device
*dev
,
1143 struct comedi_subdevice
*s
)
1147 struct comedi_cmd
*cmd
= &s
->async
->cmd
;
1149 unipolar
= inb(dev
->iobase
+ DAS1800_CONTROL_C
) & UB
;
1151 while (inb(dev
->iobase
+ DAS1800_STATUS
) & FNE
) {
1152 if (cmd
->stop_src
== TRIG_COUNT
&& devpriv
->count
== 0)
1154 dpnt
= inw(dev
->iobase
+ DAS1800_FIFO
);
1155 /* convert to unsigned type if we are in a bipolar mode */
1157 dpnt
= munge_bipolar_sample(dev
, dpnt
);
1158 cfc_write_to_buffer(s
, dpnt
);
1159 if (cmd
->stop_src
== TRIG_COUNT
)
1166 static int das1800_cancel(struct comedi_device
*dev
, struct comedi_subdevice
*s
)
1168 outb(0x0, dev
->iobase
+ DAS1800_STATUS
); /* disable conversions */
1169 outb(0x0, dev
->iobase
+ DAS1800_CONTROL_B
); /* disable interrupts and dma */
1170 outb(0x0, dev
->iobase
+ DAS1800_CONTROL_A
); /* disable and clear fifo and stop triggering */
1172 disable_dma(devpriv
->dma0
);
1174 disable_dma(devpriv
->dma1
);
1178 /* test analog input cmd */
1179 static int das1800_ai_do_cmdtest(struct comedi_device
*dev
,
1180 struct comedi_subdevice
*s
,
1181 struct comedi_cmd
*cmd
)
1185 unsigned int tmp_arg
;
1189 /* step 1: make sure trigger sources are trivially valid */
1191 tmp
= cmd
->start_src
;
1192 cmd
->start_src
&= TRIG_NOW
| TRIG_EXT
;
1193 if (!cmd
->start_src
|| tmp
!= cmd
->start_src
)
1196 tmp
= cmd
->scan_begin_src
;
1197 cmd
->scan_begin_src
&= TRIG_FOLLOW
| TRIG_TIMER
| TRIG_EXT
;
1198 if (!cmd
->scan_begin_src
|| tmp
!= cmd
->scan_begin_src
)
1201 tmp
= cmd
->convert_src
;
1202 cmd
->convert_src
&= TRIG_TIMER
| TRIG_EXT
;
1203 if (!cmd
->convert_src
|| tmp
!= cmd
->convert_src
)
1206 tmp
= cmd
->scan_end_src
;
1207 cmd
->scan_end_src
&= TRIG_COUNT
;
1208 if (!cmd
->scan_end_src
|| tmp
!= cmd
->scan_end_src
)
1211 tmp
= cmd
->stop_src
;
1212 cmd
->stop_src
&= TRIG_COUNT
| TRIG_EXT
| TRIG_NONE
;
1213 if (!cmd
->stop_src
|| tmp
!= cmd
->stop_src
)
1219 /* step 2: make sure trigger sources are unique and mutually compatible */
1221 /* uniqueness check */
1222 if (cmd
->start_src
!= TRIG_NOW
&& cmd
->start_src
!= TRIG_EXT
)
1224 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&&
1225 cmd
->scan_begin_src
!= TRIG_TIMER
&&
1226 cmd
->scan_begin_src
!= TRIG_EXT
)
1228 if (cmd
->convert_src
!= TRIG_TIMER
&& cmd
->convert_src
!= TRIG_EXT
)
1230 if (cmd
->stop_src
!= TRIG_COUNT
&&
1231 cmd
->stop_src
!= TRIG_NONE
&& cmd
->stop_src
!= TRIG_EXT
)
1233 /* compatibility check */
1234 if (cmd
->scan_begin_src
!= TRIG_FOLLOW
&&
1235 cmd
->convert_src
!= TRIG_TIMER
)
1241 /* step 3: make sure arguments are trivially compatible */
1243 if (cmd
->start_arg
!= 0) {
1247 if (cmd
->convert_src
== TRIG_TIMER
) {
1248 if (cmd
->convert_arg
< thisboard
->ai_speed
) {
1249 cmd
->convert_arg
= thisboard
->ai_speed
;
1253 if (!cmd
->chanlist_len
) {
1254 cmd
->chanlist_len
= 1;
1257 if (cmd
->scan_end_arg
!= cmd
->chanlist_len
) {
1258 cmd
->scan_end_arg
= cmd
->chanlist_len
;
1262 switch (cmd
->stop_src
) {
1264 if (!cmd
->stop_arg
) {
1270 if (cmd
->stop_arg
!= 0) {
1282 /* step 4: fix up any arguments */
1284 if (cmd
->convert_src
== TRIG_TIMER
) {
1285 /* if we are not in burst mode */
1286 if (cmd
->scan_begin_src
== TRIG_FOLLOW
) {
1287 tmp_arg
= cmd
->convert_arg
;
1288 /* calculate counter values that give desired timing */
1289 i8253_cascade_ns_to_timer_2div(TIMER_BASE
,
1290 &(devpriv
->divisor1
),
1291 &(devpriv
->divisor2
),
1292 &(cmd
->convert_arg
),
1294 flags
& TRIG_ROUND_MASK
);
1295 if (tmp_arg
!= cmd
->convert_arg
)
1298 /* if we are in burst mode */
1300 /* check that convert_arg is compatible */
1301 tmp_arg
= cmd
->convert_arg
;
1303 burst_convert_arg(cmd
->convert_arg
,
1304 cmd
->flags
& TRIG_ROUND_MASK
);
1305 if (tmp_arg
!= cmd
->convert_arg
)
1308 if (cmd
->scan_begin_src
== TRIG_TIMER
) {
1309 /* if scans are timed faster than conversion rate allows */
1310 if (cmd
->convert_arg
* cmd
->chanlist_len
>
1311 cmd
->scan_begin_arg
) {
1312 cmd
->scan_begin_arg
=
1317 tmp_arg
= cmd
->scan_begin_arg
;
1318 /* calculate counter values that give desired timing */
1319 i8253_cascade_ns_to_timer_2div(TIMER_BASE
,
1329 if (tmp_arg
!= cmd
->scan_begin_arg
)
1338 /* make sure user is not trying to mix unipolar and bipolar ranges */
1339 if (cmd
->chanlist
) {
1340 unipolar
= CR_RANGE(cmd
->chanlist
[0]) & UNIPOLAR
;
1341 for (i
= 1; i
< cmd
->chanlist_len
; i
++) {
1342 if (unipolar
!= (CR_RANGE(cmd
->chanlist
[i
]) & UNIPOLAR
)) {
1344 "unipolar and bipolar ranges cannot be mixed in the chanlist");
1357 /* analog input cmd interface */
1359 /* first, some utility functions used in the main ai_do_cmd() */
1361 /* returns appropriate bits for control register a, depending on command */
1362 static int control_a_bits(struct comedi_cmd cmd
)
1366 control_a
= FFEN
; /* enable fifo */
1367 if (cmd
.stop_src
== TRIG_EXT
) {
1370 switch (cmd
.start_src
) {
1372 control_a
|= TGEN
| CGSL
;
1384 /* returns appropriate bits for control register c, depending on command */
1385 static int control_c_bits(struct comedi_cmd cmd
)
1390 /* set clock source to internal or external, select analog reference,
1391 * select unipolar / bipolar
1393 aref
= CR_AREF(cmd
.chanlist
[0]);
1394 control_c
= UQEN
; /* enable upper qram addresses */
1395 if (aref
!= AREF_DIFF
)
1397 if (aref
== AREF_COMMON
)
1399 /* if a unipolar range was selected */
1400 if (CR_RANGE(cmd
.chanlist
[0]) & UNIPOLAR
)
1402 switch (cmd
.scan_begin_src
) {
1403 case TRIG_FOLLOW
: /* not in burst mode */
1404 switch (cmd
.convert_src
) {
1406 /* trig on cascaded counters */
1410 /* trig on falling edge of external trigger */
1418 /* burst mode with internal pacer clock */
1419 control_c
|= BMDE
| IPCLK
;
1422 /* burst mode with external trigger */
1423 control_c
|= BMDE
| XPCLK
;
1432 /* sets up counters */
1433 static int setup_counters(struct comedi_device
*dev
, struct comedi_cmd cmd
)
1435 /* setup cascaded counters for conversion/scan frequency */
1436 switch (cmd
.scan_begin_src
) {
1437 case TRIG_FOLLOW
: /* not in burst mode */
1438 if (cmd
.convert_src
== TRIG_TIMER
) {
1439 /* set conversion frequency */
1440 i8253_cascade_ns_to_timer_2div(TIMER_BASE
,
1441 &(devpriv
->divisor1
),
1442 &(devpriv
->divisor2
),
1445 flags
& TRIG_ROUND_MASK
);
1446 if (das1800_set_frequency(dev
) < 0) {
1451 case TRIG_TIMER
: /* in burst mode */
1452 /* set scan frequency */
1453 i8253_cascade_ns_to_timer_2div(TIMER_BASE
, &(devpriv
->divisor1
),
1454 &(devpriv
->divisor2
),
1455 &(cmd
.scan_begin_arg
),
1456 cmd
.flags
& TRIG_ROUND_MASK
);
1457 if (das1800_set_frequency(dev
) < 0) {
1465 /* setup counter 0 for 'about triggering' */
1466 if (cmd
.stop_src
== TRIG_EXT
) {
1467 /* load counter 0 in mode 0 */
1468 i8254_load(dev
->iobase
+ DAS1800_COUNTER
, 0, 0, 1, 0);
1475 static void setup_dma(struct comedi_device
*dev
, struct comedi_cmd cmd
)
1477 unsigned long lock_flags
;
1478 const int dual_dma
= devpriv
->irq_dma_bits
& DMA_DUAL
;
1480 if ((devpriv
->irq_dma_bits
& DMA_ENABLED
) == 0)
1483 /* determine a reasonable dma transfer size */
1484 devpriv
->dma_transfer_size
= suggest_transfer_size(&cmd
);
1485 lock_flags
= claim_dma_lock();
1486 disable_dma(devpriv
->dma0
);
1487 /* clear flip-flop to make sure 2-byte registers for
1488 * count and address get set correctly */
1489 clear_dma_ff(devpriv
->dma0
);
1490 set_dma_addr(devpriv
->dma0
, virt_to_bus(devpriv
->ai_buf0
));
1491 /* set appropriate size of transfer */
1492 set_dma_count(devpriv
->dma0
, devpriv
->dma_transfer_size
);
1493 devpriv
->dma_current
= devpriv
->dma0
;
1494 devpriv
->dma_current_buf
= devpriv
->ai_buf0
;
1495 enable_dma(devpriv
->dma0
);
1496 /* set up dual dma if appropriate */
1498 disable_dma(devpriv
->dma1
);
1499 /* clear flip-flop to make sure 2-byte registers for
1500 * count and address get set correctly */
1501 clear_dma_ff(devpriv
->dma1
);
1502 set_dma_addr(devpriv
->dma1
, virt_to_bus(devpriv
->ai_buf1
));
1503 /* set appropriate size of transfer */
1504 set_dma_count(devpriv
->dma1
, devpriv
->dma_transfer_size
);
1505 enable_dma(devpriv
->dma1
);
1507 release_dma_lock(lock_flags
);
1512 /* programs channel/gain list into card */
1513 static void program_chanlist(struct comedi_device
*dev
, struct comedi_cmd cmd
)
1515 int i
, n
, chan_range
;
1516 unsigned long irq_flags
;
1517 const int range_mask
= 0x3; /* masks unipolar/bipolar bit off range */
1518 const int range_bitshift
= 8;
1520 n
= cmd
.chanlist_len
;
1521 /* spinlock protects indirect addressing */
1522 spin_lock_irqsave(&dev
->spinlock
, irq_flags
);
1523 outb(QRAM
, dev
->iobase
+ DAS1800_SELECT
); /* select QRAM for baseAddress + 0x0 */
1524 outb(n
- 1, dev
->iobase
+ DAS1800_QRAM_ADDRESS
); /*set QRAM address start */
1525 /* make channel / gain list */
1526 for (i
= 0; i
< n
; i
++) {
1529 chanlist
[i
]) | ((CR_RANGE(cmd
.chanlist
[i
]) &
1530 range_mask
) << range_bitshift
);
1531 outw(chan_range
, dev
->iobase
+ DAS1800_QRAM
);
1533 outb(n
- 1, dev
->iobase
+ DAS1800_QRAM_ADDRESS
); /*finish write to QRAM */
1534 spin_unlock_irqrestore(&dev
->spinlock
, irq_flags
);
1539 /* analog input do_cmd */
1540 static int das1800_ai_do_cmd(struct comedi_device
*dev
,
1541 struct comedi_subdevice
*s
)
1544 int control_a
, control_c
;
1545 struct comedi_async
*async
= s
->async
;
1546 struct comedi_cmd cmd
= async
->cmd
;
1550 "no irq assigned for das-1800, cannot do hardware conversions");
1554 /* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1555 * (because dma in handler is unsafe at hard real-time priority) */
1556 if (cmd
.flags
& (TRIG_WAKE_EOS
| TRIG_RT
)) {
1557 devpriv
->irq_dma_bits
&= ~DMA_ENABLED
;
1559 devpriv
->irq_dma_bits
|= devpriv
->dma_bits
;
1561 /* interrupt on end of conversion for TRIG_WAKE_EOS */
1562 if (cmd
.flags
& TRIG_WAKE_EOS
) {
1563 /* interrupt fifo not empty */
1564 devpriv
->irq_dma_bits
&= ~FIMD
;
1566 /* interrupt fifo half full */
1567 devpriv
->irq_dma_bits
|= FIMD
;
1569 /* determine how many conversions we need */
1570 if (cmd
.stop_src
== TRIG_COUNT
) {
1571 devpriv
->count
= cmd
.stop_arg
* cmd
.chanlist_len
;
1574 das1800_cancel(dev
, s
);
1576 /* determine proper bits for control registers */
1577 control_a
= control_a_bits(cmd
);
1578 control_c
= control_c_bits(cmd
);
1580 /* setup card and start */
1581 program_chanlist(dev
, cmd
);
1582 ret
= setup_counters(dev
, cmd
);
1584 comedi_error(dev
, "Error setting up counters");
1587 setup_dma(dev
, cmd
);
1588 outb(control_c
, dev
->iobase
+ DAS1800_CONTROL_C
);
1589 /* set conversion rate and length for burst mode */
1590 if (control_c
& BMDE
) {
1591 /* program conversion period with number of microseconds minus 1 */
1592 outb(cmd
.convert_arg
/ 1000 - 1,
1593 dev
->iobase
+ DAS1800_BURST_RATE
);
1594 outb(cmd
.chanlist_len
- 1, dev
->iobase
+ DAS1800_BURST_LENGTH
);
1596 outb(devpriv
->irq_dma_bits
, dev
->iobase
+ DAS1800_CONTROL_B
); /* enable irq/dma */
1597 outb(control_a
, dev
->iobase
+ DAS1800_CONTROL_A
); /* enable fifo and triggering */
1598 outb(CVEN
, dev
->iobase
+ DAS1800_STATUS
); /* enable conversions */
1603 /* read analog input */
1604 static int das1800_ai_rinsn(struct comedi_device
*dev
,
1605 struct comedi_subdevice
*s
,
1606 struct comedi_insn
*insn
, unsigned int *data
)
1609 int chan
, range
, aref
, chan_range
;
1613 unsigned long irq_flags
;
1615 /* set up analog reference and unipolar / bipolar mode */
1616 aref
= CR_AREF(insn
->chanspec
);
1618 if (aref
!= AREF_DIFF
)
1620 if (aref
== AREF_COMMON
)
1622 /* if a unipolar range was selected */
1623 if (CR_RANGE(insn
->chanspec
) & UNIPOLAR
)
1626 outb(conv_flags
, dev
->iobase
+ DAS1800_CONTROL_C
); /* software conversion enabled */
1627 outb(CVEN
, dev
->iobase
+ DAS1800_STATUS
); /* enable conversions */
1628 outb(0x0, dev
->iobase
+ DAS1800_CONTROL_A
); /* reset fifo */
1629 outb(FFEN
, dev
->iobase
+ DAS1800_CONTROL_A
);
1631 chan
= CR_CHAN(insn
->chanspec
);
1632 /* mask of unipolar/bipolar bit from range */
1633 range
= CR_RANGE(insn
->chanspec
) & 0x3;
1634 chan_range
= chan
| (range
<< 8);
1635 spin_lock_irqsave(&dev
->spinlock
, irq_flags
);
1636 outb(QRAM
, dev
->iobase
+ DAS1800_SELECT
); /* select QRAM for baseAddress + 0x0 */
1637 outb(0x0, dev
->iobase
+ DAS1800_QRAM_ADDRESS
); /* set QRAM address start */
1638 outw(chan_range
, dev
->iobase
+ DAS1800_QRAM
);
1639 outb(0x0, dev
->iobase
+ DAS1800_QRAM_ADDRESS
); /*finish write to QRAM */
1640 outb(ADC
, dev
->iobase
+ DAS1800_SELECT
); /* select ADC for baseAddress + 0x0 */
1642 for (n
= 0; n
< insn
->n
; n
++) {
1643 /* trigger conversion */
1644 outb(0, dev
->iobase
+ DAS1800_FIFO
);
1645 for (i
= 0; i
< timeout
; i
++) {
1646 if (inb(dev
->iobase
+ DAS1800_STATUS
) & FNE
)
1650 comedi_error(dev
, "timeout");
1654 dpnt
= inw(dev
->iobase
+ DAS1800_FIFO
);
1655 /* shift data to offset binary for bipolar ranges */
1656 if ((conv_flags
& UB
) == 0)
1657 dpnt
+= 1 << (thisboard
->resolution
- 1);
1661 spin_unlock_irqrestore(&dev
->spinlock
, irq_flags
);
1666 /* writes to an analog output channel */
1667 static int das1800_ao_winsn(struct comedi_device
*dev
,
1668 struct comedi_subdevice
*s
,
1669 struct comedi_insn
*insn
, unsigned int *data
)
1671 int chan
= CR_CHAN(insn
->chanspec
);
1672 /* int range = CR_RANGE(insn->chanspec); */
1673 int update_chan
= thisboard
->ao_n_chan
- 1;
1675 unsigned long irq_flags
;
1677 /* card expects two's complement data */
1678 output
= data
[0] - (1 << (thisboard
->resolution
- 1));
1679 /* if the write is to the 'update' channel, we need to remember its value */
1680 if (chan
== update_chan
)
1681 devpriv
->ao_update_bits
= output
;
1682 /* write to channel */
1683 spin_lock_irqsave(&dev
->spinlock
, irq_flags
);
1684 outb(DAC(chan
), dev
->iobase
+ DAS1800_SELECT
); /* select dac channel for baseAddress + 0x0 */
1685 outw(output
, dev
->iobase
+ DAS1800_DAC
);
1686 /* now we need to write to 'update' channel to update all dac channels */
1687 if (chan
!= update_chan
) {
1688 outb(DAC(update_chan
), dev
->iobase
+ DAS1800_SELECT
); /* select 'update' channel for baseAddress + 0x0 */
1689 outw(devpriv
->ao_update_bits
, dev
->iobase
+ DAS1800_DAC
);
1691 spin_unlock_irqrestore(&dev
->spinlock
, irq_flags
);
1696 /* reads from digital input channels */
1697 static int das1800_di_rbits(struct comedi_device
*dev
,
1698 struct comedi_subdevice
*s
,
1699 struct comedi_insn
*insn
, unsigned int *data
)
1702 data
[1] = inb(dev
->iobase
+ DAS1800_DIGITAL
) & 0xf;
1708 /* writes to digital output channels */
1709 static int das1800_do_wbits(struct comedi_device
*dev
,
1710 struct comedi_subdevice
*s
,
1711 struct comedi_insn
*insn
, unsigned int *data
)
1715 /* only set bits that have been masked */
1716 data
[0] &= (1 << s
->n_chan
) - 1;
1717 wbits
= devpriv
->do_bits
;
1719 wbits
|= data
[0] & data
[1];
1720 devpriv
->do_bits
= wbits
;
1722 outb(devpriv
->do_bits
, dev
->iobase
+ DAS1800_DIGITAL
);
1724 data
[1] = devpriv
->do_bits
;
1729 /* loads counters with divisor1, divisor2 from private structure */
1730 static int das1800_set_frequency(struct comedi_device
*dev
)
1734 /* counter 1, mode 2 */
1735 if (i8254_load(dev
->iobase
+ DAS1800_COUNTER
, 0, 1, devpriv
->divisor1
,
1738 /* counter 2, mode 2 */
1739 if (i8254_load(dev
->iobase
+ DAS1800_COUNTER
, 0, 2, devpriv
->divisor2
,
1748 /* converts requested conversion timing to timing compatible with
1749 * hardware, used only when card is in 'burst mode'
1751 static unsigned int burst_convert_arg(unsigned int convert_arg
, int round_mode
)
1753 unsigned int micro_sec
;
1755 /* in burst mode, the maximum conversion time is 64 microseconds */
1756 if (convert_arg
> 64000)
1757 convert_arg
= 64000;
1759 /* the conversion time must be an integral number of microseconds */
1760 switch (round_mode
) {
1761 case TRIG_ROUND_NEAREST
:
1763 micro_sec
= (convert_arg
+ 500) / 1000;
1765 case TRIG_ROUND_DOWN
:
1766 micro_sec
= convert_arg
/ 1000;
1769 micro_sec
= (convert_arg
- 1) / 1000 + 1;
1773 /* return number of nanoseconds */
1774 return micro_sec
* 1000;
1777 /* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1778 static unsigned int suggest_transfer_size(struct comedi_cmd
*cmd
)
1780 unsigned int size
= DMA_BUF_SIZE
;
1781 static const int sample_size
= 2; /* size in bytes of one sample from board */
1782 unsigned int fill_time
= 300000000; /* target time in nanoseconds for filling dma buffer */
1783 unsigned int max_size
; /* maximum size we will allow for a transfer */
1785 /* make dma buffer fill in 0.3 seconds for timed modes */
1786 switch (cmd
->scan_begin_src
) {
1787 case TRIG_FOLLOW
: /* not in burst mode */
1788 if (cmd
->convert_src
== TRIG_TIMER
)
1789 size
= (fill_time
/ cmd
->convert_arg
) * sample_size
;
1792 size
= (fill_time
/ (cmd
->scan_begin_arg
* cmd
->chanlist_len
)) *
1796 size
= DMA_BUF_SIZE
;
1800 /* set a minimum and maximum size allowed */
1801 max_size
= DMA_BUF_SIZE
;
1802 /* if we are taking limited number of conversions, limit transfer size to that */
1803 if (cmd
->stop_src
== TRIG_COUNT
&&
1804 cmd
->stop_arg
* cmd
->chanlist_len
* sample_size
< max_size
)
1805 max_size
= cmd
->stop_arg
* cmd
->chanlist_len
* sample_size
;
1807 if (size
> max_size
)
1809 if (size
< sample_size
)
1815 MODULE_AUTHOR("Comedi http://www.comedi.org");
1816 MODULE_DESCRIPTION("Comedi low-level driver");
1817 MODULE_LICENSE("GPL");