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