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