das1800.c revision 845d131e2b363717d8ac8db2c6b4417de8cf10b5
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>
1045a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
105845d131e2b363717d8ac8db2c6b4417de8cf10b5Greg Kroah-Hartman#include <linux/io.h>
106a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "../comedidev.h"
107a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
108a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <linux/ioport.h>
109a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include <asm/dma.h>
110a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
111a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "8253.h"
112a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#include "comedi_fc.h"
113a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
114a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* misc. defines */
115a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DAS1800_SIZE           16	/* uses 16 io addresses */
116a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define FIFO_SIZE              1024	/*  1024 sample fifo */
117a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define TIMER_BASE             200	/*  5 Mhz master clock */
118a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define UNIPOLAR               0x4	/*  bit that determines whether input range is uni/bipolar */
119a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define DMA_BUF_SIZE           0x1ff00	/*  size in bytes of dma buffers */
120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Registers for the das1800 */
122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_FIFO            0x0
123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM            0x0
124a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DAC             0x0
125a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_SELECT          0x2
126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ADC                     0x0
127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   QRAM                    0x1
128a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DAC(a)                  (0x2 + a)
129a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_DIGITAL         0x3
130a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_A       0x4
131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FFEN                    0x1
132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGEN                    0x4
133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CGSL                    0x8
134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGEN                    0x10
135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   TGSL                    0x20
136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   ATEN                    0x80
137a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_B       0x5
138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5                 0x1
139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6                 0x2
140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7                 0x3
141a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH5_CH6             0x5
142a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH6_CH7             0x6
143a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_CH7_CH5             0x7
144a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   DMA_ENABLED             0x3	/* mask used to determine if dma is enabled */
145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMA_DUAL                0x4
146a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ3                    0x8
147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ5                    0x10
148a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ7                    0x18
149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ10                   0x28
150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ11                   0x30
151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IRQ15                   0x38
152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FIMD                    0x40
153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_CONTROL_C       0X6
154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   IPCLK                   0x1
155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   XPCLK                   0x3
156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   BMDE                    0x4
157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CMEN                    0x8
158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UQEN                    0x10
159a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   SD                      0x40
160a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   UB                      0x80
161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_STATUS          0x7
162a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* bits that prevent interrupt status bits (and CVEN) from being cleared on write */
163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CLEAR_INTR_MASK         (CVEN_MASK | 0x1f)
164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   INT                     0x1
165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   DMATC                   0x2
166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CT0TC                   0x8
167a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   OVF                     0x10
168a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FHF                     0x20
169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   FNE                     0x40
170a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define   CVEN_MASK               0x40	/*  masks CVEN on write */
171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define   CVEN                    0x80
172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_LENGTH    0x8
173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_BURST_RATE      0x9
174a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_QRAM_ADDRESS    0xa
175a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess#define DAS1800_COUNTER         0xc
176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
177a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton#define IOBASE2                   0x400	/* offset of additional ioports used on 'ao' cards */
178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessenum {
180a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701st, das1701st_da, das1702st, das1702st_da, das1702hr,
181a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1702hr_da,
182a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1701ao, das1702ao, das1801st, das1801st_da, das1802st, das1802st_da,
183a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1802hr, das1802hr_da, das1801hc, das1802hc, das1801ao, das1802ao
184a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
185a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_attach(struct comedi_device *dev,
1870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it);
188814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_detach(struct comedi_device *dev);
189814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_probe(struct comedi_device *dev);
1900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_cancel(struct comedi_device *dev,
1910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_subdevice *s);
19270265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das1800_interrupt(int irq, void *d);
1930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_poll(struct comedi_device *dev,
1940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s);
195814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_ai_handler(struct comedi_device *dev);
1960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_handle_dma(struct comedi_device *dev,
1970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s, unsigned int status);
1980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_flush_dma(struct comedi_device *dev,
1990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s);
2000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_flush_dma_channel(struct comedi_device *dev,
2010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
2020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int channel, uint16_t * buffer);
203814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device *dev,
2040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  struct comedi_subdevice *s);
205814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device *dev,
2060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  struct comedi_subdevice *s);
2070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_do_cmdtest(struct comedi_device *dev,
2080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
2090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_cmd *cmd);
2100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_do_cmd(struct comedi_device *dev,
2110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s);
2120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_rinsn(struct comedi_device *dev,
2130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
2150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ao_winsn(struct comedi_device *dev,
2160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
2180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_di_rbits(struct comedi_device *dev,
2190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
2210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_do_wbits(struct comedi_device *dev,
2220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
2230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data);
224814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pemberton
225814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic int das1800_set_frequency(struct comedi_device *dev);
226a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode);
227814900c904140cfe7f3e48cabec06b3eec57e0eaBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd *cmd);
228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
229a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input ranges */
2309ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1801 = {
231a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
232a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
2330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
2340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-1, 1),
2350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.1, 0.1),
2360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-0.02, 0.02),
2370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 5),
2380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1),
2390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.1),
2400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 0.02),
2410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
2449ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ai_das1802 = {
245a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	8,
246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
2470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
2480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-5, 5),
2490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-2.5, 2.5),
2500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-1.25, 1.25),
2510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 10),
2520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 5),
2530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 2.5),
2540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(0, 1.25),
2550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
258ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstruct das1800_board {
259a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const char *name;
260a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ai_speed;		/* max conversion period in nanoseconds */
261a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int resolution;		/* bits of ai resolution */
262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int qram_len;		/* length of card's channel / gain queue */
263a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int common;		/* supports AREF_COMMON flag */
264a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_n_chan;		/* number of digital output channels */
265a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_ability;		/* 0 == no analog out, 1 == basic analog out, 2 == waveform analog out */
266a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ao_n_chan;		/* number of analog out channels */
2679ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pemberton	const struct comedi_lrange *range_ai;	/* available input ranges */
268ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton};
269a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
270a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Warning: the maximum conversion speeds listed below are
271a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * not always achievable depending on board setup (see
272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * user manual.)
273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
274ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pembertonstatic const struct das1800_board das1800_boards[] = {
275a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
2760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1701st",
2770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
2780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
2800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
2810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
2820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
2830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
2840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
2850a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
286a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
2870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1701st-da",
2880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
2890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
2900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
2910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
2920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
2930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
2940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 4,
2950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
2960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
297a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
2980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1702st",
2990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
3000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
3050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
3060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
308a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1702st-da",
3100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
3110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
3160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 4,
3170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
319a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1702hr",
3210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 20000,
3220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 16,
3230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
3270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
3280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
330a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1702hr-da",
3320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 20000,
3330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 16,
3340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
3380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
3390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
341a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1701ao",
3430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
3440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 2,
3490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
3500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
3510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
352a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1702ao",
3540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 6250,
3550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 2,
3600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
3610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
363a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1801st",
3650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
3660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
3710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
3720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
3730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
374a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1801st-da",
3760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
3770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3790a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
3820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 4,
3830a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
3840a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
385a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3860a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802st",
3870a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
3880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
3890a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
3900a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
3910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
3920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
3930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
3940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
3950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
396a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
3970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802st-da",
3980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
3990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
4000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
4010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
4020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
4030a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
4040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 4,
4050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
4060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
407a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4080a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802hr",
4090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 10000,
4100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 16,
4110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
4120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
4130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
4140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 0,
4150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 0,
4160a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
4170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
418a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802hr-da",
4200a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 10000,
4210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 16,
4220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
4230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
4240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
4250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
4260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
4270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
4280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
429a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1801hc",
4310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
4320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
4330a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 64,
4340a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 0,
4350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 8,
4360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
4370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
4380a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
4390a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
440a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802hc",
4420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
4430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
4440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 64,
4450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 0,
4460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 8,
4470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 1,
4480a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
4490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
4500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
451a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4520a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1801ao",
4530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
4540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
4550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
4560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
4570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
4580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 2,
4590a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
4600a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1801,
4610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
4630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .name = "das-1802ao",
4640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ai_speed = 3000,
4650a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .resolution = 12,
4660a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .qram_len = 256,
4670a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .common = 1,
4680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .do_n_chan = 4,
4690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_ability = 2,
4700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .ao_n_chan = 2,
4710a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 .range_ai = &range_ai_das1802,
4720a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 },
473a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
474a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
475a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
476a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Useful for shorthand access to the particular board structure
477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
478ce422cf3569444116d7d826b274bd59cc34d3b28Bill Pemberton#define thisboard ((const struct das1800_board *)dev->board_ptr)
479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
4800c5a144d730a68967dfb3f8163260a142e3282e3Bill Pembertonstruct das1800_private {
481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int count;	/* number of data points left to be taken */
482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor1;	/* value to load into board's counter 1 for timed conversions */
483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int divisor2;	/* value to load into board's counter 2 for timed conversions */
484a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int do_bits;		/* digital output bits */
485a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int irq_dma_bits;	/* bits for control register b */
486a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* dma bits for control register b, stored so that dma can be
487a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * turned on and off */
488a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int dma_bits;
489a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0;	/* dma channels used */
490a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1;
491a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	volatile unsigned int dma_current;	/* dma channel currently in use */
492a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf0;	/* pointers to dma buffers */
493a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *ai_buf1;
494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	uint16_t *dma_current_buf;	/* pointer to dma buffer currently being used */
495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma_transfer_size;	/* size of transfer currently used, in bytes */
496a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;	/* secondary io address used for analog out on 'ao' boards */
497a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short ao_update_bits;	/* remembers the last write to the 'update' dac */
4980c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton};
499a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
5000c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton#define devpriv ((struct das1800_private *)dev->private)
501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
502a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for boards with basic analog out */
5039ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_1 = {
504a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	1,
505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
5060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 RANGE(-10, 10),
5070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	 }
508a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
509a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
510a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog out range for 'ao' boards */
511a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
5129ced1de69125b60f40127eddaa3be2a92bb0a1dfBill Pembertonstatic const struct comedi_lrange range_ao_2 = {
513a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	2,
514a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	{
515a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-10, 10),
516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		RANGE(-5, 5),
517a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
518a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess*/
520a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
521139dfbdfacb02e3ef3df936d2fabd1ad5f14ea88Bill Pembertonstatic struct comedi_driver driver_das1800 = {
52268c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.driver_name = "das1800",
52368c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.module = THIS_MODULE,
52468c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.attach = das1800_attach,
52568c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.detach = das1800_detach,
5268629efa4cbf6f89a54a85af4b8bc31762af01800Bill Pemberton	.num_names = ARRAY_SIZE(das1800_boards),
52768c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.board_name = &das1800_boards[0].name,
52868c3dbff9fc9f25872408d0e95980d41733d48d0Bill Pemberton	.offset = sizeof(struct das1800_board),
529a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
530a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
531a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/*
532a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * A convenient macro that defines init_module() and cleanup_module(),
533a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * as necessary.
534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
5357114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic int __init driver_das1800_init_module(void)
5367114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
5377114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	return comedi_driver_register(&driver_das1800);
5387114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
5397114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
5407114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasstatic void __exit driver_das1800_cleanup_module(void)
5417114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas{
5427114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas	comedi_driver_unregister(&driver_das1800);
5437114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas}
5447114a28011f9d5f3d981731ad341177c21f9d948Arun Thomas
5457114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_init(driver_das1800_init_module);
5467114a28011f9d5f3d981731ad341177c21f9d948Arun Thomasmodule_exit(driver_das1800_cleanup_module);
547a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
548da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_init_dma(struct comedi_device *dev, unsigned int dma0,
5490a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    unsigned int dma1)
550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
551a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
553a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  need an irq to do dma */
554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq && dma0) {
555a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/* encode dma0 and dma1 into 2 digit hexadecimal for switch */
556a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch ((dma0 & 0x7) | (dma1 << 4)) {
557a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x5:	/*  dma0 == 5 */
558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5;
559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
560a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x6:	/*  dma0 == 6 */
561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6;
562a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
563a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x7:	/*  dma0 == 7 */
564a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7;
565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
566a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x65:	/*  dma0 == 5, dma1 == 6 */
567a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH5_CH6;
568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
569a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x76:	/*  dma0 == 6, dma1 == 7 */
570a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH6_CH7;
571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
572a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		case 0x57:	/*  dma0 == 7, dma1 == 5 */
573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_bits |= DMA_CH7_CH5;
574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" only supports dma channels 5 through 7\n"
5770a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       " Dual dma only allows the following combinations:\n"
5780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       " dma 5,6 / 6,7 / or 7,5\n");
579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (request_dma(dma0, driver_das1800.driver_name)) {
583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" failed to allocate dma channel %i\n", dma0);
584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
586a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma0 = dma0;
587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current = dma0;
588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (request_dma(dma1, driver_das1800.driver_name)) {
590a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" failed to allocate dma channel %i\n",
5910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				       dma1);
592a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -EINVAL;
593a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
594a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma1 = dma1;
595a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
596a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 = kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
597a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->dma_current_buf = devpriv->ai_buf0;
600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->ai_buf1 =
6020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    kmalloc(DMA_BUF_SIZE, GFP_KERNEL | GFP_DMA);
603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->ai_buf1 == NULL)
604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -ENOMEM;
605a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
606a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		flags = claim_dma_lock();
607a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_mode(devpriv->dma0, DMA_MODE_READ);
609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma1) {
610a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			disable_dma(devpriv->dma1);
611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			set_dma_mode(devpriv->dma1, DMA_MODE_READ);
612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_dma_lock(flags);
614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
615a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
616a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
617a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
6180a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_attach(struct comedi_device *dev,
6190a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			  struct comedi_devconfig *it)
620a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
62134c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s;
622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase = it->options[0];
623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int irq = it->options[1];
624a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma0 = it->options[2];
625a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int dma1 = it->options[3];
626a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long iobase2;
627a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int retval;
629a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
630a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* allocate and initialize dev->private */
6310c5a144d730a68967dfb3f8163260a142e3282e3Bill Pemberton	if (alloc_private(dev, sizeof(struct das1800_private)) < 0)
632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
633a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
634a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: io 0x%lx", dev->minor, driver_das1800.driver_name,
6350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       iobase);
636a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(", irq %u", irq);
638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dma0) {
639a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(", dma %u", dma0);
640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (dma1)
641a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				printk(" and %u", dma1);
642a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
644a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("\n");
645a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
646a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (iobase == 0) {
647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" io base address required\n");
648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* check if io addresses are available */
652a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!request_region(iobase, DAS1800_SIZE, driver_das1800.driver_name)) {
6530a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
6540a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
6550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     iobase, iobase + DAS1800_SIZE - 1);
656a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EIO;
657a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
658a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->iobase = iobase;
659a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
660a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	board = das1800_probe(dev);
661a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (board < 0) {
662a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" unable to determine board type\n");
663a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENODEV;
664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_ptr = das1800_boards + board;
667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->board_name = thisboard->name;
668a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
669a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if it is an 'ao' board with fancy analog out then we need extra io ports */
670a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 2) {
671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		iobase2 = iobase + IOBASE2;
672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!request_region(iobase2, DAS1800_SIZE,
6730a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    driver_das1800.driver_name)) {
6740a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			printk
6750a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    (" I/O port conflict: failed to allocate ports 0x%lx to 0x%lx\n",
6760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     iobase2, iobase2 + DAS1800_SIZE - 1);
677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EIO;
678a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
679a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->iobase2 = iobase2;
680a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* grab our IRQ */
683a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (irq) {
6845f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		if (request_irq(irq, das1800_interrupt, 0,
685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				driver_das1800.driver_name, dev)) {
686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" unable to allocate irq %u\n", irq);
687a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -EINVAL;
688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->irq = irq;
691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
692a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set bits that tell card which irq to use */
693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (irq) {
694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0:
695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 3:
697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x8;
698a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
699a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 5:
700a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x10;
701a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 7:
703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x18;
704a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
705a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 10:
706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x28;
707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 11:
709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x30;
710a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
711a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 15:
712a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= 0x38;
713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
714a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" irq out of range\n");
716a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -EINVAL;
717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
718a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
719a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	retval = das1800_init_dma(dev, dma0, dma1);
721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (retval < 0)
722a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return retval;
723a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
724a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->ai_buf0 == NULL) {
725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ai_buf0 =
7260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    kmalloc(FIFO_SIZE * sizeof(uint16_t), GFP_KERNEL);
727a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->ai_buf0 == NULL)
728a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -ENOMEM;
729a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
730a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
731a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (alloc_subdevices(dev, 4) < 0)
732a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -ENOMEM;
733a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog input subdevice */
735a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 0;
736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	dev->read_subdev = s;
737a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_AI;
738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND | SDF_CMD_READ;
739a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->common)
740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags |= SDF_COMMON;
741a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->qram_len;
742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->len_chanlist = thisboard->qram_len;
743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = (1 << thisboard->resolution) - 1;
744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = thisboard->range_ai;
745a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmd = das1800_ai_do_cmd;
746a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->do_cmdtest = das1800_ai_do_cmdtest;
747a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_read = das1800_ai_rinsn;
748a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->poll = das1800_ai_poll;
749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->cancel = das1800_cancel;
750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* analog out */
752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 1;
753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
754a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_AO;
755a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->subdev_flags = SDF_WRITABLE;
756a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->n_chan = thisboard->ao_n_chan;
757a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->maxdata = (1 << thisboard->resolution) - 1;
758a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->range_table = &range_ao_1;
759a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->insn_write = das1800_ao_winsn;
760a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
761a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		s->type = COMEDI_SUBD_UNUSED;
762a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
763a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
764a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* di */
765a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 2;
766a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DI;
767a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_READABLE;
768a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = 4;
769a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
770a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
771a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_di_rbits;
772a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
773a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* do */
774a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s = dev->subdevices + 3;
775a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->type = COMEDI_SUBD_DO;
776a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->subdev_flags = SDF_WRITABLE | SDF_READABLE;
777a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->n_chan = thisboard->do_n_chan;
778a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->maxdata = 1;
779a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->range_table = &range_digital;
780a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	s->insn_bits = das1800_do_wbits;
781a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
782a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, dev->read_subdev);
783a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
784a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize digital out channels */
785a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
786a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
787a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  initialize analog out channels */
788a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (thisboard->ao_ability == 1) {
789a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  select 'update' dac channel for baseAddress + 0x0 */
790a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(thisboard->ao_n_chan - 1),
7910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->iobase + DAS1800_SELECT);
792a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
793a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
794a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
795a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
796a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
797a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
798da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_detach(struct comedi_device *dev)
799a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
800a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* only free stuff if it has been allocated by _attach */
801a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->iobase)
802a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		release_region(dev->iobase, DAS1800_SIZE);
803a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->irq)
8045f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman		free_irq(dev->irq, dev);
805a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->private) {
806a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->iobase2)
807a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			release_region(devpriv->iobase2, DAS1800_SIZE);
808a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma0)
809a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma0);
810a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma1)
811a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			free_dma(devpriv->dma1);
8121bf2ee4ea19d3ebeb8fe35c03dd44cb1d851e19fDavid Binderman		kfree(devpriv->ai_buf0);
8131bf2ee4ea19d3ebeb8fe35c03dd44cb1d851e19fDavid Binderman		kfree(devpriv->ai_buf1);
814a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
815a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
816a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	printk("comedi%d: %s: remove\n", dev->minor,
8170a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	       driver_das1800.driver_name);
818a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
819a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
820a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess};
821a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
822a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* probes and checks das-1800 series board type
823a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
824da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_probe(struct comedi_device *dev)
825a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
826a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int id;
827a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int board;
828a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
829a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	id = (inb(dev->iobase + DAS1800_DIGITAL) >> 4) & 0xf;	/* get id bits */
8300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	board = ((struct das1800_board *)dev->board_ptr) - das1800_boards;
831a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
832a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (id) {
833a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x3:
834a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st_da || board == das1802st_da ||
8350a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    board == das1701st_da || board == das1702st_da) {
836a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
838a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
839a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
8400a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model (probed, not recommended): das-1800st-da series\n");
842a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
843a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
844a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x4:
845a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr_da || board == das1702hr_da) {
846a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8470a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
848a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
849a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
8500a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model (probed, not recommended): das-1802hr-da\n");
852a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
853a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
854a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x5:
855a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801ao || board == das1802ao ||
8560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    board == das1701ao || board == das1702ao) {
857a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8580a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
859a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
860a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
8610a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model (probed, not recommended): das-1800ao series\n");
863a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801ao;
864a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
865a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x6:
866a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1802hr || board == das1702hr) {
867a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
869a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
870a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
871a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		printk(" Board model (probed, not recommended): das-1802hr\n");
872a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1802hr;
873a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
874a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x7:
875a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801st || board == das1802st ||
8760a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    board == das1701st || board == das1702st) {
877a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8780a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
879a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
880a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
8810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model (probed, not recommended): das-1800st series\n");
883a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801st;
884a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
885a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case 0x8:
886a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (board == das1801hc || board == das1802hc) {
887a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			printk(" Board model: %s\n",
8880a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       das1800_boards[board].name);
889a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return board;
890a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
8910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model (probed, not recommended): das-1800hc series\n");
893a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return das1801hc;
894a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
895a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
8960a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		printk
8970a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    (" Board model: probe returned 0x%x (unknown, please report)\n",
8980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     id);
899a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return board;
900a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
901a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
902a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return -1;
903a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
904a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
9050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_poll(struct comedi_device *dev,
9060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			   struct comedi_subdevice *s)
907a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
908a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
909a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
910a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  prevent race with interrupt handler */
9115f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, flags);
912a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
9135f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, flags);
914a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
915a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return s->async->buf_write_count - s->async->buf_read_count;
916a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
917a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
91870265d24e3404fe798b6edd55a02016b1edb49d7Jiri Slabystatic irqreturn_t das1800_interrupt(int irq, void *d)
919a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
92071b5f4f11971dea972832ad63a994c7e5b45db6bBill Pemberton	struct comedi_device *dev = d;
921a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status;
922a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
923a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dev->attached == 0) {
924a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "premature interrupt");
925a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_HANDLED;
926a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
927a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
928a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* Prevent race with das1800_ai_poll() on multi processor systems.
929a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * Also protects indirect addressing in das1800_ai_handler */
930a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_lock(&dev->spinlock);
931a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	status = inb(dev->iobase + DAS1800_STATUS);
932a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
933a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if interrupt was not caused by das-1800 */
934a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!(status & INT)) {
935a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		spin_unlock(&dev->spinlock);
936a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return IRQ_NONE;
937a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
938a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear the interrupt status bit INT */
939a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CLEAR_INTR_MASK & ~INT, dev->iobase + DAS1800_STATUS);
940a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  handle interrupt */
941a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_ai_handler(dev);
942a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
943a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	spin_unlock(&dev->spinlock);
944a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return IRQ_HANDLED;
945a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
946a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
947a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* the guts of the interrupt handler, that is shared with das1800_ai_poll */
948da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_ai_handler(struct comedi_device *dev)
949a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
95034c43922e62708d45e9660eee4b4f1fb7b4bf2c7Bill Pemberton	struct comedi_subdevice *s = dev->subdevices + 0;	/* analog input subdevice */
951d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
952ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &async->cmd;
953a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int status = inb(dev->iobase + DAS1800_STATUS);
954a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
955a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events = 0;
956a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  select adc for base address + 0 */
957a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);
958a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  dma buffer full */
959a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->irq_dma_bits & DMA_ENABLED) {
960a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  look for data from dma transfer even if dma terminal count hasn't happened yet */
961a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_dma(dev, s, status);
962a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FHF) {	/*  if fifo half full */
963a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_half_full(dev, s);
964a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (status & FNE) {	/*  if fifo not empty */
965a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_handle_fifo_not_empty(dev, s);
966a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
967a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
968a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	async->events |= COMEDI_CB_BLOCK;
969a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if the card's fifo has overflowed */
970a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & OVF) {
971a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear OVF interrupt bit */
972a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~OVF, dev->iobase + DAS1800_STATUS);
973a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "DAS1800 FIFO overflow");
974a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);
975a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_ERROR | COMEDI_CB_EOA;
976a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_event(dev, s);
977a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
978a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
979a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  stop taking data if appropriate */
980a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* stop_src TRIG_EXT */
981a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & CT0TC) {
982a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear CT0TC interrupt bit */
983a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~CT0TC, dev->iobase + DAS1800_STATUS);
984a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  make sure we get all remaining data from board before quitting */
985a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->irq_dma_bits & DMA_ENABLED)
986a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_flush_dma(dev, s);
987a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else
988a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			das1800_handle_fifo_not_empty(dev, s);
989a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
990a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
991a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	} else if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0) {	/*  stop_src TRIG_COUNT */
992a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_cancel(dev, s);	/* disable hardware conversions */
993a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		async->events |= COMEDI_CB_EOA;
994a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
995a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
996a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	comedi_event(dev, s);
997a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
998a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
999a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1000a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
10010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_handle_dma(struct comedi_device *dev,
10020a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			       struct comedi_subdevice *s, unsigned int status)
1003a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1004a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
1005a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1006a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1007a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
1008a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
10090a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  devpriv->dma_current_buf);
1010a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  re-enable  dma channel */
1011a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma_current,
10120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     virt_to_bus(devpriv->dma_current_buf));
1013a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma_current, devpriv->dma_transfer_size);
1014a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma_current);
1015a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
1016a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1017a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (status & DMATC) {
1018a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  clear DMATC interrupt bit */
1019a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(CLEAR_INTR_MASK & ~DMATC, dev->iobase + DAS1800_STATUS);
1020a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch dma channels for next time, if appropriate */
1021a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (dual_dma) {
1022a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  read data from the other channel next time */
1023a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (devpriv->dma_current == devpriv->dma0) {
1024a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma1;
1025a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf1;
1026a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			} else {
1027a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current = devpriv->dma0;
1028a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				devpriv->dma_current_buf = devpriv->ai_buf0;
1029a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1030a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1031a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1032a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1033a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1034a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1035a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1036da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic inline uint16_t munge_bipolar_sample(const struct comedi_device *dev,
10370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    uint16_t sample)
1038a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1039a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	sample += 1 << (thisboard->resolution - 1);
1040a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return sample;
1041a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1042a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
10430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void munge_data(struct comedi_device *dev, uint16_t * array,
10440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       unsigned int num_elements)
1045a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1046a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int i;
1047a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1048a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1049a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* see if card is using a unipolar or bipolar range so we can munge data correctly */
1050a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1051a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1052a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* convert to unsigned type if we are in a bipolar mode */
1053a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!unipolar) {
1054a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < num_elements; i++) {
1055a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			array[i] = munge_bipolar_sample(dev, array[i]);
1056a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1057a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1058a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1059a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1060a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* Utility function used by das1800_flush_dma() and das1800_handle_dma().
1061a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * Assumes dma lock is held */
10620a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_flush_dma_channel(struct comedi_device *dev,
10630a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      struct comedi_subdevice *s,
10640a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				      unsigned int channel, uint16_t * buffer)
1065a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1066a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int num_bytes, num_samples;
1067ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1068a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1069a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(channel);
1070a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1071a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers
1072a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * get set correctly */
1073a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(channel);
1074a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1075a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  figure out how many points to read */
1076a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	num_bytes = devpriv->dma_transfer_size - get_dma_residue(channel);
1077790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	num_samples = num_bytes / sizeof(short);
1078a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1079a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1080a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < num_samples)
1081a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		num_samples = devpriv->count;
1082a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1083a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, buffer, num_samples);
1084a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, buffer, num_bytes);
1085a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (s->async->cmd.stop_src == TRIG_COUNT)
1086a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= num_samples;
1087a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1088a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1089a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1090a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
109125985edcedea6396277003854657b5f3cb31a628Lucas De Marchi/* flushes remaining data from board when external trigger has stopped acquisition
1092a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * and we are using dma transfers */
10930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic void das1800_flush_dma(struct comedi_device *dev,
10940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			      struct comedi_subdevice *s)
1095a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1096a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long flags;
1097a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1098a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1099a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	flags = claim_dma_lock();
1100a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_flush_dma_channel(dev, s, devpriv->dma_current,
11010a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  devpriv->dma_current_buf);
1102a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1103a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1104a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  switch to other channel and flush it */
1105a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (devpriv->dma_current == devpriv->dma0) {
1106a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma1;
1107a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf1;
1108a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		} else {
1109a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current = devpriv->dma0;
1110a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->dma_current_buf = devpriv->ai_buf0;
1111a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1112a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		das1800_flush_dma_channel(dev, s, devpriv->dma_current,
11130a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  devpriv->dma_current_buf);
1114a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1115a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1116a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(flags);
1117a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1118a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  get any remaining samples in fifo */
1119a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_handle_fifo_not_empty(dev, s);
1120a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1121a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1122a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1123a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1124da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_handle_fifo_half_full(struct comedi_device *dev,
11250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  struct comedi_subdevice *s)
1126a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1127a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int numPoints = 0;	/* number of points to read */
1128ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1129a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1130a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	numPoints = FIFO_SIZE / 2;
1131a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if we only need some of the points */
1132a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT && devpriv->count < numPoints)
1133a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		numPoints = devpriv->count;
1134a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	insw(dev->iobase + DAS1800_FIFO, devpriv->ai_buf0, numPoints);
1135a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	munge_data(dev, devpriv->ai_buf0, numPoints);
1136a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cfc_write_array_to_buffer(s, devpriv->ai_buf0,
11370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				  numPoints * sizeof(devpriv->ai_buf0[0]));
1138a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT)
1139a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count -= numPoints;
1140a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1141a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1142a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1143da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void das1800_handle_fifo_not_empty(struct comedi_device *dev,
11440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					  struct comedi_subdevice *s)
1145a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1146790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	short dpnt;
1147a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1148ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd *cmd = &s->async->cmd;
1149a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1150a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unipolar = inb(dev->iobase + DAS1800_CONTROL_C) & UB;
1151a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1152a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	while (inb(dev->iobase + DAS1800_STATUS) & FNE) {
1153a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT && devpriv->count == 0)
1154a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1155a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1156a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* convert to unsigned type if we are in a bipolar mode */
1157a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!unipolar) ;
1158a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = munge_bipolar_sample(dev, dpnt);
1159a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cfc_write_to_buffer(s, dpnt);
1160a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_src == TRIG_COUNT)
1161a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			devpriv->count--;
1162a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1163a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1164a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1165a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1166a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1167da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
1168a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1169a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_STATUS);	/* disable conversions */
1170a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_B);	/* disable interrupts and dma */
1171a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* disable and clear fifo and stop triggering */
1172a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma0)
1173a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma0);
1174a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (devpriv->dma1)
1175a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1176a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1177a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1178a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1179a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* test analog input cmd */
11800a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_do_cmdtest(struct comedi_device *dev,
11810a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_subdevice *s,
11820a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				 struct comedi_cmd *cmd)
1183a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1184a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1185a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int tmp;
1186a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int tmp_arg;
1187a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i;
1188a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int unipolar;
1189a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1190a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 1: make sure trigger sources are trivially valid */
1191a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1192a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->start_src;
1193a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->start_src &= TRIG_NOW | TRIG_EXT;
1194a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->start_src || tmp != cmd->start_src)
1195a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1196a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1197a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_begin_src;
1198a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_EXT;
1199a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1200a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1201a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1202a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->convert_src;
1203a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->convert_src &= TRIG_TIMER | TRIG_EXT;
1204a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->convert_src || tmp != cmd->convert_src)
1205a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1206a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1207a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->scan_end_src;
1208a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->scan_end_src &= TRIG_COUNT;
1209a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1210a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1211a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1212a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	tmp = cmd->stop_src;
1213a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	cmd->stop_src &= TRIG_COUNT | TRIG_EXT | TRIG_NONE;
1214a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->stop_src || tmp != cmd->stop_src)
1215a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1216a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1217a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1218a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 1;
1219a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1220a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 2: make sure trigger sources are unique and mutually compatible */
1221a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1222a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  uniqueness check */
1223a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_src != TRIG_NOW && cmd->start_src != TRIG_EXT)
1224a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1225a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
12260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_TIMER &&
12270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->scan_begin_src != TRIG_EXT)
1228a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1229a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src != TRIG_TIMER && cmd->convert_src != TRIG_EXT)
1230a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1231a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src != TRIG_COUNT &&
12320a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->stop_src != TRIG_NONE && cmd->stop_src != TRIG_EXT)
1233a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1234a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/* compatibility check */
1235a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_begin_src != TRIG_FOLLOW &&
12360a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->convert_src != TRIG_TIMER)
1237a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1238a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1239a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1240a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 2;
1241a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1242a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 3: make sure arguments are trivially compatible */
1243a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1244a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->start_arg != 0) {
1245a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->start_arg = 0;
1246a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1247a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1248a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1249a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_arg < thisboard->ai_speed) {
1250a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg = thisboard->ai_speed;
1251a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1252a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1253a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1254a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!cmd->chanlist_len) {
1255a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->chanlist_len = 1;
1256a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1257a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1258a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->scan_end_arg != cmd->chanlist_len) {
1259a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		cmd->scan_end_arg = cmd->chanlist_len;
1260a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1261a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1262a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1263a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->stop_src) {
1264a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_COUNT:
1265a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (!cmd->stop_arg) {
1266a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 1;
1267a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1268a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1269a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1270a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NONE:
1271a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->stop_arg != 0) {
1272a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->stop_arg = 0;
1273a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			err++;
1274a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1275a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1276a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1277a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1278a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1279a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1280a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1281a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 3;
1282a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1283a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* step 4: fix up any arguments */
1284a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1285a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->convert_src == TRIG_TIMER) {
1286a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are not in burst mode */
1287a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->scan_begin_src == TRIG_FOLLOW) {
1288a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1289a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* calculate counter values that give desired timing */
1290a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
12910a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(devpriv->divisor1),
12920a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(devpriv->divisor2),
12930a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(cmd->convert_arg),
12940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       cmd->
12950a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       flags & TRIG_ROUND_MASK);
1296a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1297a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1298a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1299a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  if we are in burst mode */
1300a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		else {
1301a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton			/*  check that convert_arg is compatible */
1302a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			tmp_arg = cmd->convert_arg;
1303a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			cmd->convert_arg =
13040a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    burst_convert_arg(cmd->convert_arg,
13050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					      cmd->flags & TRIG_ROUND_MASK);
1306a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (tmp_arg != cmd->convert_arg)
1307a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1308a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1309a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (cmd->scan_begin_src == TRIG_TIMER) {
1310a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton				/*  if scans are timed faster than conversion rate allows */
1311a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (cmd->convert_arg * cmd->chanlist_len >
13120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral				    cmd->scan_begin_arg) {
1313a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					cmd->scan_begin_arg =
13140a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    cmd->convert_arg *
13150a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					    cmd->chanlist_len;
1316a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1317a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				}
1318a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				tmp_arg = cmd->scan_begin_arg;
1319a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				/* calculate counter values that give desired timing */
1320a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				i8253_cascade_ns_to_timer_2div(TIMER_BASE,
13210a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       &(devpriv->
13220a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral								 divisor1),
13230a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       &(devpriv->
13240a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral								 divisor2),
13250a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       &(cmd->
13260a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral								 scan_begin_arg),
13270a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       cmd->
13280a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       flags &
13290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral							       TRIG_ROUND_MASK);
1330a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				if (tmp_arg != cmd->scan_begin_arg)
1331a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess					err++;
1332a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1333a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1334a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1335a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1336a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1337a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 4;
1338a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1339a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make sure user is not trying to mix unipolar and bipolar ranges */
1340a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->chanlist) {
1341a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		unipolar = CR_RANGE(cmd->chanlist[0]) & UNIPOLAR;
1342a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 1; i < cmd->chanlist_len; i++) {
1343a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (unipolar != (CR_RANGE(cmd->chanlist[i]) & UNIPOLAR)) {
1344a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				comedi_error(dev,
13450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     "unipolar and bipolar ranges cannot be mixed in the chanlist");
1346a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				err++;
1347a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1348a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1349a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1350a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1351a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1352a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1353a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return 5;
1354a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1355a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1356a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1357a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1358a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* analog input cmd interface */
1359a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1360a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* first, some utility functions used in the main ai_do_cmd() */
1361a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1362a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register a, depending on command */
1363ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_a_bits(struct comedi_cmd cmd)
1364a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1365a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a;
1366a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1367a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_a = FFEN;	/* enable fifo */
1368a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1369a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= ATEN;
1370a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1371a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.start_src) {
1372a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1373a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= TGEN | CGSL;
1374a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1375a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_NOW:
1376a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_a |= CGEN;
1377a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1378a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1379a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1380a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1381a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1382a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_a;
1383a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1384a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1385a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* returns appropriate bits for control register c, depending on command */
1386ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pembertonstatic int control_c_bits(struct comedi_cmd cmd)
1387a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1388a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_c;
1389a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int aref;
1390a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1391a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set clock source to internal or external, select analog reference,
1392a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * select unipolar / bipolar
1393a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 */
1394a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(cmd.chanlist[0]);
1395a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	control_c = UQEN;	/* enable upper qram addresses */
1396a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1397a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= SD;
1398a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1399a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= CMEN;
1400a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1401a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(cmd.chanlist[0]) & UNIPOLAR)
1402a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= UB;
1403a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1404a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1405a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		switch (cmd.convert_src) {
1406a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_TIMER:
1407a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on cascaded counters */
1408a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= IPCLK;
1409a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1410a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		case TRIG_EXT:
1411a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* trig on falling edge of external trigger */
1412a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			control_c |= XPCLK;
1413a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1414a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		default:
1415a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			break;
1416a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1417a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1418a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1419a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with internal pacer clock */
1420a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | IPCLK;
1421a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1422a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_EXT:
1423a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  burst mode with external trigger */
1424a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		control_c |= BMDE | XPCLK;
1425a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1426a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1427a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1428a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1429a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1430a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return control_c;
1431a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1432a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1433a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up counters */
1434da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int setup_counters(struct comedi_device *dev, struct comedi_cmd cmd)
1435a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1436a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup cascaded counters for conversion/scan frequency */
1437a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd.scan_begin_src) {
1438a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1439a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd.convert_src == TRIG_TIMER) {
1440a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			/* set conversion frequency */
1441a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			i8253_cascade_ns_to_timer_2div(TIMER_BASE,
14420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(devpriv->divisor1),
14430a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(devpriv->divisor2),
14440a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       &(cmd.convert_arg),
14450a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       cmd.
14460a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral						       flags & TRIG_ROUND_MASK);
1447a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (das1800_set_frequency(dev) < 0) {
1448a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				return -1;
1449a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			}
1450a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1451a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1452a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_TIMER:	/*  in burst mode */
1453a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* set scan frequency */
1454a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8253_cascade_ns_to_timer_2div(TIMER_BASE, &(devpriv->divisor1),
14550a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(devpriv->divisor2),
14560a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       &(cmd.scan_begin_arg),
14570a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					       cmd.flags & TRIG_ROUND_MASK);
1458a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (das1800_set_frequency(dev) < 0) {
1459a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			return -1;
1460a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1461a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1462a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1463a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1464a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1465a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1466a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  setup counter 0 for 'about triggering' */
1467a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_EXT) {
1468a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  load counter 0 in mode 0 */
1469a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		i8254_load(dev->iobase + DAS1800_COUNTER, 0, 0, 1, 0);
1470a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1471a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1472a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1473a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1474a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1475a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* sets up dma */
1476da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void setup_dma(struct comedi_device *dev, struct comedi_cmd cmd)
1477a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1478a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long lock_flags;
1479a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int dual_dma = devpriv->irq_dma_bits & DMA_DUAL;
1480a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1481a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if ((devpriv->irq_dma_bits & DMA_ENABLED) == 0)
1482a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return;
1483a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1484a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* determine a reasonable dma transfer size */
1485a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_transfer_size = suggest_transfer_size(&cmd);
1486a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	lock_flags = claim_dma_lock();
1487a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	disable_dma(devpriv->dma0);
1488a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* clear flip-flop to make sure 2-byte registers for
1489a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * count and address get set correctly */
1490a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	clear_dma_ff(devpriv->dma0);
1491a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_addr(devpriv->dma0, virt_to_bus(devpriv->ai_buf0));
1492a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set appropriate size of transfer */
1493a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	set_dma_count(devpriv->dma0, devpriv->dma_transfer_size);
1494a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current = devpriv->dma0;
1495a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->dma_current_buf = devpriv->ai_buf0;
1496a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	enable_dma(devpriv->dma0);
1497a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set up dual dma if appropriate */
1498a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (dual_dma) {
1499a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		disable_dma(devpriv->dma1);
1500a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* clear flip-flop to make sure 2-byte registers for
1501a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		 * count and address get set correctly */
1502a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		clear_dma_ff(devpriv->dma1);
1503a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_addr(devpriv->dma1, virt_to_bus(devpriv->ai_buf1));
1504a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  set appropriate size of transfer */
1505a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		set_dma_count(devpriv->dma1, devpriv->dma_transfer_size);
1506a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		enable_dma(devpriv->dma1);
1507a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1508a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	release_dma_lock(lock_flags);
1509a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1510a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1511a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1512a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1513a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* programs channel/gain list into card */
1514da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic void program_chanlist(struct comedi_device *dev, struct comedi_cmd cmd)
1515a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1516a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n, chan_range;
1517a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1518a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	const int range_mask = 0x3;	/* masks unipolar/bipolar bit off range */
1519a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	const int range_bitshift = 8;
1520a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1521a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	n = cmd.chanlist_len;
1522a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  spinlock protects indirect addressing */
15235f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1524a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1525a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*set QRAM address start */
1526a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* make channel / gain list */
1527a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (i = 0; i < n; i++) {
1528a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		chan_range =
15290a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    CR_CHAN(cmd.
15300a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    chanlist[i]) | ((CR_RANGE(cmd.chanlist[i]) &
15310a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral					     range_mask) << range_bitshift);
1532a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(chan_range, dev->iobase + DAS1800_QRAM);
1533a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1534a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(n - 1, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
15355f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1536a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1537a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return;
1538a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1539a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1540a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* analog input do_cmd */
15410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_do_cmd(struct comedi_device *dev,
15420a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     struct comedi_subdevice *s)
1543a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1544a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int ret;
1545a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int control_a, control_c;
1546d163679ceec20c50f9aee880fa76c0c1185244a8Bill Pemberton	struct comedi_async *async = s->async;
1547ea6d0d4cab4f4f2d6a88f3bce4707fe92696fd3fBill Pemberton	struct comedi_cmd cmd = async->cmd;
1548a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1549a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (!dev->irq) {
1550a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev,
15510a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			     "no irq assigned for das-1800, cannot do hardware conversions");
1552a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1553a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1554a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1555a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* disable dma on TRIG_WAKE_EOS, or TRIG_RT
1556a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	 * (because dma in handler is unsafe at hard real-time priority) */
1557a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & (TRIG_WAKE_EOS | TRIG_RT)) {
1558a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~DMA_ENABLED;
1559a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1560a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= devpriv->dma_bits;
1561a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1562a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  interrupt on end of conversion for TRIG_WAKE_EOS */
1563a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.flags & TRIG_WAKE_EOS) {
1564a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo not empty */
1565a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits &= ~FIMD;
1566a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	} else {
1567a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  interrupt fifo half full */
1568a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->irq_dma_bits |= FIMD;
1569a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1570a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine how many conversions we need */
1571a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd.stop_src == TRIG_COUNT) {
1572a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->count = cmd.stop_arg * cmd.chanlist_len;
1573a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1574a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1575a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	das1800_cancel(dev, s);
1576a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1577a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  determine proper bits for control registers */
1578a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_a = control_a_bits(cmd);
1579a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	control_c = control_c_bits(cmd);
1580a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1581a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* setup card and start */
1582a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	program_chanlist(dev, cmd);
1583a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	ret = setup_counters(dev, cmd);
1584a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (ret < 0) {
1585a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		comedi_error(dev, "Error setting up counters");
1586a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return ret;
1587a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1588a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	setup_dma(dev, cmd);
1589a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_c, dev->iobase + DAS1800_CONTROL_C);
1590a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set conversion rate and length for burst mode */
1591a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (control_c & BMDE) {
1592a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton		/*  program conversion period with number of microseconds minus 1 */
1593a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.convert_arg / 1000 - 1,
15940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		     dev->iobase + DAS1800_BURST_RATE);
1595a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(cmd.chanlist_len - 1, dev->iobase + DAS1800_BURST_LENGTH);
1596a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1597a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	outb(devpriv->irq_dma_bits, dev->iobase + DAS1800_CONTROL_B);	/*  enable irq/dma */
1598a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(control_a, dev->iobase + DAS1800_CONTROL_A);	/* enable fifo and triggering */
1599a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1600a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1601a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1602a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1603a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1604a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* read analog input */
16050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ai_rinsn(struct comedi_device *dev,
16060a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
16070a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
1608a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1609a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int i, n;
1610a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan, range, aref, chan_range;
1611a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int timeout = 1000;
1612a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short dpnt;
1613a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int conv_flags = 0;
1614a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1615a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1616a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* set up analog reference and unipolar / bipolar mode */
1617a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	aref = CR_AREF(insn->chanspec);
1618a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	conv_flags |= UQEN;
1619a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref != AREF_DIFF)
1620a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= SD;
1621a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (aref == AREF_COMMON)
1622a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= CMEN;
1623a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* if a unipolar range was selected */
1624a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (CR_RANGE(insn->chanspec) & UNIPOLAR)
1625a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		conv_flags |= UB;
1626a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1627a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(conv_flags, dev->iobase + DAS1800_CONTROL_C);	/* software conversion enabled */
1628a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(CVEN, dev->iobase + DAS1800_STATUS);	/* enable conversions */
1629a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_CONTROL_A);	/* reset fifo */
1630a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(FFEN, dev->iobase + DAS1800_CONTROL_A);
1631a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1632a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan = CR_CHAN(insn->chanspec);
1633a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	/* mask of unipolar/bipolar bit from range */
1634a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	range = CR_RANGE(insn->chanspec) & 0x3;
1635a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	chan_range = chan | (range << 8);
16365f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1637a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(QRAM, dev->iobase + DAS1800_SELECT);	/* select QRAM for baseAddress + 0x0 */
1638a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/* set QRAM address start */
1639a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(chan_range, dev->iobase + DAS1800_QRAM);
1640a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(0x0, dev->iobase + DAS1800_QRAM_ADDRESS);	/*finish write to QRAM */
1641a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(ADC, dev->iobase + DAS1800_SELECT);	/* select ADC for baseAddress + 0x0 */
1642a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1643a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	for (n = 0; n < insn->n; n++) {
1644a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* trigger conversion */
1645a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(0, dev->iobase + DAS1800_FIFO);
1646a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		for (i = 0; i < timeout; i++) {
1647a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			if (inb(dev->iobase + DAS1800_STATUS) & FNE)
1648a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess				break;
1649a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1650a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (i == timeout) {
1651a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			comedi_error(dev, "timeout");
1652d18c5906d0914d911a13d342ff61a6bca6aff597Greg Kroah-Hartman			n = -ETIME;
1653d18c5906d0914d911a13d342ff61a6bca6aff597Greg Kroah-Hartman			goto exit;
1654a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		}
1655a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		dpnt = inw(dev->iobase + DAS1800_FIFO);
1656a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		/* shift data to offset binary for bipolar ranges */
1657a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if ((conv_flags & UB) == 0)
1658a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			dpnt += 1 << (thisboard->resolution - 1);
1659a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		data[n] = dpnt;
1660a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1661d18c5906d0914d911a13d342ff61a6bca6aff597Greg Kroah-Hartmanexit:
16625f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1663a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1664a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return n;
1665a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1666a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1667a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to an analog output channel */
16680a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_ao_winsn(struct comedi_device *dev,
16690a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
16700a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
1671a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1672a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int chan = CR_CHAN(insn->chanspec);
1673a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* int range = CR_RANGE(insn->chanspec); */
1674a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int update_chan = thisboard->ao_n_chan - 1;
1675a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	short output;
1676a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned long irq_flags;
1677a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1678a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*   card expects two's complement data */
1679a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	output = data[0] - (1 << (thisboard->resolution - 1));
1680a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if the write is to the 'update' channel, we need to remember its value */
1681a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan == update_chan)
1682a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		devpriv->ao_update_bits = output;
1683a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  write to channel */
16845f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_lock_irqsave(&dev->spinlock, irq_flags);
1685a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(DAC(chan), dev->iobase + DAS1800_SELECT);	/* select dac channel for baseAddress + 0x0 */
1686a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outw(output, dev->iobase + DAS1800_DAC);
1687a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  now we need to write to 'update' channel to update all dac channels */
1688a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (chan != update_chan) {
1689a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outb(DAC(update_chan), dev->iobase + DAS1800_SELECT);	/* select 'update' channel for baseAddress + 0x0 */
1690a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		outw(devpriv->ao_update_bits, dev->iobase + DAS1800_DAC);
1691a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
16925f74ea14c07fee91d3bdbaad88bff6264c6200e6Greg Kroah-Hartman	spin_unlock_irqrestore(&dev->spinlock, irq_flags);
1693a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1694a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 1;
1695a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1696a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1697a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* reads from digital input channels */
16980a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_di_rbits(struct comedi_device *dev,
16990a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
17000a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
1701a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1702a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1703a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = inb(dev->iobase + DAS1800_DIGITAL) & 0xf;
1704a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] = 0;
1705a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1706a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1707a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1708a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1709a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* writes to digital output channels */
17100a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukralstatic int das1800_do_wbits(struct comedi_device *dev,
17110a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_subdevice *s,
17120a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral			    struct comedi_insn *insn, unsigned int *data)
1713a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1714790c55415aa31f4c732729f94d2c3a54f7d3bfc2Bill Pemberton	unsigned int wbits;
1715a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1716a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  only set bits that have been masked */
1717a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[0] &= (1 << s->n_chan) - 1;
1718a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits = devpriv->do_bits;
1719a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits &= ~data[0];
1720a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	wbits |= data[0] & data[1];
1721a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	devpriv->do_bits = wbits;
1722a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1723a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	outb(devpriv->do_bits, dev->iobase + DAS1800_DIGITAL);
1724a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1725a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	data[1] = devpriv->do_bits;
1726a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1727a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 2;
1728a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1729a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1730a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* loads counters with divisor1, divisor2 from private structure */
1731da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic int das1800_set_frequency(struct comedi_device *dev)
1732a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1733a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	int err = 0;
1734a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1735a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 1, mode 2 */
1736a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 1, devpriv->divisor1,
17370a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       2))
1738a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1739a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  counter 2, mode 2 */
1740a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (i8254_load(dev->iobase + DAS1800_COUNTER, 0, 2, devpriv->divisor2,
17410a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		       2))
1742a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		err++;
1743a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (err)
1744a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		return -1;
1745a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1746a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return 0;
1747a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1748a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1749a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess/* converts requested conversion timing to timing compatible with
1750a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess * hardware, used only when card is in 'burst mode'
1751a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess */
1752a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hessstatic unsigned int burst_convert_arg(unsigned int convert_arg, int round_mode)
1753a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1754a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int micro_sec;
1755a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1756a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  in burst mode, the maximum conversion time is 64 microseconds */
1757a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (convert_arg > 64000)
1758a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		convert_arg = 64000;
1759a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1760a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  the conversion time must be an integral number of microseconds */
1761a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (round_mode) {
1762a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_NEAREST:
1763a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1764a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg + 500) / 1000;
1765a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1766a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_DOWN:
1767a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = convert_arg / 1000;
1768a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1769a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_ROUND_UP:
1770a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		micro_sec = (convert_arg - 1) / 1000 + 1;
1771a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1772a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1773a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1774a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  return number of nanoseconds */
1775a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return micro_sec * 1000;
1776a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
1777a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1778a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton/* utility function that suggests a dma transfer size based on the conversion period 'ns' */
1779da91b2692e0939b307f9047192d2b9fe07793e7aBill Pembertonstatic unsigned int suggest_transfer_size(struct comedi_cmd *cmd)
1780a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess{
1781a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	unsigned int size = DMA_BUF_SIZE;
1782a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	static const int sample_size = 2;	/*  size in bytes of one sample from board */
1783a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int fill_time = 300000000;	/*  target time in nanoseconds for filling dma buffer */
1784a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	unsigned int max_size;	/*  maximum size we will allow for a transfer */
1785a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1786a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  make dma buffer fill in 0.3 seconds for timed modes */
1787a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	switch (cmd->scan_begin_src) {
1788a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	case TRIG_FOLLOW:	/*  not in burst mode */
1789a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		if (cmd->convert_src == TRIG_TIMER)
1790a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess			size = (fill_time / cmd->convert_arg) * sample_size;
1791a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1792a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	case TRIG_TIMER:
1793a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = (fill_time / (cmd->scan_begin_arg * cmd->chanlist_len)) *
17940a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral		    sample_size;
1795a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1796a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	default:
1797a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = DMA_BUF_SIZE;
1798a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		break;
1799a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	}
1800a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1801a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  set a minimum and maximum size allowed */
1802a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	max_size = DMA_BUF_SIZE;
1803a351ecf3081f94796cf915dba820f9f5e62c43cfBill Pemberton	/*  if we are taking limited number of conversions, limit transfer size to that */
1804a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (cmd->stop_src == TRIG_COUNT &&
18050a85b6f0ab0d2edb0d41b32697111ce0e4f43496Mithlesh Thukral	    cmd->stop_arg * cmd->chanlist_len * sample_size < max_size)
1806a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		max_size = cmd->stop_arg * cmd->chanlist_len * sample_size;
1807a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1808a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size > max_size)
1809a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = max_size;
1810a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	if (size < sample_size)
1811a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess		size = sample_size;
1812a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess
1813a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess	return size;
1814a69cc3a9fae82f3620d7242fe5bfaedd24b65df5Frank Mori Hess}
181590f703d30dd3e0c16ff80f35e34e511385a05ad5Arun Thomas
181690f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_AUTHOR("Comedi http://www.comedi.org");
181790f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_DESCRIPTION("Comedi low-level driver");
181890f703d30dd3e0c16ff80f35e34e511385a05ad5Arun ThomasMODULE_LICENSE("GPL");
1819