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