das1800.c revision 25436dc9d84f1be60ff549c9ab712bba2835f284
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
10325436dc9d84f1be60ff549c9ab712bba2835f284Greg Kroah-Hartman#include <linux/interrupt.h>
104a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "../comedidev.h"
105a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
106a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <linux/ioport.h>
107a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <asm/dma.h>
108a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
109a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "8253.h"
110a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "comedi_fc.h"
111a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
112a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* misc. defines */
113a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DAS1800_SIZE           16	/* uses 16 io addresses */
114a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define FIFO_SIZE              1024	/*  1024 sample fifo */
115a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define TIMER_BASE             200	/*  5 Mhz master clock */
116a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
117a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
118a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
119a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Registers for the das1800 */
120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_FIFO            0x0
121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM            0x0
122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DAC             0x0
123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_SELECT          0x2
124a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ADC                     0x0
125a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   QRAM                    0x1
126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DAC(a)                  (0x2 + a)
127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DIGITAL         0x3
128a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_A       0x4
129a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FFEN                    0x1
130a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGEN                    0x4
131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGSL                    0x8
132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGEN                    0x10
133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGSL                    0x20
134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ATEN                    0x80
135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_B       0x5
136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5                 0x1
137a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6                 0x2
138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7                 0x3
139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5_CH6             0x5
140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6_CH7             0x6
141a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7_CH5             0x7
142a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   DMA_ENABLED             0x3	/* mask used to determine if dma is enabled */
143a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_DUAL                0x4
144a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ3                    0x8
145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ5                    0x10
146a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ7                    0x18
147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ10                   0x28
148a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ11                   0x30
149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ15                   0x38
150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FIMD                    0x40
151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_C       0X6
152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IPCLK                   0x1
153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   XPCLK                   0x3
154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   BMDE                    0x4
155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CMEN                    0x8
156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UQEN                    0x10
157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   SD                      0x40
158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UB                      0x80
159a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_STATUS          0x7
160a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
162a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   INT                     0x1
163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMATC                   0x2
164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CT0TC                   0x8
165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   OVF                     0x10
166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FHF                     0x20
167a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FNE                     0x40
168a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   CVEN_MASK               0x40	/*  masks CVEN on write */
169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CVEN                    0x80
170a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_LENGTH    0x8
171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_RATE      0x9
172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM_ADDRESS    0xa
173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_COUNTER         0xc
174a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
175a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define IOBASE2                   0x400	/* offset of additional ioports used on 'ao' cards */
176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
177a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessenum {
178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1702hr_da,
180a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
181a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
182a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
183a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
184814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it);
185814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_detach(struct comedi_device *dev);
186814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_probe(struct comedi_device *dev);
187814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
18870265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das1800_interrupt(int irq, void *d);
189814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s);
190814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_ai_handler(struct comedi_device *dev);
191814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
192a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status);
193814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s);
194814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
195814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	unsigned int channel, uint16_t *buffer);
196814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device *dev,
197814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_subdevice *s);
198814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device *dev,
199814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_subdevice *s);
200814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
201814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_cmd *cmd);
202814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
203814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
204814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_insn *insn, unsigned int *data);
205814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
206814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_insn *insn, unsigned int *data);
207814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
208814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_insn *insn, unsigned int *data);
209814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
210814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton	struct comedi_insn *insn, unsigned int *data);
211814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton
212814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_set_frequency(struct comedi_device *dev);
213a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
214814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
215a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
216a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input ranges */
2179ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1801 = {
218a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
219a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
220a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-5, 5),
221a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-1, 1),
222a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-0.1, 0.1),
223a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-0.02, 0.02),
224a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 5),
225a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 1),
226a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 0.1),
227a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 0.02),
228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
229a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
230a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
2319ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1802 = {
232a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
233a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
234a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-10, 10),
235a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-5, 5),
236a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-2.5, 2.5),
237a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-1.25, 1.25),
238a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 10),
239a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 5),
240a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 2.5),
241a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(0, 1.25),
242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
244a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
245ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstruct das1800_board {
246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const char *name;
247a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ai_speed;		/* max conversion period in nanoseconds */
248a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int resolution;		/* bits of ai resolution */
249a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int qram_len;		/* length of card's channel / gain queue */
250a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int common;		/* supports AREF_COMMON flag */
251a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_n_chan;		/* number of digital output channels */
252a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
253a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_n_chan;		/* number of analog out channels */
2549ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *range_ai;	/* available input ranges */
255ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton};
256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Warning: the maximum conversion speeds listed below are
258a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * not always achievable depending on board setup (see
259a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * user manual.)
260a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
261ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstatic const struct das1800_board das1800_boards[] = {
262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
26368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1701st",
26468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
26568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
26668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
26768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
26868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
26968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
27068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
27168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
27468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1701st-da",
27568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
27668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
27768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
27868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
27968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
28068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
28168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 4,
28268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
283a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
284a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
28568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1702st",
28668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
28768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
28868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
28968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
29068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
29168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
29268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
29368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
294a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
295a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
29668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1702st-da",
29768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
29868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
29968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
30068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
30168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
30268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
30368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 4,
30468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
305a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
306a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
30768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1702hr",
30868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 20000,
30968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 16,
31068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
31168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
31268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
31368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
31468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
31568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
316a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
317a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
31868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1702hr-da",
31968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 20000,
32068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 16,
32168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
32268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
32368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
32468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
32568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
32668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
327a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
328a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
32968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1701ao",
33068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
33168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
33268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
33368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
33468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
33568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 2,
33668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
33768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
338a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
339a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
34068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1702ao",
34168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 6250,
34268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
34368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
34468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
34568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
34668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 2,
34768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
34868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
349a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
350a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
35168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1801st",
35268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
35368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
35468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
35568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
35668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
35768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
35868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
35968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
360a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
361a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
36268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1801st-da",
36368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
36468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
36568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
36668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
36768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
36868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
36968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 4,
37068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
371a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
372a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
37368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802st",
37468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
37568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
37668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
37768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
37868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
37968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
38068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
38168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
382a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
383a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
38468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802st-da",
38568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
38668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
38768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
38868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
38968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
39068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
39168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 4,
39268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
393a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
394a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
39568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802hr",
39668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 10000,
39768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 16,
39868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
39968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
40068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
40168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 0,
40268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 0,
40368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
404a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
405a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
40668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802hr-da",
40768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 10000,
40868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 16,
40968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
41068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
41168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
41268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
41368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
41468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
415a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
416a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
41768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1801hc",
41868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
41968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
42068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 64,
42168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 0,
42268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 8,
42368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
42468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
42568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
426a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
427a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
42868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802hc",
42968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
43068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
43168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 64,
43268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 0,
43368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 8,
43468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 1,
43568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
43668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
437a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
438a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
43968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1801ao",
44068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
44168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
44268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
44368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
44468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
44568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 2,
44668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
44768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1801,
448a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
449a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
45068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.name = "das-1802ao",
45168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ai_speed = 3000,
45268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.resolution = 12,
45368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.qram_len = 256,
45468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.common = 1,
45568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.do_n_chan = 4,
45668c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_ability = 2,
45768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.ao_n_chan = 2,
45868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.range_ai = &range_ai_das1802,
459a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		},
460a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
461a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
463a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Useful for shorthand access to the particular board structure
464a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
465ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton#define thisboard ((const struct das1800_board *)dev->board_ptr)
466a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
4670c5a144d730a68967dfb3f8163260a142e3282e3Bill Pembertonstruct das1800_private {
468a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int count;	/* number of data points left to be taken */
469a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
470a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
471a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_bits;		/* digital output bits */
472a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int irq_dma_bits;	/* bits for control register b */
473a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* dma bits for control register b, stored so that dma can be
474a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * turned on and off */
475a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int dma_bits;
476a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0;	/* dma channels used */
477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1;
478a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int dma_current;	/* dma channel currently in use */
479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf0;	/* pointers to dma buffers */
480a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf1;
481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
484a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short ao_update_bits;	/* remembers the last write to the 'update' dac */
4850c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton};
486a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
4870c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton#define devpriv ((struct das1800_private *)dev->private)
488a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
489a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for boards with basic analog out */
4909ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_1 = {
491a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	1,
492a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
493a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			RANGE(-10, 10),
494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
496a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
497a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for 'ao' boards */
498a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
4999ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_2 = {
500a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	2,
501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
502a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-10, 10),
503a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-5, 5),
504a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
506a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
507a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
508139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das1800 = {
50968c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "das1800",
51068c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
51168c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das1800_attach,
51268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das1800_detach,
5138629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton	.num_names = ARRAY_SIZE(das1800_boards),
51468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &das1800_boards[0].name,
51568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct das1800_board),
516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
517a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
518a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * A convenient macro that defines init_module() and cleanup_module(),
520a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * as necessary.
521a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
522a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori HessCOMEDI_INITCLEANUP(driver_das1800);
523a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
524da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
525a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1)
526a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
527a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
528a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
529a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  need an irq to do dma */
530a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq && dma0) {
531a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/* encode dma0 and dma1 into 2 digit hexadecimal for switch */
532a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch ((dma0 & 0x7) | (dma1 << 4)) {
533a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x5:	/*  dma0 == 5 */
534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5;
535a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
536a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x6:	/*  dma0 == 6 */
537a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6;
538a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
539a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x7:	/*  dma0 == 7 */
540a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7;
541a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
542a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x65:	/*  dma0 == 5, dma1 == 6 */
543a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5_CH6;
544a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
545a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x76:	/*  dma0 == 6, dma1 == 7 */
546a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6_CH7;
547a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
548a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x57:	/*  dma0 == 7, dma1 == 5 */
549a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7_CH5;
550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
551a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" only supports dma channels 5 through 7\n"
553a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				" Dual dma only allows the following combinations:\n"
554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				" dma 5,6 / 6,7 / or 7,5\n");
555a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
556a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
557a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (request_dma(dma0, driver_das1800.driver_name)) {
559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" failed to allocate dma channel %i\n", dma0);
560a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
562a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma0 = dma0;
563a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current = dma0;
564a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (request_dma(dma1, driver_das1800.driver_name)) {
566a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" failed to allocate dma channel %i\n",
567a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					dma1);
568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -EINVAL;
569a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
570a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma1 = dma1;
571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
572a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf = devpriv->ai_buf0;
576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
577a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->ai_buf1 =
578a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->ai_buf1 == NULL)
580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -ENOMEM;
581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		flags = claim_dma_lock();
583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_mode(devpriv->dma0, DMA_MODE_READ);
585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
586a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			disable_dma(devpriv->dma1);
587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			set_dma_mode(devpriv->dma1, DMA_MODE_READ);
588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_dma_lock(flags);
590a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
591a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
592a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
593a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
594da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_attach(struct comedi_device *dev, struct comedi_devconfig *it)
595a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
59634c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
597a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase = it->options[0];
598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int irq = it->options[1];
599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0 = it->options[2];
600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1 = it->options[3];
601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;
602a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int retval;
604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
605a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* allocate and initialize dev->private */
6060c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton	if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
607a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
610a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		iobase);
611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(", irq %u", irq);
613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma0) {
614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(", dma %u", dma0);
615a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (dma1)
616a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" and %u", dma1);
617a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
618a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
619a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("\n");
620a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
621a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (iobase == 0) {
622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" io base address required\n");
623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
624a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
625a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
626a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* check if io addresses are available */
627a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase, iobase + DAS1800_SIZE - 1);
629a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EIO;
630a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
631a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->iobase = iobase;
632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
633a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	board = das1800_probe(dev);
634a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (board < 0) {
635a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" unable to determine board type\n");
636a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENODEV;
637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
639a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_ptr = das1800_boards + board;
640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_name = thisboard->name;
641a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
642a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if it is an 'ao' board with fancy analog out then we need extra io ports */
643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 2) {
644a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		iobase2 = iobase + IOBASE2;
645a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!request_region(iobase2, DAS1800_SIZE,
646a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				driver_das1800.driver_name)) {
647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n", iobase2, iobase2 + DAS1800_SIZE - 1);
648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EIO;
649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->iobase2 = iobase2;
651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
652a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
653a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* grab our IRQ */
654a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
6555f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(irq, das1800_interrupt, 0,
656a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				driver_das1800.driver_name, dev)) {
657a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" unable to allocate irq %u\n", irq);
658a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
659a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
660a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
661a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->irq = irq;
662a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
663a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set bits that tell card which irq to use */
664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (irq) {
665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0:
666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 3:
668a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x8;
669a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
670a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 5:
671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x10;
672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
673a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 7:
674a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x18;
675a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
676a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 10:
677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x28;
678a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
679a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 11:
680a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x30;
681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 15:
683a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x38;
684a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" irq out of range\n");
687a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	retval = das1800_init_dma(dev, dma0, dma1);
692a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (retval < 0)
693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return retval;
694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->ai_buf0 == NULL) {
696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 =
697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
698a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
699a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
700a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
701a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (alloc_subdevices(dev, 4) < 0)
703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
704a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
705a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog input subdevice */
706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 0;
707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->read_subdev = s;
708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_AI;
709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
710a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->common)
711a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags |= SDF_COMMON;
712a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->qram_len;
713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->len_chanlist = thisboard->qram_len;
714a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = (1 << thisboard->resolution) - 1;
715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = thisboard->range_ai;
716a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmd = das1800_ai_do_cmd;
717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmdtest = das1800_ai_do_cmdtest;
718a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_read = das1800_ai_rinsn;
719a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->poll = das1800_ai_poll;
720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->cancel = das1800_cancel;
721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
722a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog out */
723a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 1;
724a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_AO;
726a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags = SDF_WRITABLE;
727a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->n_chan = thisboard->ao_n_chan;
728a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->maxdata = (1 << thisboard->resolution) - 1;
729a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->range_table = &range_ao_1;
730a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->insn_write = das1800_ao_winsn;
731a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
732a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_UNUSED;
733a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
735a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* di */
736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 2;
737a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DI;
738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE;
739a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = 4;
740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
741a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_di_rbits;
743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* do */
745a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 3;
746a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DO;
747a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
748a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->do_n_chan;
749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_do_wbits;
752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, dev->read_subdev);
754a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
755a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize digital out channels */
756a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
757a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
758a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize analog out channels */
759a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
760a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  select 'update' dac channel for baseAddress + 0x0 */
761a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(thisboard->ao_n_chan - 1),
762a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dev->iobase + DAS1800_SELECT);
763a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
764a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
765a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
766a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
767a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
768a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
769da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_detach(struct comedi_device *dev)
770a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
771a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* only free stuff if it has been allocated by _attach */
772a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->iobase)
773a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_region(dev->iobase, DAS1800_SIZE);
774a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq)
7755f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
776a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->private) {
777a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->iobase2)
778a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			release_region(devpriv->iobase2, DAS1800_SIZE);
779a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma0)
780a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma0);
781a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma1)
782a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma1);
783a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0)
784a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kfree(devpriv->ai_buf0);
785a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf1)
786a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			kfree(devpriv->ai_buf1);
787a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
788a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
789a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: remove\n", dev->minor,
790a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		driver_das1800.driver_name);
791a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
792a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
793a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
794a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
795a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* probes and checks das-1800 series board type
796a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
797da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_probe(struct comedi_device *dev)
798a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
799a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int id;
800a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
801a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
802a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
803ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton	board = ((struct das1800_board *) dev->board_ptr) - das1800_boards;
804a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
805a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (id) {
806a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x3:
807a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st_da || board == das1802st_da ||
808a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701st_da || board == das1702st_da) {
809a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
810a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
811a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
812a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
813a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800st-da series\n");
814a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
815a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
816a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x4:
817a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr_da || board == das1702hr_da) {
818a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
819a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
820a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
821a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
822a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1802hr-da\n");
823a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
824a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
825a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x5:
826a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801ao || board == das1802ao ||
827a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701ao || board == das1702ao) {
828a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
829a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
830a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
831a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
832a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800ao series\n");
833a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801ao;
834a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
835a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x6:
836a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr || board == das1702hr) {
837a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
838a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
839a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
840a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
841a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1802hr\n");
842a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
843a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
844a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x7:
845a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st || board == das1802st ||
846a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			board == das1701st || board == das1702st) {
847a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
848a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
849a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
850a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
851a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800st series\n");
852a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
853a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
854a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x8:
855a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801hc || board == das1802hc) {
856a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
857a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				das1800_boards[board].name);
858a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
859a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
860a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1800hc series\n");
861a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801hc;
862a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
863a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
864a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model: probe returned 0x%x (unknown, please report)\n", id);
865a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return board;
866a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
867a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
868a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return -1;
869a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
870a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
871da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_ai_poll(struct comedi_device *dev, struct comedi_subdevice *s)
872a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
873a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
874a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
875a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  prevent race with interrupt handler */
8765f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
877a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
8785f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
879a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
880a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return s->async->buf_write_count - s->async->buf_read_count;
881a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
882a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
88370265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das1800_interrupt(int irq, void *d)
884a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
88571b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
886a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status;
887a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
888a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->attached == 0) {
889a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "premature interrupt");
890a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_HANDLED;
891a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
892a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
893a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* Prevent race with das1800_ai_poll() on multi processor systems.
894a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * Also protects indirect addressing in das1800_ai_handler */
895a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_lock(&dev->spinlock);
896a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	status = inb(dev->iobase + DAS1800_STATUS);
897a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
898a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if interrupt was not caused by das-1800 */
899a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!(status & INT)) {
900a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		spin_unlock(&dev->spinlock);
901a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_NONE;
902a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
903a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear the interrupt status bit INT */
904a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
905a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  handle interrupt */
906a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
907a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
908a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_unlock(&dev->spinlock);
909a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return IRQ_HANDLED;
910a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
911a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
912a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
913da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_ai_handler(struct comedi_device *dev)
914a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
91534c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
916d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
917ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
918a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
919a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
920a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events = 0;
921a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  select adc for base address + 0 */
922a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);
923a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  dma buffer full */
924a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->irq_dma_bits & DMA_ENABLED) {
925a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  look for data from dma transfer even if dma terminal count hasn't happened yet */
926a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_dma(dev, s, status);
927a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FHF) {	/*  if fifo half full */
928a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_half_full(dev, s);
929a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FNE) {	/*  if fifo not empty */
930a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_not_empty(dev, s);
931a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
932a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
933a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events |= COMEDI_CB_BLOCK;
934a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if the card's fifo has overflowed */
935a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & OVF) {
936a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear OVF interrupt bit */
937a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
938a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "DAS1800 FIFO overflow");
939a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);
940a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
941a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_event(dev, s);
942a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
943a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
944a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  stop taking data if appropriate */
945a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* stop_src TRIG_EXT */
946a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & CT0TC) {
947a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear CT0TC interrupt bit */
948a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
949a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  make sure we get all remaining data from board before quitting */
950a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->irq_dma_bits & DMA_ENABLED)
951a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_flush_dma(dev, s);
952a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else
953a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_handle_fifo_not_empty(dev, s);
954a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
955a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
956a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	/*  stop_src TRIG_COUNT */
957a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
958a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
959a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
960a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
961a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_event(dev, s);
962a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
963a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
964a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
965a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
966da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_handle_dma(struct comedi_device *dev, struct comedi_subdevice *s,
967a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status)
968a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
969a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
970a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
971a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
972a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
973a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
974a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf);
975a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  re-enable  dma channel */
976a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma_current,
977a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		virt_to_bus(devpriv->dma_current_buf));
978a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
979a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma_current);
980a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
981a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
982a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & DMATC) {
983a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear DMATC interrupt bit */
984a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
985a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch dma channels for next time, if appropriate */
986a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dual_dma) {
987a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  read data from the other channel next time */
988a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->dma_current == devpriv->dma0) {
989a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma1;
990a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf1;
991a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			} else {
992a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma0;
993a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf0;
994a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
995a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
996a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
997a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
998a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
999a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1000a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1001da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
1002a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t sample)
1003a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1004a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	sample += 1 << (thisboard->resolution - 1);
1005a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return sample;
1006a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1007a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1008da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void munge_data(struct comedi_device *dev, uint16_t *array,
1009a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int num_elements)
1010a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1011a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int i;
1012a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1013a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1014a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* see if card is using a unipolar or bipolar range so we can munge data correctly */
1015a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1016a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1017a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* convert to unsigned type if we are in a bipolar mode */
1018a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!unipolar) {
1019a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < num_elements; i++) {
1020a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			array[i] = munge_bipolar_sample(dev, array[i]);
1021a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1022a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1023a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1024a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1025a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1026a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Assumes dma lock is held */
1027da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_flush_dma_channel(struct comedi_device *dev, struct comedi_subdevice *s,
1028da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	unsigned int channel, uint16_t *buffer)
1029a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1030a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int num_bytes, num_samples;
1031ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1032a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1033a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(channel);
1034a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1035a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers
1036a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * get set correctly */
1037a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(channel);
1038a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1039a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  figure out how many points to read */
1040a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1041790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_samples = num_bytes / sizeof(short);
1042a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1043a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1044a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1045a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		num_samples = devpriv->count;
1046a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1047a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, buffer, num_samples);
1048a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, buffer, num_bytes);
1049a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (s->async->cmd.stop_src == TRIG_COUNT)
1050a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= num_samples;
1051a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1052a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1053a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1054a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1055a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* flushes remaining data from board when external trigger has stopped aquisition
1056a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * and we are using dma transfers */
1057da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_flush_dma(struct comedi_device *dev, struct comedi_subdevice *s)
1058a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1059a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
1060a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1061a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1062a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
1063a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1064a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf);
1065a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1066a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1067a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch to other channel and flush it */
1068a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma_current == devpriv->dma0) {
1069a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma1;
1070a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf1;
1071a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		} else {
1072a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma0;
1073a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf0;
1074a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1075a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_flush_dma_channel(dev, s, devpriv->dma_current,
1076a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf);
1077a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1078a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1079a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
1080a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1081a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  get any remaining samples in fifo */
1082a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_handle_fifo_not_empty(dev, s);
1083a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1084a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1085a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1086a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1087da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device *dev,
1088da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s)
1089a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1090a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int numPoints = 0;	/* number of points to read */
1091ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1092a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1093a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	numPoints = FIFO_SIZE / 2;
1094a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1095a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1096a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		numPoints = devpriv->count;
1097a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1098a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, devpriv->ai_buf0, numPoints);
1099a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, devpriv->ai_buf0,
1100a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		numPoints * sizeof(devpriv->ai_buf0[0]));
1101a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT)
1102a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= numPoints;
1103a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1104a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1105a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1106da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device *dev,
1107da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_subdevice *s)
1108a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1109790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short dpnt;
1110a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1111ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1112a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1113a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1114a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1115a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1116a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1117a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1118a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1119a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* convert to unsigned type if we are in a bipolar mode */
1120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!unipolar) ;
1121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = munge_bipolar_sample(dev, dpnt);
1122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cfc_write_to_buffer(s, dpnt);
1123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT)
1124a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->count--;
1125a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1128a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1129a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1130da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
1133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
1134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
1135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma0)
1136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
1137a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma1)
1138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1141a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1142a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* test analog input cmd */
1143da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_ai_do_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1144da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_cmd *cmd)
1145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1146a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int tmp;
1148a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int tmp_arg;
1149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i;
1150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 1: make sure trigger sources are trivially valid */
1153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->start_src;
1155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->start_src &= TRIG_NOW | TRIG_EXT;
1156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->start_src || tmp != cmd->start_src)
1157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1159a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_begin_src;
1160a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1162a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->convert_src;
1165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->convert_src || tmp != cmd->convert_src)
1167a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1168a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_end_src;
1170a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_end_src &= TRIG_COUNT;
1171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1174a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->stop_src;
1175a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->stop_src || tmp != cmd->stop_src)
1177a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1180a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 1;
1181a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1182a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 2: make sure trigger sources are unique and mutually compatible */
1183a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1184a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  uniqueness check */
1185a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1186a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1187a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1188a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_begin_src != TRIG_TIMER &&
1189a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_begin_src != TRIG_EXT)
1190a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1191a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1192a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1193a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src != TRIG_COUNT &&
1194a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1195a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1196a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/* compatibility check */
1197a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
1198a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->convert_src != TRIG_TIMER)
1199a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1200a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1201a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1202a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 2;
1203a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1204a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 3: make sure arguments are trivially compatible */
1205a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1206a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_arg != 0) {
1207a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->start_arg = 0;
1208a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1209a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1210a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1211a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_arg < thisboard->ai_speed) {
1212a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg = thisboard->ai_speed;
1213a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1214a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1215a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1216a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->chanlist_len) {
1217a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->chanlist_len = 1;
1218a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1219a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1220a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_end_arg != cmd->chanlist_len) {
1221a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_end_arg = cmd->chanlist_len;
1222a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1223a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1224a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1225a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->stop_src) {
1226a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_COUNT:
1227a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!cmd->stop_arg) {
1228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 1;
1229a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1230a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1231a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1232a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NONE:
1233a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_arg != 0) {
1234a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 0;
1235a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1236a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1237a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1238a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1239a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1240a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1241a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 3;
1244a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1245a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 4: fix up any arguments */
1246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1247a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1248a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are not in burst mode */
1249a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->scan_begin_src == TRIG_FOLLOW) {
1250a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1251a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* calculate counter values that give desired timing */
1252a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1253a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(devpriv->divisor1), &(devpriv->divisor2),
1254a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(cmd->convert_arg),
1255a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd->flags & TRIG_ROUND_MASK);
1256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1258a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1259a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are in burst mode */
1260a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else {
1261a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  check that convert_arg is compatible */
1262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1263a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg =
1264a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				burst_convert_arg(cmd->convert_arg,
1265a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd->flags & TRIG_ROUND_MASK);
1266a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1267a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1268a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1269a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (cmd->scan_begin_src == TRIG_TIMER) {
1270a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton				/*  if scans are timed faster than conversion rate allows */
1271a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (cmd->convert_arg * cmd->chanlist_len >
1272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->scan_begin_arg) {
1273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->scan_begin_arg =
1274a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess						cmd->convert_arg *
1275a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess						cmd->chanlist_len;
1276a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1277a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				}
1278a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				tmp_arg = cmd->scan_begin_arg;
1279a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				/* calculate counter values that give desired timing */
1280a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1281a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(devpriv->divisor1),
1282a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(devpriv->divisor2),
1283a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					&(cmd->scan_begin_arg),
1284a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->flags & TRIG_ROUND_MASK);
1285a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (tmp_arg != cmd->scan_begin_arg)
1286a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1287a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1288a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1289a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1290a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1291a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1292a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 4;
1293a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1294a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make sure user is not trying to mix unipolar and bipolar ranges */
1295a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->chanlist) {
1296a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1297a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 1; i < cmd->chanlist_len; i++) {
1298a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1299a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				comedi_error(dev,
1300a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					"unipolar and bipolar ranges cannot be mixed in the chanlist");
1301a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1302a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1303a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1304a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1305a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1306a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1307a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1308a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 5;
1309a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1310a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1311a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1312a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1313a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* analog input cmd interface */
1314a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1315a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* first, some utility functions used in the main ai_do_cmd() */
1316a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1317a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register a, depending on command */
1318ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_a_bits(struct comedi_cmd cmd)
1319a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1320a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a;
1321a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1322a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_a = FFEN;	/* enable fifo */
1323a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1324a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= ATEN;
1325a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1326a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.start_src) {
1327a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1328a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= TGEN | CGSL;
1329a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1330a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NOW:
1331a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= CGEN;
1332a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1333a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1334a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1335a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1336a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1337a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_a;
1338a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1339a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1340a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register c, depending on command */
1341ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_c_bits(struct comedi_cmd cmd)
1342a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1343a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_c;
1344a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int aref;
1345a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1346a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set clock source to internal or external, select analog reference,
1347a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * select unipolar / bipolar
1348a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 */
1349a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(cmd.chanlist[0]);
1350a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_c = UQEN;	/* enable upper qram addresses */
1351a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1352a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= SD;
1353a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1354a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= CMEN;
1355a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1356a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1357a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= UB;
1358a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1359a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1360a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch (cmd.convert_src) {
1361a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_TIMER:
1362a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on cascaded counters */
1363a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= IPCLK;
1364a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1365a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_EXT:
1366a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on falling edge of external trigger */
1367a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= XPCLK;
1368a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1369a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
1370a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1371a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1372a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1373a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1374a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with internal pacer clock */
1375a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | IPCLK;
1376a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1377a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1378a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with external trigger */
1379a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | XPCLK;
1380a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1381a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1382a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1383a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1384a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1385a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_c;
1386a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1387a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1388a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up counters */
1389da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
1390a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1391a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup cascaded counters for conversion/scan frequency */
1392a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1393a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1394a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd.convert_src == TRIG_TIMER) {
1395a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* set conversion frequency */
1396a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
1397a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(devpriv->divisor1), &(devpriv->divisor2),
1398a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				&(cmd.convert_arg),
1399a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				cmd.flags & TRIG_ROUND_MASK);
1400a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (das1800_set_frequency(dev) < 0) {
1401a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -1;
1402a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1403a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1404a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1405a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_TIMER:	/*  in burst mode */
1406a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* set scan frequency */
1407a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
1408a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			&(devpriv->divisor2), &(cmd.scan_begin_arg),
1409a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd.flags & TRIG_ROUND_MASK);
1410a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (das1800_set_frequency(dev) < 0) {
1411a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -1;
1412a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1413a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1414a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1415a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1416a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1417a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1418a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup counter 0 for 'about triggering' */
1419a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1420a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  load counter 0 in mode 0 */
1421a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1422a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1423a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1424a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1425a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1426a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1427a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up dma */
1428da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
1429a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1430a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long lock_flags;
1431a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1432a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1433a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1434a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
1435a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1436a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* determine a reasonable dma transfer size */
1437a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1438a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	lock_flags = claim_dma_lock();
1439a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(devpriv->dma0);
1440a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers for
1441a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * count and address get set correctly */
1442a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(devpriv->dma0);
1443a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1444a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set appropriate size of transfer */
1445a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1446a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current = devpriv->dma0;
1447a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current_buf = devpriv->ai_buf0;
1448a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma0);
1449a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set up dual dma if appropriate */
1450a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1451a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1452a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* clear flip-flop to make sure 2-byte registers for
1453a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		 * count and address get set correctly */
1454a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		clear_dma_ff(devpriv->dma1);
1455a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1456a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  set appropriate size of transfer */
1457a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1458a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		enable_dma(devpriv->dma1);
1459a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1460a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(lock_flags);
1461a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1463a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1464a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1465a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* programs channel/gain list into card */
1466da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
1467a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1468a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n, chan_range;
1469a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1470a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	const int range_mask = 0x3;	/* masks unipolar/bipolar bit off range */
1471a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int range_bitshift = 8;
1472a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1473a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	n = cmd.chanlist_len;
1474a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  spinlock protects indirect addressing */
14755f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1476a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*set QRAM address start */
1478a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* make channel / gain list */
1479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (i = 0; i < n; i++) {
1480a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		chan_range =
1481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			CR_CHAN(cmd.chanlist[i]) | ((CR_RANGE(cmd.
1482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					chanlist[i]) & range_mask) <<
1483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			range_bitshift);
1484a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(chan_range, dev->iobase + DAS1800_QRAM);
1485a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1486a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
14875f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1488a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1489a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1490a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1491a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1492a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input do_cmd */
1493da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_ai_do_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ret;
1496a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a, control_c;
1497d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1498ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd cmd = async->cmd;
1499a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1500a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!dev->irq) {
1501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev,
1502a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			"no irq assigned for das-1800, cannot do hardware conversions");
1503a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1504a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1506a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1507a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * (because dma in handler is unsafe at hard real-time priority) */
1508a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1509a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~DMA_ENABLED;
1510a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1511a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= devpriv->dma_bits;
1512a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1513a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
1514a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & TRIG_WAKE_EOS) {
1515a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo not empty */
1516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~FIMD;
1517a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1518a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo half full */
1519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= FIMD;
1520a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1521a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine how many conversions we need */
1522a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_COUNT) {
1523a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1524a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1525a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1526a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, s);
1527a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1528a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine proper bits for control registers */
1529a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_a = control_a_bits(cmd);
1530a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_c = control_c_bits(cmd);
1531a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1532a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* setup card and start */
1533a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	program_chanlist(dev, cmd);
1534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	ret = setup_counters(dev, cmd);
1535a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (ret < 0) {
1536a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "Error setting up counters");
1537a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return ret;
1538a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1539a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	setup_dma(dev, cmd);
1540a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1541a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set conversion rate and length for burst mode */
1542a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (control_c & BMDE) {
1543a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  program conversion period with number of microseconds minus 1 */
1544a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.convert_arg / 1000 - 1,
1545a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dev->iobase + DAS1800_BURST_RATE);
1546a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1547a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1548a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	/*  enable irq/dma */
1549a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_a, dev->iobase + DAS1800_CONTROL_A);	/* enable fifo and triggering */
1550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1551a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1553a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1555a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* read analog input */
1556da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1557da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
1558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n;
1560a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan, range, aref, chan_range;
1561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int timeout = 1000;
1562a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short dpnt;
1563a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int conv_flags = 0;
1564a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1566a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set up analog reference and unipolar / bipolar mode */
1567a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(insn->chanspec);
1568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	conv_flags |= UQEN;
1569a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1570a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= SD;
1571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1572a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= CMEN;
1573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= UB;
1576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1577a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);	/* software conversion enabled */
1578a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* reset fifo */
1580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan = CR_CHAN(insn->chanspec);
1583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* mask of unipolar/bipolar bit from range */
1584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	range = CR_RANGE(insn->chanspec) & 0x3;
1585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan_range = chan | (range << 8);
15865f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/* set QRAM address start */
1589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(chan_range, dev->iobase + DAS1800_QRAM);
1590a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1591a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);	/* select ADC for baseAddress + 0x0 */
1592a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1593a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (n = 0; n < insn->n; n++) {
1594a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* trigger conversion */
1595a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(0, dev->iobase + DAS1800_FIFO);
1596a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < timeout; i++) {
1597a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (i == timeout) {
1601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			comedi_error(dev, "timeout");
1602a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ETIME;
1603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1605a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* shift data to offset binary for bipolar ranges */
1606a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if ((conv_flags & UB) == 0)
1607a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dpnt += 1 << (thisboard->resolution - 1);
1608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		data[n] = dpnt;
1609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
16105f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return n;
1613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1615a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to an analog output channel */
1616da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
1617da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
1618a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1619a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan = CR_CHAN(insn->chanspec);
1620a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* int range = CR_RANGE(insn->chanspec); */
1621a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int update_chan = thisboard->ao_n_chan - 1;
1622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short output;
1623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1624a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1625a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*   card expects two's complement data */
1626a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	output = data[0] - (1 << (thisboard->resolution - 1));
1627a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if the write is to the 'update' channel, we need to remember its value */
1628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan == update_chan)
1629a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ao_update_bits = output;
1630a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  write to channel */
16315f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(DAC(chan), dev->iobase + DAS1800_SELECT);	/* select dac channel for baseAddress + 0x0 */
1633a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(output, dev->iobase + DAS1800_DAC);
1634a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  now we need to write to 'update' channel to update all dac channels */
1635a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan != update_chan) {
1636a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);	/* select 'update' channel for baseAddress + 0x0 */
1637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
16395f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1641a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 1;
1642a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1644a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* reads from digital input channels */
1645da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_di_rbits(struct comedi_device *dev, struct comedi_subdevice *s,
1646da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
1647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] = 0;
1651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1652a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1653a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1654a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1655a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to digital output channels */
1656da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_do_wbits(struct comedi_device *dev, struct comedi_subdevice *s,
1657da91b2692e0939b307f9047192d2b9fe07793e7aBill Pemberton	struct comedi_insn *insn, unsigned int *data)
1658a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1659790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int wbits;
1660a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1661a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  only set bits that have been masked */
1662a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] &= (1 << s->n_chan) - 1;
1663a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits = devpriv->do_bits;
1664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits &= ~data[0];
1665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits |= data[0] & data[1];
1666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->do_bits = wbits;
1667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1668a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1669a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1670a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = devpriv->do_bits;
1671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1673a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1674a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1675a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* loads counters with divisor1, divisor2 from private structure */
1676da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_set_frequency(struct comedi_device *dev)
1677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1678a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1679a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1680a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 1, mode 2 */
1681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
1682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			2))
1683a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1684a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 2, mode 2 */
1685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
1686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			2))
1687a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1692a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* converts requested conversion timing to timing compatible with
1695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * hardware, used only when card is in 'burst mode'
1696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
1697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1698a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1699a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int micro_sec;
1700a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1701a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  in burst mode, the maximum conversion time is 64 microseconds */
1702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (convert_arg > 64000)
1703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		convert_arg = 64000;
1704a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1705a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  the conversion time must be an integral number of microseconds */
1706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (round_mode) {
1707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_NEAREST:
1708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg + 500) / 1000;
1710a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1711a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_DOWN:
1712a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = convert_arg / 1000;
1713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1714a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_UP:
1715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg - 1) / 1000 + 1;
1716a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1718a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1719a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  return number of nanoseconds */
1720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return micro_sec * 1000;
1721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1722a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1723a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1724da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
1725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1726a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int size = DMA_BUF_SIZE;
1727a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	static const int sample_size = 2;	/*  size in bytes of one sample from board */
1728a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int fill_time = 300000000;	/*  target time in nanoseconds for filling dma buffer */
1729a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int max_size;	/*  maximum size we will allow for a transfer */
1730a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1731a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make dma buffer fill in 0.3 seconds for timed modes */
1732a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->scan_begin_src) {
1733a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_src == TRIG_TIMER)
1735a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			size = (fill_time / cmd->convert_arg) * sample_size;
1736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1737a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
1739a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			sample_size;
1740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1741a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = DMA_BUF_SIZE;
1743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1745a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1746a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set a minimum and maximum size allowed */
1747a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	max_size = DMA_BUF_SIZE;
1748a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if we are taking limited number of conversions, limit transfer size to that */
1749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT &&
1750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size > max_size)
1754a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = max_size;
1755a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size < sample_size)
1756a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = sample_size;
1757a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1758a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return size;
1759a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1760