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