m4/as-linux.m4: don't use backported pcmcia_loop_tuple()
[comedi.git] / comedi / drivers / amplc_pci230.c
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 /*
25 Driver: amplc_pci230
26 Description: Amplicon PCI230, PCI260 Multifunction I/O boards
27 Author: Allan Willcox <allanwillcox@ozemail.com.au>,
28   Steve D Sharples <steve.sharples@nottingham.ac.uk>,
29   Ian Abbott <abbotti@mev.co.uk>
30 Updated: Wed, 22 Oct 2008 12:34:49 +0100
31 Devices: [Amplicon] PCI230 (pci230 or amplc_pci230),
32   PCI230+ (pci230+ or amplc_pci230),
33   PCI260 (pci260 or amplc_pci230), PCI260+ (pci260+ or amplc_pci230)
34 Status: works
35
36 Configuration 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
42 Configuring a "amplc_pci230" will match any supported card and it will
43 choose the best match, picking the "+" models if possible.  Configuring
44 a "pci230" will match a PCI230 or PCI230+ card and it will be treated as
45 a PCI230.  Configuring a "pci260" will match a PCI260 or PCI260+ card
46 and it will be treated as a PCI260.  Configuring a "pci230+" will match
47 a PCI230+ card.  Configuring a "pci260+" will match a PCI260+ card.
48
49 Subdevices:
50
51                 PCI230(+)    PCI260(+)
52                 ---------    ---------
53   Subdevices       3            1
54         0          AI           AI
55         1          AO
56         2          DIO
57
58 AI 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
87 AI 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
135 AO 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
144 AO 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
169 DIO 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 /*
186 Extra triggered scan functionality, interrupt bug-fix added by Steve Sharples.
187 Support for PCI230+/260+, more triggered scan functionality, and workarounds
188 for (or detection of) various hardware problems added by Ian Abbott.
189 */
190 #include <linux/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 */
412 enum {
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
419 enum {
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
446 typedef struct pci230_board_struct {
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 } pci230_board;
456 static const 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
501 static 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
509 MODULE_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 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 comedi_device struct.  */
519 struct 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         lsampl_t 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 */
562 static 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 */
571 static const 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. */
583 static 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. */
586 static const unsigned char pci230_ai_bipolar[7] = { 1, 1, 1, 1, 0, 0, 0 };
587
588 /* PCI230 analogue output range table */
589 static const 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. */
596 static const unsigned char pci230_ao_bipolar[2] = { 0, 1 };
597
598 /*
599  * The 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  */
604 static int pci230_attach(comedi_device * dev, comedi_devconfig * it);
605 static int pci230_detach(comedi_device * dev);
606 static 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
616 COMEDI_PCI_INITCLEANUP(driver_amplc_pci230, pci230_pci_table);
617
618 static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
619         comedi_insn * insn, lsampl_t * data);
620 static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
621         comedi_insn * insn, lsampl_t * data);
622 static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
623         comedi_insn * insn, lsampl_t * data);
624 static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
625         unsigned int mode, uint64_t ns, unsigned int round);
626 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round);
627 static void pci230_cancel_ct(comedi_device * dev, unsigned int ct);
628 static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG);
629 static int pci230_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
630         comedi_cmd * cmd);
631 static int pci230_ao_cmd(comedi_device * dev, comedi_subdevice * s);
632 static int pci230_ao_cancel(comedi_device * dev, comedi_subdevice * s);
633 static void pci230_ao_stop(comedi_device * dev, comedi_subdevice * s);
634 static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s);
635 static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s);
636 static int pci230_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
637         comedi_cmd * cmd);
638 static int pci230_ai_cmd(comedi_device * dev, comedi_subdevice * s);
639 static int pci230_ai_cancel(comedi_device * dev, comedi_subdevice * s);
640 static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s);
641 static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s);
642
643 static sampl_t pci230_ai_read(comedi_device * dev)
644 {
645         /* Read sample. */
646         sampl_t data = (sampl_t) 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
661 static inline unsigned short pci230_ao_mangle_datum(comedi_device * dev,
662         sampl_t 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
677 static inline void pci230_ao_write_nofifo(comedi_device * dev, sampl_t 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
688 static inline void pci230_ao_write_fifo(comedi_device * dev, sampl_t 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  */
705 static int pci230_attach(comedi_device * dev, comedi_devconfig * it)
706 {
707         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  */
962 static int pci230_detach(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
985 static int get_resources(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
1021 static inline int get_one_resource(comedi_device * dev, unsigned int resource,
1022         unsigned char owner)
1023 {
1024         return get_resources(dev, (1U << resource), owner);
1025 }
1026
1027 static void put_resources(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
1047 static inline void put_one_resource(comedi_device * dev, unsigned int resource,
1048         unsigned char owner)
1049 {
1050         put_resources(dev, (1U << resource), owner);
1051 }
1052
1053 static inline void put_all_resources(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  */
1061 static int pci230_ai_rinsn(comedi_device * dev, comedi_subdevice * s,
1062         comedi_insn * insn, lsampl_t * 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  */
1166 static int pci230_ao_winsn(comedi_device * dev, comedi_subdevice * s,
1167         comedi_insn * insn, lsampl_t * 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. */
1194 static int pci230_ao_rinsn(comedi_device * dev, comedi_subdevice * s,
1195         comedi_insn * insn, lsampl_t * 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
1206 static int pci230_ao_cmdtest(comedi_device * dev, comedi_subdevice * s,
1207         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
1419 static int pci230_ao_inttrig_scan_begin(comedi_device * dev,
1420         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         } else {
1447                 comedi_spin_unlock_irqrestore(&devpriv-> ao_stop_spinlock,
1448                         irqflags);
1449         }
1450
1451         return 1;
1452 }
1453
1454 static void pci230_ao_start(comedi_device * dev, comedi_subdevice * s)
1455 {
1456         comedi_async *async = s->async;
1457         comedi_cmd *cmd = &async->cmd;
1458         unsigned long irqflags;
1459
1460         set_bit(AO_CMD_STARTED, &devpriv->state);
1461         if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
1462                 /* An empty acquisition! */
1463                 async->events |= COMEDI_CB_EOA;
1464                 pci230_ao_stop(dev, s);
1465                 comedi_event(dev, s);
1466         } else {
1467                 if (devpriv->hwver >= 2) {
1468                         /* Using DAC FIFO. */
1469                         unsigned short scantrig;
1470                         int run;
1471
1472                         /* Preload FIFO data. */
1473                         run = pci230_handle_ao_fifo(dev, s);
1474                         comedi_event(dev, s);
1475                         if (!run) {
1476                                 /* Stopped. */
1477                                 return;
1478                         }
1479                         /* Set scan trigger source. */
1480                         switch (cmd->scan_begin_src) {
1481                         case TRIG_TIMER:
1482                                 scantrig = PCI230P2_DAC_TRIG_Z2CT1;
1483                                 break;
1484                         case TRIG_EXT:
1485                                 /* Trigger on EXTTRIG/EXTCONVCLK pin. */
1486                                 if ((cmd->scan_begin_arg & CR_INVERT) == 0) {
1487                                         /* +ve edge */
1488                                         scantrig = PCI230P2_DAC_TRIG_EXTP;
1489                                 } else {
1490                                         /* -ve edge */
1491                                         scantrig = PCI230P2_DAC_TRIG_EXTN;
1492                                 }
1493                                 break;
1494                         case TRIG_INT:
1495                                 scantrig = PCI230P2_DAC_TRIG_SW;
1496                                 break;
1497                         default:
1498                                 /* Shouldn't get here. */
1499                                 scantrig = PCI230P2_DAC_TRIG_NONE;
1500                                 break;
1501                         }
1502                         devpriv->daccon = (devpriv->daccon
1503                                 & ~PCI230P2_DAC_TRIG_MASK) | scantrig;
1504                         outw(devpriv->daccon, dev->iobase + PCI230_DACCON);
1505
1506                 }
1507                 switch (cmd->scan_begin_src) {
1508                 case TRIG_TIMER:
1509                         if (devpriv->hwver < 2) {
1510                                 /* Not using DAC FIFO. */
1511                                 /* Enable CT1 timer interrupt. */
1512                                 comedi_spin_lock_irqsave(&devpriv->isr_spinlock,
1513                                         irqflags);
1514                                 devpriv->int_en |= PCI230_INT_ZCLK_CT1;
1515                                 devpriv->ier |= PCI230_INT_ZCLK_CT1;
1516                                 outb(devpriv->ier,
1517                                         devpriv->iobase1 + PCI230_INT_SCE);
1518                                 comedi_spin_unlock_irqrestore(&devpriv->
1519                                         isr_spinlock, irqflags);
1520                         }
1521                         /* Set CT1 gate high to start counting. */
1522                         outb(GAT_CONFIG(1, GAT_VCC),
1523                                 devpriv->iobase1 + PCI230_ZGAT_SCE);
1524                         break;
1525                 case TRIG_INT:
1526                         async->inttrig = pci230_ao_inttrig_scan_begin;
1527                         break;
1528                 }
1529                 if (devpriv->hwver >= 2) {
1530                         /* Using DAC FIFO.  Enable DAC FIFO interrupt. */
1531                         comedi_spin_lock_irqsave(&devpriv->isr_spinlock,
1532                                 irqflags);
1533                         devpriv->int_en |= PCI230P2_INT_DAC;
1534                         devpriv->ier |= PCI230P2_INT_DAC;
1535                         outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
1536                         comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock,
1537                                 irqflags);
1538                 }
1539         }
1540 }
1541
1542 static int pci230_ao_inttrig_start(comedi_device * dev, comedi_subdevice * s,
1543         unsigned int trig_num)
1544 {
1545         if (trig_num != 0)
1546                 return -EINVAL;
1547
1548         s->async->inttrig = NULLFUNC;
1549         pci230_ao_start(dev, s);
1550
1551         return 1;
1552 }
1553
1554 static int pci230_ao_cmd(comedi_device * dev, comedi_subdevice * s)
1555 {
1556         unsigned short daccon;
1557         unsigned int range;
1558
1559         /* Get the command. */
1560         comedi_cmd *cmd = &s->async->cmd;
1561
1562         if (cmd->scan_begin_src == TRIG_TIMER) {
1563                 /* Claim Z2-CT1. */
1564                 if (!get_one_resource(dev, RES_Z2CT1, OWNER_AOCMD)) {
1565                         return -EBUSY;
1566                 }
1567         }
1568
1569         /* Get number of scans required. */
1570         if (cmd->stop_src == TRIG_COUNT) {
1571                 devpriv->ao_scan_count = cmd->stop_arg;
1572                 devpriv->ao_continuous = 0;
1573         } else {
1574                 /* TRIG_NONE, user calls cancel. */
1575                 devpriv->ao_scan_count = 0;
1576                 devpriv->ao_continuous = 1;
1577         }
1578
1579         /* Set range - see analogue output range table; 0 => unipolar 10V,
1580          * 1 => bipolar +/-10V range scale */
1581         range = CR_RANGE(cmd->chanlist[0]);
1582         devpriv->ao_bipolar = pci230_ao_bipolar[range];
1583         daccon = devpriv->ao_bipolar ? PCI230_DAC_OR_BIP : PCI230_DAC_OR_UNI;
1584         /* Use DAC FIFO for hardware version 2 onwards. */
1585         if (devpriv->hwver >= 2) {
1586                 unsigned short dacen;
1587                 unsigned int i;
1588
1589                 dacen = 0;
1590                 for (i = 0; i < cmd->chanlist_len; i++) {
1591                         dacen |= 1 << CR_CHAN(cmd->chanlist[i]);
1592                 }
1593                 /* Set channel scan list. */
1594                 outw(dacen, dev->iobase + PCI230P2_DACEN);
1595                 /*
1596                  * Enable DAC FIFO.
1597                  * Set DAC scan source to 'none'.
1598                  * Set DAC FIFO interrupt trigger level to 'not half full'.
1599                  * Reset DAC FIFO and clear underrun.
1600                  *
1601                  * N.B. DAC FIFO interrupts are currently disabled.
1602                  */
1603                 daccon |= PCI230P2_DAC_FIFO_EN | PCI230P2_DAC_FIFO_RESET
1604                         | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR
1605                         | PCI230P2_DAC_TRIG_NONE | PCI230P2_DAC_INT_FIFO_NHALF;
1606         }
1607
1608         /* Set DACCON. */
1609         outw(daccon, dev->iobase + PCI230_DACCON);
1610         /* Preserve most of DACCON apart from write-only, transient bits. */
1611         devpriv->daccon = daccon
1612                 & ~(PCI230P2_DAC_FIFO_RESET | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR);
1613
1614         if (cmd->scan_begin_src == TRIG_TIMER) {
1615                 /* Set the counter timer 1 to the specified scan frequency. */
1616                 /* cmd->scan_begin_arg is sampling period in ns */
1617                 /* gate it off for now. */
1618                 outb(GAT_CONFIG(1, GAT_GND),
1619                         devpriv->iobase1 + PCI230_ZGAT_SCE);
1620                 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
1621                         cmd->scan_begin_arg, cmd->flags & TRIG_ROUND_MASK);
1622         }
1623
1624         /* N.B. cmd->start_src == TRIG_INT */
1625         s->async->inttrig = pci230_ao_inttrig_start;
1626
1627         return 0;
1628 }
1629
1630 static int pci230_ai_check_scan_period(comedi_cmd * cmd)
1631 {
1632         unsigned int min_scan_period, chanlist_len;
1633         int err = 0;
1634
1635         chanlist_len = cmd->chanlist_len;
1636         if (cmd->chanlist_len == 0) {
1637                 chanlist_len = 1;
1638         }
1639         min_scan_period = chanlist_len * cmd->convert_arg;
1640         if ((min_scan_period < chanlist_len)
1641                 || (min_scan_period < cmd->convert_arg)) {
1642                 /* Arithmetic overflow. */
1643                 min_scan_period = UINT_MAX;
1644                 err++;
1645         }
1646         if (cmd->scan_begin_arg < min_scan_period) {
1647                 cmd->scan_begin_arg = min_scan_period;
1648                 err++;
1649         }
1650
1651         return !err;
1652 }
1653
1654 static int pci230_ai_cmdtest(comedi_device * dev, comedi_subdevice * s,
1655         comedi_cmd * cmd)
1656 {
1657         int err = 0;
1658         unsigned int tmp;
1659
1660         /* cmdtest tests a particular command to see if it is valid.
1661          * Using the cmdtest ioctl, a user can create a valid cmd
1662          * and then have it executes by the cmd ioctl.
1663          *
1664          * cmdtest returns 1,2,3,4,5 or 0, depending on which tests
1665          * the command passes. */
1666
1667         /* Step 1: make sure trigger sources are trivially valid.
1668          * "invalid source" returned by comedilib to user mode process
1669          * if this fails. */
1670
1671         tmp = cmd->start_src;
1672         cmd->start_src &= TRIG_NOW | TRIG_INT;
1673         if (!cmd->start_src || tmp != cmd->start_src)
1674                 err++;
1675
1676         tmp = cmd->scan_begin_src;
1677         /* Unfortunately, we cannot trigger a scan off an external source
1678          * on the PCI260 board, since it uses the PPIC0 (DIO) input, which
1679          * isn't present on the PCI260.  For PCI260+ we can use the
1680          * EXTTRIG/EXTCONVCLK input on pin 17 instead. */
1681         if ((thisboard->have_dio) || (thisboard->min_hwver > 0)) {
1682                 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT
1683                         | TRIG_EXT;
1684         } else {
1685                 cmd->scan_begin_src &= TRIG_FOLLOW | TRIG_TIMER | TRIG_INT;
1686         }
1687         if (!cmd->scan_begin_src || tmp != cmd->scan_begin_src)
1688                 err++;
1689
1690         tmp = cmd->convert_src;
1691         cmd->convert_src &= TRIG_TIMER | TRIG_INT | TRIG_EXT;
1692         if (!cmd->convert_src || tmp != cmd->convert_src)
1693                 err++;
1694
1695         tmp = cmd->scan_end_src;
1696         cmd->scan_end_src &= TRIG_COUNT;
1697         if (!cmd->scan_end_src || tmp != cmd->scan_end_src)
1698                 err++;
1699
1700         tmp = cmd->stop_src;
1701         cmd->stop_src &= TRIG_COUNT | TRIG_NONE;
1702         if (!cmd->stop_src || tmp != cmd->stop_src)
1703                 err++;
1704
1705         if (err)
1706                 return 1;
1707
1708         /* Step 2: make sure trigger sources are unique and mutually compatible
1709          * "source conflict" returned by comedilib to user mode process
1710          * if this fails. */
1711
1712         /* these tests are true if more than one _src bit is set */
1713         if ((cmd->start_src & (cmd->start_src - 1)) != 0)
1714                 err++;
1715         if ((cmd->scan_begin_src & (cmd->scan_begin_src - 1)) != 0)
1716                 err++;
1717         if ((cmd->convert_src & (cmd->convert_src - 1)) != 0)
1718                 err++;
1719         if ((cmd->scan_end_src & (cmd->scan_end_src - 1)) != 0)
1720                 err++;
1721         if ((cmd->stop_src & (cmd->stop_src - 1)) != 0)
1722                 err++;
1723
1724         /* If scan_begin_src is not TRIG_FOLLOW, then a monostable will be
1725          * set up to generate a fixed number of timed conversion pulses. */
1726         if ((cmd->scan_begin_src != TRIG_FOLLOW)
1727                 && (cmd->convert_src != TRIG_TIMER))
1728                 err++;
1729
1730         if (err)
1731                 return 2;
1732
1733         /* Step 3: make sure arguments are trivially compatible.
1734          * "invalid argument" returned by comedilib to user mode process
1735          * if this fails. */
1736
1737         if (cmd->start_arg != 0) {
1738                 cmd->start_arg = 0;
1739                 err++;
1740         }
1741 #define MAX_SPEED_AI_SE         3200    /* PCI230 SE:   3200 ns => 312.5 kHz */
1742 #define MAX_SPEED_AI_DIFF       8000    /* PCI230 DIFF: 8000 ns => 125 kHz */
1743 #define MAX_SPEED_AI_PLUS       4000    /* PCI230+:     4000 ns => 250 kHz */
1744 #define MIN_SPEED_AI    4294967295u     /* 4294967295ns = 4.29s */
1745                         /*- Comedi limit due to unsigned int cmd.  Driver limit
1746                          * = 2^16 (16bit * counter) * 1000000ns (1kHz onboard
1747                          * clock) = 65.536s */
1748
1749         if (cmd->convert_src == TRIG_TIMER) {
1750                 unsigned int max_speed_ai;
1751
1752                 if (devpriv->hwver == 0) {
1753                         /* PCI230 or PCI260.  Max speed depends whether
1754                          * single-ended or pseudo-differential. */
1755                         if (cmd->chanlist && (cmd->chanlist_len > 0)) {
1756                                 /* Peek analogue reference of first channel. */
1757                                 if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
1758                                         max_speed_ai = MAX_SPEED_AI_DIFF;
1759                                 } else {
1760                                         max_speed_ai = MAX_SPEED_AI_SE;
1761                                 }
1762                         } else {
1763                                 /* No channel list.  Assume single-ended. */
1764                                 max_speed_ai = MAX_SPEED_AI_SE;
1765                         }
1766                 } else {
1767                         /* PCI230+ or PCI260+. */
1768                         max_speed_ai = MAX_SPEED_AI_PLUS;
1769                 }
1770
1771                 if (cmd->convert_arg < max_speed_ai) {
1772                         cmd->convert_arg = max_speed_ai;
1773                         err++;
1774                 }
1775                 if (cmd->convert_arg > MIN_SPEED_AI) {
1776                         cmd->convert_arg = MIN_SPEED_AI;
1777                         err++;
1778                 }
1779         } else if (cmd->convert_src == TRIG_EXT) {
1780                 /*
1781                  * external trigger
1782                  *
1783                  * convert_arg == (CR_EDGE | 0)
1784                  *                => trigger on +ve edge.
1785                  * convert_arg == (CR_EDGE | CR_INVERT | 0)
1786                  *                => trigger on -ve edge.
1787                  */
1788                 if ((cmd->convert_arg & CR_FLAGS_MASK) != 0) {
1789                         /* Trigger number must be 0. */
1790                         if ((cmd->convert_arg & ~CR_FLAGS_MASK) != 0) {
1791                                 cmd->convert_arg = COMBINE(cmd->convert_arg, 0,
1792                                         ~CR_FLAGS_MASK);
1793                                 err++;
1794                         }
1795                         /* The only flags allowed are CR_INVERT and CR_EDGE.
1796                          * CR_EDGE is required. */
1797                         if ((cmd->convert_arg & (CR_FLAGS_MASK & ~CR_INVERT))
1798                                 != CR_EDGE) {
1799                                 /* Set CR_EDGE, preserve CR_INVERT. */
1800                                 cmd->convert_arg =
1801                                         COMBINE(cmd->start_arg, (CR_EDGE | 0),
1802                                         CR_FLAGS_MASK & ~CR_INVERT);
1803                                 err++;
1804                         }
1805                 } else {
1806                         /* Backwards compatibility with previous versions. */
1807                         /* convert_arg == 0 => trigger on -ve edge. */
1808                         /* convert_arg == 1 => trigger on +ve edge. */
1809                         if (cmd->convert_arg > 1) {
1810                                 /* Default to trigger on +ve edge. */
1811                                 cmd->convert_arg = 1;
1812                                 err++;
1813                         }
1814                 }
1815         } else {
1816                 if (cmd->convert_arg != 0) {
1817                         cmd->convert_arg = 0;
1818                         err++;
1819                 }
1820         }
1821
1822         if (cmd->scan_end_arg != cmd->chanlist_len) {
1823                 cmd->scan_end_arg = cmd->chanlist_len;
1824                 err++;
1825         }
1826
1827         if (cmd->stop_src == TRIG_NONE) {
1828                 if (cmd->stop_arg != 0) {
1829                         cmd->stop_arg = 0;
1830                         err++;
1831                 }
1832         }
1833
1834         if (cmd->scan_begin_src == TRIG_EXT) {
1835                 /* external "trigger" to begin each scan
1836                  * scan_begin_arg==0 => use PPC0 input -> gate of CT0 -> gate
1837                  * of CT2 (sample convert trigger is CT2) */
1838                 if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
1839                         cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1840                                 ~CR_FLAGS_MASK);
1841                         err++;
1842                 }
1843                 /* The only flag allowed is CR_EDGE, which is ignored. */
1844                 if ((cmd->scan_begin_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
1845                         cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
1846                                 CR_FLAGS_MASK & ~CR_EDGE);
1847                         err++;
1848                 }
1849         } else if (cmd->scan_begin_src == TRIG_TIMER) {
1850                 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1851                 if (!pci230_ai_check_scan_period(cmd)) {
1852                         err++;
1853                 }
1854         } else {
1855                 if (cmd->scan_begin_arg != 0) {
1856                         cmd->scan_begin_arg = 0;
1857                         err++;
1858                 }
1859         }
1860
1861         if (err)
1862                 return 3;
1863
1864         /* Step 4: fix up any arguments.
1865          * "argument conflict" returned by comedilib to user mode process
1866          * if this fails. */
1867
1868         if (cmd->convert_src == TRIG_TIMER) {
1869                 tmp = cmd->convert_arg;
1870                 pci230_ns_to_single_timer(&cmd->convert_arg,
1871                         cmd->flags & TRIG_ROUND_MASK);
1872                 if (tmp != cmd->convert_arg)
1873                         err++;
1874         }
1875
1876         if (cmd->scan_begin_src == TRIG_TIMER) {
1877                 /* N.B. cmd->convert_arg is also TRIG_TIMER */
1878                 tmp = cmd->scan_begin_arg;
1879                 pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1880                         cmd->flags & TRIG_ROUND_MASK);
1881                 if (!pci230_ai_check_scan_period(cmd)) {
1882                         /* Was below minimum required.  Round up. */
1883                         pci230_ns_to_single_timer(&cmd->scan_begin_arg,
1884                                 TRIG_ROUND_UP);
1885                         pci230_ai_check_scan_period(cmd);
1886                 }
1887                 if (tmp != cmd->scan_begin_arg)
1888                         err++;
1889         }
1890
1891         if (err)
1892                 return 4;
1893
1894         /* Step 5: check channel list if it exists. */
1895
1896         if (cmd->chanlist && cmd->chanlist_len > 0) {
1897                 enum {
1898                         seq_err = 1 << 0,
1899                         rangepair_err = 1 << 1,
1900                         polarity_err = 1 << 2,
1901                         aref_err = 1 << 3,
1902                         diffchan_err = 1 << 4,
1903                         buggy_chan0_err = 1 << 5
1904                 };
1905                 unsigned int errors;
1906                 unsigned int chan, prev_chan;
1907                 unsigned int range, prev_range;
1908                 unsigned int polarity, prev_polarity;
1909                 unsigned int aref, prev_aref;
1910                 unsigned int subseq_len;
1911                 unsigned int n;
1912
1913                 subseq_len = 0;
1914                 errors = 0;
1915                 prev_chan = prev_aref = prev_range = prev_polarity = 0;
1916                 for (n = 0; n < cmd->chanlist_len; n++) {
1917                         chan = CR_CHAN(cmd->chanlist[n]);
1918                         range = CR_RANGE(cmd->chanlist[n]);
1919                         aref = CR_AREF(cmd->chanlist[n]);
1920                         polarity = pci230_ai_bipolar[range];
1921                         /* Only the first half of the channels are available if
1922                          * differential.  (These are remapped in software.  In
1923                          * hardware, only the even channels are available.) */
1924                         if ((aref == AREF_DIFF)
1925                                 && (chan >= (s->n_chan / 2))) {
1926                                 errors |= diffchan_err;
1927                         }
1928                         if (n > 0) {
1929                                 /* Channel numbers must strictly increase or
1930                                  * subsequence must repeat exactly. */
1931                                 if ((chan <= prev_chan)
1932                                         && (subseq_len == 0)) {
1933                                         subseq_len = n;
1934                                 }
1935                                 if ((subseq_len > 0)
1936                                         && (cmd->chanlist[n] !=
1937                                                 cmd->chanlist[n %
1938                                                         subseq_len])) {
1939                                         errors |= seq_err;
1940                                 }
1941                                 /* Channels must have same AREF. */
1942                                 if (aref != prev_aref) {
1943                                         errors |= aref_err;
1944                                 }
1945                                 /* Channel ranges must have same polarity. */
1946                                 if (polarity != prev_polarity) {
1947                                         errors |= polarity_err;
1948                                 }
1949                                 /* Single-ended channel pairs must have same
1950                                  * range.  */
1951                                 if ((aref != AREF_DIFF)
1952                                         && (((chan ^ prev_chan) & ~1) == 0)
1953                                         && (range != prev_range)) {
1954                                         errors |= rangepair_err;
1955                                 }
1956                         }
1957                         prev_chan = chan;
1958                         prev_range = range;
1959                         prev_aref = aref;
1960                         prev_polarity = polarity;
1961                 }
1962                 if (subseq_len == 0) {
1963                         /* Subsequence is whole sequence. */
1964                         subseq_len = n;
1965                 }
1966                 /* If channel list is a repeating subsequence, need a whole
1967                  * number of repeats. */
1968                 if ((n % subseq_len) != 0) {
1969                         errors |= seq_err;
1970                 }
1971                 if ((devpriv->hwver > 0) && (devpriv->hwver < 4)) {
1972                         /*
1973                          * Buggy PCI230+ or PCI260+ requires channel 0 to be
1974                          * (first) in the sequence if the sequence contains
1975                          * more than one channel.  Hardware versions 1 and 2
1976                          * have the bug.  There is no hardware version 3.
1977                          *
1978                          * Actually, there are two firmwares that report
1979                          * themselves as hardware version 1 (the boards
1980                          * have different ADC chips with slightly different
1981                          * timing requirements, which was supposed to be
1982                          * invisible to software).  The first one doesn't
1983                          * seem to have the bug, but the second one
1984                          * does, and we can't tell them apart!
1985                          */
1986                         if ((subseq_len > 1)
1987                                 && (CR_CHAN(cmd->chanlist[0]) != 0)) {
1988                                 errors |= buggy_chan0_err;
1989                         }
1990                 }
1991                 if (errors != 0) {
1992                         err++;
1993                         if ((errors & seq_err) != 0) {
1994                                 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
1995                                         "channel numbers must increase or "
1996                                         "sequence must repeat exactly\n",
1997                                         dev->minor);
1998                         }
1999                         if ((errors & rangepair_err) != 0) {
2000                                 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2001                                         "single-ended channel pairs must "
2002                                         "have the same range\n", dev->minor);
2003                         }
2004                         if ((errors & polarity_err) != 0) {
2005                                 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2006                                         "channel sequence ranges must be all "
2007                                         "bipolar or all unipolar\n",
2008                                         dev->minor);
2009                         }
2010                         if ((errors & aref_err) != 0) {
2011                                 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2012                                         "channel sequence analogue references "
2013                                         "must be all the same (single-ended "
2014                                         "or differential)\n", dev->minor);
2015                         }
2016                         if ((errors & diffchan_err) != 0) {
2017                                 DPRINTK("comedi%d: amplc_pci230: ai_cmdtest: "
2018                                         "differential channel number out of "
2019                                         "range 0 to %u\n", dev->minor,
2020                                         (s->n_chan / 2) - 1);
2021                         }
2022                         if ((errors & buggy_chan0_err) != 0) {
2023                                 /* Use printk instead of DPRINTK here. */
2024                                 printk("comedi: comedi%d: amplc_pci230: "
2025                                         "ai_cmdtest: Buggy PCI230+/260+ "
2026                                         "h/w version %u requires first channel "
2027                                         "of multi-channel sequence to be 0 "
2028                                         "(corrected in h/w version 4)\n",
2029                                         dev->minor, devpriv->hwver);
2030                         }
2031                 }
2032         }
2033
2034         if (err)
2035                 return 5;
2036
2037         return 0;
2038 }
2039
2040 static void pci230_ai_update_fifo_trigger_level(comedi_device * dev,
2041         comedi_subdevice * s)
2042 {
2043         comedi_cmd *cmd = &s->async->cmd;
2044         unsigned int scanlen = cmd->scan_end_arg;
2045         unsigned int wake;
2046         unsigned short triglev;
2047         unsigned short adccon;
2048
2049         if ((cmd->flags & TRIG_WAKE_EOS) != 0) {
2050                 /* Wake at end of scan. */
2051                 wake = scanlen - devpriv->ai_scan_pos;
2052         } else {
2053                 if (devpriv->ai_continuous
2054                         || (devpriv->ai_scan_count
2055                                 >= PCI230_ADC_FIFOLEVEL_HALFFULL)
2056                         || (scanlen >= PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2057                         wake = PCI230_ADC_FIFOLEVEL_HALFFULL;
2058                 } else {
2059                         wake = (devpriv->ai_scan_count * scanlen)
2060                                 - devpriv->ai_scan_pos;
2061                 }
2062         }
2063         if (wake >= PCI230_ADC_FIFOLEVEL_HALFFULL) {
2064                 triglev = PCI230_ADC_INT_FIFO_HALF;
2065         } else {
2066                 if ((wake > 1) && (devpriv->hwver > 0)) {
2067                         /* PCI230+/260+ programmable FIFO interrupt level. */
2068                         if (devpriv->adcfifothresh != wake) {
2069                                 devpriv->adcfifothresh = wake;
2070                                 outw(wake, dev->iobase + PCI230P_ADCFFTH);
2071                         }
2072                         triglev = PCI230P_ADC_INT_FIFO_THRESH;
2073                 } else {
2074                         triglev = PCI230_ADC_INT_FIFO_NEMPTY;
2075                 }
2076         }
2077         adccon = (devpriv->adccon & ~PCI230_ADC_INT_FIFO_MASK) | triglev;
2078         if (adccon != devpriv->adccon) {
2079                 devpriv->adccon = adccon;
2080                 outw(adccon, dev->iobase + PCI230_ADCCON);
2081         }
2082 }
2083
2084 static int pci230_ai_inttrig_convert(comedi_device * dev, comedi_subdevice * s,
2085         unsigned int trig_num)
2086 {
2087         unsigned long irqflags;
2088
2089         if (trig_num != 0)
2090                 return -EINVAL;
2091
2092         comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2093         if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2094                 unsigned int delayus;
2095
2096                 /* Trigger conversion by toggling Z2-CT2 output.  Finish
2097                  * with output high. */
2098                 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2099                         I8254_MODE0);
2100                 i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2,
2101                         I8254_MODE1);
2102                 /* Delay.  Should driver be responsible for this?  An
2103                  * alternative would be to wait until conversion is complete,
2104                  * but we can't tell when it's complete because the ADC busy
2105                  * bit has a different meaning when FIFO enabled (and when
2106                  * FIFO not enabled, it only works for software triggers). */
2107                 if (((devpriv->adccon & PCI230_ADC_IM_MASK)
2108                                 == PCI230_ADC_IM_DIF)
2109                         && (devpriv->hwver == 0)) {
2110                         /* PCI230/260 in differential mode */
2111                         delayus = 8;
2112                 } else {
2113                         /* single-ended or PCI230+/260+ */
2114                         delayus = 4;
2115                 }
2116                 comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock,
2117                         irqflags);
2118                 comedi_udelay(delayus);
2119         } else {
2120                 comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock,
2121                         irqflags);
2122         }
2123
2124         return 1;
2125 }
2126
2127 static int pci230_ai_inttrig_scan_begin(comedi_device * dev,
2128         comedi_subdevice * s, unsigned int trig_num)
2129 {
2130         unsigned long irqflags;
2131         unsigned char zgat;
2132
2133         if (trig_num != 0)
2134                 return -EINVAL;
2135
2136         comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2137         if (test_bit(AI_CMD_STARTED, &devpriv->state)) {
2138                 /* Trigger scan by waggling CT0 gate source. */
2139                 zgat = GAT_CONFIG(0, GAT_GND);
2140                 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2141                 zgat = GAT_CONFIG(0, GAT_VCC);
2142                 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2143         }
2144         comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2145
2146         return 1;
2147 }
2148
2149 static void pci230_ai_start(comedi_device * dev, comedi_subdevice * s)
2150 {
2151         unsigned long irqflags;
2152         unsigned short conv;
2153         comedi_async *async = s->async;
2154         comedi_cmd *cmd = &async->cmd;
2155
2156         set_bit(AI_CMD_STARTED, &devpriv->state);
2157         if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2158                 /* An empty acquisition! */
2159                 async->events |= COMEDI_CB_EOA;
2160                 pci230_ai_stop(dev, s);
2161                 comedi_event(dev, s);
2162         } else {
2163                 /* Enable ADC FIFO trigger level interrupt. */
2164                 comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2165                 devpriv->int_en |= PCI230_INT_ADC;
2166                 devpriv->ier |= PCI230_INT_ADC;
2167                 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2168                 comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2169
2170                 /* Update conversion trigger source which is currently set
2171                  * to CT2 output, which is currently stuck high. */
2172                 switch (cmd->convert_src) {
2173                 default:
2174                         conv = PCI230_ADC_TRIG_NONE;
2175                         break;
2176                 case TRIG_TIMER:
2177                         /* Using CT2 output. */
2178                         conv = PCI230_ADC_TRIG_Z2CT2;
2179                         break;
2180                 case TRIG_EXT:
2181                         if ((cmd->convert_arg & CR_EDGE) != 0) {
2182                                 if ((cmd->convert_arg & CR_INVERT) == 0) {
2183                                         /* Trigger on +ve edge. */
2184                                         conv = PCI230_ADC_TRIG_EXTP;
2185                                 } else {
2186                                         /* Trigger on -ve edge. */
2187                                         conv = PCI230_ADC_TRIG_EXTN;
2188                                 }
2189                         } else {
2190                                 /* Backwards compatibility. */
2191                                 if (cmd->convert_arg != 0) {
2192                                         /* Trigger on +ve edge. */
2193                                         conv = PCI230_ADC_TRIG_EXTP;
2194                                 } else {
2195                                         /* Trigger on -ve edge. */
2196                                         conv = PCI230_ADC_TRIG_EXTN;
2197                                 }
2198                         }
2199                         break;
2200                 case TRIG_INT:
2201                         /* Use CT2 output for software trigger due to problems
2202                          * in differential mode on PCI230/260. */
2203                         conv = PCI230_ADC_TRIG_Z2CT2;
2204                         break;
2205                 }
2206                 devpriv->adccon = (devpriv->adccon & ~PCI230_ADC_TRIG_MASK)
2207                         | conv;
2208                 outw(devpriv->adccon, dev->iobase + PCI230_ADCCON);
2209                 if (cmd->convert_src == TRIG_INT) {
2210                         async->inttrig = pci230_ai_inttrig_convert;
2211                 }
2212                 /* Update FIFO interrupt trigger level, which is currently
2213                  * set to "full".  */
2214                 pci230_ai_update_fifo_trigger_level(dev, s);
2215                 if (cmd->convert_src == TRIG_TIMER) {
2216                         /* Update timer gates. */
2217                         unsigned char zgat;
2218
2219                         if (cmd->scan_begin_src != TRIG_FOLLOW) {
2220                                 /* Conversion timer CT2 needs to be gated by
2221                                  * inverted output of monostable CT2. */
2222                                 zgat = GAT_CONFIG(2, GAT_NOUTNM2);
2223                         } else {
2224                                 /* Conversion timer CT2 needs to be gated on
2225                                  * continuously. */
2226                                 zgat = GAT_CONFIG(2, GAT_VCC);
2227                         }
2228                         outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2229                         if (cmd->scan_begin_src != TRIG_FOLLOW) {
2230                                 /* Set monostable CT0 trigger source. */
2231                                 switch (cmd->scan_begin_src) {
2232                                 default:
2233                                         zgat = GAT_CONFIG(0, GAT_VCC);
2234                                         break;
2235                                 case TRIG_EXT:
2236                                         /*
2237                                          * For CT0 on PCI230, the external
2238                                          * trigger (gate) signal comes from
2239                                          * PPC0, which is channel 16 of the DIO
2240                                          * subdevice.  The application needs to
2241                                          * configure this as an input in order
2242                                          * to use it as an external scan
2243                                          * trigger.
2244                                          */
2245                                         zgat = GAT_CONFIG(0, GAT_EXT);
2246                                         break;
2247                                 case TRIG_TIMER:
2248                                         /*
2249                                          * Monostable CT0 triggered by rising
2250                                          * edge on inverted output of CT1
2251                                          * (falling edge on CT1).
2252                                          */
2253                                         zgat = GAT_CONFIG(0, GAT_NOUTNM2);
2254                                         break;
2255                                 case TRIG_INT:
2256                                         /*
2257                                          * Monostable CT0 is triggered by
2258                                          * inttrig function waggling the CT0
2259                                          * gate source.
2260                                          */
2261                                         zgat = GAT_CONFIG(0, GAT_VCC);
2262                                         break;
2263                                 }
2264                                 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2265                                 switch (cmd->scan_begin_src) {
2266                                 case TRIG_TIMER:
2267                                         /* Scan period timer CT1 needs to be
2268                                          * gated on to start counting. */
2269                                         zgat = GAT_CONFIG(1, GAT_VCC);
2270                                         outb(zgat, devpriv->iobase1
2271                                                 + PCI230_ZGAT_SCE);
2272                                         break;
2273                                 case TRIG_INT:
2274                                         async->inttrig =
2275                                                 pci230_ai_inttrig_scan_begin;
2276                                         break;
2277                                 }
2278                         }
2279                 } else if (cmd->convert_src != TRIG_INT) {
2280                         /* No longer need Z2-CT2. */
2281                         put_one_resource(dev, RES_Z2CT2, OWNER_AICMD);
2282                 }
2283         }
2284 }
2285
2286 static int pci230_ai_inttrig_start(comedi_device * dev, comedi_subdevice * s,
2287         unsigned int trig_num)
2288 {
2289         if (trig_num != 0)
2290                 return -EINVAL;
2291
2292         s->async->inttrig = NULLFUNC;
2293         pci230_ai_start(dev, s);
2294
2295         return 1;
2296 }
2297
2298 static int pci230_ai_cmd(comedi_device * dev, comedi_subdevice * s)
2299 {
2300         unsigned int i, chan, range, diff;
2301         unsigned int res_mask;
2302         unsigned short adccon, adcen;
2303         unsigned char zgat;
2304
2305         /* Get the command. */
2306         comedi_async *async = s->async;
2307         comedi_cmd *cmd = &async->cmd;
2308
2309         /*
2310          * Determine which shared resources are needed.
2311          */
2312         res_mask = 0;
2313         /* Need Z2-CT2 to supply a conversion trigger source at a high
2314          * logic level, even if not doing timed conversions. */
2315         res_mask |= (1U << RES_Z2CT2);
2316         if (cmd->scan_begin_src != TRIG_FOLLOW) {
2317                 /* Using Z2-CT0 monostable to gate Z2-CT2 conversion timer */
2318                 res_mask |= (1U << RES_Z2CT0);
2319                 if (cmd->scan_begin_src == TRIG_TIMER) {
2320                         /* Using Z2-CT1 for scan frequency */
2321                         res_mask |= (1U << RES_Z2CT1);
2322                 }
2323         }
2324         /* Claim resources. */
2325         if (!get_resources(dev, res_mask, OWNER_AICMD)) {
2326                 return -EBUSY;
2327         }
2328
2329         /* Get number of scans required. */
2330         if (cmd->stop_src == TRIG_COUNT) {
2331                 devpriv->ai_scan_count = cmd->stop_arg;
2332                 devpriv->ai_continuous = 0;
2333         } else {
2334                 /* TRIG_NONE, user calls cancel. */
2335                 devpriv->ai_scan_count = 0;
2336                 devpriv->ai_continuous = 1;
2337         }
2338         devpriv->ai_scan_pos = 0;       /* Position within scan. */
2339
2340         /* Steps;
2341          * - Set channel scan list.
2342          * - Set channel gains.
2343          * - Enable and reset FIFO, specify uni/bip, se/diff, and set
2344          *   start conversion source to point to something at a high logic
2345          *   level (we use the output of counter/timer 2 for this purpose.
2346          * - PAUSE to allow things to settle down.
2347          * - Reset the FIFO again because it needs resetting twice and there
2348          *   may have been a false conversion trigger on some versions of
2349          *   PCI230/260 due to the start conversion source being set to a
2350          *   high logic level.
2351          * - Enable ADC FIFO level interrupt.
2352          * - Set actual conversion trigger source and FIFO interrupt trigger
2353          *   level.
2354          * - If convert_src is TRIG_TIMER, set up the timers.
2355          */
2356
2357         adccon = PCI230_ADC_FIFO_EN;
2358         adcen = 0;
2359
2360         if (CR_AREF(cmd->chanlist[0]) == AREF_DIFF) {
2361                 /* Differential - all channels must be differential. */
2362                 diff = 1;
2363                 adccon |= PCI230_ADC_IM_DIF;
2364         } else {
2365                 /* Single ended - all channels must be single-ended. */
2366                 diff = 0;
2367                 adccon |= PCI230_ADC_IM_SE;
2368         }
2369
2370         range = CR_RANGE(cmd->chanlist[0]);
2371         devpriv->ai_bipolar = pci230_ai_bipolar[range];
2372         if (devpriv->ai_bipolar) {
2373                 adccon |= PCI230_ADC_IR_BIP;
2374         } else {
2375                 adccon |= PCI230_ADC_IR_UNI;
2376         }
2377         for (i = 0; i < cmd->chanlist_len; i++) {
2378                 unsigned int gainshift;
2379
2380                 chan = CR_CHAN(cmd->chanlist[i]);
2381                 range = CR_RANGE(cmd->chanlist[i]);
2382                 if (diff) {
2383                         gainshift = 2 * chan;
2384                         if (devpriv->hwver == 0) {
2385                                 /* Original PCI230/260 expects both inputs of
2386                                  * the differential channel to be enabled. */
2387                                 adcen |= 3 << gainshift;
2388                         } else {
2389                                 /* PCI230+/260+ expects only one input of the
2390                                  * differential channel to be enabled. */
2391                                 adcen |= 1 << gainshift;
2392                         }
2393                 } else {
2394                         gainshift = (chan & ~1);
2395                         adcen |= 1 << chan;
2396                 }
2397                 devpriv->adcg = (devpriv->adcg & ~(3 << gainshift))
2398                         | (pci230_ai_gain[range] << gainshift);
2399         }
2400
2401         /* Set channel scan list. */
2402         outw(adcen, dev->iobase + PCI230_ADCEN);
2403
2404         /* Set channel gains. */
2405         outw(devpriv->adcg, dev->iobase + PCI230_ADCG);
2406
2407         /* Set counter/timer 2 output high for use as the initial start
2408          * conversion source. */
2409         i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, 2, I8254_MODE1);
2410
2411         /* Temporarily use CT2 output as conversion trigger source and
2412          * temporarily set FIFO interrupt trigger level to 'full'. */
2413         adccon |= PCI230_ADC_INT_FIFO_FULL | PCI230_ADC_TRIG_Z2CT2;
2414
2415         /* Enable and reset FIFO, specify FIFO trigger level full, specify
2416          * uni/bip, se/diff, and temporarily set the start conversion source
2417          * to CT2 output.  Note that CT2 output is currently high, and this
2418          * will produce a false conversion trigger on some versions of the
2419          * PCI230/260, but that will be dealt with later. */
2420         devpriv->adccon = adccon;
2421         outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2422
2423         /* Delay */
2424         /* Failure to include this will result in the first few channels'-worth
2425          * of data being corrupt, normally manifesting itself by large negative
2426          * voltages. It seems the board needs time to settle between the first
2427          * FIFO reset (above) and the second FIFO reset (below). Setting the
2428          * channel gains and scan list _before_ the first FIFO reset also
2429          * helps, though only slightly. */
2430         comedi_udelay(25);
2431
2432         /* Reset FIFO again. */
2433         outw(adccon | PCI230_ADC_FIFO_RESET, dev->iobase + PCI230_ADCCON);
2434
2435         if (cmd->convert_src == TRIG_TIMER) {
2436                 /* Set up CT2 as conversion timer, but gate it off for now.
2437                  * Note, counter/timer output 2 can be monitored on the
2438                  * connector: PCI230 pin 21, PCI260 pin 18. */
2439                 zgat = GAT_CONFIG(2, GAT_GND);
2440                 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2441                 /* Set counter/timer 2 to the specified conversion period. */
2442                 pci230_ct_setup_ns_mode(dev, 2, I8254_MODE3, cmd->convert_arg,
2443                         cmd->flags & TRIG_ROUND_MASK);
2444                 if (cmd->scan_begin_src != TRIG_FOLLOW) {
2445                         /*
2446                          * Set up monostable on CT0 output for scan timing.  A
2447                          * rising edge on the trigger (gate) input of CT0 will
2448                          * trigger the monostable, causing its output to go low
2449                          * for the configured period.  The period depends on
2450                          * the conversion period and the number of conversions
2451                          * in the scan.
2452                          *
2453                          * Set the trigger high before setting up the
2454                          * monostable to stop it triggering.  The trigger
2455                          * source will be changed later.
2456                          */
2457                         zgat = GAT_CONFIG(0, GAT_VCC);
2458                         outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2459                         pci230_ct_setup_ns_mode(dev, 0, I8254_MODE1,
2460                                 ((uint64_t) cmd->convert_arg
2461                                         * cmd->scan_end_arg), TRIG_ROUND_UP);
2462                         if (cmd->scan_begin_src == TRIG_TIMER) {
2463                                 /*
2464                                  * Monostable on CT0 will be triggered by
2465                                  * output of CT1 at configured scan frequency.
2466                                  *
2467                                  * Set up CT1 but gate it off for now.
2468                                  */
2469                                 zgat = GAT_CONFIG(1, GAT_GND);
2470                                 outb(zgat, devpriv->iobase1 + PCI230_ZGAT_SCE);
2471                                 pci230_ct_setup_ns_mode(dev, 1, I8254_MODE3,
2472                                         cmd->scan_begin_arg,
2473                                         cmd->flags & TRIG_ROUND_MASK);
2474                         }
2475                 }
2476         }
2477
2478         if (cmd->start_src == TRIG_INT) {
2479                 s->async->inttrig = pci230_ai_inttrig_start;
2480         } else {
2481                 /* TRIG_NOW */
2482                 pci230_ai_start(dev, s);
2483         }
2484
2485         return 0;
2486 }
2487
2488 static unsigned int divide_ns(uint64_t ns, unsigned int timebase,
2489         unsigned int round_mode)
2490 {
2491         uint64_t div;
2492         unsigned int rem;
2493
2494         div = ns;
2495         rem = do_div(div, timebase);
2496         round_mode &= TRIG_ROUND_MASK;
2497         switch (round_mode) {
2498         default:
2499         case TRIG_ROUND_NEAREST:
2500                 div += (rem + (timebase / 2)) / timebase;
2501                 break;
2502         case TRIG_ROUND_DOWN:
2503                 break;
2504         case TRIG_ROUND_UP:
2505                 div += (rem + timebase - 1) / timebase;
2506                 break;
2507         }
2508         return div > UINT_MAX ? UINT_MAX : (unsigned int)div;
2509 }
2510
2511 /* Given desired period in ns, returns the required internal clock source
2512  * and gets the initial count. */
2513 static unsigned int pci230_choose_clk_count(uint64_t ns, unsigned int *count,
2514         unsigned int round_mode)
2515 {
2516         unsigned int clk_src, cnt;
2517
2518         for (clk_src = CLK_10MHZ;; clk_src++) {
2519                 cnt = divide_ns(ns, pci230_timebase[clk_src], round_mode);
2520                 if ((cnt <= 65536) || (clk_src == CLK_1KHZ)) {
2521                         break;
2522                 }
2523         }
2524         *count = cnt;
2525         return clk_src;
2526 }
2527
2528 static void pci230_ns_to_single_timer(unsigned int *ns, unsigned int round)
2529 {
2530         unsigned int count;
2531         unsigned int clk_src;
2532
2533         clk_src = pci230_choose_clk_count(*ns, &count, round);
2534         *ns = count * pci230_timebase[clk_src];
2535         return;
2536 }
2537
2538 static void pci230_ct_setup_ns_mode(comedi_device * dev, unsigned int ct,
2539         unsigned int mode, uint64_t ns, unsigned int round)
2540 {
2541         unsigned int clk_src;
2542         unsigned int count;
2543
2544         /* Set mode. */
2545         i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, mode);
2546         /* Determine clock source and count. */
2547         clk_src = pci230_choose_clk_count(ns, &count, round);
2548         /* Program clock source. */
2549         outb(CLK_CONFIG(ct, clk_src), devpriv->iobase1 + PCI230_ZCLK_SCE);
2550         /* Set initial count. */
2551         if (count >= 65536) {
2552                 count = 0;
2553         }
2554         i8254_write(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct, count);
2555 }
2556
2557 static void pci230_cancel_ct(comedi_device * dev, unsigned int ct)
2558 {
2559         i8254_set_mode(devpriv->iobase1 + PCI230_Z2_CT_BASE, 0, ct,
2560                 I8254_MODE1);
2561         /* Counter ct, 8254 mode 1, initial count not written. */
2562 }
2563
2564 /* Interrupt handler */
2565 static irqreturn_t pci230_interrupt(int irq, void *d PT_REGS_ARG)
2566 {
2567         unsigned char status_int, valid_status_int;
2568         comedi_device *dev = (comedi_device *) d;
2569         comedi_subdevice *s;
2570         unsigned long irqflags;
2571
2572         /* Read interrupt status/enable register. */
2573         status_int = inb(devpriv->iobase1 + PCI230_INT_STAT);
2574
2575         if (status_int == PCI230_INT_DISABLE) {
2576                 return IRQ_NONE;
2577         }
2578
2579         comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2580         valid_status_int = devpriv->int_en & status_int;
2581         /* Disable triggered interrupts.
2582          * (Only those interrupts that need re-enabling, are, later in the
2583          * handler).  */
2584         devpriv->ier = devpriv->int_en & ~status_int;
2585         outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2586         devpriv->intr_running = 1;
2587         devpriv->intr_cpuid = THISCPU;
2588         comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2589
2590         /*
2591          * Check the source of interrupt and handle it.
2592          * The PCI230 can cope with concurrent ADC, DAC, PPI C0 and C3
2593          * interrupts.  However, at present (Comedi-0.7.60) does not allow
2594          * concurrent execution of commands, instructions or a mixture of the
2595          * two.
2596          */
2597
2598         if ((valid_status_int & PCI230_INT_ZCLK_CT1) != 0) {
2599                 s = dev->write_subdev;
2600                 pci230_handle_ao_nofifo(dev, s);
2601                 comedi_event(dev, s);
2602         }
2603
2604         if ((valid_status_int & PCI230P2_INT_DAC) != 0) {
2605                 s = dev->write_subdev;
2606                 pci230_handle_ao_fifo(dev, s);
2607                 comedi_event(dev, s);
2608         }
2609
2610         if ((valid_status_int & PCI230_INT_ADC) != 0) {
2611                 s = dev->read_subdev;
2612                 pci230_handle_ai(dev, s);
2613                 comedi_event(dev, s);
2614         }
2615
2616         /* Reenable interrupts. */
2617         comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2618         if (devpriv->ier != devpriv->int_en) {
2619                 devpriv->ier = devpriv->int_en;
2620                 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2621         }
2622         devpriv->intr_running = 0;
2623         comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2624
2625         return IRQ_HANDLED;
2626 }
2627
2628 static void pci230_handle_ao_nofifo(comedi_device * dev, comedi_subdevice * s)
2629 {
2630         sampl_t data;
2631         int i, ret;
2632         comedi_async *async = s->async;
2633         comedi_cmd *cmd = &async->cmd;
2634
2635         if (!devpriv->ao_continuous && (devpriv->ao_scan_count == 0)) {
2636                 return;
2637         }
2638
2639         for (i = 0; i < cmd->chanlist_len; i++) {
2640                 /* Read sample from Comedi's circular buffer. */
2641                 ret = comedi_buf_get(s->async, &data);
2642                 if (ret == 0) {
2643                         s->async->events |= COMEDI_CB_OVERFLOW;
2644                         pci230_ao_stop(dev, s);
2645                         comedi_error(dev, "AO buffer underrun");
2646                         return;
2647                 }
2648                 /* Write value to DAC. */
2649                 pci230_ao_write_nofifo(dev, data, CR_CHAN(cmd->chanlist[i]));
2650         }
2651
2652         async->events |= COMEDI_CB_BLOCK | COMEDI_CB_EOS;
2653         if (!devpriv->ao_continuous) {
2654                 devpriv->ao_scan_count--;
2655                 if (devpriv->ao_scan_count == 0) {
2656                         /* End of acquisition. */
2657                         async->events |= COMEDI_CB_EOA;
2658                         pci230_ao_stop(dev, s);
2659                 }
2660         }
2661 }
2662
2663 /* Loads DAC FIFO (if using it) from buffer. */
2664 /* Returns 0 if AO finished due to completion or error, 1 if still going. */
2665 static int pci230_handle_ao_fifo(comedi_device * dev, comedi_subdevice * s)
2666 {
2667         comedi_async *async = s->async;
2668         comedi_cmd *cmd = &async->cmd;
2669         unsigned int num_scans;
2670         unsigned int room;
2671         unsigned short dacstat;
2672         unsigned int i, n;
2673         unsigned int bytes_per_scan;
2674         unsigned int events = 0;
2675         int running;
2676
2677         /* Get DAC FIFO status. */
2678         dacstat = inw(dev->iobase + PCI230_DACCON);
2679
2680         /* Determine number of scans available in buffer. */
2681         bytes_per_scan = cmd->chanlist_len * sizeof(sampl_t);
2682         num_scans = comedi_buf_read_n_available(async) / bytes_per_scan;
2683         if (!devpriv->ao_continuous) {
2684                 /* Fixed number of scans. */
2685                 if (num_scans > devpriv->ao_scan_count) {
2686                         num_scans = devpriv->ao_scan_count;
2687                 }
2688                 if (devpriv->ao_scan_count == 0) {
2689                         /* End of acquisition. */
2690                         events |= COMEDI_CB_EOA;
2691                 }
2692         }
2693         if (events == 0) {
2694                 /* Check for FIFO underrun. */
2695                 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2696                         comedi_error(dev, "AO FIFO underrun");
2697                         events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2698                 }
2699                 /* Check for buffer underrun if FIFO less than half full
2700                  * (otherwise there will be loads of "DAC FIFO not half full"
2701                  * interrupts). */
2702                 if ((num_scans == 0)
2703                         && ((dacstat & PCI230P2_DAC_FIFO_HALF) == 0)) {
2704                         comedi_error(dev, "AO buffer underrun");
2705                         events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2706                 }
2707         }
2708         if (events == 0) {
2709                 /* Determine how much room is in the FIFO (in samples). */
2710                 if ((dacstat & PCI230P2_DAC_FIFO_FULL) != 0) {
2711                         room = PCI230P2_DAC_FIFOROOM_FULL;
2712                 } else if ((dacstat & PCI230P2_DAC_FIFO_HALF) != 0) {
2713                         room = PCI230P2_DAC_FIFOROOM_HALFTOFULL;
2714                 } else if ((dacstat & PCI230P2_DAC_FIFO_EMPTY) != 0) {
2715                         room = PCI230P2_DAC_FIFOROOM_EMPTY;
2716                 } else {
2717                         room = PCI230P2_DAC_FIFOROOM_ONETOHALF;
2718                 }
2719                 /* Convert room to number of scans that can be added. */
2720                 room /= cmd->chanlist_len;
2721                 /* Determine number of scans to process. */
2722                 if (num_scans > room) {
2723                         num_scans = room;
2724                 }
2725                 /* Process scans. */
2726                 for (n = 0; n < num_scans; n++) {
2727                         for (i = 0; i < cmd->chanlist_len; i++) {
2728                                 sampl_t datum;
2729
2730                                 comedi_buf_get(async, &datum);
2731                                 pci230_ao_write_fifo(dev, datum,
2732                                         CR_CHAN(cmd->chanlist[i]));
2733                         }
2734                 }
2735                 events |= COMEDI_CB_EOS | COMEDI_CB_BLOCK;
2736                 if (!devpriv->ao_continuous) {
2737                         devpriv->ao_scan_count -= num_scans;
2738                         if (devpriv->ao_scan_count == 0) {
2739                                 /* All data for the command has been written
2740                                  * to FIFO.  Set FIFO interrupt trigger level
2741                                  * to 'empty'. */
2742                                 devpriv->daccon = (devpriv->daccon
2743                                         & ~PCI230P2_DAC_INT_FIFO_MASK)
2744                                         | PCI230P2_DAC_INT_FIFO_EMPTY;
2745                                 outw(devpriv->daccon,
2746                                         dev->iobase + PCI230_DACCON);
2747                         }
2748                 }
2749                 /* Check if FIFO underrun occurred while writing to FIFO. */
2750                 dacstat = inw(dev->iobase + PCI230_DACCON);
2751                 if ((dacstat & PCI230P2_DAC_FIFO_UNDERRUN_LATCHED) != 0) {
2752                         comedi_error(dev, "AO FIFO underrun");
2753                         events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2754                 }
2755         }
2756         if ((events & (COMEDI_CB_EOA | COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW))
2757                 != 0) {
2758                 /* Stopping AO due to completion or error. */
2759                 pci230_ao_stop(dev, s);
2760                 running = 0;
2761         } else {
2762                 running = 1;
2763         }
2764         async->events |= events;
2765         return running;
2766 }
2767
2768 static void pci230_handle_ai(comedi_device * dev, comedi_subdevice * s)
2769 {
2770         unsigned int events = 0;
2771         unsigned int status_fifo;
2772         unsigned int i;
2773         unsigned int todo;
2774         unsigned int fifoamount;
2775         comedi_async *async = s->async;
2776         unsigned int scanlen = async->cmd.scan_end_arg;
2777
2778         /* Determine number of samples to read. */
2779         if (devpriv->ai_continuous) {
2780                 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2781         } else if (devpriv->ai_scan_count == 0) {
2782                 todo = 0;
2783         } else if ((devpriv->ai_scan_count > PCI230_ADC_FIFOLEVEL_HALFFULL)
2784                 || (scanlen > PCI230_ADC_FIFOLEVEL_HALFFULL)) {
2785                 todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2786         } else {
2787                 todo = (devpriv->ai_scan_count * scanlen)
2788                         - devpriv->ai_scan_pos;
2789                 if (todo > PCI230_ADC_FIFOLEVEL_HALFFULL) {
2790                         todo = PCI230_ADC_FIFOLEVEL_HALFFULL;
2791                 }
2792         }
2793
2794         if (todo == 0) {
2795                 return;
2796         }
2797
2798         fifoamount = 0;
2799         for (i = 0; i < todo; i++) {
2800                 if (fifoamount == 0) {
2801                         /* Read FIFO state. */
2802                         status_fifo = inw(dev->iobase + PCI230_ADCCON);
2803
2804                         if ((status_fifo & PCI230_ADC_FIFO_FULL_LATCHED) != 0) {
2805                                 /* Report error otherwise FIFO overruns will go
2806                                  * unnoticed by the caller. */
2807                                 comedi_error(dev, "AI FIFO overrun");
2808                                 events |= COMEDI_CB_OVERFLOW | COMEDI_CB_ERROR;
2809                                 break;
2810                         } else if ((status_fifo & PCI230_ADC_FIFO_EMPTY) != 0) {
2811                                 /* FIFO empty. */
2812                                 break;
2813                         } else if ((status_fifo & PCI230_ADC_FIFO_HALF) != 0) {
2814                                 /* FIFO half full. */
2815                                 fifoamount = PCI230_ADC_FIFOLEVEL_HALFFULL;
2816                         } else {
2817                                 /* FIFO not empty. */
2818                                 if (devpriv->hwver > 0) {
2819                                         /* Read PCI230+/260+ ADC FIFO level. */
2820                                         fifoamount = inw(dev->iobase
2821                                                 + PCI230P_ADCFFLEV);
2822                                         if (fifoamount == 0) {
2823                                                 /* Shouldn't happen. */
2824                                                 break;
2825                                         }
2826                                 } else {
2827                                         fifoamount = 1;
2828                                 }
2829                         }
2830                 }
2831
2832                 /* Read sample and store in Comedi's circular buffer. */
2833                 if (comedi_buf_put(async, pci230_ai_read(dev)) == 0) {
2834                         events |= COMEDI_CB_ERROR | COMEDI_CB_OVERFLOW;
2835                         comedi_error(dev, "AI buffer overflow");
2836                         break;
2837                 }
2838                 fifoamount--;
2839                 devpriv->ai_scan_pos++;
2840                 if (devpriv->ai_scan_pos == scanlen) {
2841                         /* End of scan. */
2842                         devpriv->ai_scan_pos = 0;
2843                         devpriv->ai_scan_count--;
2844                         async->events |= COMEDI_CB_EOS;
2845                 }
2846         }
2847
2848         if (!devpriv->ai_continuous && (devpriv->ai_scan_count == 0)) {
2849                 /* End of acquisition. */
2850                 events |= COMEDI_CB_EOA;
2851         } else {
2852                 /* More samples required, tell Comedi to block. */
2853                 events |= COMEDI_CB_BLOCK;
2854         }
2855         async->events |= events;
2856
2857         if ((async->events & (COMEDI_CB_EOA | COMEDI_CB_ERROR |
2858                                 COMEDI_CB_OVERFLOW)) != 0) {
2859                 /* disable hardware conversions */
2860                 pci230_ai_stop(dev, s);
2861         } else {
2862                 /* update FIFO interrupt trigger level */
2863                 pci230_ai_update_fifo_trigger_level(dev, s);
2864         }
2865 }
2866
2867 static void pci230_ao_stop(comedi_device * dev, comedi_subdevice * s)
2868 {
2869         unsigned long irqflags;
2870         unsigned char intsrc;
2871         int started;
2872         comedi_cmd *cmd;
2873
2874         comedi_spin_lock_irqsave(&devpriv->ao_stop_spinlock, irqflags);
2875         started = test_and_clear_bit(AO_CMD_STARTED, &devpriv->state);
2876         comedi_spin_unlock_irqrestore(&devpriv->ao_stop_spinlock, irqflags);
2877         if (!started) {
2878                 return;
2879         }
2880
2881         cmd = &s->async->cmd;
2882         if (cmd->scan_begin_src == TRIG_TIMER) {
2883                 /* Stop scan rate generator. */
2884                 pci230_cancel_ct(dev, 1);
2885         }
2886
2887         /* Determine interrupt source. */
2888         if (devpriv->hwver < 2) {
2889                 /* Not using DAC FIFO.  Using CT1 interrupt. */
2890                 intsrc = PCI230_INT_ZCLK_CT1;
2891         } else {
2892                 /* Using DAC FIFO interrupt. */
2893                 intsrc = PCI230P2_INT_DAC;
2894         }
2895         /* Disable interrupt and wait for interrupt routine to finish running
2896          * unless we are called from the interrupt routine. */
2897         comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2898         devpriv->int_en &= ~intsrc;
2899         while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2900                 comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2901                 comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2902         }
2903         if (devpriv->ier != devpriv->int_en) {
2904                 devpriv->ier = devpriv->int_en;
2905                 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2906         }
2907         comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2908
2909         if (devpriv->hwver >= 2) {
2910                 /* Using DAC FIFO.  Reset FIFO, clear underrun error,
2911                  * disable FIFO. */
2912                 devpriv->daccon &= PCI230_DAC_OR_MASK;
2913                 outw(devpriv->daccon | PCI230P2_DAC_FIFO_RESET
2914                         | PCI230P2_DAC_FIFO_UNDERRUN_CLEAR,
2915                         dev->iobase + PCI230_DACCON);
2916         }
2917
2918         /* Release resources. */
2919         put_all_resources(dev, OWNER_AOCMD);
2920 }
2921
2922 static int pci230_ao_cancel(comedi_device * dev, comedi_subdevice * s)
2923 {
2924         pci230_ao_stop(dev, s);
2925         return 0;
2926 }
2927
2928 static void pci230_ai_stop(comedi_device * dev, comedi_subdevice * s)
2929 {
2930         unsigned long irqflags;
2931         comedi_cmd *cmd;
2932         int started;
2933
2934         comedi_spin_lock_irqsave(&devpriv->ai_stop_spinlock, irqflags);
2935         started = test_and_clear_bit(AI_CMD_STARTED, &devpriv->state);
2936         comedi_spin_unlock_irqrestore(&devpriv->ai_stop_spinlock, irqflags);
2937         if (!started) {
2938                 return;
2939         }
2940
2941         cmd = &s->async->cmd;
2942         if (cmd->convert_src == TRIG_TIMER) {
2943                 /* Stop conversion rate generator. */
2944                 pci230_cancel_ct(dev, 2);
2945         }
2946         if (cmd->scan_begin_src != TRIG_FOLLOW) {
2947                 /* Stop scan period monostable. */
2948                 pci230_cancel_ct(dev, 0);
2949         }
2950
2951         comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2952         /* Disable ADC interrupt and wait for interrupt routine to finish
2953          * running unless we are called from the interrupt routine. */
2954         devpriv->int_en &= ~PCI230_INT_ADC;
2955         while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
2956                 comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2957                 comedi_spin_lock_irqsave(&devpriv->isr_spinlock, irqflags);
2958         }
2959         if (devpriv->ier != devpriv->int_en) {
2960                 devpriv->ier = devpriv->int_en;
2961                 outb(devpriv->ier, devpriv->iobase1 + PCI230_INT_SCE);
2962         }
2963         comedi_spin_unlock_irqrestore(&devpriv->isr_spinlock, irqflags);
2964
2965         /* Reset FIFO, disable FIFO and set start conversion source to none.
2966          * Keep se/diff and bip/uni settings */
2967         devpriv->adccon = (devpriv->adccon & (PCI230_ADC_IR_MASK
2968                         | PCI230_ADC_IM_MASK)) | PCI230_ADC_TRIG_NONE;
2969         outw(devpriv->adccon | PCI230_ADC_FIFO_RESET,
2970                 dev->iobase + PCI230_ADCCON);
2971
2972         /* Release resources. */
2973         put_all_resources(dev, OWNER_AICMD);
2974 }
2975
2976 static int pci230_ai_cancel(comedi_device * dev, comedi_subdevice * s)
2977 {
2978         pci230_ai_stop(dev, s);
2979         return 0;
2980 }