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