linux/drivers/comedi/drivers/amplc_pci230.c
<<
>>
Prefs
   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
 371static 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
 384static 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 */
 415enum {
 416        RES_Z2CT0 = BIT(0),     /* Z2-CT0 */
 417        RES_Z2CT1 = BIT(1),     /* Z2-CT1 */
 418        RES_Z2CT2 = BIT(2)      /* Z2-CT2 */
 419};
 420
 421enum {
 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
 441struct 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
 450static 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
 479struct 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 */
 501static 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 */
 510static 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. */
 523static const unsigned char pci230_ai_gain[7] = { 0, 1, 2, 3, 1, 2, 3 };
 524
 525/* PCI230 analogue output range table */
 526static const struct comedi_lrange pci230_ao_range = {
 527        2, {
 528                UNI_RANGE(10),
 529                BIP_RANGE(10)
 530        }
 531};
 532
 533static 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
 554static 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
 574static 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
 584static 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
 594static 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
 616static 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
 627static 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
 633static 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 */
 659static 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
 673static 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
 682static 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
 702static 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
 708static 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
 722static 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
 822static 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
 849static 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
 881static 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
1008static 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
1062static 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 */
1092static 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
1176static 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
1209static 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
1286static 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
1301static 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
1372static 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
1379static 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
1403static 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
1506static 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
1712static 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
1745static 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
1787static 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
1811static 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
1859static 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
1997static 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
2012static 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
2078static 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
2273static 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 */
2281static 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. */
2341static 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. */
2360static 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
2370static 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
2544static 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
2551static 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
2558static 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};
2563MODULE_DEVICE_TABLE(pci, amplc_pci230_pci_table);
2564
2565static 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};
2571module_comedi_pci_driver(amplc_pci230_driver, amplc_pci230_pci_driver);
2572
2573MODULE_AUTHOR("Comedi https://www.comedi.org");
2574MODULE_DESCRIPTION("Comedi driver for Amplicon PCI230(+) and PCI260(+)");
2575MODULE_LICENSE("GPL");
2576