amplc_pci230.c revision 814900c904140cfe7f3e48cabec06b3eec57e0ea
1 /*
2    comedi/drivers/amplc_pci230.c
3    Driver for Amplicon PCI230 and PCI260 Multifunction I/O boards.
4
5    Copyright (C) 2001 Allan Willcox <allanwillcox@ozemail.com.au>
6
7    COMEDI - Linux Control and Measurement Device Interface
8    Copyright (C) 2000 David A. Schleef <ds@schleef.org>
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 2 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program; if not, write to the Free Software
22    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24/*
25Driver: amplc_pci230
26Description: Amplicon PCI230, PCI260 Multifunction I/O boards
27Author: Allan Willcox <allanwillcox@ozemail.com.au>,
28  Steve D Sharples <steve.sharples@nottingham.ac.uk>,
29  Ian Abbott <abbotti@mev.co.uk>
30Updated: Wed, 22 Oct 2008 12:34:49 +0100
31Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
32  PCI230+ (pci230+ or amplc_pci230),
33  PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
34Status: works
35
36Configuration options:
37  [0] - PCI bus of device (optional).
38  [1] - PCI slot of device (optional).
39          If bus/slot is not specified, the first available PCI device
40          will be used.
41
42Configuring a "amplc_pci230" will match any supported card and it will
43choose the best match, picking the "+" models if possible.  Configuring
44a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
45a PCI230.  Configuring a "pci260" will match a PCI260 or PCI260+ card
46and it will be treated as a PCI260.  Configuring a "pci230+" will match
47a PCI230+ card.  Configuring a "pci260+" will match a PCI260+ card.
48
49Subdevices:
50
51                PCI230(+)    PCI260(+)
52                ---------    ---------
53  Subdevices       3            1
54        0          AI           AI
55	1          AO
56	2          DIO
57
58AI Subdevice:
59
60  The AI subdevice has 16 single-ended channels or 8 differential
61  channels.
62
63  The PCI230 and PCI260 cards have 12-bit resolution.  The PCI230+ and
64  PCI260+ cards have 16-bit resolution.
65
66  For differential mode, use inputs 2N and 2N+1 for channel N (e.g. use
67  inputs 14 and 15 for channel 7).  If the card is physically a PCI230
68  or PCI260 then it actually uses a "pseudo-differential" mode where the
69  inputs are sampled a few microseconds apart.  The PCI230+ and PCI260+
70  use true differential sampling.  Another difference is that if the
71  card is physically a PCI230 or PCI260, the inverting input is 2N,
72  whereas for a PCI230+ or PCI260+ the inverting input is 2N+1.  So if a
73  PCI230 is physically replaced by a PCI230+ (or a PCI260 with a
74  PCI260+) and differential mode is used, the differential inputs need
75  to be physically swapped on the connector.
76
77  The following input ranges are supported:
78
79    0 => [-10, +10] V
80    1 => [-5, +5] V
81    2 => [-2.5, +2.5] V
82    3 => [-1.25, +1.25] V
83    4 => [0, 10] V
84    5 => [0, 5] V
85    6 => [0, 2.5] V
86
87AI Commands:
88
89  +=========+==============+===========+============+==========+
90  |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
91  +=========+==============+===========+============+==========+
92  |TRIG_NOW | TRIG_FOLLOW  |TRIG_TIMER | TRIG_COUNT |TRIG_NONE |
93  |TRIG_INT |              |TRIG_EXT(3)|            |TRIG_COUNT|
94  |         |              |TRIG_INT   |            |          |
95  |         |--------------|-----------|            |          |
96  |         | TRIG_TIMER(1)|TRIG_TIMER |            |          |
97  |         | TRIG_EXT(2)  |           |            |          |
98  |         | TRIG_INT     |           |            |          |
99  +---------+--------------+-----------+------------+----------+
100
101  Note 1: If AI command and AO command are used simultaneously, only
102          one may have scan_begin_src == TRIG_TIMER.
103
104  Note 2: For PCI230 and PCI230+, scan_begin_src == TRIG_EXT uses
105          DIO channel 16 (pin 49) which will need to be configured as
106          a digital input.  For PCI260+, the EXTTRIG/EXTCONVCLK input
107          (pin 17) is used instead.  For PCI230, scan_begin_src ==
108          TRIG_EXT is not supported.  The trigger is a rising edge
109          on the input.
110
111  Note 3: For convert_src == TRIG_EXT, the EXTTRIG/EXTCONVCLK input
112          (pin 25 on PCI230(+), pin 17 on PCI260(+)) is used.  The
113          convert_arg value is interpreted as follows:
114
115            convert_arg == (CR_EDGE | 0) => rising edge
116            convert_arg == (CR_EDGE | CR_INVERT | 0) => falling edge
117            convert_arg == 0 => falling edge (backwards compatibility)
118            convert_arg == 1 => rising edge (backwards compatibility)
119
120  All entries in the channel list must use the same analogue reference.
121  If the analogue reference is not AREF_DIFF (not differential) each
122  pair of channel numbers (0 and 1, 2 and 3, etc.) must use the same
123  input range.  The input ranges used in the sequence must be all
124  bipolar (ranges 0 to 3) or all unipolar (ranges 4 to 6).  The channel
125  sequence must consist of 1 or more identical subsequences.  Within the
126  subsequence, channels must be in ascending order with no repeated
127  channels.  For example, the following sequences are valid: 0 1 2 3
128  (single valid subsequence), 0 2 3 5 0 2 3 5 (repeated valid
129  subsequence), 1 1 1 1 (repeated valid subsequence).  The following
130  sequences are invalid: 0 3 2 1 (invalid subsequence), 0 2 3 5 0 2 3
131  (incompletely repeated subsequence).  Some versions of the PCI230+ and
132  PCI260+ have a bug that requires a subsequence longer than one entry
133  long to include channel 0.
134
135AO Subdevice:
136
137  The AO subdevice has 2 channels with 12-bit resolution.
138
139  The following output ranges are supported:
140
141    0 => [0, 10] V
142    1 => [-10, +10] V
143
144AO Commands:
145
146  +=========+==============+===========+============+==========+
147  |start_src|scan_begin_src|convert_src|scan_end_src| stop_src |
148  +=========+==============+===========+============+==========+
149  |TRIG_INT | TRIG_TIMER(1)| TRIG_NOW  | TRIG_COUNT |TRIG_NONE |
150  |         | TRIG_EXT(2)  |           |            |TRIG_COUNT|
151  |         | TRIG_INT     |           |            |          |
152  +---------+--------------+-----------+------------+----------+
153
154  Note 1: If AI command and AO command are used simultaneously, only
155          one may have scan_begin_src == TRIG_TIMER.
156
157  Note 2: scan_begin_src == TRIG_EXT is only supported if the card is
158          configured as a PCI230+ and is only supported on later
159          versions of the card.  As a card configured as a PCI230+ is
160          not guaranteed to support external triggering, please consider
161          this support to be a bonus.  It uses the EXTTRIG/ EXTCONVCLK
162          input (PCI230+ pin 25).  Triggering will be on the rising edge
163          unless the CR_INVERT flag is set in scan_begin_arg.
164
165  The channels in the channel sequence must be in ascending order with
166  no repeats.  All entries in the channel sequence must use the same
167  output range.
168
169DIO Subdevice:
170
171  The DIO subdevice is a 8255 chip providing 24 DIO channels.  The DIO
172  channels are configurable as inputs or outputs in four groups:
173
174    Port A  - channels  0 to  7
175    Port B  - channels  8 to 15
176    Port CL - channels 16 to 19
177    Port CH - channels 20 to 23
178
179  Only mode 0 of the 8255 chip is supported.
180
181  Bit 0 of port C (DIO channel 16) is also used as an external scan
182  trigger input for AI commands on PCI230 and PCI230+, so would need to
183  be configured as an input to use it for that purpose.
184*/
185/*
186Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
187Support for PCI230+/260+, more triggered scan functionality, and workarounds
188for (or detection of) various hardware problems added by Ian Abbott.
189*/
190
191#include "../comedidev.h"
192
193#include <linux/delay.h>
194#include <linux/interrupt.h>
195
196#include "comedi_pci.h"
197#include "8253.h"
198#include "8255.h"
199
200/* PCI230 PCI configuration register information */
201#define PCI_VENDOR_ID_AMPLICON 0x14dc
202#define PCI_DEVICE_ID_PCI230 0x0000
203#define PCI_DEVICE_ID_PCI260 0x0006
204#define PCI_DEVICE_ID_INVALID 0xffff
205
206#define PCI230_IO1_SIZE 32	/* Size of I/O space 1 */
207#define PCI230_IO2_SIZE 16	/* Size of I/O space 2 */
208
209/* PCI230 i/o space 1 registers. */
210#define PCI230_PPI_X_BASE	0x00	/* User PPI (82C55) base */
211#define PCI230_PPI_X_A		0x00	/* User PPI (82C55) port A */
212#define PCI230_PPI_X_B		0x01	/* User PPI (82C55) port B */
213#define PCI230_PPI_X_C		0x02	/* User PPI (82C55) port C */
214#define PCI230_PPI_X_CMD	0x03	/* User PPI (82C55) control word */
215#define PCI230_Z2_CT_BASE	0x14	/* 82C54 counter/timer base */
216#define PCI230_Z2_CT0		0x14	/* 82C54 counter/timer 0 */
217#define PCI230_Z2_CT1		0x15	/* 82C54 counter/timer 1 */
218#define PCI230_Z2_CT2		0x16	/* 82C54 counter/timer 2 */
219#define PCI230_Z2_CTC		0x17	/* 82C54 counter/timer control word */
220#define PCI230_ZCLK_SCE		0x1A	/* Group Z Clock Configuration */
221#define PCI230_ZGAT_SCE		0x1D	/* Group Z Gate Configuration */
222#define PCI230_INT_SCE		0x1E	/* Interrupt source mask (w) */
223#define PCI230_INT_STAT		0x1E	/* Interrupt status (r) */
224
225/* PCI230 i/o space 2 registers. */
226#define PCI230_DACCON		0x00	/* DAC control */
227#define PCI230_DACOUT1		0x02	/* DAC channel 0 (w) */
228#define PCI230_DACOUT2		0x04	/* DAC channel 1 (w) (not FIFO mode) */
229#define PCI230_ADCDATA		0x08	/* ADC data (r) */
230#define PCI230_ADCSWTRIG	0x08	/* ADC software trigger (w) */
231#define PCI230_ADCCON		0x0A	/* ADC control */
232#define PCI230_ADCEN		0x0C	/* ADC channel enable bits */
233#define PCI230_ADCG		0x0E	/* ADC gain control bits */
234/* PCI230+ i/o space 2 additional registers. */
235#define PCI230P_ADCTRIG		0x10	/* ADC start acquisition trigger */
236#define PCI230P_ADCTH		0x12	/* ADC analog trigger threshold */
237#define PCI230P_ADCFFTH		0x14	/* ADC FIFO interrupt threshold */
238#define PCI230P_ADCFFLEV	0x16	/* ADC FIFO level (r) */
239#define PCI230P_ADCPTSC		0x18	/* ADC pre-trigger sample count (r) */
240#define PCI230P_ADCHYST		0x1A	/* ADC analog trigger hysteresys */
241#define PCI230P_EXTFUNC		0x1C	/* Extended functions */
242#define PCI230P_HWVER		0x1E	/* Hardware version (r) */
243/* PCI230+ hardware version 2 onwards. */
244#define PCI230P2_DACDATA	0x02	/* DAC data (FIFO mode) (w) */
245#define PCI230P2_DACSWTRIG	0x02	/* DAC soft trigger (FIFO mode) (r) */
246#define PCI230P2_DACEN		0x06	/* DAC channel enable (FIFO mode) */
247
248/* Convertor related constants. */
249#define PCI230_DAC_SETTLE 5	/* Analogue output settling time in µs */
250				/* (DAC itself is 1µs nominally). */
251#define PCI230_ADC_SETTLE 1	/* Analogue input settling time in µs */
252				/* (ADC itself is 1.6µs nominally but we poll
253				 * anyway). */
254#define PCI230_MUX_SETTLE 10	/* ADC MUX settling time in µS */
255				/* - 10µs for se, 20µs de. */
256
257/* DACCON read-write values. */
258#define PCI230_DAC_OR_UNI		(0<<0)	/* Output range unipolar */
259#define PCI230_DAC_OR_BIP		(1<<0)	/* Output range bipolar */
260#define PCI230_DAC_OR_MASK		(1<<0)
261/* The following applies only if DAC FIFO support is enabled in the EXTFUNC
262 * register (and only for PCI230+ hardware version 2 onwards). */
263#define PCI230P2_DAC_FIFO_EN		(1<<8)	/* FIFO enable */
264/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
265 * hardware version 2 onwards). */
266#define PCI230P2_DAC_TRIG_NONE		(0<<2)	/* No trigger */
267#define PCI230P2_DAC_TRIG_SW		(1<<2)	/* Software trigger trigger */
268#define PCI230P2_DAC_TRIG_EXTP		(2<<2)	/* EXTTRIG +ve edge trigger */
269#define PCI230P2_DAC_TRIG_EXTN		(3<<2)	/* EXTTRIG -ve edge trigger */
270#define PCI230P2_DAC_TRIG_Z2CT0		(4<<2)	/* CT0-OUT +ve edge trigger */
271#define PCI230P2_DAC_TRIG_Z2CT1		(5<<2)	/* CT1-OUT +ve edge trigger */
272#define PCI230P2_DAC_TRIG_Z2CT2		(6<<2)	/* CT2-OUT +ve edge trigger */
273#define PCI230P2_DAC_TRIG_MASK		(7<<2)
274#define PCI230P2_DAC_FIFO_WRAP		(1<<7)	/* FIFO wraparound mode */
275#define PCI230P2_DAC_INT_FIFO_EMPTY	(0<<9)	/* FIFO interrupt empty */
276#define PCI230P2_DAC_INT_FIFO_NEMPTY	(1<<9)
277#define PCI230P2_DAC_INT_FIFO_NHALF	(2<<9)	/* FIFO intr not half full */
278#define PCI230P2_DAC_INT_FIFO_HALF	(3<<9)
279#define PCI230P2_DAC_INT_FIFO_NFULL	(4<<9)	/* FIFO interrupt not full */
280#define PCI230P2_DAC_INT_FIFO_FULL	(5<<9)
281#define PCI230P2_DAC_INT_FIFO_MASK	(7<<9)
282
283/* DACCON read-only values. */
284#define PCI230_DAC_BUSY			(1<<1)	/* DAC busy. */
285/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
286 * hardware version 2 onwards). */
287#define PCI230P2_DAC_FIFO_UNDERRUN_LATCHED	(1<<5)	/* Underrun error */
288#define PCI230P2_DAC_FIFO_EMPTY		(1<<13)	/* FIFO empty */
289#define PCI230P2_DAC_FIFO_FULL		(1<<14)	/* FIFO full */
290#define PCI230P2_DAC_FIFO_HALF		(1<<15)	/* FIFO half full */
291
292/* DACCON write-only, transient values. */
293/* The following apply only if the DAC FIFO is enabled (and only for PCI230+
294 * hardware version 2 onwards). */
295#define PCI230P2_DAC_FIFO_UNDERRUN_CLEAR	(1<<5)	/* Clear underrun */
296#define PCI230P2_DAC_FIFO_RESET		(1<<12)	/* FIFO reset */
297
298/* PCI230+ hardware version 2 DAC FIFO levels. */
299#define PCI230P2_DAC_FIFOLEVEL_HALF	512
300#define PCI230P2_DAC_FIFOLEVEL_FULL	1024
301/* Free space in DAC FIFO. */
302#define PCI230P2_DAC_FIFOROOM_EMPTY		PCI230P2_DAC_FIFOLEVEL_FULL
303#define PCI230P2_DAC_FIFOROOM_ONETOHALF		\
304	(PCI230P2_DAC_FIFOLEVEL_FULL - PCI230P2_DAC_FIFOLEVEL_HALF)
305#define PCI230P2_DAC_FIFOROOM_HALFTOFULL	1
306#define PCI230P2_DAC_FIFOROOM_FULL		0
307
308/* ADCCON read/write values. */
309#define PCI230_ADC_TRIG_NONE		(0<<0)	/* No trigger */
310#define PCI230_ADC_TRIG_SW		(1<<0)	/* Software trigger trigger */
311#define PCI230_ADC_TRIG_EXTP		(2<<0)	/* EXTTRIG +ve edge trigger */
312#define PCI230_ADC_TRIG_EXTN		(3<<0)	/* EXTTRIG -ve edge trigger */
313#define PCI230_ADC_TRIG_Z2CT0		(4<<0)	/* CT0-OUT +ve edge trigger */
314#define PCI230_ADC_TRIG_Z2CT1		(5<<0)	/* CT1-OUT +ve edge trigger */
315#define PCI230_ADC_TRIG_Z2CT2		(6<<0)	/* CT2-OUT +ve edge trigger */
316#define PCI230_ADC_TRIG_MASK		(7<<0)
317#define PCI230_ADC_IR_UNI		(0<<3)	/* Input range unipolar */
318#define PCI230_ADC_IR_BIP		(1<<3)	/* Input range bipolar */
319#define PCI230_ADC_IR_MASK		(1<<3)
320#define PCI230_ADC_IM_SE		(0<<4)	/* Input mode single ended */
321#define PCI230_ADC_IM_DIF		(1<<4)	/* Input mode differential */
322#define PCI230_ADC_IM_MASK		(1<<4)
323#define PCI230_ADC_FIFO_EN		(1<<8)	/* FIFO enable */
324#define PCI230_ADC_INT_FIFO_EMPTY	(0<<9)
325#define PCI230_ADC_INT_FIFO_NEMPTY	(1<<9)	/* FIFO interrupt not empty */
326#define PCI230_ADC_INT_FIFO_NHALF	(2<<9)
327#define PCI230_ADC_INT_FIFO_HALF	(3<<9)	/* FIFO interrupt half full */
328#define PCI230_ADC_INT_FIFO_NFULL	(4<<9)
329#define PCI230_ADC_INT_FIFO_FULL	(5<<9)	/* FIFO interrupt full */
330#define PCI230P_ADC_INT_FIFO_THRESH	(7<<9)	/* FIFO interrupt threshold */
331#define PCI230_ADC_INT_FIFO_MASK	(7<<9)
332
333/* ADCCON write-only, transient values. */
334#define PCI230_ADC_FIFO_RESET		(1<<12)	/* FIFO reset */
335#define PCI230_ADC_GLOB_RESET		(1<<13)	/* Global reset */
336
337/* ADCCON read-only values. */
338#define PCI230_ADC_BUSY			(1<<15)	/* ADC busy */
339#define PCI230_ADC_FIFO_EMPTY		(1<<12)	/* FIFO empty */
340#define PCI230_ADC_FIFO_FULL		(1<<13)	/* FIFO full */
341#define PCI230_ADC_FIFO_HALF		(1<<14)	/* FIFO half full */
342#define PCI230_ADC_FIFO_FULL_LATCHED	(1<<5)	/* Indicates overrun occurred */
343
344/* PCI230 ADC FIFO levels. */
345#define PCI230_ADC_FIFOLEVEL_HALFFULL	2049	/* Value for FIFO half full */
346#define PCI230_ADC_FIFOLEVEL_FULL	4096	/* FIFO size */
347
348/* Value to write to ADCSWTRIG to trigger ADC conversion in software trigger
349 * mode.  Can be anything.  */
350#define PCI230_ADC_CONV			0xffff
351
352/* PCI230+ EXTFUNC values. */
353#define PCI230P_EXTFUNC_GAT_EXTTRIG	(1<<0)
354			/* Route EXTTRIG pin to external gate inputs. */
355/* PCI230+ hardware version 2 values. */
356#define PCI230P2_EXTFUNC_DACFIFO	(1<<1)
357			/* Allow DAC FIFO to be enabled. */
358
359/*
360 * Counter/timer clock input configuration sources.
361 */
362#define CLK_CLK		0	/* reserved (channel-specific clock) */
363#define CLK_10MHZ	1	/* internal 10 MHz clock */
364#define CLK_1MHZ	2	/* internal 1 MHz clock */
365#define CLK_100KHZ	3	/* internal 100 kHz clock */
366#define CLK_10KHZ	4	/* internal 10 kHz clock */
367#define CLK_1KHZ	5	/* internal 1 kHz clock */
368#define CLK_OUTNM1	6	/* output of channel-1 modulo total */
369#define CLK_EXT		7	/* external clock */
370/* Macro to construct clock input configuration register value. */
371#define CLK_CONFIG(chan, src)	((((chan) & 3) << 3) | ((src) & 7))
372/* Timebases in ns. */
373#define TIMEBASE_10MHZ		100
374#define TIMEBASE_1MHZ		1000
375#define TIMEBASE_100KHZ		10000
376#define TIMEBASE_10KHZ		100000
377#define TIMEBASE_1KHZ		1000000
378
379/*
380 * Counter/timer gate input configuration sources.
381 */
382#define GAT_VCC		0	/* VCC (i.e. enabled) */
383#define GAT_GND		1	/* GND (i.e. disabled) */
384#define GAT_EXT		2	/* external gate input (PPCn on PCI230) */
385#define GAT_NOUTNM2	3	/* inverted output of channel-2 modulo total */
386/* Macro to construct gate input configuration register value. */
387#define GAT_CONFIG(chan, src)	((((chan) & 3) << 3) | ((src) & 7))
388
389/*
390 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI230 and PCI260:
391 *
392 *              Channel's       Channel's
393 *              clock input     gate input
394 * Channel      CLK_OUTNM1      GAT_NOUTNM2
395 * -------      ----------      -----------
396 * Z2-CT0       Z2-CT2-OUT      /Z2-CT1-OUT
397 * Z2-CT1       Z2-CT0-OUT      /Z2-CT2-OUT
398 * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
399 */
400
401/* Interrupt enables/status register values. */
402#define PCI230_INT_DISABLE		0
403#define PCI230_INT_PPI_C0		(1<<0)
404#define PCI230_INT_PPI_C3		(1<<1)
405#define PCI230_INT_ADC			(1<<2)
406#define PCI230_INT_ZCLK_CT1		(1<<5)
407/* For PCI230+ hardware version 2 when DAC FIFO enabled. */
408#define PCI230P2_INT_DAC		(1<<4)
409
410#define PCI230_TEST_BIT(val, n)	((val>>n)&1)
411			/* Assumes bits numbered with zero offset, ie. 0-15 */
412
413/* (Potentially) shared resources and their owners */
414enum {
415	RES_Z2CT0,		/* Z2-CT0 */
416	RES_Z2CT1,		/* Z2-CT1 */
417	RES_Z2CT2,		/* Z2-CT2 */
418	NUM_RESOURCES		/* Number of (potentially) shared resources. */
419};
420
421enum {
422	OWNER_NONE,		/* Not owned */
423	OWNER_AICMD,		/* Owned by AI command */
424	OWNER_AOCMD		/* Owned by AO command */
425};
426
427/*
428 * Handy macros.
429 */
430
431/* Combine old and new bits. */
432#define COMBINE(old, new, mask)	(((old) & ~(mask)) | ((new) & (mask)))
433
434/* A generic null function pointer value.  */
435#define NULLFUNC	0
436
437/* Current CPU.  XXX should this be hard_smp_processor_id()? */
438#define THISCPU		smp_processor_id()
439
440/* State flags for atomic bit operations */
441#define AI_CMD_STARTED	0
442#define AO_CMD_STARTED	1
443
444/*
445 * Board descriptions for the two boards supported.
446 */
447
448struct pci230_board {
449	const char *name;
450	unsigned short id;
451	int ai_chans;
452	int ai_bits;
453	int ao_chans;
454	int ao_bits;
455	int have_dio;
456	unsigned int min_hwver;	/* Minimum hardware version supported. */
457};
458static const struct pci230_board pci230_boards[] = {
459	{
460	.name = "pci230+",
461	.id = PCI_DEVICE_ID_PCI230,
462	.ai_chans = 16,
463	.ai_bits = 16,
464	.ao_chans = 2,
465	.ao_bits = 12,
466	.have_dio = 1,
467	.min_hwver = 1,
468		},
469	{
470	.name = "pci260+",
471	.id = PCI_DEVICE_ID_PCI260,
472	.ai_chans = 16,
473	.ai_bits = 16,
474	.ao_chans = 0,
475	.ao_bits = 0,
476	.have_dio = 0,
477	.min_hwver = 1,
478		},
479	{
480	.name = "pci230",
481	.id = PCI_DEVICE_ID_PCI230,
482	.ai_chans = 16,
483	.ai_bits = 12,
484	.ao_chans = 2,
485	.ao_bits = 12,
486	.have_dio = 1,
487		},
488	{
489	.name = "pci260",
490	.id = PCI_DEVICE_ID_PCI260,
491	.ai_chans = 16,
492	.ai_bits = 12,
493	.ao_chans = 0,
494	.ao_bits = 0,
495	.have_dio = 0,
496		},
497	{
498	.name = "amplc_pci230",	/* Wildcard matches any above */
499	.id = PCI_DEVICE_ID_INVALID,
500		},
501};
502
503static DEFINE_PCI_DEVICE_TABLE(pci230_pci_table) = {
504	{PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI230, PCI_ANY_ID, PCI_ANY_ID,
505		0, 0, 0},
506	{PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_PCI260, PCI_ANY_ID, PCI_ANY_ID,
507		0, 0, 0},
508	{0}
509};
510
511MODULE_DEVICE_TABLE(pci, pci230_pci_table);
512/*
513 * Useful for shorthand access to the particular board structure
514 */
515#define n_pci230_boards (sizeof(pci230_boards)/sizeof(pci230_boards[0]))
516#define thisboard ((const struct pci230_board *)dev->board_ptr)
517
518/* this structure is for data unique to this hardware driver.  If
519   several hardware drivers keep similar information in this structure,
520   feel free to suggest moving the variable to the struct comedi_device struct.  */
521struct pci230_private {
522	struct pci_dev *pci_dev;
523	spinlock_t isr_spinlock;	/* Interrupt spin lock */
524	spinlock_t res_spinlock;	/* Shared resources spin lock */
525	spinlock_t ai_stop_spinlock;	/* Spin lock for stopping AI command */
526	spinlock_t ao_stop_spinlock;	/* Spin lock for stopping AO command */
527	unsigned long state;	/* State flags */
528	unsigned long iobase1;	/* PCI230's I/O space 1 */
529	unsigned int ao_readback[2];	/* Used for AO readback */
530	unsigned int ai_scan_count;	/* Number of analogue input scans
531					 * remaining.  */
532	unsigned int ai_scan_pos;	/* Current position within analogue
533					 * input scan */
534	unsigned int ao_scan_count;	/* Number of analogue output scans
535					 * remaining.  */
536	int intr_cpuid;		/* ID of CPU running interrupt routine. */
537	unsigned short hwver;	/* Hardware version (for '+' models). */
538	unsigned short adccon;	/* ADCCON register value. */
539	unsigned short daccon;	/* DACCON register value. */
540	unsigned short adcfifothresh;	/* ADC FIFO programmable interrupt
541					 * level threshold (PCI230+/260+). */
542	unsigned short adcg;	/* ADCG register value. */
543	unsigned char int_en;	/* Interrupt enables bits. */
544	unsigned char ai_continuous;	/* Flag set when cmd->stop_src ==
545					 * TRIG_NONE - user chooses to stop
546					 * continuous conversion by
547					 * cancelation. */
548	unsigned char ao_continuous;	/* Flag set when cmd->stop_src ==
549					 * TRIG_NONE - user chooses to stop
550					 * continuous conversion by
551					 * cancelation. */
552	unsigned char ai_bipolar;	/* Set if bipolar input range so we
553					 * know to mangle it. */
554	unsigned char ao_bipolar;	/* Set if bipolar output range so we
555					 * know to mangle it. */
556	unsigned char ier;	/* Copy of interrupt enables/status register. */
557	unsigned char intr_running;	/* Flag set in interrupt routine. */
558	unsigned char res_owner[NUM_RESOURCES];	/* Shared resource owners. */
559};
560
561#define devpriv ((struct pci230_private *)dev->private)
562
563/* PCI230 clock source periods in ns */
564static const unsigned int pci230_timebase[8] = {
565	[CLK_10MHZ] = TIMEBASE_10MHZ,
566	[CLK_1MHZ] = TIMEBASE_1MHZ,
567	[CLK_100KHZ] = TIMEBASE_100KHZ,
568	[CLK_10KHZ] = TIMEBASE_10KHZ,
569	[CLK_1KHZ] = TIMEBASE_1KHZ,
570};
571
572/* PCI230 analogue input range table */
573static const struct comedi_lrange pci230_ai_range = { 7, {
574			BIP_RANGE(10),
575			BIP_RANGE(5),
576			BIP_RANGE(2.5),
577			BIP_RANGE(1.25),
578			UNI_RANGE(10),
579			UNI_RANGE(5),
580			UNI_RANGE(2.5)
581	}
582};
583
584/* PCI230 analogue gain bits for each input range. */
585static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
586
587/* PCI230 adccon bipolar flag for each analogue input range. */
588static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
589
590/* PCI230 analogue output range table */
591static const struct comedi_lrange pci230_ao_range = { 2, {
592			UNI_RANGE(10),
593			BIP_RANGE(10)
594	}
595};
596
597/* PCI230 daccon bipolar flag for each analogue output range. */
598static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
599
600/*
601 * The struct comedi_driver structure tells the Comedi core module
602 * which functions to call to configure/deconfigure (attach/detach)
603 * the board, and also about the kernel module that contains
604 * the device code.
605 */
606static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it);
607static int pci230_detach(struct comedi_device *dev);
608static struct comedi_driver driver_amplc_pci230 = {
609	.driver_name = "amplc_pci230",
610	.module = THIS_MODULE,
611	.attach = pci230_attach,
612	.detach = pci230_detach,
613	.board_name = &pci230_boards[0].name,
614	.offset = sizeof(pci230_boards[0]),
615	.num_names = sizeof(pci230_boards) / sizeof(pci230_boards[0]),
616};
617
618COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
619
620static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
621	struct comedi_insn *insn, unsigned int *data);
622static int pci230_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
623	struct comedi_insn *insn, unsigned int *data);
624static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
625	struct comedi_insn *insn, unsigned int *data);
626static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
627	unsigned int mode, uint64_t ns, unsigned int round);
628static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
629static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct);
630static irqreturn_t pci230_interrupt(int irq, void *d);
631static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
632	struct comedi_cmd *cmd);
633static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
634static int pci230_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
635static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s);
636static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s);
637static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s);
638static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
639	struct comedi_cmd *cmd);
640static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s);
641static int pci230_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s);
642static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s);
643static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s);
644
645static short pci230_ai_read(struct comedi_device *dev)
646{
647	/* Read sample. */
648	short data = (short) inw(dev->iobase + PCI230_ADCDATA);
649
650	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
651	 * four bits reserved for expansion). */
652	/* PCI230+ is 16 bit AI. */
653	data = data >> (16 - thisboard->ai_bits);
654
655	/* If a bipolar range was specified, mangle it (twos
656	 * complement->straight binary). */
657	if (devpriv->ai_bipolar) {
658		data ^= 1 << (thisboard->ai_bits - 1);
659	}
660	return data;
661}
662
663static inline unsigned short pci230_ao_mangle_datum(struct comedi_device *dev,
664	short datum)
665{
666	/* If a bipolar range was specified, mangle it (straight binary->twos
667	 * complement). */
668	if (devpriv->ao_bipolar) {
669		datum ^= 1 << (thisboard->ao_bits - 1);
670	}
671
672	/* PCI230 is 12 bit - stored in upper bits of 16 bit register (lower
673	 * four bits reserved for expansion). */
674	/* PCI230+ is also 12 bit AO. */
675	datum <<= (16 - thisboard->ao_bits);
676	return (unsigned short)datum;
677}
678
679static inline void pci230_ao_write_nofifo(struct comedi_device *dev, short datum,
680	unsigned int chan)
681{
682	/* Store unmangled datum to be read back later. */
683	devpriv->ao_readback[chan] = datum;
684
685	/* Write mangled datum to appropriate DACOUT register. */
686	outw(pci230_ao_mangle_datum(dev, datum), dev->iobase + (((chan) == 0)
687			? PCI230_DACOUT1 : PCI230_DACOUT2));
688}
689
690static inline void pci230_ao_write_fifo(struct comedi_device *dev, short datum,
691	unsigned int chan)
692{
693	/* Store unmangled datum to be read back later. */
694	devpriv->ao_readback[chan] = datum;
695
696	/* Write mangled datum to appropriate DACDATA register. */
697	outw(pci230_ao_mangle_datum(dev, datum),
698		dev->iobase + PCI230P2_DACDATA);
699}
700
701/*
702 * Attach is called by the Comedi core to configure the driver
703 * for a particular board.  If you specified a board_name array
704 * in the driver structure, dev->board_ptr contains that
705 * address.
706 */
707static int pci230_attach(struct comedi_device *dev, struct comedi_devconfig *it)
708{
709	struct comedi_subdevice *s;
710	unsigned long iobase1, iobase2;
711	/* PCI230's I/O spaces 1 and 2 respectively. */
712	struct pci_dev *pci_dev;
713	int i = 0, irq_hdl, rc;
714
715	printk("comedi%d: amplc_pci230: attach %s %d,%d\n", dev->minor,
716		thisboard->name, it->options[0], it->options[1]);
717
718	/* Allocate the private structure area using alloc_private().
719	 * Macro defined in comedidev.h - memsets struct fields to 0. */
720	if ((alloc_private(dev, sizeof(struct pci230_private))) < 0) {
721		return -ENOMEM;
722	}
723	spin_lock_init(&devpriv->isr_spinlock);
724	spin_lock_init(&devpriv->res_spinlock);
725	spin_lock_init(&devpriv->ai_stop_spinlock);
726	spin_lock_init(&devpriv->ao_stop_spinlock);
727	/* Find card */
728	for (pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, NULL);
729		pci_dev != NULL;
730		pci_dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, pci_dev)) {
731		if (it->options[0] || it->options[1]) {
732			/* Match against bus/slot options. */
733			if (it->options[0] != pci_dev->bus->number ||
734				it->options[1] != PCI_SLOT(pci_dev->devfn))
735				continue;
736		}
737		if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
738			continue;
739		if (thisboard->id == PCI_DEVICE_ID_INVALID) {
740			/* The name was specified as "amplc_pci230" which is
741			 * used to match any supported device.  Replace the
742			 * current dev->board_ptr with one that matches the
743			 * PCI device ID. */
744			for (i = 0; i < n_pci230_boards; i++) {
745				if (pci_dev->device == pci230_boards[i].id) {
746					if (pci230_boards[i].min_hwver > 0) {
747						/* Check for a '+' model.
748						 * First check length of
749						 * registers. */
750						if (pci_resource_len(pci_dev, 3)
751							< 32) {
752							/* Not a '+' model. */
753							continue;
754						}
755						/* TODO: temporarily enable the
756						 * PCI device and read the
757						 * hardware version register.
758						 * For now assume it's okay. */
759					}
760					/* Change board_ptr to matched board */
761					dev->board_ptr = &pci230_boards[i];
762					break;
763				}
764			}
765			if (i < n_pci230_boards)
766				break;
767		} else {
768			/* The name was specified as a specific device name.
769			 * The current dev->board_ptr is correct.  Check
770			 * whether it matches the PCI device ID. */
771			if (thisboard->id == pci_dev->device) {
772				/* Check minimum hardware version. */
773				if (thisboard->min_hwver > 0) {
774					/* Looking for a '+' model.  First
775					 * check length of registers. */
776					if (pci_resource_len(pci_dev, 3) < 32) {
777						/* Not a '+' model. */
778						continue;
779					}
780					/* TODO: temporarily enable the PCI
781					 * device and read the hardware version
782					 * register.  For now, assume it's
783					 * okay. */
784					break;
785				} else {
786					break;
787				}
788			}
789		}
790	}
791	if (!pci_dev) {
792		printk("comedi%d: No %s card found\n", dev->minor,
793			thisboard->name);
794		return -EIO;
795	}
796	devpriv->pci_dev = pci_dev;
797
798	/*
799	 * Initialize dev->board_name.
800	 */
801	dev->board_name = thisboard->name;
802
803	/* Enable PCI device and reserve I/O spaces. */
804	if (comedi_pci_enable(pci_dev, "amplc_pci230") < 0) {
805		printk("comedi%d: failed to enable PCI device "
806			"and request regions\n", dev->minor);
807		return -EIO;
808	}
809
810	/* Read base addresses of the PCI230's two I/O regions from PCI
811	 * configuration register. */
812	iobase1 = pci_resource_start(pci_dev, 2);
813	iobase2 = pci_resource_start(pci_dev, 3);
814
815	printk("comedi%d: %s I/O region 1 0x%04lx I/O region 2 0x%04lx\n",
816		dev->minor, dev->board_name, iobase1, iobase2);
817
818	devpriv->iobase1 = iobase1;
819	dev->iobase = iobase2;
820
821	/* Read bits of DACCON register - only the output range. */
822	devpriv->daccon = inw(dev->iobase + PCI230_DACCON) & PCI230_DAC_OR_MASK;
823
824	/* Read hardware version register and set extended function register
825	 * if they exist. */
826	if (pci_resource_len(pci_dev, 3) >= 32) {
827		unsigned short extfunc = 0;
828
829		devpriv->hwver = inw(dev->iobase + PCI230P_HWVER);
830		if (devpriv->hwver < thisboard->min_hwver) {
831			printk("comedi%d: %s - bad hardware version "
832				"- got %u, need %u\n", dev->minor,
833				dev->board_name, devpriv->hwver,
834				thisboard->min_hwver);
835			return -EIO;
836		}
837		if (devpriv->hwver > 0) {
838			if (!thisboard->have_dio) {
839				/* No DIO ports.  Route counters' external gates
840				 * to the EXTTRIG signal (PCI260+ pin 17).
841				 * (Otherwise, they would be routed to DIO
842				 * inputs PC0, PC1 and PC2 which don't exist
843				 * on PCI260[+].) */
844				extfunc |= PCI230P_EXTFUNC_GAT_EXTTRIG;
845			}
846			if ((thisboard->ao_chans > 0)
847				&& (devpriv->hwver >= 2)) {
848				/* Enable DAC FIFO functionality. */
849				extfunc |= PCI230P2_EXTFUNC_DACFIFO;
850			}
851		}
852		outw(extfunc, dev->iobase + PCI230P_EXTFUNC);
853		if ((extfunc & PCI230P2_EXTFUNC_DACFIFO) != 0) {
854			/* Temporarily enable DAC FIFO, reset it and disable
855			 * FIFO wraparound. */
856			outw(devpriv->daccon | PCI230P2_DAC_FIFO_EN
857				| PCI230P2_DAC_FIFO_RESET,
858				dev->iobase + PCI230_DACCON);
859			/* Clear DAC FIFO channel enable register. */
860			outw(0, dev->iobase + PCI230P2_DACEN);
861			/* Disable DAC FIFO. */
862			outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
863		}
864	}
865
866	/* Disable board's interrupts. */
867	outb(0, devpriv->iobase1 + PCI230_INT_SCE);
868
869	/* Set ADC to a reasonable state. */
870	devpriv->adcg = 0;
871	devpriv->adccon = PCI230_ADC_TRIG_NONE | PCI230_ADC_IM_SE
872		| PCI230_ADC_IR_BIP;
873	outw(1 << 0, dev->iobase + PCI230_ADCEN);
874	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
875	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
876		dev->iobase + PCI230_ADCCON);
877
878	/* Register the interrupt handler. */
879	irq_hdl = comedi_request_irq(devpriv->pci_dev->irq, pci230_interrupt,
880		IRQF_SHARED, "amplc_pci230", dev);
881	if (irq_hdl < 0) {
882		printk("comedi%d: unable to register irq, "
883			"commands will not be available %d\n", dev->minor,
884			devpriv->pci_dev->irq);
885	} else {
886		dev->irq = devpriv->pci_dev->irq;
887		printk("comedi%d: registered irq %u\n", dev->minor,
888			devpriv->pci_dev->irq);
889	}
890
891	/*
892	 * Allocate the subdevice structures.  alloc_subdevice() is a
893	 * convenient macro defined in comedidev.h.
894	 */
895	if (alloc_subdevices(dev, 3) < 0)
896		return -ENOMEM;
897
898	s = dev->subdevices + 0;
899	/* analog input subdevice */
900	s->type = COMEDI_SUBD_AI;
901	s->subdev_flags = SDF_READABLE | SDF_DIFF | SDF_GROUND;
902	s->n_chan = thisboard->ai_chans;
903	s->maxdata = (1 << thisboard->ai_bits) - 1;
904	s->range_table = &pci230_ai_range;
905	s->insn_read = &pci230_ai_rinsn;
906	s->len_chanlist = 256;	/* but there are restrictions. */
907	/* Only register commands if the interrupt handler is installed. */
908	if (irq_hdl == 0) {
909		dev->read_subdev = s;
910		s->subdev_flags |= SDF_CMD_READ;
911		s->do_cmd = &pci230_ai_cmd;
912		s->do_cmdtest = &pci230_ai_cmdtest;
913		s->cancel = pci230_ai_cancel;
914	}
915
916	s = dev->subdevices + 1;
917	/* analog output subdevice */
918	if (thisboard->ao_chans > 0) {
919		s->type = COMEDI_SUBD_AO;
920		s->subdev_flags = SDF_WRITABLE | SDF_GROUND;
921		s->n_chan = thisboard->ao_chans;;
922		s->maxdata = (1 << thisboard->ao_bits) - 1;
923		s->range_table = &pci230_ao_range;
924		s->insn_write = &pci230_ao_winsn;
925		s->insn_read = &pci230_ao_rinsn;
926		s->len_chanlist = thisboard->ao_chans;
927		/* Only register commands if the interrupt handler is
928		 * installed. */
929		if (irq_hdl == 0) {
930			dev->write_subdev = s;
931			s->subdev_flags |= SDF_CMD_WRITE;
932			s->do_cmd = &pci230_ao_cmd;
933			s->do_cmdtest = &pci230_ao_cmdtest;
934			s->cancel = pci230_ao_cancel;
935		}
936	} else {
937		s->type = COMEDI_SUBD_UNUSED;
938	}
939
940	s = dev->subdevices + 2;
941	/* digital i/o subdevice */
942	if (thisboard->have_dio) {
943		rc = subdev_8255_init(dev, s, NULL,
944			(devpriv->iobase1 + PCI230_PPI_X_BASE));
945		if (rc < 0)
946			return rc;
947	} else {
948		s->type = COMEDI_SUBD_UNUSED;
949	}
950
951	printk("comedi%d: attached\n", dev->minor);
952
953	return 1;
954}
955
956/*
957 * _detach is called to deconfigure a device.  It should deallocate
958 * resources.
959 * This function is also called when _attach() fails, so it should be
960 * careful not to release resources that were not necessarily
961 * allocated by _attach().  dev->private and dev->subdevices are
962 * deallocated automatically by the core.
963 */
964static int pci230_detach(struct comedi_device *dev)
965{
966	printk("comedi%d: amplc_pci230: remove\n", dev->minor);
967
968	if (dev->subdevices && thisboard->have_dio)
969		/* Clean up dio subdevice. */
970		subdev_8255_cleanup(dev, dev->subdevices + 2);
971
972	if (dev->irq)
973		comedi_free_irq(dev->irq, dev);
974
975	if (devpriv) {
976		if (devpriv->pci_dev) {
977			if (dev->iobase) {
978				comedi_pci_disable(devpriv->pci_dev);
979			}
980			pci_dev_put(devpriv->pci_dev);
981		}
982	}
983
984	return 0;
985}
986
987static int get_resources(struct comedi_device *dev, unsigned int res_mask,
988	unsigned char owner)
989{
990	int ok;
991	unsigned int i;
992	unsigned int b;
993	unsigned int claimed;
994	unsigned long irqflags;
995
996	ok = 1;
997	claimed = 0;
998	comedi_spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
999	for (b = 1, i = 0; (i < NUM_RESOURCES)
1000		&& (res_mask != 0); b <<= 1, i++) {
1001		if ((res_mask & b) != 0) {
1002			res_mask &= ~b;
1003			if (devpriv->res_owner[i] == OWNER_NONE) {
1004				devpriv->res_owner[i] = owner;
1005				claimed |= b;
1006			} else if (devpriv->res_owner[i] != owner) {
1007				for (b = 1, i = 0; claimed != 0; b <<= 1, i++) {
1008					if ((claimed & b) != 0) {
1009						devpriv->res_owner[i]
1010							= OWNER_NONE;
1011						claimed &= ~b;
1012					}
1013				}
1014				ok = 0;
1015				break;
1016			}
1017		}
1018	}
1019	comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1020	return ok;
1021}
1022
1023static inline int get_one_resource(struct comedi_device *dev, unsigned int resource,
1024	unsigned char owner)
1025{
1026	return get_resources(dev, (1U << resource), owner);
1027}
1028
1029static void put_resources(struct comedi_device *dev, unsigned int res_mask,
1030	unsigned char owner)
1031{
1032	unsigned int i;
1033	unsigned int b;
1034	unsigned long irqflags;
1035
1036	comedi_spin_lock_irqsave(&devpriv->res_spinlock, irqflags);
1037	for (b = 1, i = 0; (i < NUM_RESOURCES)
1038		&& (res_mask != 0); b <<= 1, i++) {
1039		if ((res_mask & b) != 0) {
1040			res_mask &= ~b;
1041			if (devpriv->res_owner[i] == owner) {
1042				devpriv->res_owner[i] = OWNER_NONE;
1043			}
1044		}
1045	}
1046	comedi_spin_unlock_irqrestore(&devpriv->res_spinlock, irqflags);
1047}
1048
1049static inline void put_one_resource(struct comedi_device *dev, unsigned int resource,
1050	unsigned char owner)
1051{
1052	put_resources(dev, (1U << resource), owner);
1053}
1054
1055static inline void put_all_resources(struct comedi_device *dev, unsigned char owner)
1056{
1057	put_resources(dev, (1U << NUM_RESOURCES) - 1, owner);
1058}
1059
1060/*
1061 *  COMEDI_SUBD_AI instruction;
1062 */
1063static int pci230_ai_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1064	struct comedi_insn *insn, unsigned int *data)
1065{
1066	unsigned int n, i;
1067	unsigned int chan, range, aref;
1068	unsigned int gainshift;
1069	unsigned int status;
1070	unsigned short adccon, adcen;
1071
1072	/* Unpack channel and range. */
1073	chan = CR_CHAN(insn->chanspec);
1074	range = CR_RANGE(insn->chanspec);
1075	aref = CR_AREF(insn->chanspec);
1076	if (aref == AREF_DIFF) {
1077		/* Differential. */
1078		if (chan >= s->n_chan / 2) {
1079			DPRINTK("comedi%d: amplc_pci230: ai_rinsn: "
1080				"differential channel number out of range "
1081				"0 to %u\n", dev->minor, (s->n_chan / 2) - 1);
1082			return -EINVAL;
1083		}
1084	}
1085
1086	/* Use Z2-CT2 as a conversion trigger instead of the built-in
1087	 * software trigger, as otherwise triggering of differential channels
1088	 * doesn't work properly for some versions of PCI230/260.  Also set
1089	 * FIFO mode because the ADC busy bit only works for software triggers.
1090	 */
1091	adccon = PCI230_ADC_TRIG_Z2CT2 | PCI230_ADC_FIFO_EN;
1092	/* Set Z2-CT2 output low to avoid any false triggers. */
1093	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE0);
1094	devpriv->ai_bipolar = pci230_ai_bipolar[range];
1095	if (aref == AREF_DIFF) {
1096		/* Differential. */
1097		gainshift = chan * 2;
1098		if (devpriv->hwver == 0) {
1099			/* Original PCI230/260 expects both inputs of the
1100			 * differential channel to be enabled. */
1101			adcen = 3 << gainshift;
1102		} else {
1103			/* PCI230+/260+ expects only one input of the
1104			 * differential channel to be enabled. */
1105			adcen = 1 << gainshift;
1106		}
1107		adccon |= PCI230_ADC_IM_DIF;
1108	} else {
1109		/* Single ended. */
1110		adcen = 1 << chan;
1111		gainshift = chan & ~1;
1112		adccon |= PCI230_ADC_IM_SE;
1113	}
1114	devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
1115		| (pci230_ai_gain[range] << gainshift);
1116	if (devpriv->ai_bipolar) {
1117		adccon |= PCI230_ADC_IR_BIP;
1118	} else {
1119		adccon |= PCI230_ADC_IR_UNI;
1120	}
1121
1122	/* Enable only this channel in the scan list - otherwise by default
1123	 * we'll get one sample from each channel. */
1124	outw(adcen, dev->iobase + PCI230_ADCEN);
1125
1126	/* Set gain for channel. */
1127	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
1128
1129	/* Specify uni/bip, se/diff, conversion source, and reset FIFO. */
1130	devpriv->adccon = adccon;
1131	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
1132
1133	/* Convert n samples */
1134	for (n = 0; n < insn->n; n++) {
1135		/* Trigger conversion by toggling Z2-CT2 output (finish with
1136		 * output high). */
1137		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1138			I8254_MODE0);
1139		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
1140			I8254_MODE1);
1141
1142#define TIMEOUT 100
1143		/* wait for conversion to end */
1144		for (i = 0; i < TIMEOUT; i++) {
1145			status = inw(dev->iobase + PCI230_ADCCON);
1146			if (!(status & PCI230_ADC_FIFO_EMPTY))
1147				break;
1148			comedi_udelay(1);
1149		}
1150		if (i == TIMEOUT) {
1151			/* rt_printk() should be used instead of printk()
1152			 * whenever the code can be called from real-time. */
1153			rt_printk("timeout\n");
1154			return -ETIMEDOUT;
1155		}
1156
1157		/* read data */
1158		data[n] = pci230_ai_read(dev);
1159	}
1160
1161	/* return the number of samples read/written */
1162	return n;
1163}
1164
1165/*
1166 *  COMEDI_SUBD_AO instructions;
1167 */
1168static int pci230_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
1169	struct comedi_insn *insn, unsigned int *data)
1170{
1171	int i;
1172	int chan, range;
1173
1174	/* Unpack channel and range. */
1175	chan = CR_CHAN(insn->chanspec);
1176	range = CR_RANGE(insn->chanspec);
1177
1178	/* Set range - see analogue output range table; 0 => unipolar 10V,
1179	 * 1 => bipolar +/-10V range scale */
1180	devpriv->ao_bipolar = pci230_ao_bipolar[range];
1181	outw(range, dev->iobase + PCI230_DACCON);
1182
1183	/* Writing a list of values to an AO channel is probably not
1184	 * very useful, but that's how the interface is defined. */
1185	for (i = 0; i < insn->n; i++) {
1186		/* Write value to DAC and store it. */
1187		pci230_ao_write_nofifo(dev, data[i], chan);
1188	}
1189
1190	/* return the number of samples read/written */
1191	return i;
1192}
1193
1194/* AO subdevices should have a read insn as well as a write insn.
1195 * Usually this means copying a value stored in devpriv. */
1196static int pci230_ao_rinsn(struct comedi_device *dev, struct comedi_subdevice *s,
1197	struct comedi_insn *insn, unsigned int *data)
1198{
1199	int i;
1200	int chan = CR_CHAN(insn->chanspec);
1201
1202	for (i = 0; i < insn->n; i++)
1203		data[i] = devpriv->ao_readback[chan];
1204
1205	return i;
1206}
1207
1208static int pci230_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1209	struct comedi_cmd *cmd)
1210{
1211	int err = 0;
1212	unsigned int tmp;
1213
1214	/* cmdtest tests a particular command to see if it is valid.
1215	 * Using the cmdtest ioctl, a user can create a valid cmd
1216	 * and then have it executes by the cmd ioctl.
1217	 *
1218	 * cmdtest returns 1,2,3,4 or 0, depending on which tests
1219	 * the command passes. */
1220
1221	/* Step 1: make sure trigger sources are trivially valid.
1222	 * "invalid source" returned by comedilib to user mode process
1223	 * if this fails. */
1224
1225	tmp = cmd->start_src;
1226	cmd->start_src &= TRIG_INT;
1227	if (!cmd->start_src || tmp != cmd->start_src)
1228		err++;
1229
1230	tmp = cmd->scan_begin_src;
1231	if ((thisboard->min_hwver > 0) && (devpriv->hwver >= 2)) {
1232		/*
1233		 * For PCI230+ hardware version 2 onwards, allow external
1234		 * trigger from EXTTRIG/EXTCONVCLK input (PCI230+ pin 25).
1235		 *
1236		 * FIXME: The permitted scan_begin_src values shouldn't depend
1237		 * on devpriv->hwver (the detected card's actual hardware
1238		 * version).  They should only depend on thisboard->min_hwver
1239		 * (the static capabilities of the configured card).  To fix
1240		 * it, a new card model, e.g. "pci230+2" would have to be
1241		 * defined with min_hwver set to 2.  It doesn't seem worth it
1242		 * for this alone.  At the moment, please consider
1243		 * scan_begin_src==TRIG_EXT support to be a bonus rather than a
1244		 * guarantee!
1245		 */
1246		cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1247	} else {
1248		cmd->scan_begin_src &= TRIG_TIMER | TRIG_INT;
1249	}
1250	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1251		err++;
1252
1253	tmp = cmd->convert_src;
1254	cmd->convert_src &= TRIG_NOW;
1255	if (!cmd->convert_src || tmp != cmd->convert_src)
1256		err++;
1257
1258	tmp = cmd->scan_end_src;
1259	cmd->scan_end_src &= TRIG_COUNT;
1260	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1261		err++;
1262
1263	tmp = cmd->stop_src;
1264	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1265	if (!cmd->stop_src || tmp != cmd->stop_src)
1266		err++;
1267
1268	if (err)
1269		return 1;
1270
1271	/* Step 2: make sure trigger sources are unique and mutually compatible
1272	 * "source conflict" returned by comedilib to user mode process
1273	 * if this fails. */
1274
1275	/* these tests are true if more than one _src bit is set */
1276	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1277		err++;
1278	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1279		err++;
1280	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1281		err++;
1282	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1283		err++;
1284	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1285		err++;
1286
1287	if (err)
1288		return 2;
1289
1290	/* Step 3: make sure arguments are trivially compatible.
1291	 * "invalid argument" returned by comedilib to user mode process
1292	 * if this fails. */
1293
1294	if (cmd->start_arg != 0) {
1295		cmd->start_arg = 0;
1296		err++;
1297	}
1298#define MAX_SPEED_AO	8000	/* 8000 ns => 125 kHz */
1299#define MIN_SPEED_AO	4294967295u	/* 4294967295ns = 4.29s */
1300			/*- Comedi limit due to unsigned int cmd.  Driver limit
1301			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1302			 * clock) = 65.536s */
1303
1304	switch (cmd->scan_begin_src) {
1305	case TRIG_TIMER:
1306		if (cmd->scan_begin_arg < MAX_SPEED_AO) {
1307			cmd->scan_begin_arg = MAX_SPEED_AO;
1308			err++;
1309		}
1310		if (cmd->scan_begin_arg > MIN_SPEED_AO) {
1311			cmd->scan_begin_arg = MIN_SPEED_AO;
1312			err++;
1313		}
1314		break;
1315	case TRIG_EXT:
1316		/* External trigger - for PCI230+ hardware version 2 onwards. */
1317		/* Trigger number must be 0. */
1318		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1319			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1320				~CR_FLAGS_MASK);
1321			err++;
1322		}
1323		/* The only flags allowed are CR_EDGE and CR_INVERT.  The
1324		 * CR_EDGE flag is ignored. */
1325		if ((cmd->scan_begin_arg
1326				& (CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT))) !=
1327			0) {
1328			cmd->scan_begin_arg =
1329				COMBINE(cmd->scan_begin_arg, 0,
1330				CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
1331			err++;
1332		}
1333		break;
1334	default:
1335		if (cmd->scan_begin_arg != 0) {
1336			cmd->scan_begin_arg = 0;
1337			err++;
1338		}
1339		break;
1340	}
1341
1342	if (cmd->scan_end_arg != cmd->chanlist_len) {
1343		cmd->scan_end_arg = cmd->chanlist_len;
1344		err++;
1345	}
1346	if (cmd->stop_src == TRIG_NONE) {
1347		/* TRIG_NONE */
1348		if (cmd->stop_arg != 0) {
1349			cmd->stop_arg = 0;
1350			err++;
1351		}
1352	}
1353
1354	if (err)
1355		return 3;
1356
1357	/* Step 4: fix up any arguments.
1358	 * "argument conflict" returned by comedilib to user mode process
1359	 * if this fails. */
1360
1361	if (cmd->scan_begin_src == TRIG_TIMER) {
1362		tmp = cmd->scan_begin_arg;
1363		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1364			cmd->flags & TRIG_ROUND_MASK);
1365		if (tmp != cmd->scan_begin_arg)
1366			err++;
1367	}
1368
1369	if (err)
1370		return 4;
1371
1372	/* Step 5: check channel list if it exists. */
1373
1374	if (cmd->chanlist && cmd->chanlist_len > 0) {
1375		enum {
1376			seq_err = (1 << 0),
1377			range_err = (1 << 1)
1378		};
1379		unsigned int errors;
1380		unsigned int n;
1381		unsigned int chan, prev_chan;
1382		unsigned int range, first_range;
1383
1384		prev_chan = CR_CHAN(cmd->chanlist[0]);
1385		first_range = CR_RANGE(cmd->chanlist[0]);
1386		errors = 0;
1387		for (n = 1; n < cmd->chanlist_len; n++) {
1388			chan = CR_CHAN(cmd->chanlist[n]);
1389			range = CR_RANGE(cmd->chanlist[n]);
1390			/* Channel numbers must strictly increase. */
1391			if (chan < prev_chan) {
1392				errors |= seq_err;
1393			}
1394			/* Ranges must be the same. */
1395			if (range != first_range) {
1396				errors |= range_err;
1397			}
1398			prev_chan = chan;
1399		}
1400		if (errors != 0) {
1401			err++;
1402			if ((errors & seq_err) != 0) {
1403				DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1404					"channel numbers must increase\n",
1405					dev->minor);
1406			}
1407			if ((errors & range_err) != 0) {
1408				DPRINTK("comedi%d: amplc_pci230: ao_cmdtest: "
1409					"channels must have the same range\n",
1410					dev->minor);
1411			}
1412		}
1413	}
1414
1415	if (err)
1416		return 5;
1417
1418	return 0;
1419}
1420
1421static int pci230_ao_inttrig_scan_begin(struct comedi_device *dev,
1422	struct comedi_subdevice *s, unsigned int trig_num)
1423{
1424	unsigned long irqflags;
1425
1426	if (trig_num != 0)
1427		return -EINVAL;
1428
1429	comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
1430	if (test_bit(AO_CMD_STARTED, &devpriv->state)) {
1431		/* Perform scan. */
1432		if (devpriv->hwver < 2) {
1433			/* Not using DAC FIFO. */
1434			comedi_spin_unlock_irqrestore(&devpriv->
1435				ao_stop_spinlock, irqflags);
1436			pci230_handle_ao_nofifo(dev, s);
1437			comedi_event(dev, s);
1438		} else {
1439			/* Using DAC FIFO. */
1440			/* Read DACSWTRIG register to trigger conversion. */
1441			inw(dev->iobase + PCI230P2_DACSWTRIG);
1442			comedi_spin_unlock_irqrestore(&devpriv->
1443				ao_stop_spinlock, irqflags);
1444		}
1445		/* Delay.  Should driver be responsible for this? */
1446		/* XXX TODO: See if DAC busy bit can be used. */
1447		comedi_udelay(8);
1448	}
1449
1450	return 1;
1451}
1452
1453static void pci230_ao_start(struct comedi_device *dev, struct comedi_subdevice *s)
1454{
1455	struct comedi_async *async = s->async;
1456	struct comedi_cmd *cmd = &async->cmd;
1457	unsigned long irqflags;
1458
1459	set_bit(AO_CMD_STARTED, &devpriv->state);
1460	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1461		/* An empty acquisition! */
1462		async->events |= COMEDI_CB_EOA;
1463		pci230_ao_stop(dev, s);
1464		comedi_event(dev, s);
1465	} else {
1466		if (devpriv->hwver >= 2) {
1467			/* Using DAC FIFO. */
1468			unsigned short scantrig;
1469			int run;
1470
1471			/* Preload FIFO data. */
1472			run = pci230_handle_ao_fifo(dev, s);
1473			comedi_event(dev, s);
1474			if (!run) {
1475				/* Stopped. */
1476				return;
1477			}
1478			/* Set scan trigger source. */
1479			switch (cmd->scan_begin_src) {
1480			case TRIG_TIMER:
1481				scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1482				break;
1483			case TRIG_EXT:
1484				/* Trigger on EXTTRIG/EXTCONVCLK pin. */
1485				if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1486					/* +ve edge */
1487					scantrig = PCI230P2_DAC_TRIG_EXTP;
1488				} else {
1489					/* -ve edge */
1490					scantrig = PCI230P2_DAC_TRIG_EXTN;
1491				}
1492				break;
1493			case TRIG_INT:
1494				scantrig = PCI230P2_DAC_TRIG_SW;
1495				break;
1496			default:
1497				/* Shouldn't get here. */
1498				scantrig = PCI230P2_DAC_TRIG_NONE;
1499				break;
1500			}
1501			devpriv->daccon = (devpriv->daccon
1502				& ~PCI230P2_DAC_TRIG_MASK) | scantrig;
1503			outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1504
1505		}
1506		switch (cmd->scan_begin_src) {
1507		case TRIG_TIMER:
1508			if (devpriv->hwver < 2) {
1509				/* Not using DAC FIFO. */
1510				/* Enable CT1 timer interrupt. */
1511				comedi_spin_lock_irqsave(&devpriv->isr_spinlock,
1512					irqflags);
1513				devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1514				devpriv->ier |= PCI230_INT_ZCLK_CT1;
1515				outb(devpriv->ier,
1516					devpriv->iobase1 + PCI230_INT_SCE);
1517				comedi_spin_unlock_irqrestore(&devpriv->
1518					isr_spinlock, irqflags);
1519			}
1520			/* Set CT1 gate high to start counting. */
1521			outb(GAT_CONFIG(1, GAT_VCC),
1522				devpriv->iobase1 + PCI230_ZGAT_SCE);
1523			break;
1524		case TRIG_INT:
1525			async->inttrig = pci230_ao_inttrig_scan_begin;
1526			break;
1527		}
1528		if (devpriv->hwver >= 2) {
1529			/* Using DAC FIFO.  Enable DAC FIFO interrupt. */
1530			comedi_spin_lock_irqsave(&devpriv->isr_spinlock,
1531				irqflags);
1532			devpriv->int_en |= PCI230P2_INT_DAC;
1533			devpriv->ier |= PCI230P2_INT_DAC;
1534			outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1535			comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock,
1536				irqflags);
1537		}
1538	}
1539}
1540
1541static int pci230_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
1542	unsigned int trig_num)
1543{
1544	if (trig_num != 0)
1545		return -EINVAL;
1546
1547	s->async->inttrig = NULLFUNC;
1548	pci230_ao_start(dev, s);
1549
1550	return 1;
1551}
1552
1553static int pci230_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
1554{
1555	unsigned short daccon;
1556	unsigned int range;
1557
1558	/* Get the command. */
1559	struct comedi_cmd *cmd = &s->async->cmd;
1560
1561	if (cmd->scan_begin_src == TRIG_TIMER) {
1562		/* Claim Z2-CT1. */
1563		if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD)) {
1564			return -EBUSY;
1565		}
1566	}
1567
1568	/* Get number of scans required. */
1569	if (cmd->stop_src == TRIG_COUNT) {
1570		devpriv->ao_scan_count = cmd->stop_arg;
1571		devpriv->ao_continuous = 0;
1572	} else {
1573		/* TRIG_NONE, user calls cancel. */
1574		devpriv->ao_scan_count = 0;
1575		devpriv->ao_continuous = 1;
1576	}
1577
1578	/* Set range - see analogue output range table; 0 => unipolar 10V,
1579	 * 1 => bipolar +/-10V range scale */
1580	range = CR_RANGE(cmd->chanlist[0]);
1581	devpriv->ao_bipolar = pci230_ao_bipolar[range];
1582	daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1583	/* Use DAC FIFO for hardware version 2 onwards. */
1584	if (devpriv->hwver >= 2) {
1585		unsigned short dacen;
1586		unsigned int i;
1587
1588		dacen = 0;
1589		for (i = 0; i < cmd->chanlist_len; i++) {
1590			dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1591		}
1592		/* Set channel scan list. */
1593		outw(dacen, dev->iobase + PCI230P2_DACEN);
1594		/*
1595		 * Enable DAC FIFO.
1596		 * Set DAC scan source to 'none'.
1597		 * Set DAC FIFO interrupt trigger level to 'not half full'.
1598		 * Reset DAC FIFO and clear underrun.
1599		 *
1600		 * N.B. DAC FIFO interrupts are currently disabled.
1601		 */
1602		daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1603			| PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1604			| PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1605	}
1606
1607	/* Set DACCON. */
1608	outw(daccon, dev->iobase + PCI230_DACCON);
1609	/* Preserve most of DACCON apart from write-only, transient bits. */
1610	devpriv->daccon = daccon
1611		& ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1612
1613	if (cmd->scan_begin_src == TRIG_TIMER) {
1614		/* Set the counter timer 1 to the specified scan frequency. */
1615		/* cmd->scan_begin_arg is sampling period in ns */
1616		/* gate it off for now. */
1617		outb(GAT_CONFIG(1, GAT_GND),
1618			devpriv->iobase1 + PCI230_ZGAT_SCE);
1619		pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1620			cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
1621	}
1622
1623	/* N.B. cmd->start_src == TRIG_INT */
1624	s->async->inttrig = pci230_ao_inttrig_start;
1625
1626	return 0;
1627}
1628
1629static int pci230_ai_check_scan_period(struct comedi_cmd *cmd)
1630{
1631	unsigned int min_scan_period, chanlist_len;
1632	int err = 0;
1633
1634	chanlist_len = cmd->chanlist_len;
1635	if (cmd->chanlist_len == 0) {
1636		chanlist_len = 1;
1637	}
1638	min_scan_period = chanlist_len * cmd->convert_arg;
1639	if ((min_scan_period < chanlist_len)
1640		|| (min_scan_period < cmd->convert_arg)) {
1641		/* Arithmetic overflow. */
1642		min_scan_period = UINT_MAX;
1643		err++;
1644	}
1645	if (cmd->scan_begin_arg < min_scan_period) {
1646		cmd->scan_begin_arg = min_scan_period;
1647		err++;
1648	}
1649
1650	return !err;
1651}
1652
1653static int pci230_ai_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
1654	struct comedi_cmd *cmd)
1655{
1656	int err = 0;
1657	unsigned int tmp;
1658
1659	/* cmdtest tests a particular command to see if it is valid.
1660	 * Using the cmdtest ioctl, a user can create a valid cmd
1661	 * and then have it executes by the cmd ioctl.
1662	 *
1663	 * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
1664	 * the command passes. */
1665
1666	/* Step 1: make sure trigger sources are trivially valid.
1667	 * "invalid source" returned by comedilib to user mode process
1668	 * if this fails. */
1669
1670	tmp = cmd->start_src;
1671	cmd->start_src &= TRIG_NOW | TRIG_INT;
1672	if (!cmd->start_src || tmp != cmd->start_src)
1673		err++;
1674
1675	tmp = cmd->scan_begin_src;
1676	/* Unfortunately, we cannot trigger a scan off an external source
1677	 * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
1678	 * isn't present on the PCI260.  For PCI260+ we can use the
1679	 * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
1680	if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1681		cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
1682			| TRIG_EXT;
1683	} else {
1684		cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1685	}
1686	if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1687		err++;
1688
1689	tmp = cmd->convert_src;
1690	cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1691	if (!cmd->convert_src || tmp != cmd->convert_src)
1692		err++;
1693
1694	tmp = cmd->scan_end_src;
1695	cmd->scan_end_src &= TRIG_COUNT;
1696	if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1697		err++;
1698
1699	tmp = cmd->stop_src;
1700	cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1701	if (!cmd->stop_src || tmp != cmd->stop_src)
1702		err++;
1703
1704	if (err)
1705		return 1;
1706
1707	/* Step 2: make sure trigger sources are unique and mutually compatible
1708	 * "source conflict" returned by comedilib to user mode process
1709	 * if this fails. */
1710
1711	/* these tests are true if more than one _src bit is set */
1712	if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1713		err++;
1714	if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1715		err++;
1716	if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1717		err++;
1718	if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1719		err++;
1720	if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1721		err++;
1722
1723	/* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1724	 * set up to generate a fixed number of timed conversion pulses. */
1725	if ((cmd->scan_begin_src != TRIG_FOLLOW)
1726		&& (cmd->convert_src != TRIG_TIMER))
1727		err++;
1728
1729	if (err)
1730		return 2;
1731
1732	/* Step 3: make sure arguments are trivially compatible.
1733	 * "invalid argument" returned by comedilib to user mode process
1734	 * if this fails. */
1735
1736	if (cmd->start_arg != 0) {
1737		cmd->start_arg = 0;
1738		err++;
1739	}
1740#define MAX_SPEED_AI_SE		3200	/* PCI230 SE:   3200 ns => 312.5 kHz */
1741#define MAX_SPEED_AI_DIFF	8000	/* PCI230 DIFF: 8000 ns => 125 kHz */
1742#define MAX_SPEED_AI_PLUS	4000	/* PCI230+:     4000 ns => 250 kHz */
1743#define MIN_SPEED_AI	4294967295u	/* 4294967295ns = 4.29s */
1744			/*- Comedi limit due to unsigned int cmd.  Driver limit
1745			 * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1746			 * clock) = 65.536s */
1747
1748	if (cmd->convert_src == TRIG_TIMER) {
1749		unsigned int max_speed_ai;
1750
1751		if (devpriv->hwver == 0) {
1752			/* PCI230 or PCI260.  Max speed depends whether
1753			 * single-ended or pseudo-differential. */
1754			if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1755				/* Peek analogue reference of first channel. */
1756				if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
1757					max_speed_ai = MAX_SPEED_AI_DIFF;
1758				} else {
1759					max_speed_ai = MAX_SPEED_AI_SE;
1760				}
1761			} else {
1762				/* No channel list.  Assume single-ended. */
1763				max_speed_ai = MAX_SPEED_AI_SE;
1764			}
1765		} else {
1766			/* PCI230+ or PCI260+. */
1767			max_speed_ai = MAX_SPEED_AI_PLUS;
1768		}
1769
1770		if (cmd->convert_arg < max_speed_ai) {
1771			cmd->convert_arg = max_speed_ai;
1772			err++;
1773		}
1774		if (cmd->convert_arg > MIN_SPEED_AI) {
1775			cmd->convert_arg = MIN_SPEED_AI;
1776			err++;
1777		}
1778	} else if (cmd->convert_src == TRIG_EXT) {
1779		/*
1780		 * external trigger
1781		 *
1782		 * convert_arg == (CR_EDGE | 0)
1783		 *                => trigger on +ve edge.
1784		 * convert_arg == (CR_EDGE | CR_INVERT | 0)
1785		 *                => trigger on -ve edge.
1786		 */
1787		if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1788			/* Trigger number must be 0. */
1789			if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1790				cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1791					~CR_FLAGS_MASK);
1792				err++;
1793			}
1794			/* The only flags allowed are CR_INVERT and CR_EDGE.
1795			 * CR_EDGE is required. */
1796			if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1797				!= CR_EDGE) {
1798				/* Set CR_EDGE, preserve CR_INVERT. */
1799				cmd->convert_arg =
1800					COMBINE(cmd->start_arg, (CR_EDGE | 0),
1801					CR_FLAGS_MASK & ~CR_INVERT);
1802				err++;
1803			}
1804		} else {
1805			/* Backwards compatibility with previous versions. */
1806			/* convert_arg == 0 => trigger on -ve edge. */
1807			/* convert_arg == 1 => trigger on +ve edge. */
1808			if (cmd->convert_arg > 1) {
1809				/* Default to trigger on +ve edge. */
1810				cmd->convert_arg = 1;
1811				err++;
1812			}
1813		}
1814	} else {
1815		if (cmd->convert_arg != 0) {
1816			cmd->convert_arg = 0;
1817			err++;
1818		}
1819	}
1820
1821	if (cmd->scan_end_arg != cmd->chanlist_len) {
1822		cmd->scan_end_arg = cmd->chanlist_len;
1823		err++;
1824	}
1825
1826	if (cmd->stop_src == TRIG_NONE) {
1827		if (cmd->stop_arg != 0) {
1828			cmd->stop_arg = 0;
1829			err++;
1830		}
1831	}
1832
1833	if (cmd->scan_begin_src == TRIG_EXT) {
1834		/* external "trigger" to begin each scan
1835		 * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1836		 * of CT2 (sample convert trigger is CT2) */
1837		if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1838			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1839				~CR_FLAGS_MASK);
1840			err++;
1841		}
1842		/* The only flag allowed is CR_EDGE, which is ignored. */
1843		if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1844			cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1845				CR_FLAGS_MASK & ~CR_EDGE);
1846			err++;
1847		}
1848	} else if (cmd->scan_begin_src == TRIG_TIMER) {
1849		/* N.B. cmd->convert_arg is also TRIG_TIMER */
1850		if (!pci230_ai_check_scan_period(cmd)) {
1851			err++;
1852		}
1853	} else {
1854		if (cmd->scan_begin_arg != 0) {
1855			cmd->scan_begin_arg = 0;
1856			err++;
1857		}
1858	}
1859
1860	if (err)
1861		return 3;
1862
1863	/* Step 4: fix up any arguments.
1864	 * "argument conflict" returned by comedilib to user mode process
1865	 * if this fails. */
1866
1867	if (cmd->convert_src == TRIG_TIMER) {
1868		tmp = cmd->convert_arg;
1869		pci230_ns_to_single_timer(&cmd->convert_arg,
1870			cmd->flags & TRIG_ROUND_MASK);
1871		if (tmp != cmd->convert_arg)
1872			err++;
1873	}
1874
1875	if (cmd->scan_begin_src == TRIG_TIMER) {
1876		/* N.B. cmd->convert_arg is also TRIG_TIMER */
1877		tmp = cmd->scan_begin_arg;
1878		pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1879			cmd->flags & TRIG_ROUND_MASK);
1880		if (!pci230_ai_check_scan_period(cmd)) {
1881			/* Was below minimum required.  Round up. */
1882			pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1883				TRIG_ROUND_UP);
1884			pci230_ai_check_scan_period(cmd);
1885		}
1886		if (tmp != cmd->scan_begin_arg)
1887			err++;
1888	}
1889
1890	if (err)
1891		return 4;
1892
1893	/* Step 5: check channel list if it exists. */
1894
1895	if (cmd->chanlist && cmd->chanlist_len > 0) {
1896		enum {
1897			seq_err = 1 << 0,
1898			rangepair_err = 1 << 1,
1899			polarity_err = 1 << 2,
1900			aref_err = 1 << 3,
1901			diffchan_err = 1 << 4,
1902			buggy_chan0_err = 1 << 5
1903		};
1904		unsigned int errors;
1905		unsigned int chan, prev_chan;
1906		unsigned int range, prev_range;
1907		unsigned int polarity, prev_polarity;
1908		unsigned int aref, prev_aref;
1909		unsigned int subseq_len;
1910		unsigned int n;
1911
1912		subseq_len = 0;
1913		errors = 0;
1914		prev_chan = prev_aref = prev_range = prev_polarity = 0;
1915		for (n = 0; n < cmd->chanlist_len; n++) {
1916			chan = CR_CHAN(cmd->chanlist[n]);
1917			range = CR_RANGE(cmd->chanlist[n]);
1918			aref = CR_AREF(cmd->chanlist[n]);
1919			polarity = pci230_ai_bipolar[range];
1920			/* Only the first half of the channels are available if
1921			 * differential.  (These are remapped in software.  In
1922			 * hardware, only the even channels are available.) */
1923			if ((aref == AREF_DIFF)
1924				&& (chan >= (s->n_chan / 2))) {
1925				errors |= diffchan_err;
1926			}
1927			if (n > 0) {
1928				/* Channel numbers must strictly increase or
1929				 * subsequence must repeat exactly. */
1930				if ((chan <= prev_chan)
1931					&& (subseq_len == 0)) {
1932					subseq_len = n;
1933				}
1934				if ((subseq_len > 0)
1935					&& (cmd->chanlist[n] !=
1936						cmd->chanlist[n %
1937							subseq_len])) {
1938					errors |= seq_err;
1939				}
1940				/* Channels must have same AREF. */
1941				if (aref != prev_aref) {
1942					errors |= aref_err;
1943				}
1944				/* Channel ranges must have same polarity. */
1945				if (polarity != prev_polarity) {
1946					errors |= polarity_err;
1947				}
1948				/* Single-ended channel pairs must have same
1949				 * range.  */
1950				if ((aref != AREF_DIFF)
1951					&& (((chan ^ prev_chan) & ~1) == 0)
1952					&& (range != prev_range)) {
1953					errors |= rangepair_err;
1954				}
1955			}
1956			prev_chan = chan;
1957			prev_range = range;
1958			prev_aref = aref;
1959			prev_polarity = polarity;
1960		}
1961		if (subseq_len == 0) {
1962			/* Subsequence is whole sequence. */
1963			subseq_len = n;
1964		}
1965		/* If channel list is a repeating subsequence, need a whole
1966		 * number of repeats. */
1967		if ((n % subseq_len) != 0) {
1968			errors |= seq_err;
1969		}
1970		if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1971			/*
1972			 * Buggy PCI230+ or PCI260+ requires channel 0 to be
1973			 * (first) in the sequence if the sequence contains
1974			 * more than one channel.  Hardware versions 1 and 2
1975			 * have the bug.  There is no hardware version 3.
1976			 *
1977			 * Actually, there are two firmwares that report
1978			 * themselves as hardware version 1 (the boards
1979			 * have different ADC chips with slightly different
1980			 * timing requirements, which was supposed to be
1981			 * invisible to software).  The first one doesn't
1982			 * seem to have the bug, but the second one
1983			 * does, and we can't tell them apart!
1984			 */
1985			if ((subseq_len > 1)
1986				&& (CR_CHAN(cmd->chanlist[0]) != 0)) {
1987				errors |= buggy_chan0_err;
1988			}
1989		}
1990		if (errors != 0) {
1991			err++;
1992			if ((errors & seq_err) != 0) {
1993				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1994					"channel numbers must increase or "
1995					"sequence must repeat exactly\n",
1996					dev->minor);
1997			}
1998			if ((errors & rangepair_err) != 0) {
1999				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2000					"single-ended channel pairs must "
2001					"have the same range\n", dev->minor);
2002			}
2003			if ((errors & polarity_err) != 0) {
2004				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2005					"channel sequence ranges must be all "
2006					"bipolar or all unipolar\n",
2007					dev->minor);
2008			}
2009			if ((errors & aref_err) != 0) {
2010				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2011					"channel sequence analogue references "
2012					"must be all the same (single-ended "
2013					"or differential)\n", dev->minor);
2014			}
2015			if ((errors & diffchan_err) != 0) {
2016				DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2017					"differential channel number out of "
2018					"range 0 to %u\n", dev->minor,
2019					(s->n_chan / 2) - 1);
2020			}
2021			if ((errors & buggy_chan0_err) != 0) {
2022				/* Use printk instead of DPRINTK here. */
2023				printk("comedi: comedi%d: amplc_pci230: "
2024					"ai_cmdtest: Buggy PCI230+/260+ "
2025					"h/w version %u requires first channel "
2026					"of multi-channel sequence to be 0 "
2027					"(corrected in h/w version 4)\n",
2028					dev->minor, devpriv->hwver);
2029			}
2030		}
2031	}
2032
2033	if (err)
2034		return 5;
2035
2036	return 0;
2037}
2038
2039static void pci230_ai_update_fifo_trigger_level(struct comedi_device *dev,
2040	struct comedi_subdevice *s)
2041{
2042	struct comedi_cmd *cmd = &s->async->cmd;
2043	unsigned int scanlen = cmd->scan_end_arg;
2044	unsigned int wake;
2045	unsigned short triglev;
2046	unsigned short adccon;
2047
2048	if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
2049		/* Wake at end of scan. */
2050		wake = scanlen - devpriv->ai_scan_pos;
2051	} else {
2052		if (devpriv->ai_continuous
2053			|| (devpriv->ai_scan_count
2054				>= PCI230_ADC_FIFOLEVEL_HALFFULL)
2055			|| (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2056			wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
2057		} else {
2058			wake = (devpriv->ai_scan_count * scanlen)
2059				- devpriv->ai_scan_pos;
2060		}
2061	}
2062	if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
2063		triglev = PCI230_ADC_INT_FIFO_HALF;
2064	} else {
2065		if ((wake > 1) && (devpriv->hwver > 0)) {
2066			/* PCI230+/260+ programmable FIFO interrupt level. */
2067			if (devpriv->adcfifothresh != wake) {
2068				devpriv->adcfifothresh = wake;
2069				outw(wake, dev->iobase + PCI230P_ADCFFTH);
2070			}
2071			triglev = PCI230P_ADC_INT_FIFO_THRESH;
2072		} else {
2073			triglev = PCI230_ADC_INT_FIFO_NEMPTY;
2074		}
2075	}
2076	adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
2077	if (adccon != devpriv->adccon) {
2078		devpriv->adccon = adccon;
2079		outw(adccon, dev->iobase + PCI230_ADCCON);
2080	}
2081}
2082
2083static int pci230_ai_inttrig_convert(struct comedi_device *dev, struct comedi_subdevice *s,
2084	unsigned int trig_num)
2085{
2086	unsigned long irqflags;
2087
2088	if (trig_num != 0)
2089		return -EINVAL;
2090
2091	comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2092	if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2093		unsigned int delayus;
2094
2095		/* Trigger conversion by toggling Z2-CT2 output.  Finish
2096		 * with output high. */
2097		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2098			I8254_MODE0);
2099		i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2100			I8254_MODE1);
2101		/* Delay.  Should driver be responsible for this?  An
2102		 * alternative would be to wait until conversion is complete,
2103		 * but we can't tell when it's complete because the ADC busy
2104		 * bit has a different meaning when FIFO enabled (and when
2105		 * FIFO not enabled, it only works for software triggers). */
2106		if (((devpriv->adccon & PCI230_ADC_IM_MASK)
2107				== PCI230_ADC_IM_DIF)
2108			&& (devpriv->hwver == 0)) {
2109			/* PCI230/260 in differential mode */
2110			delayus = 8;
2111		} else {
2112			/* single-ended or PCI230+/260+ */
2113			delayus = 4;
2114		}
2115		comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock,
2116			irqflags);
2117		comedi_udelay(delayus);
2118	} else {
2119		comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock,
2120			irqflags);
2121	}
2122
2123	return 1;
2124}
2125
2126static int pci230_ai_inttrig_scan_begin(struct comedi_device *dev,
2127	struct comedi_subdevice *s, unsigned int trig_num)
2128{
2129	unsigned long irqflags;
2130	unsigned char zgat;
2131
2132	if (trig_num != 0)
2133		return -EINVAL;
2134
2135	comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2136	if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2137		/* Trigger scan by waggling CT0 gate source. */
2138		zgat = GAT_CONFIG(0, GAT_GND);
2139		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2140		zgat = GAT_CONFIG(0, GAT_VCC);
2141		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2142	}
2143	comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2144
2145	return 1;
2146}
2147
2148static void pci230_ai_start(struct comedi_device *dev, struct comedi_subdevice *s)
2149{
2150	unsigned long irqflags;
2151	unsigned short conv;
2152	struct comedi_async *async = s->async;
2153	struct comedi_cmd *cmd = &async->cmd;
2154
2155	set_bit(AI_CMD_STARTED, &devpriv->state);
2156	if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2157		/* An empty acquisition! */
2158		async->events |= COMEDI_CB_EOA;
2159		pci230_ai_stop(dev, s);
2160		comedi_event(dev, s);
2161	} else {
2162		/* Enable ADC FIFO trigger level interrupt. */
2163		comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2164		devpriv->int_en |= PCI230_INT_ADC;
2165		devpriv->ier |= PCI230_INT_ADC;
2166		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2167		comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2168
2169		/* Update conversion trigger source which is currently set
2170		 * to CT2 output, which is currently stuck high. */
2171		switch (cmd->convert_src) {
2172		default:
2173			conv = PCI230_ADC_TRIG_NONE;
2174			break;
2175		case TRIG_TIMER:
2176			/* Using CT2 output. */
2177			conv = PCI230_ADC_TRIG_Z2CT2;
2178			break;
2179		case TRIG_EXT:
2180			if ((cmd->convert_arg & CR_EDGE) != 0) {
2181				if ((cmd->convert_arg & CR_INVERT) == 0) {
2182					/* Trigger on +ve edge. */
2183					conv = PCI230_ADC_TRIG_EXTP;
2184				} else {
2185					/* Trigger on -ve edge. */
2186					conv = PCI230_ADC_TRIG_EXTN;
2187				}
2188			} else {
2189				/* Backwards compatibility. */
2190				if (cmd->convert_arg != 0) {
2191					/* Trigger on +ve edge. */
2192					conv = PCI230_ADC_TRIG_EXTP;
2193				} else {
2194					/* Trigger on -ve edge. */
2195					conv = PCI230_ADC_TRIG_EXTN;
2196				}
2197			}
2198			break;
2199		case TRIG_INT:
2200			/* Use CT2 output for software trigger due to problems
2201			 * in differential mode on PCI230/260. */
2202			conv = PCI230_ADC_TRIG_Z2CT2;
2203			break;
2204		}
2205		devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2206			| conv;
2207		outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2208		if (cmd->convert_src == TRIG_INT) {
2209			async->inttrig = pci230_ai_inttrig_convert;
2210		}
2211		/* Update FIFO interrupt trigger level, which is currently
2212		 * set to "full".  */
2213		pci230_ai_update_fifo_trigger_level(dev, s);
2214		if (cmd->convert_src == TRIG_TIMER) {
2215			/* Update timer gates. */
2216			unsigned char zgat;
2217
2218			if (cmd->scan_begin_src != TRIG_FOLLOW) {
2219				/* Conversion timer CT2 needs to be gated by
2220				 * inverted output of monostable CT2. */
2221				zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2222			} else {
2223				/* Conversion timer CT2 needs to be gated on
2224				 * continuously. */
2225				zgat = GAT_CONFIG(2, GAT_VCC);
2226			}
2227			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2228			if (cmd->scan_begin_src != TRIG_FOLLOW) {
2229				/* Set monostable CT0 trigger source. */
2230				switch (cmd->scan_begin_src) {
2231				default:
2232					zgat = GAT_CONFIG(0, GAT_VCC);
2233					break;
2234				case TRIG_EXT:
2235					/*
2236					 * For CT0 on PCI230, the external
2237					 * trigger (gate) signal comes from
2238					 * PPC0, which is channel 16 of the DIO
2239					 * subdevice.  The application needs to
2240					 * configure this as an input in order
2241					 * to use it as an external scan
2242					 * trigger.
2243					 */
2244					zgat = GAT_CONFIG(0, GAT_EXT);
2245					break;
2246				case TRIG_TIMER:
2247					/*
2248					 * Monostable CT0 triggered by rising
2249					 * edge on inverted output of CT1
2250					 * (falling edge on CT1).
2251					 */
2252					zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2253					break;
2254				case TRIG_INT:
2255					/*
2256					 * Monostable CT0 is triggered by
2257					 * inttrig function waggling the CT0
2258					 * gate source.
2259					 */
2260					zgat = GAT_CONFIG(0, GAT_VCC);
2261					break;
2262				}
2263				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2264				switch (cmd->scan_begin_src) {
2265				case TRIG_TIMER:
2266					/* Scan period timer CT1 needs to be
2267					 * gated on to start counting. */
2268					zgat = GAT_CONFIG(1, GAT_VCC);
2269					outb(zgat, devpriv->iobase1
2270						+ PCI230_ZGAT_SCE);
2271					break;
2272				case TRIG_INT:
2273					async->inttrig =
2274						pci230_ai_inttrig_scan_begin;
2275					break;
2276				}
2277			}
2278		} else if (cmd->convert_src != TRIG_INT) {
2279			/* No longer need Z2-CT2. */
2280			put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2281		}
2282	}
2283}
2284
2285static int pci230_ai_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
2286	unsigned int trig_num)
2287{
2288	if (trig_num != 0)
2289		return -EINVAL;
2290
2291	s->async->inttrig = NULLFUNC;
2292	pci230_ai_start(dev, s);
2293
2294	return 1;
2295}
2296
2297static int pci230_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
2298{
2299	unsigned int i, chan, range, diff;
2300	unsigned int res_mask;
2301	unsigned short adccon, adcen;
2302	unsigned char zgat;
2303
2304	/* Get the command. */
2305	struct comedi_async *async = s->async;
2306	struct comedi_cmd *cmd = &async->cmd;
2307
2308	/*
2309	 * Determine which shared resources are needed.
2310	 */
2311	res_mask = 0;
2312	/* Need Z2-CT2 to supply a conversion trigger source at a high
2313	 * logic level, even if not doing timed conversions. */
2314	res_mask |= (1U << RES_Z2CT2);
2315	if (cmd->scan_begin_src != TRIG_FOLLOW) {
2316		/* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2317		res_mask |= (1U << RES_Z2CT0);
2318		if (cmd->scan_begin_src == TRIG_TIMER) {
2319			/* Using Z2-CT1 for scan frequency */
2320			res_mask |= (1U << RES_Z2CT1);
2321		}
2322	}
2323	/* Claim resources. */
2324	if (!get_resources(dev, res_mask, OWNER_AICMD)) {
2325		return -EBUSY;
2326	}
2327
2328	/* Get number of scans required. */
2329	if (cmd->stop_src == TRIG_COUNT) {
2330		devpriv->ai_scan_count = cmd->stop_arg;
2331		devpriv->ai_continuous = 0;
2332	} else {
2333		/* TRIG_NONE, user calls cancel. */
2334		devpriv->ai_scan_count = 0;
2335		devpriv->ai_continuous = 1;
2336	}
2337	devpriv->ai_scan_pos = 0;	/* Position within scan. */
2338
2339	/* Steps;
2340	 * - Set channel scan list.
2341	 * - Set channel gains.
2342	 * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2343	 *   start conversion source to point to something at a high logic
2344	 *   level (we use the output of counter/timer 2 for this purpose.
2345	 * - PAUSE to allow things to settle down.
2346	 * - Reset the FIFO again because it needs resetting twice and there
2347	 *   may have been a false conversion trigger on some versions of
2348	 *   PCI230/260 due to the start conversion source being set to a
2349	 *   high logic level.
2350	 * - Enable ADC FIFO level interrupt.
2351	 * - Set actual conversion trigger source and FIFO interrupt trigger
2352	 *   level.
2353	 * - If convert_src is TRIG_TIMER, set up the timers.
2354	 */
2355
2356	adccon = PCI230_ADC_FIFO_EN;
2357	adcen = 0;
2358
2359	if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2360		/* Differential - all channels must be differential. */
2361		diff = 1;
2362		adccon |= PCI230_ADC_IM_DIF;
2363	} else {
2364		/* Single ended - all channels must be single-ended. */
2365		diff = 0;
2366		adccon |= PCI230_ADC_IM_SE;
2367	}
2368
2369	range = CR_RANGE(cmd->chanlist[0]);
2370	devpriv->ai_bipolar = pci230_ai_bipolar[range];
2371	if (devpriv->ai_bipolar) {
2372		adccon |= PCI230_ADC_IR_BIP;
2373	} else {
2374		adccon |= PCI230_ADC_IR_UNI;
2375	}
2376	for (i = 0; i < cmd->chanlist_len; i++) {
2377		unsigned int gainshift;
2378
2379		chan = CR_CHAN(cmd->chanlist[i]);
2380		range = CR_RANGE(cmd->chanlist[i]);
2381		if (diff) {
2382			gainshift = 2 * chan;
2383			if (devpriv->hwver == 0) {
2384				/* Original PCI230/260 expects both inputs of
2385				 * the differential channel to be enabled. */
2386				adcen |= 3 << gainshift;
2387			} else {
2388				/* PCI230+/260+ expects only one input of the
2389				 * differential channel to be enabled. */
2390				adcen |= 1 << gainshift;
2391			}
2392		} else {
2393			gainshift = (chan & ~1);
2394			adcen |= 1 << chan;
2395		}
2396		devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2397			| (pci230_ai_gain[range] << gainshift);
2398	}
2399
2400	/* Set channel scan list. */
2401	outw(adcen, dev->iobase + PCI230_ADCEN);
2402
2403	/* Set channel gains. */
2404	outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2405
2406	/* Set counter/timer 2 output high for use as the initial start
2407	 * conversion source. */
2408	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2409
2410	/* Temporarily use CT2 output as conversion trigger source and
2411	 * temporarily set FIFO interrupt trigger level to 'full'. */
2412	adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2413
2414	/* Enable and reset FIFO, specify FIFO trigger level full, specify
2415	 * uni/bip, se/diff, and temporarily set the start conversion source
2416	 * to CT2 output.  Note that CT2 output is currently high, and this
2417	 * will produce a false conversion trigger on some versions of the
2418	 * PCI230/260, but that will be dealt with later. */
2419	devpriv->adccon = adccon;
2420	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2421
2422	/* Delay */
2423	/* Failure to include this will result in the first few channels'-worth
2424	 * of data being corrupt, normally manifesting itself by large negative
2425	 * voltages. It seems the board needs time to settle between the first
2426	 * FIFO reset (above) and the second FIFO reset (below). Setting the
2427	 * channel gains and scan list _before_ the first FIFO reset also
2428	 * helps, though only slightly. */
2429	comedi_udelay(25);
2430
2431	/* Reset FIFO again. */
2432	outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2433
2434	if (cmd->convert_src == TRIG_TIMER) {
2435		/* Set up CT2 as conversion timer, but gate it off for now.
2436		 * Note, counter/timer output 2 can be monitored on the
2437		 * connector: PCI230 pin 21, PCI260 pin 18. */
2438		zgat = GAT_CONFIG(2, GAT_GND);
2439		outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2440		/* Set counter/timer 2 to the specified conversion period. */
2441		pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2442			cmd->flags & TRIG_ROUND_MASK);
2443		if (cmd->scan_begin_src != TRIG_FOLLOW) {
2444			/*
2445			 * Set up monostable on CT0 output for scan timing.  A
2446			 * rising edge on the trigger (gate) input of CT0 will
2447			 * trigger the monostable, causing its output to go low
2448			 * for the configured period.  The period depends on
2449			 * the conversion period and the number of conversions
2450			 * in the scan.
2451			 *
2452			 * Set the trigger high before setting up the
2453			 * monostable to stop it triggering.  The trigger
2454			 * source will be changed later.
2455			 */
2456			zgat = GAT_CONFIG(0, GAT_VCC);
2457			outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2458			pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2459				((uint64_t) cmd->convert_arg
2460					* cmd->scan_end_arg), TRIG_ROUND_UP);
2461			if (cmd->scan_begin_src == TRIG_TIMER) {
2462				/*
2463				 * Monostable on CT0 will be triggered by
2464				 * output of CT1 at configured scan frequency.
2465				 *
2466				 * Set up CT1 but gate it off for now.
2467				 */
2468				zgat = GAT_CONFIG(1, GAT_GND);
2469				outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2470				pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2471					cmd->scan_begin_arg,
2472					cmd->flags & TRIG_ROUND_MASK);
2473			}
2474		}
2475	}
2476
2477	if (cmd->start_src == TRIG_INT) {
2478		s->async->inttrig = pci230_ai_inttrig_start;
2479	} else {
2480		/* TRIG_NOW */
2481		pci230_ai_start(dev, s);
2482	}
2483
2484	return 0;
2485}
2486
2487static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
2488	unsigned int round_mode)
2489{
2490	uint64_t div;
2491	unsigned int rem;
2492
2493	div = ns;
2494	rem = do_div(div, timebase);
2495	round_mode &= TRIG_ROUND_MASK;
2496	switch (round_mode) {
2497	default:
2498	case TRIG_ROUND_NEAREST:
2499		div += (rem + (timebase / 2)) / timebase;
2500		break;
2501	case TRIG_ROUND_DOWN:
2502		break;
2503	case TRIG_ROUND_UP:
2504		div += (rem + timebase - 1) / timebase;
2505		break;
2506	}
2507	return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
2508}
2509
2510/* Given desired period in ns, returns the required internal clock source
2511 * and gets the initial count. */
2512static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
2513	unsigned int round_mode)
2514{
2515	unsigned int clk_src, cnt;
2516
2517	for (clk_src = CLK_10MHZ;; clk_src++) {
2518		cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
2519		if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) {
2520			break;
2521		}
2522	}
2523	*count = cnt;
2524	return clk_src;
2525}
2526
2527static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
2528{
2529	unsigned int count;
2530	unsigned int clk_src;
2531
2532	clk_src = pci230_choose_clk_count(*ns, &count, round);
2533	*ns = count * pci230_timebase[clk_src];
2534	return;
2535}
2536
2537static void pci230_ct_setup_ns_mode(struct comedi_device *dev, unsigned int ct,
2538	unsigned int mode, uint64_t ns, unsigned int round)
2539{
2540	unsigned int clk_src;
2541	unsigned int count;
2542
2543	/* Set mode. */
2544	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
2545	/* Determine clock source and count. */
2546	clk_src = pci230_choose_clk_count(ns, &count, round);
2547	/* Program clock source. */
2548	outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
2549	/* Set initial count. */
2550	if (count >= 65536) {
2551		count = 0;
2552	}
2553	i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
2554}
2555
2556static void pci230_cancel_ct(struct comedi_device *dev, unsigned int ct)
2557{
2558	i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
2559		I8254_MODE1);
2560	/* Counter ct, 8254 mode 1, initial count not written. */
2561}
2562
2563/* Interrupt handler */
2564static irqreturn_t pci230_interrupt(int irq, void *d)
2565{
2566	unsigned char status_int, valid_status_int;
2567	struct comedi_device *dev = (struct comedi_device *) d;
2568	struct comedi_subdevice *s;
2569	unsigned long irqflags;
2570
2571	/* Read interrupt status/enable register. */
2572	status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2573
2574	if (status_int == PCI230_INT_DISABLE) {
2575		return IRQ_NONE;
2576	}
2577
2578	comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2579	valid_status_int = devpriv->int_en & status_int;
2580	/* Disable triggered interrupts.
2581	 * (Only those interrupts that need re-enabling, are, later in the
2582	 * handler).  */
2583	devpriv->ier = devpriv->int_en & ~status_int;
2584	outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2585	devpriv->intr_running = 1;
2586	devpriv->intr_cpuid = THISCPU;
2587	comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2588
2589	/*
2590	 * Check the source of interrupt and handle it.
2591	 * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2592	 * interrupts.  However, at present (Comedi-0.7.60) does not allow
2593	 * concurrent execution of commands, instructions or a mixture of the
2594	 * two.
2595	 */
2596
2597	if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2598		s = dev->write_subdev;
2599		pci230_handle_ao_nofifo(dev, s);
2600		comedi_event(dev, s);
2601	}
2602
2603	if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2604		s = dev->write_subdev;
2605		pci230_handle_ao_fifo(dev, s);
2606		comedi_event(dev, s);
2607	}
2608
2609	if ((valid_status_int & PCI230_INT_ADC) != 0) {
2610		s = dev->read_subdev;
2611		pci230_handle_ai(dev, s);
2612		comedi_event(dev, s);
2613	}
2614
2615	/* Reenable interrupts. */
2616	comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2617	if (devpriv->ier != devpriv->int_en) {
2618		devpriv->ier = devpriv->int_en;
2619		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2620	}
2621	devpriv->intr_running = 0;
2622	comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2623
2624	return IRQ_HANDLED;
2625}
2626
2627static void pci230_handle_ao_nofifo(struct comedi_device *dev, struct comedi_subdevice *s)
2628{
2629	short data;
2630	int i, ret;
2631	struct comedi_async *async = s->async;
2632	struct comedi_cmd *cmd = &async->cmd;
2633
2634	if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
2635		return;
2636	}
2637
2638	for (i = 0; i < cmd->chanlist_len; i++) {
2639		/* Read sample from Comedi's circular buffer. */
2640		ret = comedi_buf_get(s->async, &data);
2641		if (ret == 0) {
2642			s->async->events |= COMEDI_CB_OVERFLOW;
2643			pci230_ao_stop(dev, s);
2644			comedi_error(dev, "AO buffer underrun");
2645			return;
2646		}
2647		/* Write value to DAC. */
2648		pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
2649	}
2650
2651	async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2652	if (!devpriv->ao_continuous) {
2653		devpriv->ao_scan_count--;
2654		if (devpriv->ao_scan_count == 0) {
2655			/* End of acquisition. */
2656			async->events |= COMEDI_CB_EOA;
2657			pci230_ao_stop(dev, s);
2658		}
2659	}
2660}
2661
2662/* Loads DAC FIFO (if using it) from buffer. */
2663/* Returns 0 if AO finished due to completion or error, 1 if still going. */
2664static int pci230_handle_ao_fifo(struct comedi_device *dev, struct comedi_subdevice *s)
2665{
2666	struct comedi_async *async = s->async;
2667	struct comedi_cmd *cmd = &async->cmd;
2668	unsigned int num_scans;
2669	unsigned int room;
2670	unsigned short dacstat;
2671	unsigned int i, n;
2672	unsigned int bytes_per_scan;
2673	unsigned int events = 0;
2674	int running;
2675
2676	/* Get DAC FIFO status. */
2677	dacstat = inw(dev->iobase + PCI230_DACCON);
2678
2679	/* Determine number of scans available in buffer. */
2680	bytes_per_scan = cmd->chanlist_len * sizeof(short);
2681	num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
2682	if (!devpriv->ao_continuous) {
2683		/* Fixed number of scans. */
2684		if (num_scans > devpriv->ao_scan_count) {
2685			num_scans = devpriv->ao_scan_count;
2686		}
2687		if (devpriv->ao_scan_count == 0) {
2688			/* End of acquisition. */
2689			events |= COMEDI_CB_EOA;
2690		}
2691	}
2692	if (events == 0) {
2693		/* Check for FIFO underrun. */
2694		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2695			comedi_error(dev, "AO FIFO underrun");
2696			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2697		}
2698		/* Check for buffer underrun if FIFO less than half full
2699		 * (otherwise there will be loads of "DAC FIFO not half full"
2700		 * interrupts). */
2701		if ((num_scans == 0)
2702			&& ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
2703			comedi_error(dev, "AO buffer underrun");
2704			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2705		}
2706	}
2707	if (events == 0) {
2708		/* Determine how much room is in the FIFO (in samples). */
2709		if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) {
2710			room = PCI230P2_DAC_FIFOROOM_FULL;
2711		} else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) {
2712			room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
2713		} else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) {
2714			room = PCI230P2_DAC_FIFOROOM_EMPTY;
2715		} else {
2716			room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
2717		}
2718		/* Convert room to number of scans that can be added. */
2719		room /= cmd->chanlist_len;
2720		/* Determine number of scans to process. */
2721		if (num_scans > room) {
2722			num_scans = room;
2723		}
2724		/* Process scans. */
2725		for (n = 0; n < num_scans; n++) {
2726			for (i = 0; i < cmd->chanlist_len; i++) {
2727				short datum;
2728
2729				comedi_buf_get(async, &datum);
2730				pci230_ao_write_fifo(dev, datum,
2731					CR_CHAN(cmd->chanlist[i]));
2732			}
2733		}
2734		events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
2735		if (!devpriv->ao_continuous) {
2736			devpriv->ao_scan_count -= num_scans;
2737			if (devpriv->ao_scan_count == 0) {
2738				/* All data for the command has been written
2739				 * to FIFO.  Set FIFO interrupt trigger level
2740				 * to 'empty'. */
2741				devpriv->daccon = (devpriv->daccon
2742					& ~PCI230P2_DAC_INT_FIFO_MASK)
2743					| PCI230P2_DAC_INT_FIFO_EMPTY;
2744				outw(devpriv->daccon,
2745					dev->iobase + PCI230_DACCON);
2746			}
2747		}
2748		/* Check if FIFO underrun occurred while writing to FIFO. */
2749		dacstat = inw(dev->iobase + PCI230_DACCON);
2750		if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2751			comedi_error(dev, "AO FIFO underrun");
2752			events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2753		}
2754	}
2755	if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
2756		!= 0) {
2757		/* Stopping AO due to completion or error. */
2758		pci230_ao_stop(dev, s);
2759		running = 0;
2760	} else {
2761		running = 1;
2762	}
2763	async->events |= events;
2764	return running;
2765}
2766
2767static void pci230_handle_ai(struct comedi_device *dev, struct comedi_subdevice *s)
2768{
2769	unsigned int events = 0;
2770	unsigned int status_fifo;
2771	unsigned int i;
2772	unsigned int todo;
2773	unsigned int fifoamount;
2774	struct comedi_async *async = s->async;
2775	unsigned int scanlen = async->cmd.scan_end_arg;
2776
2777	/* Determine number of samples to read. */
2778	if (devpriv->ai_continuous) {
2779		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2780	} else if (devpriv->ai_scan_count == 0) {
2781		todo = 0;
2782	} else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2783		|| (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2784		todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2785	} else {
2786		todo = (devpriv->ai_scan_count * scanlen)
2787			- devpriv->ai_scan_pos;
2788		if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) {
2789			todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2790		}
2791	}
2792
2793	if (todo == 0) {
2794		return;
2795	}
2796
2797	fifoamount = 0;
2798	for (i = 0; i < todo; i++) {
2799		if (fifoamount == 0) {
2800			/* Read FIFO state. */
2801			status_fifo = inw(dev->iobase + PCI230_ADCCON);
2802
2803			if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2804				/* Report error otherwise FIFO overruns will go
2805				 * unnoticed by the caller. */
2806				comedi_error(dev, "AI FIFO overrun");
2807				events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2808				break;
2809			} else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2810				/* FIFO empty. */
2811				break;
2812			} else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2813				/* FIFO half full. */
2814				fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2815			} else {
2816				/* FIFO not empty. */
2817				if (devpriv->hwver > 0) {
2818					/* Read PCI230+/260+ ADC FIFO level. */
2819					fifoamount = inw(dev->iobase
2820						+ PCI230P_ADCFFLEV);
2821					if (fifoamount == 0) {
2822						/* Shouldn't happen. */
2823						break;
2824					}
2825				} else {
2826					fifoamount = 1;
2827				}
2828			}
2829		}
2830
2831		/* Read sample and store in Comedi's circular buffer. */
2832		if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2833			events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2834			comedi_error(dev, "AI buffer overflow");
2835			break;
2836		}
2837		fifoamount--;
2838		devpriv->ai_scan_pos++;
2839		if (devpriv->ai_scan_pos == scanlen) {
2840			/* End of scan. */
2841			devpriv->ai_scan_pos = 0;
2842			devpriv->ai_scan_count--;
2843			async->events |= COMEDI_CB_EOS;
2844		}
2845	}
2846
2847	if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2848		/* End of acquisition. */
2849		events |= COMEDI_CB_EOA;
2850	} else {
2851		/* More samples required, tell Comedi to block. */
2852		events |= COMEDI_CB_BLOCK;
2853	}
2854	async->events |= events;
2855
2856	if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2857				COMEDI_CB_OVERFLOW)) != 0) {
2858		/* disable hardware conversions */
2859		pci230_ai_stop(dev, s);
2860	} else {
2861		/* update FIFO interrupt trigger level */
2862		pci230_ai_update_fifo_trigger_level(dev, s);
2863	}
2864}
2865
2866static void pci230_ao_stop(struct comedi_device *dev, struct comedi_subdevice *s)
2867{
2868	unsigned long irqflags;
2869	unsigned char intsrc;
2870	int started;
2871	struct comedi_cmd *cmd;
2872
2873	comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
2874	started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
2875	comedi_spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
2876	if (!started) {
2877		return;
2878	}
2879
2880	cmd = &s->async->cmd;
2881	if (cmd->scan_begin_src == TRIG_TIMER) {
2882		/* Stop scan rate generator. */
2883		pci230_cancel_ct(dev, 1);
2884	}
2885
2886	/* Determine interrupt source. */
2887	if (devpriv->hwver < 2) {
2888		/* Not using DAC FIFO.  Using CT1 interrupt. */
2889		intsrc = PCI230_INT_ZCLK_CT1;
2890	} else {
2891		/* Using DAC FIFO interrupt. */
2892		intsrc = PCI230P2_INT_DAC;
2893	}
2894	/* Disable interrupt and wait for interrupt routine to finish running
2895	 * unless we are called from the interrupt routine. */
2896	comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2897	devpriv->int_en &= ~intsrc;
2898	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2899		comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2900		comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2901	}
2902	if (devpriv->ier != devpriv->int_en) {
2903		devpriv->ier = devpriv->int_en;
2904		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2905	}
2906	comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2907
2908	if (devpriv->hwver >= 2) {
2909		/* Using DAC FIFO.  Reset FIFO, clear underrun error,
2910		 * disable FIFO. */
2911		devpriv->daccon &= PCI230_DAC_OR_MASK;
2912		outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
2913			| PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
2914			dev->iobase + PCI230_DACCON);
2915	}
2916
2917	/* Release resources. */
2918	put_all_resources(dev, OWNER_AOCMD);
2919}
2920
2921static int pci230_ao_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2922{
2923	pci230_ao_stop(dev, s);
2924	return 0;
2925}
2926
2927static void pci230_ai_stop(struct comedi_device *dev, struct comedi_subdevice *s)
2928{
2929	unsigned long irqflags;
2930	struct comedi_cmd *cmd;
2931	int started;
2932
2933	comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2934	started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
2935	comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2936	if (!started) {
2937		return;
2938	}
2939
2940	cmd = &s->async->cmd;
2941	if (cmd->convert_src == TRIG_TIMER) {
2942		/* Stop conversion rate generator. */
2943		pci230_cancel_ct(dev, 2);
2944	}
2945	if (cmd->scan_begin_src != TRIG_FOLLOW) {
2946		/* Stop scan period monostable. */
2947		pci230_cancel_ct(dev, 0);
2948	}
2949
2950	comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2951	/* Disable ADC interrupt and wait for interrupt routine to finish
2952	 * running unless we are called from the interrupt routine. */
2953	devpriv->int_en &= ~PCI230_INT_ADC;
2954	while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2955		comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2956		comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2957	}
2958	if (devpriv->ier != devpriv->int_en) {
2959		devpriv->ier = devpriv->int_en;
2960		outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2961	}
2962	comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2963
2964	/* Reset FIFO, disable FIFO and set start conversion source to none.
2965	 * Keep se/diff and bip/uni settings */
2966	devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2967			| PCI230_ADC_IM_MASK)) | PCI230_ADC_TRIG_NONE;
2968	outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2969		dev->iobase + PCI230_ADCCON);
2970
2971	/* Release resources. */
2972	put_all_resources(dev, OWNER_AICMD);
2973}
2974
2975static int pci230_ai_cancel(struct comedi_device *dev, struct comedi_subdevice *s)
2976{
2977	pci230_ai_stop(dev, s);
2978	return 0;
2979}
2980