Version:  2.0.40 2.2.26 2.4.37 3.5 3.6 3.7 3.8 3.9 3.10 3.11 3.12 3.13 3.14 3.15 3.16 3.17 3.18 3.19 4.0 4.1

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

This page was automatically generated by LXR 0.3.1 (source).  •  Linux is a registered trademark of Linus Torvalds  •  Contact us