root/drivers/staging/comedi/drivers/amplc_pci230.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. pci230_clk_config
  2. pci230_gat_config
  3. pci230_ai_read
  4. pci230_ao_mangle_datum
  5. pci230_ao_write_nofifo
  6. pci230_ao_write_fifo
  7. pci230_claim_shared
  8. pci230_release_shared
  9. pci230_release_all_resources
  10. pci230_divide_ns
  11. pci230_choose_clk_count
  12. pci230_ns_to_single_timer
  13. pci230_ct_setup_ns_mode
  14. pci230_cancel_ct
  15. pci230_ai_eoc
  16. pci230_ai_insn_read
  17. pci230_ao_insn_write
  18. pci230_ao_check_chanlist
  19. pci230_ao_cmdtest
  20. pci230_ao_stop
  21. pci230_handle_ao_nofifo
  22. pci230_handle_ao_fifo
  23. pci230_ao_inttrig_scan_begin
  24. pci230_ao_start
  25. pci230_ao_inttrig_start
  26. pci230_ao_cmd
  27. pci230_ao_cancel
  28. pci230_ai_check_scan_period
  29. pci230_ai_check_chanlist
  30. pci230_ai_cmdtest
  31. pci230_ai_update_fifo_trigger_level
  32. pci230_ai_inttrig_convert
  33. pci230_ai_inttrig_scan_begin
  34. pci230_ai_stop
  35. pci230_ai_start
  36. pci230_ai_inttrig_start
  37. pci230_handle_ai
  38. pci230_ai_cmd
  39. pci230_ai_cancel
  40. pci230_interrupt
  41. pci230_match_pci_board
  42. pci230_find_pci_board
  43. pci230_auto_attach
  44. amplc_pci230_pci_probe

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

/* [<][>][^][v][top][bottom][index][help] */