das1800.c revision a351ecf3081f94796cf915dba820f9f5e62c43cf
1a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
2a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    comedi/drivers/das1800.c
3a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    Driver for Keitley das1700/das1800 series boards
4a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    Copyright (C) 2000 Frank Mori Hess <fmhess@users.sourceforge.net>
5a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
6a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    COMEDI - Linux Control and Measurement Device Interface
7a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
8a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
9a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    This program is free software; you can redistribute it and/or modify
10a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    it under the terms of the GNU General Public License as published by
11a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    the Free Software Foundation; either version 2 of the License, or
12a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    (at your option) any later version.
13a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
14a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    This program is distributed in the hope that it will be useful,
15a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    but WITHOUT ANY WARRANTY; without even the implied warranty of
16a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    GNU General Public License for more details.
18a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
19a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    You should have received a copy of the GNU General Public License
20a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    along with this program; if not, write to the Free Software
21a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
23a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess************************************************************************
24a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
25a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
26a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessDriver: das1800
27a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessDescription: Keithley Metrabyte DAS1800 (& compatibles)
28a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessAuthor: Frank Mori Hess <fmhess@users.sourceforge.net>
29a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessDevices: [Keithley Metrabyte] DAS-1701ST (das-1701st),
30a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1701ST-DA (das-1701st-da), DAS-1701/AO (das-1701ao),
31a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1702ST (das-1702st), DAS-1702ST-DA (das-1702st-da),
32a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1702HR (das-1702hr), DAS-1702HR-DA (das-1702hr-da),
33a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1702/AO (das-1702ao), DAS-1801ST (das-1801st),
34a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1801ST-DA (das-1801st-da), DAS-1801HC (das-1801hc),
35a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1801AO (das-1801ao), DAS-1802ST (das-1802st),
36a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1802ST-DA (das-1802st-da), DAS-1802HR (das-1802hr),
37a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1802HR-DA (das-1802hr-da), DAS-1802HC (das-1802hc),
38a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  DAS-1802AO (das-1802ao)
39a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessStatus: works
40a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
41a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessThe waveform analog output on the 'ao' cards is not supported.
42a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessIf you need it, send me (Frank Hess) an email.
43a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
44a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessConfiguration options:
45a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  [0] - I/O port base address
46a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  [1] - IRQ (optional, required for timed or externally triggered conversions)
47a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  [2] - DMA0 (optional, requires irq)
48a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess  [3] - DMA1 (optional, requires irq and dma0)
49a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
50a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
51a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
52a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessThis driver supports the following Keithley boards:
53a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
54a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1701st
55a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1701st-da
56a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1701ao
57a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1702st
58a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1702st-da
59a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1702hr
60a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1702hr-da
61a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1702ao
62a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1801st
63a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1801st-da
64a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1801hc
65a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1801ao
66a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802st
67a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802st-da
68a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802hr
69a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802hr-da
70a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802hc
71a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessdas-1802ao
72a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
73a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessOptions:
74a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	[0] - base io address
75a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	[1] - irq (optional, required for timed or externally triggered conversions)
76a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	[2] - dma0 (optional, requires irq)
77a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	[3] - dma1 (optional, requires irq and dma0)
78a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
79a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessirq can be omitted, although the cmd interface will not work without it.
80a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
81a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessanalog input cmd triggers supported:
82a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	start_src:      TRIG_NOW | TRIG_EXT
83a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	scan_begin_src: TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT
84a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	scan_end_src:   TRIG_COUNT
85a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	convert_src:    TRIG_TIMER | TRIG_EXT (TRIG_EXT requires scan_begin_src == TRIG_FOLLOW)
86a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	stop_src:       TRIG_COUNT | TRIG_EXT | TRIG_NONE
87a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
88a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessscan_begin_src triggers TRIG_TIMER and TRIG_EXT use the card's
89a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess'burst mode' which limits the valid conversion time to 64 microseconds
90a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess(convert_arg <= 64000).  This limitation does not apply if scan_begin_src
91a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessis TRIG_FOLLOW.
92a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
93a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessNOTES:
94a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessOnly the DAS-1801ST has been tested by me.
95a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessUnipolar and bipolar ranges cannot be mixed in the channel/gain list.
96a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
97a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessTODO:
98a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	Make it automatically allocate irq and dma channels if they are not specified
99a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	Add support for analog out on 'ao' cards
100a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	read insn for analog out
101a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
102a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
103a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "../comedidev.h"
104a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
105a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <linux/ioport.h>
106a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <asm/dma.h>
107a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
108a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "8253.h"
109a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "comedi_fc.h"
110a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
111a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* misc. defines */
112a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DAS1800_SIZE           16	/* uses 16 io addresses */
113a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define FIFO_SIZE              1024	/*  1024 sample fifo */
114a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define TIMER_BASE             200	/*  5 Mhz master clock */
115a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
116a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
117a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
118a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Registers for the das1800 */
119a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_FIFO            0x0
120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM            0x0
121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DAC             0x0
122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_SELECT          0x2
123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ADC                     0x0
124a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   QRAM                    0x1
125a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DAC(a)                  (0x2 + a)
126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DIGITAL         0x3
127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_A       0x4
128a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FFEN                    0x1
129a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGEN                    0x4
130a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGSL                    0x8
131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGEN                    0x10
132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGSL                    0x20
133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ATEN                    0x80
134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_B       0x5
135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5                 0x1
136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6                 0x2
137a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7                 0x3
138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5_CH6             0x5
139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6_CH7             0x6
140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7_CH5             0x7
141a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   DMA_ENABLED             0x3	/* mask used to determine if dma is enabled */
142a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_DUAL                0x4
143a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ3                    0x8
144a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ5                    0x10
145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ7                    0x18
146a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ10                   0x28
147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ11                   0x30
148a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ15                   0x38
149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FIMD                    0x40
150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_C       0X6
151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IPCLK                   0x1
152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   XPCLK                   0x3
153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   BMDE                    0x4
154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CMEN                    0x8
155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UQEN                    0x10
156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   SD                      0x40
157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UB                      0x80
158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_STATUS          0x7
159a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
160a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   INT                     0x1
162a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMATC                   0x2
163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CT0TC                   0x8
164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   OVF                     0x10
165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FHF                     0x20
166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FNE                     0x40
167a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   CVEN_MASK               0x40	/*  masks CVEN on write */
168a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CVEN                    0x80
169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_LENGTH    0x8
170a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_RATE      0x9
171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM_ADDRESS    0xa
172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_COUNTER         0xc
173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
174a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define IOBASE2                   0x400	/* offset of additional ioports used on 'ao' cards */
175a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessenum {
177a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1702hr_da,
179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
180a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
181a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
182a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1830707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it);
18471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_detach(struct comedi_device * dev);
18571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_probe(struct comedi_device * dev);
18634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s);
187a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG);
18834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s);
18971b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_ai_handler(struct comedi_device * dev);
19034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
191a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status);
19234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s);
19334c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
194a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int channel, uint16_t * buffer);
19571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device * dev,
19634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice * s);
19771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device * dev,
19834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice * s);
19934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
200ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd);
20134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s);
20234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
20390035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
20434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
20590035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
20634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
20790035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
20834c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
20990035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data);
210a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
21171b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_set_frequency(struct comedi_device * dev);
212a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
213ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd * cmd);
214a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
215a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input ranges */
2169ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1801 = {
217a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
218a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
219a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-5, 5),
220a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-1, 1),
221a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-0.1, 0.1),
222a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-0.02, 0.02),
223a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 5),
224a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 1),
225a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 0.1),
226a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 0.02),
227a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
229a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
2309ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1802 = {
231a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
232a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
233a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-10, 10),
234a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-5, 5),
235a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-2.5, 2.5),
236a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-1.25, 1.25),
237a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 10),
238a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 5),
239a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 2.5),
240a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 1.25),
241a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
244ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstruct das1800_board {
245a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const char *name;
246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ai_speed;		/* max conversion period in nanoseconds */
247a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int resolution;		/* bits of ai resolution */
248a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int qram_len;		/* length of card's channel / gain queue */
249a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int common;		/* supports AREF_COMMON flag */
250a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_n_chan;		/* number of digital output channels */
251a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
252a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_n_chan;		/* number of analog out channels */
2539ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *range_ai;	/* available input ranges */
254ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton};
255a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Warning: the maximum conversion speeds listed below are
257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * not always achievable depending on board setup (see
258a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * user manual.)
259a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
260ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstatic const struct das1800_board das1800_boards[] = {
261a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1701st",
263a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
264a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
265a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
266a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
267a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
268a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
269a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
270a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
271a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1701st-da",
274a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
275a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
276a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
277a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
278a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
279a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
280a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:4,
281a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
282a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
283a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
284a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1702st",
285a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
286a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
287a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
288a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
289a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
290a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
291a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
292a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
293a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
294a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
295a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1702st-da",
296a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
297a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
298a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
299a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
300a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
301a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
302a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:4,
303a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
304a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
305a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
306a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1702hr",
307a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:20000,
308a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:16,
309a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
310a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
311a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
312a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
313a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
314a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
315a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
316a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
317a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1702hr-da",
318a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:20000,
319a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:16,
320a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
321a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
322a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
323a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
324a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
325a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
326a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
327a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
328a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1701ao",
329a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
330a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
331a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
332a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
333a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
334a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:2,
335a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
336a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
337a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
338a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
339a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1702ao",
340a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:6250,
341a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
342a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
343a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
344a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
345a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:2,
346a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
347a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
348a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
349a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
350a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1801st",
351a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
352a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
353a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
354a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
355a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
356a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
357a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
358a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
359a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
360a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
361a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1801st-da",
362a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
363a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
364a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
365a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
366a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
367a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
368a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:4,
369a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
370a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
371a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
372a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802st",
373a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
374a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
375a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
376a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
377a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
378a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
379a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
380a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
381a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
382a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
383a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802st-da",
384a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
385a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
386a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
387a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
388a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
389a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
390a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:4,
391a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
392a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
393a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
394a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802hr",
395a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:10000,
396a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:16,
397a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
398a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
399a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
400a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:0,
401a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:0,
402a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
403a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
404a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
405a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802hr-da",
406a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:10000,
407a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:16,
408a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
409a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
410a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
411a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
412a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
413a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
414a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
415a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
416a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1801hc",
417a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
418a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
419a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:64,
420a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	0,
421a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:8,
422a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
423a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
424a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
425a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
426a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
427a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802hc",
428a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
429a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
430a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:64,
431a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	0,
432a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:8,
433a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:1,
434a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
435a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
436a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
437a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
438a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1801ao",
439a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
440a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
441a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
442a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
443a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
444a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:2,
445a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
446a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1801,
447a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
448a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
449a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      name:	"das-1802ao",
450a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ai_speed:3000,
451a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      resolution:12,
452a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      qram_len:256,
453a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      common:	1,
454a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      do_n_chan:4,
455a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_ability:2,
456a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      ao_n_chan:2,
457a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	      range_ai:&range_ai_das1802,
458a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
459a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
460a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
461a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Useful for shorthand access to the particular board structure
463a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
464ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton#define thisboard ((const struct das1800_board *)dev->board_ptr)
465a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
4660c5a144d730a68967dfb3f8163260a142e3282e3Bill Pembertonstruct das1800_private {
467a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int count;	/* number of data points left to be taken */
468a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
469a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
470a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_bits;		/* digital output bits */
471a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int irq_dma_bits;	/* bits for control register b */
472a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* dma bits for control register b, stored so that dma can be
473a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * turned on and off */
474a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int dma_bits;
475a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0;	/* dma channels used */
476a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1;
477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int dma_current;	/* dma channel currently in use */
478a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf0;	/* pointers to dma buffers */
479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf1;
480a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short ao_update_bits;	/* remembers the last write to the 'update' dac */
4840c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton};
485a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
4860c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton#define devpriv ((struct das1800_private *)dev->private)
487a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
488a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for boards with basic analog out */
4899ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_1 = {
490a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	1,
491a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
492a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-10, 10),
493a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
496a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for 'ao' boards */
497a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
4989ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_2 = {
499a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	2,
500a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-10, 10),
502a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-5, 5),
503a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
504a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
506a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
507139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das1800 = {
508a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess      driver_name:"das1800",
509a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess      module:THIS_MODULE,
510a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess      attach:das1800_attach,
511a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess      detach:das1800_detach,
512ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton      num_names:sizeof(das1800_boards) / sizeof(struct das1800_board),
513a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess      board_name:&das1800_boards[0].name,
514ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton      offset:sizeof(struct das1800_board),
515a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
517a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
518a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * A convenient macro that defines init_module() and cleanup_module(),
519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * as necessary.
520a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
521a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessCOMEDI_INITCLEANUP(driver_das1800);
522a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
52371b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_init_dma(struct comedi_device * dev, unsigned int dma0,
524a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1)
525a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
526a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
527a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
528a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  need an irq to do dma */
529a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq && dma0) {
530a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/* encode dma0 and dma1 into 2 digit hexadecimal for switch */
531a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch ((dma0 & 0x7) | (dma1 << 4)) {
532a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x5:	/*  dma0 == 5 */
533a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5;
534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
535a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x6:	/*  dma0 == 6 */
536a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6;
537a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
538a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x7:	/*  dma0 == 7 */
539a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7;
540a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
541a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x65:	/*  dma0 == 5, dma1 == 6 */
542a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5_CH6;
543a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
544a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x76:	/*  dma0 == 6, dma1 == 7 */
545a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6_CH7;
546a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
547a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x57:	/*  dma0 == 7, dma1 == 5 */
548a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7_CH5;
549a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
551a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" only supports dma channels 5 through 7\n"
552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				" Dual dma only allows the following combinations:\n"
553a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				" dma 5,6 / 6,7 / or 7,5\n");
554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
555a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
556a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
557a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (request_dma(dma0, driver_das1800.driver_name)) {
558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" failed to allocate dma channel %i\n", dma0);
559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
560a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma0 = dma0;
562a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current = dma0;
563a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
564a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (request_dma(dma1, driver_das1800.driver_name)) {
565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" failed to allocate dma channel %i\n",
566a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					dma1);
567a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -EINVAL;
568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
569a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma1 = dma1;
570a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
572a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf = devpriv->ai_buf0;
575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->ai_buf1 =
577a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
578a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->ai_buf1 == NULL)
579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -ENOMEM;
580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		flags = claim_dma_lock();
582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_mode(devpriv->dma0, DMA_MODE_READ);
584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			disable_dma(devpriv->dma1);
586a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			set_dma_mode(devpriv->dma1, DMA_MODE_READ);
587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_dma_lock(flags);
589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
590a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
591a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
592a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
5930707bb04be89b18ee83b5a997e36cc585f0b988dBill Pembertonstatic int das1800_attach(struct comedi_device * dev, struct comedi_devconfig * it)
594a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
59534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
596a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase = it->options[0];
597a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int irq = it->options[1];
598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0 = it->options[2];
599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1 = it->options[3];
600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;
601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
602a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int retval;
603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* allocate and initialize dev->private */
6050c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton	if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
606a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
607a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		iobase);
610a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(", irq %u", irq);
612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma0) {
613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(", dma %u", dma0);
614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (dma1)
615a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" and %u", dma1);
616a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
617a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
618a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("\n");
619a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
620a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (iobase == 0) {
621a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" io base address required\n");
622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
624a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
625a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* check if io addresses are available */
626a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
627a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1);
628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EIO;
629a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
630a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->iobase = iobase;
631a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	board = das1800_probe(dev);
633a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (board < 0) {
634a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" unable to determine board type\n");
635a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENODEV;
636a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_ptr = das1800_boards + board;
639a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_name = thisboard->name;
640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
641a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if it is an 'ao' board with fancy analog out then we need extra io ports */
642a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 2) {
643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		iobase2 = iobase + IOBASE2;
644a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!request_region(iobase2, DAS1800_SIZE,
645a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				driver_das1800.driver_name)) {
646a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1);
647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EIO;
648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->iobase2 = iobase2;
650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
652a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* grab our IRQ */
653a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
654a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (comedi_request_irq(irq, das1800_interrupt, 0,
655a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				driver_das1800.driver_name, dev)) {
656a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" unable to allocate irq %u\n", irq);
657a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
658a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
659a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
660a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->irq = irq;
661a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
662a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set bits that tell card which irq to use */
663a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (irq) {
664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0:
665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 3:
667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x8;
668a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
669a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 5:
670a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x10;
671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 7:
673a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x18;
674a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
675a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 10:
676a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x28;
677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
678a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 11:
679a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x30;
680a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 15:
682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x38;
683a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
684a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" irq out of range\n");
686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
687a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	retval = das1800_init_dma(dev, dma0, dma1);
691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (retval < 0)
692a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return retval;
693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->ai_buf0 == NULL) {
695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 =
696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
698a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
699a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
700a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
701a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (alloc_subdevices(dev, 4) < 0)
702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
704a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog input subdevice */
705a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 0;
706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->read_subdev = s;
707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_AI;
708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->common)
710a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags |= SDF_COMMON;
711a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->qram_len;
712a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->len_chanlist = thisboard->qram_len;
713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = (1 << thisboard->resolution) - 1;
714a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = thisboard->range_ai;
715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmd = das1800_ai_do_cmd;
716a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmdtest = das1800_ai_do_cmdtest;
717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_read = das1800_ai_rinsn;
718a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->poll = das1800_ai_poll;
719a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->cancel = das1800_cancel;
720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog out */
722a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 1;
723a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
724a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_AO;
725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags = SDF_WRITABLE;
726a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->n_chan = thisboard->ao_n_chan;
727a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->maxdata = (1 << thisboard->resolution) - 1;
728a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->range_table = &range_ao_1;
729a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->insn_write = das1800_ao_winsn;
730a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
731a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_UNUSED;
732a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
733a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* di */
735a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 2;
736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DI;
737a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE;
738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = 4;
739a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
741a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_di_rbits;
742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* do */
744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 3;
745a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DO;
746a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
747a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->do_n_chan;
748a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_do_wbits;
751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, dev->read_subdev);
753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
754a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize digital out channels */
755a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
756a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
757a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize analog out channels */
758a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
759a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  select 'update' dac channel for baseAddress + 0x0 */
760a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(thisboard->ao_n_chan - 1),
761a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dev->iobase + DAS1800_SELECT);
762a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
763a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
764a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
765a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
766a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
767a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
76871b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_detach(struct comedi_device * dev)
769a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
770a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* only free stuff if it has been allocated by _attach */
771a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->iobase)
772a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_region(dev->iobase, DAS1800_SIZE);
773a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq)
774a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_free_irq(dev->irq, dev);
775a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->private) {
776a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->iobase2)
777a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			release_region(devpriv->iobase2, DAS1800_SIZE);
778a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma0)
779a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma0);
780a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma1)
781a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma1);
782a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0)
783a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kfree(devpriv->ai_buf0);
784a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf1)
785a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kfree(devpriv->ai_buf1);
786a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
787a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
788a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: remove\n", dev->minor,
789a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		driver_das1800.driver_name);
790a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
791a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
792a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
793a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
794a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* probes and checks das-1800 series board type
795a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
79671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_probe(struct comedi_device * dev)
797a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
798a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int id;
799a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
800a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
801a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
802ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton	board = ((struct das1800_board *) dev->board_ptr) - das1800_boards;
803a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
804a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (id) {
805a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x3:
806a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st_da || board == das1802st_da ||
807a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701st_da || board == das1702st_da) {
808a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
809a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
810a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
811a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
812a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800st-da series\n");
813a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
814a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
815a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x4:
816a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr_da || board == das1702hr_da) {
817a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
818a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
819a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
820a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
821a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1802hr-da\n");
822a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
823a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
824a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x5:
825a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801ao || board == das1802ao ||
826a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701ao || board == das1702ao) {
827a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
828a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
829a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
830a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
831a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800ao series\n");
832a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801ao;
833a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
834a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x6:
835a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr || board == das1702hr) {
836a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
837a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
838a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
839a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
840a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1802hr\n");
841a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
842a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
843a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x7:
844a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st || board == das1802st ||
845a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701st || board == das1702st) {
846a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
847a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
848a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
849a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
850a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800st series\n");
851a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
852a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
853a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x8:
854a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801hc || board == das1802hc) {
855a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
856a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
857a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
858a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
859a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800hc series\n");
860a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801hc;
861a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
862a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
863a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model: probe returned 0x%x (unknown, please report)\n", id);
864a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return board;
865a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
866a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
867a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return -1;
868a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
869a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
87034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_poll(struct comedi_device * dev, struct comedi_subdevice * s)
871a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
872a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
873a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
874a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  prevent race with interrupt handler */
875a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_lock_irqsave(&dev->spinlock, flags);
876a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
877a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_unlock_irqrestore(&dev->spinlock, flags);
878a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
879a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return s->async->buf_write_count - s->async->buf_read_count;
880a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
881a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
882a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic irqreturn_t das1800_interrupt(int irq, void *d PT_REGS_ARG)
883a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
88471b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
885a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status;
886a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
887a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->attached == 0) {
888a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "premature interrupt");
889a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_HANDLED;
890a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
891a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
892a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* Prevent race with das1800_ai_poll() on multi processor systems.
893a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * Also protects indirect addressing in das1800_ai_handler */
894a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_lock(&dev->spinlock);
895a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	status = inb(dev->iobase + DAS1800_STATUS);
896a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
897a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if interrupt was not caused by das-1800 */
898a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!(status & INT)) {
899a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		spin_unlock(&dev->spinlock);
900a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_NONE;
901a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
902a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear the interrupt status bit INT */
903a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
904a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  handle interrupt */
905a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
906a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
907a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_unlock(&dev->spinlock);
908a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return IRQ_HANDLED;
909a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
910a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
911a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
91271b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_ai_handler(struct comedi_device * dev)
913a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
91434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
915d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
916ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
917a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
918a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
919a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events = 0;
920a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  select adc for base address + 0 */
921a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);
922a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  dma buffer full */
923a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->irq_dma_bits & DMA_ENABLED) {
924a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  look for data from dma transfer even if dma terminal count hasn't happened yet */
925a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_dma(dev, s, status);
926a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FHF) {	/*  if fifo half full */
927a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_half_full(dev, s);
928a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FNE) {	/*  if fifo not empty */
929a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_not_empty(dev, s);
930a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
931a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
932a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events |= COMEDI_CB_BLOCK;
933a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if the card's fifo has overflowed */
934a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & OVF) {
935a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear OVF interrupt bit */
936a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
937a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "DAS1800 FIFO overflow");
938a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);
939a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
940a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_event(dev, s);
941a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
942a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
943a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  stop taking data if appropriate */
944a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* stop_src TRIG_EXT */
945a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & CT0TC) {
946a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear CT0TC interrupt bit */
947a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
948a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  make sure we get all remaining data from board before quitting */
949a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->irq_dma_bits & DMA_ENABLED)
950a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_flush_dma(dev, s);
951a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else
952a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_handle_fifo_not_empty(dev, s);
953a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
954a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
955a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	/*  stop_src TRIG_COUNT */
956a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
957a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
958a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
959a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
960a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_event(dev, s);
961a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
962a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
963a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
964a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
96534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_handle_dma(struct comedi_device * dev, struct comedi_subdevice * s,
966a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status)
967a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
968a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
969a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
970a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
971a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
972a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
973a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf);
974a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  re-enable  dma channel */
975a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma_current,
976a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		virt_to_bus(devpriv->dma_current_buf));
977a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
978a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma_current);
979a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
980a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
981a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & DMATC) {
982a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear DMATC interrupt bit */
983a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
984a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch dma channels for next time, if appropriate */
985a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dual_dma) {
986a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  read data from the other channel next time */
987a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->dma_current == devpriv->dma0) {
988a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma1;
989a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf1;
990a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			} else {
991a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma0;
992a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf0;
993a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
994a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
995a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
996a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
997a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
998a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
999a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
100071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic inline uint16_t munge_bipolar_sample(const struct comedi_device * dev,
1001a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t sample)
1002a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1003a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	sample += 1 << (thisboard->resolution - 1);
1004a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return sample;
1005a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1006a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
100771b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void munge_data(struct comedi_device * dev, uint16_t * array,
1008a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int num_elements)
1009a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1010a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int i;
1011a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1012a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1013a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* see if card is using a unipolar or bipolar range so we can munge data correctly */
1014a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1015a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1016a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* convert to unsigned type if we are in a bipolar mode */
1017a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!unipolar) {
1018a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < num_elements; i++) {
1019a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			array[i] = munge_bipolar_sample(dev, array[i]);
1020a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1021a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1022a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1023a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1024a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1025a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Assumes dma lock is held */
102634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_flush_dma_channel(struct comedi_device * dev, struct comedi_subdevice * s,
1027a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int channel, uint16_t * buffer)
1028a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1029a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int num_bytes, num_samples;
1030ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1031a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1032a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(channel);
1033a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1034a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers
1035a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * get set correctly */
1036a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(channel);
1037a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1038a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  figure out how many points to read */
1039a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1040790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_samples = num_bytes / sizeof(short);
1041a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1042a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1043a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1044a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		num_samples = devpriv->count;
1045a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1046a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, buffer, num_samples);
1047a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, buffer, num_bytes);
1048a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (s->async->cmd.stop_src == TRIG_COUNT)
1049a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= num_samples;
1050a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1051a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1052a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1053a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1054a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* flushes remaining data from board when external trigger has stopped aquisition
1055a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * and we are using dma transfers */
105634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic void das1800_flush_dma(struct comedi_device * dev, struct comedi_subdevice * s)
1057a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1058a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
1059a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1060a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1061a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
1062a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1063a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf);
1064a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1065a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1066a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch to other channel and flush it */
1067a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma_current == devpriv->dma0) {
1068a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma1;
1069a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf1;
1070a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		} else {
1071a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma0;
1072a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf0;
1073a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1074a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1075a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf);
1076a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1077a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1078a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
1079a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1080a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  get any remaining samples in fifo */
1081a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_handle_fifo_not_empty(dev, s);
1082a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1083a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1084a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1085a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
108671b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device * dev,
108734c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice * s)
1088a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1089a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int numPoints = 0;	/* number of points to read */
1090ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1091a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1092a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	numPoints = FIFO_SIZE / 2;
1093a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1094a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1095a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		numPoints = devpriv->count;
1096a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1097a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, devpriv->ai_buf0, numPoints);
1098a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1099a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		numPoints * sizeof(devpriv->ai_buf0[0]));
1100a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT)
1101a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= numPoints;
1102a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1103a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1104a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
110571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device * dev,
110634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice * s)
1107a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1108790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short dpnt;
1109a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1110ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1111a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1112a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1113a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1114a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1115a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1116a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1117a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1118a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* convert to unsigned type if we are in a bipolar mode */
1119a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!unipolar) ;
1120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = munge_bipolar_sample(dev, dpnt);
1121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cfc_write_to_buffer(s, dpnt);
1122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT)
1123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->count--;
1124a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1125a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1128a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
112934c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_cancel(struct comedi_device * dev, struct comedi_subdevice * s)
1130a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
1132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
1133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
1134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma0)
1135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
1136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma1)
1137a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1141a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* test analog input cmd */
114234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_do_cmdtest(struct comedi_device * dev, struct comedi_subdevice * s,
1143ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd * cmd)
1144a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1146a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int tmp;
1147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int tmp_arg;
1148a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i;
1149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 1: make sure trigger sources are trivially valid */
1152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->start_src;
1154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->start_src &= TRIG_NOW | TRIG_EXT;
1155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->start_src || tmp != cmd->start_src)
1156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_begin_src;
1159a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1160a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1162a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->convert_src;
1164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->convert_src || tmp != cmd->convert_src)
1166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1167a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1168a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_end_src;
1169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_end_src &= TRIG_COUNT;
1170a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->stop_src;
1174a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1175a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->stop_src || tmp != cmd->stop_src)
1176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1177a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 1;
1180a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1181a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 2: make sure trigger sources are unique and mutually compatible */
1182a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1183a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  uniqueness check */
1184a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1185a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1186a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1187a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_begin_src != TRIG_TIMER &&
1188a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_begin_src != TRIG_EXT)
1189a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1190a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1191a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1192a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src != TRIG_COUNT &&
1193a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1194a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1195a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/* compatibility check */
1196a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1197a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->convert_src != TRIG_TIMER)
1198a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1199a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1200a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1201a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 2;
1202a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1203a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 3: make sure arguments are trivially compatible */
1204a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1205a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_arg != 0) {
1206a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->start_arg = 0;
1207a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1208a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1209a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1210a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_arg < thisboard->ai_speed) {
1211a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg = thisboard->ai_speed;
1212a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1213a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1214a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1215a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->chanlist_len) {
1216a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->chanlist_len = 1;
1217a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1218a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1219a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_end_arg != cmd->chanlist_len) {
1220a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_end_arg = cmd->chanlist_len;
1221a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1222a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1223a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1224a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->stop_src) {
1225a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_COUNT:
1226a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!cmd->stop_arg) {
1227a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 1;
1228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1229a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1230a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1231a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NONE:
1232a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_arg != 0) {
1233a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 0;
1234a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1235a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1236a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1237a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1238a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1239a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1240a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1241a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 3;
1243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1244a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 4: fix up any arguments */
1245a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1247a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are not in burst mode */
1248a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->scan_begin_src == TRIG_FOLLOW) {
1249a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1250a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* calculate counter values that give desired timing */
1251a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1252a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(devpriv->divisor1), &(devpriv->divisor2),
1253a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(cmd->convert_arg),
1254a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd->flags & TRIG_ROUND_MASK);
1255a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1258a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are in burst mode */
1259a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else {
1260a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  check that convert_arg is compatible */
1261a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg =
1263a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				burst_convert_arg(cmd->convert_arg,
1264a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd->flags & TRIG_ROUND_MASK);
1265a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1266a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1267a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1268a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (cmd->scan_begin_src == TRIG_TIMER) {
1269a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton				/*  if scans are timed faster than conversion rate allows */
1270a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (cmd->convert_arg * cmd->chanlist_len >
1271a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->scan_begin_arg) {
1272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->scan_begin_arg =
1273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess						cmd->convert_arg *
1274a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess						cmd->chanlist_len;
1275a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1276a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				}
1277a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				tmp_arg = cmd->scan_begin_arg;
1278a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				/* calculate counter values that give desired timing */
1279a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1280a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(devpriv->divisor1),
1281a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(devpriv->divisor2),
1282a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(cmd->scan_begin_arg),
1283a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->flags & TRIG_ROUND_MASK);
1284a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (tmp_arg != cmd->scan_begin_arg)
1285a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1286a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1287a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1288a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1289a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1290a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1291a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 4;
1292a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1293a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make sure user is not trying to mix unipolar and bipolar ranges */
1294a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->chanlist) {
1295a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1296a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 1; i < cmd->chanlist_len; i++) {
1297a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1298a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				comedi_error(dev,
1299a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					"unipolar and bipolar ranges cannot be mixed in the chanlist");
1300a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1301a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1302a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1303a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1304a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1305a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1306a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1307a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 5;
1308a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1309a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1310a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1311a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1312a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* analog input cmd interface */
1313a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1314a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* first, some utility functions used in the main ai_do_cmd() */
1315a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1316a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register a, depending on command */
1317ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_a_bits(struct comedi_cmd cmd)
1318a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1319a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a;
1320a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1321a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_a = FFEN;	/* enable fifo */
1322a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1323a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= ATEN;
1324a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1325a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.start_src) {
1326a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1327a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= TGEN | CGSL;
1328a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1329a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NOW:
1330a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= CGEN;
1331a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1332a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1333a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1334a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1335a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1336a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_a;
1337a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1338a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1339a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register c, depending on command */
1340ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_c_bits(struct comedi_cmd cmd)
1341a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1342a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_c;
1343a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int aref;
1344a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1345a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set clock source to internal or external, select analog reference,
1346a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * select unipolar / bipolar
1347a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 */
1348a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(cmd.chanlist[0]);
1349a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_c = UQEN;	/* enable upper qram addresses */
1350a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1351a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= SD;
1352a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1353a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= CMEN;
1354a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1355a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1356a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= UB;
1357a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1358a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1359a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch (cmd.convert_src) {
1360a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_TIMER:
1361a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on cascaded counters */
1362a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= IPCLK;
1363a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1364a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_EXT:
1365a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on falling edge of external trigger */
1366a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= XPCLK;
1367a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1368a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
1369a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1370a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1371a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1372a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1373a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with internal pacer clock */
1374a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | IPCLK;
1375a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1376a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1377a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with external trigger */
1378a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | XPCLK;
1379a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1380a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1381a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1382a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1383a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1384a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_c;
1385a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1386a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1387a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up counters */
1388ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int setup_counters(struct comedi_device * dev, struct comedi_cmd cmd)
1389a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1390a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup cascaded counters for conversion/scan frequency */
1391a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1392a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1393a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd.convert_src == TRIG_TIMER) {
1394a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* set conversion frequency */
1395a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1396a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(devpriv->divisor1), &(devpriv->divisor2),
1397a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(cmd.convert_arg),
1398a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd.flags & TRIG_ROUND_MASK);
1399a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (das1800_set_frequency(dev) < 0) {
1400a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -1;
1401a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1402a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1403a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1404a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_TIMER:	/*  in burst mode */
1405a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* set scan frequency */
1406a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1407a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			&(devpriv->divisor2), &(cmd.scan_begin_arg),
1408a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd.flags & TRIG_ROUND_MASK);
1409a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (das1800_set_frequency(dev) < 0) {
1410a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -1;
1411a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1412a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1413a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1414a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1415a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1416a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1417a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup counter 0 for 'about triggering' */
1418a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1419a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  load counter 0 in mode 0 */
1420a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1421a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1422a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1423a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1424a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1425a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1426a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up dma */
1427ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic void setup_dma(struct comedi_device * dev, struct comedi_cmd cmd)
1428a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1429a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long lock_flags;
1430a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1431a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1432a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1433a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
1434a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1435a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* determine a reasonable dma transfer size */
1436a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1437a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	lock_flags = claim_dma_lock();
1438a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(devpriv->dma0);
1439a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers for
1440a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * count and address get set correctly */
1441a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(devpriv->dma0);
1442a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1443a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set appropriate size of transfer */
1444a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1445a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current = devpriv->dma0;
1446a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current_buf = devpriv->ai_buf0;
1447a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma0);
1448a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set up dual dma if appropriate */
1449a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1450a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1451a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* clear flip-flop to make sure 2-byte registers for
1452a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		 * count and address get set correctly */
1453a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		clear_dma_ff(devpriv->dma1);
1454a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1455a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  set appropriate size of transfer */
1456a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1457a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		enable_dma(devpriv->dma1);
1458a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1459a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(lock_flags);
1460a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1461a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1463a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1464a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* programs channel/gain list into card */
1465ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic void program_chanlist(struct comedi_device * dev, struct comedi_cmd cmd)
1466a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1467a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n, chan_range;
1468a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1469a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	const int range_mask = 0x3;	/* masks unipolar/bipolar bit off range */
1470a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int range_bitshift = 8;
1471a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1472a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	n = cmd.chanlist_len;
1473a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  spinlock protects indirect addressing */
1474a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1475a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1476a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*set QRAM address start */
1477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* make channel / gain list */
1478a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (i = 0; i < n; i++) {
1479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		chan_range =
1480a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd.
1481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					chanlist[i]) & range_mask) <<
1482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			range_bitshift);
1483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(chan_range, dev->iobase + DAS1800_QRAM);
1484a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1485a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1486a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1487a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1488a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1489a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1490a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1491a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input do_cmd */
149234c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_do_cmd(struct comedi_device * dev, struct comedi_subdevice * s)
1493a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ret;
1495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a, control_c;
1496d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1497ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd cmd = async->cmd;
1498a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1499a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!dev->irq) {
1500a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev,
1501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			"no irq assigned for das-1800, cannot do hardware conversions");
1502a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1503a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1504a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1506a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * (because dma in handler is unsafe at hard real-time priority) */
1507a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1508a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~DMA_ENABLED;
1509a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1510a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= devpriv->dma_bits;
1511a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1512a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
1513a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & TRIG_WAKE_EOS) {
1514a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo not empty */
1515a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~FIMD;
1516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1517a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo half full */
1518a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= FIMD;
1519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1520a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine how many conversions we need */
1521a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_COUNT) {
1522a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1523a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1524a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1525a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, s);
1526a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1527a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine proper bits for control registers */
1528a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_a = control_a_bits(cmd);
1529a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_c = control_c_bits(cmd);
1530a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1531a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* setup card and start */
1532a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	program_chanlist(dev, cmd);
1533a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	ret = setup_counters(dev, cmd);
1534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (ret < 0) {
1535a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "Error setting up counters");
1536a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return ret;
1537a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1538a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	setup_dma(dev, cmd);
1539a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1540a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set conversion rate and length for burst mode */
1541a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (control_c & BMDE) {
1542a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  program conversion period with number of microseconds minus 1 */
1543a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.convert_arg / 1000 - 1,
1544a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dev->iobase + DAS1800_BURST_RATE);
1545a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1546a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1547a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	/*  enable irq/dma */
1548a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_a, dev->iobase + DAS1800_CONTROL_A);	/* enable fifo and triggering */
1549a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1551a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1553a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* read analog input */
155534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ai_rinsn(struct comedi_device * dev, struct comedi_subdevice * s,
155690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
1557a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n;
1559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan, range, aref, chan_range;
1560a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int timeout = 1000;
1561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short dpnt;
1562a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int conv_flags = 0;
1563a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1564a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set up analog reference and unipolar / bipolar mode */
1566a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(insn->chanspec);
1567a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	conv_flags |= UQEN;
1568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1569a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= SD;
1570a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= CMEN;
1572a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= UB;
1575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);	/* software conversion enabled */
1577a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1578a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* reset fifo */
1579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan = CR_CHAN(insn->chanspec);
1582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* mask of unipolar/bipolar bit from range */
1583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	range = CR_RANGE(insn->chanspec) & 0x3;
1584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan_range = chan | (range << 8);
1585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1586a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/* set QRAM address start */
1588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(chan_range, dev->iobase + DAS1800_QRAM);
1589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1590a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);	/* select ADC for baseAddress + 0x0 */
1591a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1592a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (n = 0; n < insn->n; n++) {
1593a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* trigger conversion */
1594a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(0, dev->iobase + DAS1800_FIFO);
1595a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < timeout; i++) {
1596a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1597a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (i == timeout) {
1600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			comedi_error(dev, "timeout");
1601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ETIME;
1602a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* shift data to offset binary for bipolar ranges */
1605a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if ((conv_flags & UB) == 0)
1606a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dpnt += 1 << (thisboard->resolution - 1);
1607a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		data[n] = dpnt;
1608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1610a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return n;
1612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to an analog output channel */
161534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_ao_winsn(struct comedi_device * dev, struct comedi_subdevice * s,
161690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
1617a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1618a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan = CR_CHAN(insn->chanspec);
1619a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* int range = CR_RANGE(insn->chanspec); */
1620a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int update_chan = thisboard->ao_n_chan - 1;
1621a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short output;
1622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1624a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*   card expects two's complement data */
1625a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	output = data[0] - (1 << (thisboard->resolution - 1));
1626a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if the write is to the 'update' channel, we need to remember its value */
1627a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan == update_chan)
1628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ao_update_bits = output;
1629a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  write to channel */
1630a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_lock_irqsave(&dev->spinlock, irq_flags);
1631a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(DAC(chan), dev->iobase + DAS1800_SELECT);	/* select dac channel for baseAddress + 0x0 */
1632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(output, dev->iobase + DAS1800_DAC);
1633a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  now we need to write to 'update' channel to update all dac channels */
1634a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan != update_chan) {
1635a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);	/* select 'update' channel for baseAddress + 0x0 */
1636a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1639a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 1;
1641a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1642a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* reads from digital input channels */
164434c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_di_rbits(struct comedi_device * dev, struct comedi_subdevice * s,
164590035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
1646a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] = 0;
1650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1652a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1653a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1654a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to digital output channels */
165534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pembertonstatic int das1800_do_wbits(struct comedi_device * dev, struct comedi_subdevice * s,
165690035c0886b256d75bced13b3b3cea5234aff136Bill Pemberton	struct comedi_insn * insn, unsigned int * data)
1657a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1658790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int wbits;
1659a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1660a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  only set bits that have been masked */
1661a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] &= (1 << s->n_chan) - 1;
1662a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits = devpriv->do_bits;
1663a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits &= ~data[0];
1664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits |= data[0] & data[1];
1665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->do_bits = wbits;
1666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1668a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1669a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = devpriv->do_bits;
1670a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1673a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1674a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* loads counters with divisor1, divisor2 from private structure */
167571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pembertonstatic int das1800_set_frequency(struct comedi_device * dev)
1676a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1678a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1679a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 1, mode 2 */
1680a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			2))
1682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1683a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 2, mode 2 */
1684a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			2))
1686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1687a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1692a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* converts requested conversion timing to timing compatible with
1694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * hardware, used only when card is in 'burst mode'
1695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
1696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1698a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int micro_sec;
1699a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1700a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  in burst mode, the maximum conversion time is 64 microseconds */
1701a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (convert_arg > 64000)
1702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		convert_arg = 64000;
1703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1704a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  the conversion time must be an integral number of microseconds */
1705a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (round_mode) {
1706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_NEAREST:
1707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg + 500) / 1000;
1709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1710a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_DOWN:
1711a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = convert_arg / 1000;
1712a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_UP:
1714a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg - 1) / 1000 + 1;
1715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1716a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1718a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  return number of nanoseconds */
1719a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return micro_sec * 1000;
1720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1722a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1723ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd * cmd)
1724a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int size = DMA_BUF_SIZE;
1726a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	static const int sample_size = 2;	/*  size in bytes of one sample from board */
1727a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int fill_time = 300000000;	/*  target time in nanoseconds for filling dma buffer */
1728a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int max_size;	/*  maximum size we will allow for a transfer */
1729a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1730a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make dma buffer fill in 0.3 seconds for timed modes */
1731a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->scan_begin_src) {
1732a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1733a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_src == TRIG_TIMER)
1734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			size = (fill_time / cmd->convert_arg) * sample_size;
1735a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1737a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			sample_size;
1739a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1741a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = DMA_BUF_SIZE;
1742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1745a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set a minimum and maximum size allowed */
1746a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	max_size = DMA_BUF_SIZE;
1747a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if we are taking limited number of conversions, limit transfer size to that */
1748a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT &&
1749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size > max_size)
1753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = max_size;
1754a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size < sample_size)
1755a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = sample_size;
1756a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1757a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return size;
1758a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1759