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