linux/drivers/staging/comedi/drivers/amplc_pci224.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * comedi/drivers/amplc_pci224.c
   4 * Driver for Amplicon PCI224 and PCI234 AO boards.
   5 *
   6 * Copyright (C) 2005 MEV Ltd. <http://www.mev.co.uk/>
   7 *
   8 * COMEDI - Linux Control and Measurement Device Interface
   9 * Copyright (C) 1998,2000 David A. Schleef <ds@schleef.org>
  10 */
  11
  12/*
  13 * Driver: amplc_pci224
  14 * Description: Amplicon PCI224, PCI234
  15 * Author: Ian Abbott <abbotti@mev.co.uk>
  16 * Devices: [Amplicon] PCI224 (amplc_pci224), PCI234
  17 * Updated: Thu, 31 Jul 2014 11:08:03 +0000
  18 * Status: works, but see caveats
  19 *
  20 * Supports:
  21 *
  22 *   - ao_insn read/write
  23 *   - ao_do_cmd mode with the following sources:
  24 *
  25 *     - start_src         TRIG_INT        TRIG_EXT
  26 *     - scan_begin_src    TRIG_TIMER      TRIG_EXT
  27 *     - convert_src       TRIG_NOW
  28 *     - scan_end_src      TRIG_COUNT
  29 *     - stop_src          TRIG_COUNT      TRIG_EXT        TRIG_NONE
  30 *
  31 *     The channel list must contain at least one channel with no repeated
  32 *     channels.  The scan end count must equal the number of channels in
  33 *     the channel list.
  34 *
  35 *     There is only one external trigger source so only one of start_src,
  36 *     scan_begin_src or stop_src may use TRIG_EXT.
  37 *
  38 * Configuration options:
  39 *   none
  40 *
  41 * Manual configuration of PCI cards is not supported; they are configured
  42 * automatically.
  43 *
  44 * Output range selection - PCI224:
  45 *
  46 *   Output ranges on PCI224 are partly software-selectable and partly
  47 *   hardware-selectable according to jumper LK1.  All channels are set
  48 *   to the same range:
  49 *
  50 *   - LK1 position 1-2 (factory default) corresponds to the following
  51 *     comedi ranges:
  52 *
  53 *       0: [-10V,+10V]; 1: [-5V,+5V]; 2: [-2.5V,+2.5V], 3: [-1.25V,+1.25V],
  54 *       4: [0,+10V],    5: [0,+5V],   6: [0,+2.5V],     7: [0,+1.25V]
  55 *
  56 *   - LK1 position 2-3 corresponds to the following Comedi ranges, using
  57 *     an external voltage reference:
  58 *
  59 *       0: [-Vext,+Vext],
  60 *       1: [0,+Vext]
  61 *
  62 * Output range selection - PCI234:
  63 *
  64 *   Output ranges on PCI234 are hardware-selectable according to jumper
  65 *   LK1 which affects all channels, and jumpers LK2, LK3, LK4 and LK5
  66 *   which affect channels 0, 1, 2 and 3 individually.  LK1 chooses between
  67 *   an internal 5V reference and an external voltage reference (Vext).
  68 *   LK2/3/4/5 choose (per channel) to double the reference or not according
  69 *   to the following table:
  70 *
  71 *     LK1 position   LK2/3/4/5 pos  Comedi range
  72 *     -------------  -------------  --------------
  73 *     2-3 (factory)  1-2 (factory)  0: [-10V,+10V]
  74 *     2-3 (factory)  2-3            1: [-5V,+5V]
  75 *     1-2            1-2 (factory)  2: [-2*Vext,+2*Vext]
  76 *     1-2            2-3            3: [-Vext,+Vext]
  77 *
  78 * Caveats:
  79 *
  80 *   1) All channels on the PCI224 share the same range.  Any change to the
  81 *      range as a result of insn_write or a streaming command will affect
  82 *      the output voltages of all channels, including those not specified
  83 *      by the instruction or command.
  84 *
  85 *   2) For the analog output command,  the first scan may be triggered
  86 *      falsely at the start of acquisition.  This occurs when the DAC scan
  87 *      trigger source is switched from 'none' to 'timer' (scan_begin_src =
  88 *      TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start
  89 *      of acquisition and the trigger source is at logic level 1 at the
  90 *      time of the switch.  This is very likely for TRIG_TIMER.  For
  91 *      TRIG_EXT, it depends on the state of the external line and whether
  92 *      the CR_INVERT flag has been set.  The remaining scans are triggered
  93 *      correctly.
  94 */
  95
  96#include <linux/module.h>
  97#include <linux/interrupt.h>
  98#include <linux/slab.h>
  99
 100#include "../comedi_pci.h"
 101
 102#include "comedi_8254.h"
 103
 104/*
 105 * PCI224/234 i/o space 1 (PCIBAR2) registers.
 106 */
 107#define PCI224_Z2_BASE  0x14    /* 82C54 counter/timer */
 108#define PCI224_ZCLK_SCE 0x1A    /* Group Z Clock Configuration Register */
 109#define PCI224_ZGAT_SCE 0x1D    /* Group Z Gate Configuration Register */
 110#define PCI224_INT_SCE  0x1E    /* ISR Interrupt source mask register */
 111                                /* /Interrupt status */
 112
 113/*
 114 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
 115 */
 116#define PCI224_DACDATA  0x00    /* (w-o) DAC FIFO data. */
 117#define PCI224_SOFTTRIG 0x00    /* (r-o) DAC software scan trigger. */
 118#define PCI224_DACCON   0x02    /* (r/w) DAC status/configuration. */
 119#define PCI224_FIFOSIZ  0x04    /* (w-o) FIFO size for wraparound mode. */
 120#define PCI224_DACCEN   0x06    /* (w-o) DAC channel enable register. */
 121
 122/*
 123 * DACCON values.
 124 */
 125/* (r/w) Scan trigger. */
 126#define PCI224_DACCON_TRIG(x)           (((x) & 0x7) << 0)
 127#define PCI224_DACCON_TRIG_MASK         PCI224_DACCON_TRIG(7)
 128#define PCI224_DACCON_TRIG_NONE         PCI224_DACCON_TRIG(0)   /* none */
 129#define PCI224_DACCON_TRIG_SW           PCI224_DACCON_TRIG(1)   /* soft trig */
 130#define PCI224_DACCON_TRIG_EXTP         PCI224_DACCON_TRIG(2)   /* ext + edge */
 131#define PCI224_DACCON_TRIG_EXTN         PCI224_DACCON_TRIG(3)   /* ext - edge */
 132#define PCI224_DACCON_TRIG_Z2CT0        PCI224_DACCON_TRIG(4)   /* Z2 CT0 out */
 133#define PCI224_DACCON_TRIG_Z2CT1        PCI224_DACCON_TRIG(5)   /* Z2 CT1 out */
 134#define PCI224_DACCON_TRIG_Z2CT2        PCI224_DACCON_TRIG(6)   /* Z2 CT2 out */
 135/* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
 136#define PCI224_DACCON_POLAR(x)          (((x) & 0x1) << 3)
 137#define PCI224_DACCON_POLAR_MASK        PCI224_DACCON_POLAR(1)
 138#define PCI224_DACCON_POLAR_UNI         PCI224_DACCON_POLAR(0)  /* [0,+V] */
 139#define PCI224_DACCON_POLAR_BI          PCI224_DACCON_POLAR(1)  /* [-V,+V] */
 140/* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
 141#define PCI224_DACCON_VREF(x)           (((x) & 0x3) << 4)
 142#define PCI224_DACCON_VREF_MASK         PCI224_DACCON_VREF(3)
 143#define PCI224_DACCON_VREF_1_25         PCI224_DACCON_VREF(0)   /* 1.25V */
 144#define PCI224_DACCON_VREF_2_5          PCI224_DACCON_VREF(1)   /* 2.5V */
 145#define PCI224_DACCON_VREF_5            PCI224_DACCON_VREF(2)   /* 5V */
 146#define PCI224_DACCON_VREF_10           PCI224_DACCON_VREF(3)   /* 10V */
 147/* (r/w) Wraparound mode enable (to play back stored waveform). */
 148#define PCI224_DACCON_FIFOWRAP          BIT(7)
 149/* (r/w) FIFO enable.  It MUST be set! */
 150#define PCI224_DACCON_FIFOENAB          BIT(8)
 151/* (r/w) FIFO interrupt trigger level (most values are not very useful). */
 152#define PCI224_DACCON_FIFOINTR(x)       (((x) & 0x7) << 9)
 153#define PCI224_DACCON_FIFOINTR_MASK     PCI224_DACCON_FIFOINTR(7)
 154#define PCI224_DACCON_FIFOINTR_EMPTY    PCI224_DACCON_FIFOINTR(0) /* empty */
 155#define PCI224_DACCON_FIFOINTR_NEMPTY   PCI224_DACCON_FIFOINTR(1) /* !empty */
 156#define PCI224_DACCON_FIFOINTR_NHALF    PCI224_DACCON_FIFOINTR(2) /* !half */
 157#define PCI224_DACCON_FIFOINTR_HALF     PCI224_DACCON_FIFOINTR(3) /* half */
 158#define PCI224_DACCON_FIFOINTR_NFULL    PCI224_DACCON_FIFOINTR(4) /* !full */
 159#define PCI224_DACCON_FIFOINTR_FULL     PCI224_DACCON_FIFOINTR(5) /* full */
 160/* (r-o) FIFO fill level. */
 161#define PCI224_DACCON_FIFOFL(x)         (((x) & 0x7) << 12)
 162#define PCI224_DACCON_FIFOFL_MASK       PCI224_DACCON_FIFOFL(7)
 163#define PCI224_DACCON_FIFOFL_EMPTY      PCI224_DACCON_FIFOFL(1) /* 0 */
 164#define PCI224_DACCON_FIFOFL_ONETOHALF  PCI224_DACCON_FIFOFL(0) /* 1-2048 */
 165#define PCI224_DACCON_FIFOFL_HALFTOFULL PCI224_DACCON_FIFOFL(4) /* 2049-4095 */
 166#define PCI224_DACCON_FIFOFL_FULL       PCI224_DACCON_FIFOFL(6) /* 4096 */
 167/* (r-o) DAC busy flag. */
 168#define PCI224_DACCON_BUSY              BIT(15)
 169/* (w-o) FIFO reset. */
 170#define PCI224_DACCON_FIFORESET         BIT(12)
 171/* (w-o) Global reset (not sure what it does). */
 172#define PCI224_DACCON_GLOBALRESET       BIT(13)
 173
 174/*
 175 * DAC FIFO size.
 176 */
 177#define PCI224_FIFO_SIZE        4096
 178
 179/*
 180 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
 181 * The maximum room available depends on the reported fill level and how much
 182 * has been written!
 183 */
 184#define PCI224_FIFO_ROOM_EMPTY          PCI224_FIFO_SIZE
 185#define PCI224_FIFO_ROOM_ONETOHALF      (PCI224_FIFO_SIZE / 2)
 186#define PCI224_FIFO_ROOM_HALFTOFULL     1
 187#define PCI224_FIFO_ROOM_FULL           0
 188
 189/*
 190 * Counter/timer clock input configuration sources.
 191 */
 192#define CLK_CLK         0       /* reserved (channel-specific clock) */
 193#define CLK_10MHZ       1       /* internal 10 MHz clock */
 194#define CLK_1MHZ        2       /* internal 1 MHz clock */
 195#define CLK_100KHZ      3       /* internal 100 kHz clock */
 196#define CLK_10KHZ       4       /* internal 10 kHz clock */
 197#define CLK_1KHZ        5       /* internal 1 kHz clock */
 198#define CLK_OUTNM1      6       /* output of channel-1 modulo total */
 199#define CLK_EXT         7       /* external clock */
 200
 201static unsigned int pci224_clk_config(unsigned int chan, unsigned int src)
 202{
 203        return ((chan & 3) << 3) | (src & 7);
 204}
 205
 206/*
 207 * Counter/timer gate input configuration sources.
 208 */
 209#define GAT_VCC         0       /* VCC (i.e. enabled) */
 210#define GAT_GND         1       /* GND (i.e. disabled) */
 211#define GAT_EXT         2       /* reserved (external gate input) */
 212#define GAT_NOUTNM2     3       /* inverted output of channel-2 modulo total */
 213
 214static unsigned int pci224_gat_config(unsigned int chan, unsigned int src)
 215{
 216        return ((chan & 3) << 3) | (src & 7);
 217}
 218
 219/*
 220 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
 221 *
 222 *              Channel's       Channel's
 223 *              clock input     gate input
 224 * Channel      CLK_OUTNM1      GAT_NOUTNM2
 225 * -------      ----------      -----------
 226 * Z2-CT0       Z2-CT2-OUT      /Z2-CT1-OUT
 227 * Z2-CT1       Z2-CT0-OUT      /Z2-CT2-OUT
 228 * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
 229 */
 230
 231/*
 232 * Interrupt enable/status bits
 233 */
 234#define PCI224_INTR_EXT         0x01    /* rising edge on external input */
 235#define PCI224_INTR_DAC         0x04    /* DAC (FIFO) interrupt */
 236#define PCI224_INTR_Z2CT1       0x20    /* rising edge on Z2-CT1 output */
 237
 238#define PCI224_INTR_EDGE_BITS   (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
 239#define PCI224_INTR_LEVEL_BITS  PCI224_INTR_DACFIFO
 240
 241/*
 242 * Handy macros.
 243 */
 244
 245/* Combine old and new bits. */
 246#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
 247
 248/* Current CPU.  XXX should this be hard_smp_processor_id()? */
 249#define THISCPU         smp_processor_id()
 250
 251/* State bits for use with atomic bit operations. */
 252#define AO_CMD_STARTED  0
 253
 254/*
 255 * Range tables.
 256 */
 257
 258/*
 259 * The ranges for PCI224.
 260 *
 261 * These are partly hardware-selectable by jumper LK1 and partly
 262 * software-selectable.
 263 *
 264 * All channels share the same hardware range.
 265 */
 266static const struct comedi_lrange range_pci224 = {
 267        10, {
 268                /* jumper LK1 in position 1-2 (factory default) */
 269                BIP_RANGE(10),
 270                BIP_RANGE(5),
 271                BIP_RANGE(2.5),
 272                BIP_RANGE(1.25),
 273                UNI_RANGE(10),
 274                UNI_RANGE(5),
 275                UNI_RANGE(2.5),
 276                UNI_RANGE(1.25),
 277                /* jumper LK1 in position 2-3 */
 278                RANGE_ext(-1, 1),       /* bipolar [-Vext,+Vext] */
 279                RANGE_ext(0, 1),        /* unipolar [0,+Vext] */
 280        }
 281};
 282
 283static const unsigned short hwrange_pci224[10] = {
 284        /* jumper LK1 in position 1-2 (factory default) */
 285        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
 286        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
 287        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
 288        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
 289        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
 290        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
 291        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
 292        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
 293        /* jumper LK1 in position 2-3 */
 294        PCI224_DACCON_POLAR_BI,
 295        PCI224_DACCON_POLAR_UNI,
 296};
 297
 298/* Used to check all channels set to the same range on PCI224. */
 299static const unsigned char range_check_pci224[10] = {
 300        0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
 301};
 302
 303/*
 304 * The ranges for PCI234.
 305 *
 306 * These are all hardware-selectable by jumper LK1 affecting all channels,
 307 * and jumpers LK2, LK3, LK4 and LK5 affecting channels 0, 1, 2 and 3
 308 * individually.
 309 */
 310static const struct comedi_lrange range_pci234 = {
 311        4, {
 312                /* LK1: 1-2 (fact def), LK2/3/4/5: 2-3 (fac def) */
 313                BIP_RANGE(10),
 314                /* LK1: 1-2 (fact def), LK2/3/4/5: 1-2 */
 315                BIP_RANGE(5),
 316                /* LK1: 2-3, LK2/3/4/5: 2-3 (fac def) */
 317                RANGE_ext(-2, 2),       /* bipolar [-2*Vext,+2*Vext] */
 318                /* LK1: 2-3, LK2/3/4/5: 1-2 */
 319                RANGE_ext(-1, 1),       /* bipolar [-Vext,+Vext] */
 320        }
 321};
 322
 323/* N.B. PCI234 ignores the polarity bit, but software uses it. */
 324static const unsigned short hwrange_pci234[4] = {
 325        PCI224_DACCON_POLAR_BI,
 326        PCI224_DACCON_POLAR_BI,
 327        PCI224_DACCON_POLAR_BI,
 328        PCI224_DACCON_POLAR_BI,
 329};
 330
 331/* Used to check all channels use same LK1 setting on PCI234. */
 332static const unsigned char range_check_pci234[4] = {
 333        0, 0, 1, 1,
 334};
 335
 336/*
 337 * Board descriptions.
 338 */
 339
 340enum pci224_model { pci224_model, pci234_model };
 341
 342struct pci224_board {
 343        const char *name;
 344        unsigned int ao_chans;
 345        unsigned int ao_bits;
 346        const struct comedi_lrange *ao_range;
 347        const unsigned short *ao_hwrange;
 348        const unsigned char *ao_range_check;
 349};
 350
 351static const struct pci224_board pci224_boards[] = {
 352        [pci224_model] = {
 353                .name           = "pci224",
 354                .ao_chans       = 16,
 355                .ao_bits        = 12,
 356                .ao_range       = &range_pci224,
 357                .ao_hwrange     = &hwrange_pci224[0],
 358                .ao_range_check = &range_check_pci224[0],
 359        },
 360        [pci234_model] = {
 361                .name           = "pci234",
 362                .ao_chans       = 4,
 363                .ao_bits        = 16,
 364                .ao_range       = &range_pci234,
 365                .ao_hwrange     = &hwrange_pci234[0],
 366                .ao_range_check = &range_check_pci234[0],
 367        },
 368};
 369
 370struct pci224_private {
 371        unsigned long iobase1;
 372        unsigned long state;
 373        spinlock_t ao_spinlock; /* spinlock for AO command handling */
 374        unsigned short *ao_scan_vals;
 375        unsigned char *ao_scan_order;
 376        int intr_cpuid;
 377        short intr_running;
 378        unsigned short daccon;
 379        unsigned short ao_enab; /* max 16 channels so 'short' will do */
 380        unsigned char intsce;
 381};
 382
 383/*
 384 * Called from the 'insn_write' function to perform a single write.
 385 */
 386static void
 387pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
 388                   unsigned int data)
 389{
 390        const struct pci224_board *board = dev->board_ptr;
 391        struct pci224_private *devpriv = dev->private;
 392        unsigned short mangled;
 393
 394        /* Enable the channel. */
 395        outw(1 << chan, dev->iobase + PCI224_DACCEN);
 396        /* Set range and reset FIFO. */
 397        devpriv->daccon = COMBINE(devpriv->daccon, board->ao_hwrange[range],
 398                                  PCI224_DACCON_POLAR_MASK |
 399                                  PCI224_DACCON_VREF_MASK);
 400        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 401             dev->iobase + PCI224_DACCON);
 402        /*
 403         * Mangle the data.  The hardware expects:
 404         * - bipolar: 16-bit 2's complement
 405         * - unipolar: 16-bit unsigned
 406         */
 407        mangled = (unsigned short)data << (16 - board->ao_bits);
 408        if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
 409            PCI224_DACCON_POLAR_BI) {
 410                mangled ^= 0x8000;
 411        }
 412        /* Write mangled data to the FIFO. */
 413        outw(mangled, dev->iobase + PCI224_DACDATA);
 414        /* Trigger the conversion. */
 415        inw(dev->iobase + PCI224_SOFTTRIG);
 416}
 417
 418static int pci224_ao_insn_write(struct comedi_device *dev,
 419                                struct comedi_subdevice *s,
 420                                struct comedi_insn *insn,
 421                                unsigned int *data)
 422{
 423        unsigned int chan = CR_CHAN(insn->chanspec);
 424        unsigned int range = CR_RANGE(insn->chanspec);
 425        unsigned int val = s->readback[chan];
 426        int i;
 427
 428        for (i = 0; i < insn->n; i++) {
 429                val = data[i];
 430                pci224_ao_set_data(dev, chan, range, val);
 431        }
 432        s->readback[chan] = val;
 433
 434        return insn->n;
 435}
 436
 437/*
 438 * Kills a command running on the AO subdevice.
 439 */
 440static void pci224_ao_stop(struct comedi_device *dev,
 441                           struct comedi_subdevice *s)
 442{
 443        struct pci224_private *devpriv = dev->private;
 444        unsigned long flags;
 445
 446        if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
 447                return;
 448
 449        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 450        /* Kill the interrupts. */
 451        devpriv->intsce = 0;
 452        outb(0, devpriv->iobase1 + PCI224_INT_SCE);
 453        /*
 454         * Interrupt routine may or may not be running.  We may or may not
 455         * have been called from the interrupt routine (directly or
 456         * indirectly via a comedi_events() callback routine).  It's highly
 457         * unlikely that we've been called from some other interrupt routine
 458         * but who knows what strange things coders get up to!
 459         *
 460         * If the interrupt routine is currently running, wait for it to
 461         * finish, unless we appear to have been called via the interrupt
 462         * routine.
 463         */
 464        while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
 465                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 466                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 467        }
 468        spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 469        /* Reconfigure DAC for insn_write usage. */
 470        outw(0, dev->iobase + PCI224_DACCEN);   /* Disable channels. */
 471        devpriv->daccon =
 472             COMBINE(devpriv->daccon,
 473                     PCI224_DACCON_TRIG_SW | PCI224_DACCON_FIFOINTR_EMPTY,
 474                     PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
 475        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 476             dev->iobase + PCI224_DACCON);
 477}
 478
 479/*
 480 * Handles start of acquisition for the AO subdevice.
 481 */
 482static void pci224_ao_start(struct comedi_device *dev,
 483                            struct comedi_subdevice *s)
 484{
 485        struct pci224_private *devpriv = dev->private;
 486        struct comedi_cmd *cmd = &s->async->cmd;
 487        unsigned long flags;
 488
 489        set_bit(AO_CMD_STARTED, &devpriv->state);
 490
 491        /* Enable interrupts. */
 492        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 493        if (cmd->stop_src == TRIG_EXT)
 494                devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
 495        else
 496                devpriv->intsce = PCI224_INTR_DAC;
 497
 498        outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
 499        spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 500}
 501
 502/*
 503 * Handles interrupts from the DAC FIFO.
 504 */
 505static void pci224_ao_handle_fifo(struct comedi_device *dev,
 506                                  struct comedi_subdevice *s)
 507{
 508        struct pci224_private *devpriv = dev->private;
 509        struct comedi_cmd *cmd = &s->async->cmd;
 510        unsigned int num_scans = comedi_nscans_left(s, 0);
 511        unsigned int room;
 512        unsigned short dacstat;
 513        unsigned int i, n;
 514
 515        /* Determine how much room is in the FIFO (in samples). */
 516        dacstat = inw(dev->iobase + PCI224_DACCON);
 517        switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
 518        case PCI224_DACCON_FIFOFL_EMPTY:
 519                room = PCI224_FIFO_ROOM_EMPTY;
 520                if (cmd->stop_src == TRIG_COUNT &&
 521                    s->async->scans_done >= cmd->stop_arg) {
 522                        /* FIFO empty at end of counted acquisition. */
 523                        s->async->events |= COMEDI_CB_EOA;
 524                        comedi_handle_events(dev, s);
 525                        return;
 526                }
 527                break;
 528        case PCI224_DACCON_FIFOFL_ONETOHALF:
 529                room = PCI224_FIFO_ROOM_ONETOHALF;
 530                break;
 531        case PCI224_DACCON_FIFOFL_HALFTOFULL:
 532                room = PCI224_FIFO_ROOM_HALFTOFULL;
 533                break;
 534        default:
 535                room = PCI224_FIFO_ROOM_FULL;
 536                break;
 537        }
 538        if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
 539                /* FIFO is less than half-full. */
 540                if (num_scans == 0) {
 541                        /* Nothing left to put in the FIFO. */
 542                        dev_err(dev->class_dev, "AO buffer underrun\n");
 543                        s->async->events |= COMEDI_CB_OVERFLOW;
 544                }
 545        }
 546        /* Determine how many new scans can be put in the FIFO. */
 547        room /= cmd->chanlist_len;
 548
 549        /* Determine how many scans to process. */
 550        if (num_scans > room)
 551                num_scans = room;
 552
 553        /* Process scans. */
 554        for (n = 0; n < num_scans; n++) {
 555                comedi_buf_read_samples(s, &devpriv->ao_scan_vals[0],
 556                                        cmd->chanlist_len);
 557                for (i = 0; i < cmd->chanlist_len; i++) {
 558                        outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
 559                             dev->iobase + PCI224_DACDATA);
 560                }
 561        }
 562        if (cmd->stop_src == TRIG_COUNT &&
 563            s->async->scans_done >= cmd->stop_arg) {
 564                /*
 565                 * Change FIFO interrupt trigger level to wait
 566                 * until FIFO is empty.
 567                 */
 568                devpriv->daccon = COMBINE(devpriv->daccon,
 569                                          PCI224_DACCON_FIFOINTR_EMPTY,
 570                                          PCI224_DACCON_FIFOINTR_MASK);
 571                outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 572        }
 573        if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
 574            PCI224_DACCON_TRIG_NONE) {
 575                unsigned short trig;
 576
 577                /*
 578                 * This is the initial DAC FIFO interrupt at the
 579                 * start of the acquisition.  The DAC's scan trigger
 580                 * has been set to 'none' up until now.
 581                 *
 582                 * Now that data has been written to the FIFO, the
 583                 * DAC's scan trigger source can be set to the
 584                 * correct value.
 585                 *
 586                 * BUG: The first scan will be triggered immediately
 587                 * if the scan trigger source is at logic level 1.
 588                 */
 589                if (cmd->scan_begin_src == TRIG_TIMER) {
 590                        trig = PCI224_DACCON_TRIG_Z2CT0;
 591                } else {
 592                        /* cmd->scan_begin_src == TRIG_EXT */
 593                        if (cmd->scan_begin_arg & CR_INVERT)
 594                                trig = PCI224_DACCON_TRIG_EXTN;
 595                        else
 596                                trig = PCI224_DACCON_TRIG_EXTP;
 597                }
 598                devpriv->daccon =
 599                    COMBINE(devpriv->daccon, trig, PCI224_DACCON_TRIG_MASK);
 600                outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 601        }
 602
 603        comedi_handle_events(dev, s);
 604}
 605
 606static int pci224_ao_inttrig_start(struct comedi_device *dev,
 607                                   struct comedi_subdevice *s,
 608                                   unsigned int trig_num)
 609{
 610        struct comedi_cmd *cmd = &s->async->cmd;
 611
 612        if (trig_num != cmd->start_arg)
 613                return -EINVAL;
 614
 615        s->async->inttrig = NULL;
 616        pci224_ao_start(dev, s);
 617
 618        return 1;
 619}
 620
 621static int pci224_ao_check_chanlist(struct comedi_device *dev,
 622                                    struct comedi_subdevice *s,
 623                                    struct comedi_cmd *cmd)
 624{
 625        const struct pci224_board *board = dev->board_ptr;
 626        unsigned int range_check_0;
 627        unsigned int chan_mask = 0;
 628        int i;
 629
 630        range_check_0 = board->ao_range_check[CR_RANGE(cmd->chanlist[0])];
 631        for (i = 0; i < cmd->chanlist_len; i++) {
 632                unsigned int chan = CR_CHAN(cmd->chanlist[i]);
 633
 634                if (chan_mask & (1 << chan)) {
 635                        dev_dbg(dev->class_dev,
 636                                "%s: entries in chanlist must contain no duplicate channels\n",
 637                                __func__);
 638                        return -EINVAL;
 639                }
 640                chan_mask |= 1 << chan;
 641
 642                if (board->ao_range_check[CR_RANGE(cmd->chanlist[i])] !=
 643                    range_check_0) {
 644                        dev_dbg(dev->class_dev,
 645                                "%s: entries in chanlist have incompatible ranges\n",
 646                                __func__);
 647                        return -EINVAL;
 648                }
 649        }
 650
 651        return 0;
 652}
 653
 654#define MAX_SCAN_PERIOD         0xFFFFFFFFU
 655#define MIN_SCAN_PERIOD         2500
 656#define CONVERT_PERIOD          625
 657
 658/*
 659 * 'do_cmdtest' function for AO subdevice.
 660 */
 661static int
 662pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 663                  struct comedi_cmd *cmd)
 664{
 665        int err = 0;
 666        unsigned int arg;
 667
 668        /* Step 1 : check if triggers are trivially valid */
 669
 670        err |= comedi_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
 671        err |= comedi_check_trigger_src(&cmd->scan_begin_src,
 672                                        TRIG_EXT | TRIG_TIMER);
 673        err |= comedi_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 674        err |= comedi_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 675        err |= comedi_check_trigger_src(&cmd->stop_src,
 676                                        TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 677
 678        if (err)
 679                return 1;
 680
 681        /* Step 2a : make sure trigger sources are unique */
 682
 683        err |= comedi_check_trigger_is_unique(cmd->start_src);
 684        err |= comedi_check_trigger_is_unique(cmd->scan_begin_src);
 685        err |= comedi_check_trigger_is_unique(cmd->stop_src);
 686
 687        /* Step 2b : and mutually compatible */
 688
 689        /*
 690         * There's only one external trigger signal (which makes these
 691         * tests easier).  Only one thing can use it.
 692         */
 693        arg = 0;
 694        if (cmd->start_src & TRIG_EXT)
 695                arg++;
 696        if (cmd->scan_begin_src & TRIG_EXT)
 697                arg++;
 698        if (cmd->stop_src & TRIG_EXT)
 699                arg++;
 700        if (arg > 1)
 701                err |= -EINVAL;
 702
 703        if (err)
 704                return 2;
 705
 706        /* Step 3: check if arguments are trivially valid */
 707
 708        switch (cmd->start_src) {
 709        case TRIG_INT:
 710                err |= comedi_check_trigger_arg_is(&cmd->start_arg, 0);
 711                break;
 712        case TRIG_EXT:
 713                /* Force to external trigger 0. */
 714                if (cmd->start_arg & ~CR_FLAGS_MASK) {
 715                        cmd->start_arg =
 716                            COMBINE(cmd->start_arg, 0, ~CR_FLAGS_MASK);
 717                        err |= -EINVAL;
 718                }
 719                /* The only flag allowed is CR_EDGE, which is ignored. */
 720                if (cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) {
 721                        cmd->start_arg = COMBINE(cmd->start_arg, 0,
 722                                                 CR_FLAGS_MASK & ~CR_EDGE);
 723                        err |= -EINVAL;
 724                }
 725                break;
 726        }
 727
 728        switch (cmd->scan_begin_src) {
 729        case TRIG_TIMER:
 730                err |= comedi_check_trigger_arg_max(&cmd->scan_begin_arg,
 731                                                    MAX_SCAN_PERIOD);
 732
 733                arg = cmd->chanlist_len * CONVERT_PERIOD;
 734                if (arg < MIN_SCAN_PERIOD)
 735                        arg = MIN_SCAN_PERIOD;
 736                err |= comedi_check_trigger_arg_min(&cmd->scan_begin_arg, arg);
 737                break;
 738        case TRIG_EXT:
 739                /* Force to external trigger 0. */
 740                if (cmd->scan_begin_arg & ~CR_FLAGS_MASK) {
 741                        cmd->scan_begin_arg =
 742                            COMBINE(cmd->scan_begin_arg, 0, ~CR_FLAGS_MASK);
 743                        err |= -EINVAL;
 744                }
 745                /* Only allow flags CR_EDGE and CR_INVERT.  Ignore CR_EDGE. */
 746                if (cmd->scan_begin_arg & CR_FLAGS_MASK &
 747                    ~(CR_EDGE | CR_INVERT)) {
 748                        cmd->scan_begin_arg =
 749                            COMBINE(cmd->scan_begin_arg, 0,
 750                                    CR_FLAGS_MASK & ~(CR_EDGE | CR_INVERT));
 751                        err |= -EINVAL;
 752                }
 753                break;
 754        }
 755
 756        err |= comedi_check_trigger_arg_is(&cmd->convert_arg, 0);
 757        err |= comedi_check_trigger_arg_is(&cmd->scan_end_arg,
 758                                           cmd->chanlist_len);
 759
 760        switch (cmd->stop_src) {
 761        case TRIG_COUNT:
 762                err |= comedi_check_trigger_arg_min(&cmd->stop_arg, 1);
 763                break;
 764        case TRIG_EXT:
 765                /* Force to external trigger 0. */
 766                if (cmd->stop_arg & ~CR_FLAGS_MASK) {
 767                        cmd->stop_arg =
 768                            COMBINE(cmd->stop_arg, 0, ~CR_FLAGS_MASK);
 769                        err |= -EINVAL;
 770                }
 771                /* The only flag allowed is CR_EDGE, which is ignored. */
 772                if (cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) {
 773                        cmd->stop_arg =
 774                            COMBINE(cmd->stop_arg, 0, CR_FLAGS_MASK & ~CR_EDGE);
 775                }
 776                break;
 777        case TRIG_NONE:
 778                err |= comedi_check_trigger_arg_is(&cmd->stop_arg, 0);
 779                break;
 780        }
 781
 782        if (err)
 783                return 3;
 784
 785        /* Step 4: fix up any arguments. */
 786
 787        if (cmd->scan_begin_src == TRIG_TIMER) {
 788                arg = cmd->scan_begin_arg;
 789                /* Use two timers. */
 790                comedi_8254_cascade_ns_to_timer(dev->pacer, &arg, cmd->flags);
 791                err |= comedi_check_trigger_arg_is(&cmd->scan_begin_arg, arg);
 792        }
 793
 794        if (err)
 795                return 4;
 796
 797        /* Step 5: check channel list if it exists */
 798        if (cmd->chanlist && cmd->chanlist_len > 0)
 799                err |= pci224_ao_check_chanlist(dev, s, cmd);
 800
 801        if (err)
 802                return 5;
 803
 804        return 0;
 805}
 806
 807static void pci224_ao_start_pacer(struct comedi_device *dev,
 808                                  struct comedi_subdevice *s)
 809{
 810        struct pci224_private *devpriv = dev->private;
 811
 812        /*
 813         * The output of timer Z2-0 will be used as the scan trigger
 814         * source.
 815         */
 816        /* Make sure Z2-0 is gated on.  */
 817        outb(pci224_gat_config(0, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
 818        /* Cascading with Z2-2. */
 819        /* Make sure Z2-2 is gated on.  */
 820        outb(pci224_gat_config(2, GAT_VCC), devpriv->iobase1 + PCI224_ZGAT_SCE);
 821        /* Z2-2 needs 10 MHz clock. */
 822        outb(pci224_clk_config(2, CLK_10MHZ),
 823             devpriv->iobase1 + PCI224_ZCLK_SCE);
 824        /* Z2-0 is clocked from Z2-2's output. */
 825        outb(pci224_clk_config(0, CLK_OUTNM1),
 826             devpriv->iobase1 + PCI224_ZCLK_SCE);
 827
 828        comedi_8254_pacer_enable(dev->pacer, 2, 0, false);
 829}
 830
 831static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 832{
 833        const struct pci224_board *board = dev->board_ptr;
 834        struct pci224_private *devpriv = dev->private;
 835        struct comedi_cmd *cmd = &s->async->cmd;
 836        int range;
 837        unsigned int i, j;
 838        unsigned int ch;
 839        unsigned int rank;
 840        unsigned long flags;
 841
 842        /* Cannot handle null/empty chanlist. */
 843        if (!cmd->chanlist || cmd->chanlist_len == 0)
 844                return -EINVAL;
 845
 846        /* Determine which channels are enabled and their load order.  */
 847        devpriv->ao_enab = 0;
 848
 849        for (i = 0; i < cmd->chanlist_len; i++) {
 850                ch = CR_CHAN(cmd->chanlist[i]);
 851                devpriv->ao_enab |= 1U << ch;
 852                rank = 0;
 853                for (j = 0; j < cmd->chanlist_len; j++) {
 854                        if (CR_CHAN(cmd->chanlist[j]) < ch)
 855                                rank++;
 856                }
 857                devpriv->ao_scan_order[rank] = i;
 858        }
 859
 860        /* Set enabled channels. */
 861        outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
 862
 863        /* Determine range and polarity.  All channels the same.  */
 864        range = CR_RANGE(cmd->chanlist[0]);
 865
 866        /*
 867         * Set DAC range and polarity.
 868         * Set DAC scan trigger source to 'none'.
 869         * Set DAC FIFO interrupt trigger level to 'not half full'.
 870         * Reset DAC FIFO.
 871         *
 872         * N.B. DAC FIFO interrupts are currently disabled.
 873         */
 874        devpriv->daccon =
 875            COMBINE(devpriv->daccon,
 876                    board->ao_hwrange[range] | PCI224_DACCON_TRIG_NONE |
 877                    PCI224_DACCON_FIFOINTR_NHALF,
 878                    PCI224_DACCON_POLAR_MASK | PCI224_DACCON_VREF_MASK |
 879                    PCI224_DACCON_TRIG_MASK | PCI224_DACCON_FIFOINTR_MASK);
 880        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 881             dev->iobase + PCI224_DACCON);
 882
 883        if (cmd->scan_begin_src == TRIG_TIMER) {
 884                comedi_8254_update_divisors(dev->pacer);
 885                pci224_ao_start_pacer(dev, s);
 886        }
 887
 888        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 889        if (cmd->start_src == TRIG_INT) {
 890                s->async->inttrig = pci224_ao_inttrig_start;
 891        } else {        /* TRIG_EXT */
 892                /* Enable external interrupt trigger to start acquisition. */
 893                devpriv->intsce |= PCI224_INTR_EXT;
 894                outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
 895        }
 896        spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 897
 898        return 0;
 899}
 900
 901/*
 902 * 'cancel' function for AO subdevice.
 903 */
 904static int pci224_ao_cancel(struct comedi_device *dev,
 905                            struct comedi_subdevice *s)
 906{
 907        pci224_ao_stop(dev, s);
 908        return 0;
 909}
 910
 911/*
 912 * 'munge' data for AO command.
 913 */
 914static void
 915pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
 916                void *data, unsigned int num_bytes, unsigned int chan_index)
 917{
 918        const struct pci224_board *board = dev->board_ptr;
 919        struct comedi_cmd *cmd = &s->async->cmd;
 920        unsigned short *array = data;
 921        unsigned int length = num_bytes / sizeof(*array);
 922        unsigned int offset;
 923        unsigned int shift;
 924        unsigned int i;
 925
 926        /* The hardware expects 16-bit numbers. */
 927        shift = 16 - board->ao_bits;
 928        /* Channels will be all bipolar or all unipolar. */
 929        if ((board->ao_hwrange[CR_RANGE(cmd->chanlist[0])] &
 930             PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
 931                /* Unipolar */
 932                offset = 0;
 933        } else {
 934                /* Bipolar */
 935                offset = 32768;
 936        }
 937        /* Munge the data. */
 938        for (i = 0; i < length; i++)
 939                array[i] = (array[i] << shift) - offset;
 940}
 941
 942/*
 943 * Interrupt handler.
 944 */
 945static irqreturn_t pci224_interrupt(int irq, void *d)
 946{
 947        struct comedi_device *dev = d;
 948        struct pci224_private *devpriv = dev->private;
 949        struct comedi_subdevice *s = dev->write_subdev;
 950        struct comedi_cmd *cmd;
 951        unsigned char intstat, valid_intstat;
 952        unsigned char curenab;
 953        int retval = 0;
 954        unsigned long flags;
 955
 956        intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
 957        if (intstat) {
 958                retval = 1;
 959                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 960                valid_intstat = devpriv->intsce & intstat;
 961                /* Temporarily disable interrupt sources. */
 962                curenab = devpriv->intsce & ~intstat;
 963                outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
 964                devpriv->intr_running = 1;
 965                devpriv->intr_cpuid = THISCPU;
 966                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 967                if (valid_intstat) {
 968                        cmd = &s->async->cmd;
 969                        if (valid_intstat & PCI224_INTR_EXT) {
 970                                devpriv->intsce &= ~PCI224_INTR_EXT;
 971                                if (cmd->start_src == TRIG_EXT)
 972                                        pci224_ao_start(dev, s);
 973                                else if (cmd->stop_src == TRIG_EXT)
 974                                        pci224_ao_stop(dev, s);
 975                        }
 976                        if (valid_intstat & PCI224_INTR_DAC)
 977                                pci224_ao_handle_fifo(dev, s);
 978                }
 979                /* Reenable interrupt sources. */
 980                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 981                if (curenab != devpriv->intsce) {
 982                        outb(devpriv->intsce,
 983                             devpriv->iobase1 + PCI224_INT_SCE);
 984                }
 985                devpriv->intr_running = 0;
 986                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 987        }
 988        return IRQ_RETVAL(retval);
 989}
 990
 991static int
 992pci224_auto_attach(struct comedi_device *dev, unsigned long context_model)
 993{
 994        struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
 995        const struct pci224_board *board = NULL;
 996        struct pci224_private *devpriv;
 997        struct comedi_subdevice *s;
 998        unsigned int irq;
 999        int ret;
1000
1001        if (context_model < ARRAY_SIZE(pci224_boards))
1002                board = &pci224_boards[context_model];
1003        if (!board || !board->name) {
1004                dev_err(dev->class_dev,
1005                        "amplc_pci224: BUG! cannot determine board type!\n");
1006                return -EINVAL;
1007        }
1008        dev->board_ptr = board;
1009        dev->board_name = board->name;
1010
1011        dev_info(dev->class_dev, "amplc_pci224: attach pci %s - %s\n",
1012                 pci_name(pci_dev), dev->board_name);
1013
1014        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1015        if (!devpriv)
1016                return -ENOMEM;
1017
1018        ret = comedi_pci_enable(dev);
1019        if (ret)
1020                return ret;
1021
1022        spin_lock_init(&devpriv->ao_spinlock);
1023
1024        devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1025        dev->iobase = pci_resource_start(pci_dev, 3);
1026        irq = pci_dev->irq;
1027
1028        /* Allocate buffer to hold values for AO channel scan. */
1029        devpriv->ao_scan_vals = kmalloc_array(board->ao_chans,
1030                                              sizeof(devpriv->ao_scan_vals[0]),
1031                                              GFP_KERNEL);
1032        if (!devpriv->ao_scan_vals)
1033                return -ENOMEM;
1034
1035        /* Allocate buffer to hold AO channel scan order. */
1036        devpriv->ao_scan_order =
1037                                kmalloc_array(board->ao_chans,
1038                                              sizeof(devpriv->ao_scan_order[0]),
1039                                              GFP_KERNEL);
1040        if (!devpriv->ao_scan_order)
1041                return -ENOMEM;
1042
1043        /* Disable interrupt sources. */
1044        devpriv->intsce = 0;
1045        outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1046
1047        /* Initialize the DAC hardware. */
1048        outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1049        outw(0, dev->iobase + PCI224_DACCEN);
1050        outw(0, dev->iobase + PCI224_FIFOSIZ);
1051        devpriv->daccon = PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1052                          PCI224_DACCON_FIFOENAB | PCI224_DACCON_FIFOINTR_EMPTY;
1053        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1054             dev->iobase + PCI224_DACCON);
1055
1056        dev->pacer = comedi_8254_init(devpriv->iobase1 + PCI224_Z2_BASE,
1057                                      I8254_OSC_BASE_10MHZ, I8254_IO8, 0);
1058        if (!dev->pacer)
1059                return -ENOMEM;
1060
1061        ret = comedi_alloc_subdevices(dev, 1);
1062        if (ret)
1063                return ret;
1064
1065        s = &dev->subdevices[0];
1066        /* Analog output subdevice. */
1067        s->type = COMEDI_SUBD_AO;
1068        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1069        s->n_chan = board->ao_chans;
1070        s->maxdata = (1 << board->ao_bits) - 1;
1071        s->range_table = board->ao_range;
1072        s->insn_write = pci224_ao_insn_write;
1073        s->len_chanlist = s->n_chan;
1074        dev->write_subdev = s;
1075        s->do_cmd = pci224_ao_cmd;
1076        s->do_cmdtest = pci224_ao_cmdtest;
1077        s->cancel = pci224_ao_cancel;
1078        s->munge = pci224_ao_munge;
1079
1080        ret = comedi_alloc_subdev_readback(s);
1081        if (ret)
1082                return ret;
1083
1084        if (irq) {
1085                ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1086                                  dev->board_name, dev);
1087                if (ret < 0) {
1088                        dev_err(dev->class_dev,
1089                                "error! unable to allocate irq %u\n", irq);
1090                        return ret;
1091                }
1092                dev->irq = irq;
1093        }
1094
1095        return 0;
1096}
1097
1098static void pci224_detach(struct comedi_device *dev)
1099{
1100        struct pci224_private *devpriv = dev->private;
1101
1102        comedi_pci_detach(dev);
1103        if (devpriv) {
1104                kfree(devpriv->ao_scan_vals);
1105                kfree(devpriv->ao_scan_order);
1106        }
1107}
1108
1109static struct comedi_driver amplc_pci224_driver = {
1110        .driver_name    = "amplc_pci224",
1111        .module         = THIS_MODULE,
1112        .detach         = pci224_detach,
1113        .auto_attach    = pci224_auto_attach,
1114        .board_name     = &pci224_boards[0].name,
1115        .offset         = sizeof(struct pci224_board),
1116        .num_names      = ARRAY_SIZE(pci224_boards),
1117};
1118
1119static int amplc_pci224_pci_probe(struct pci_dev *dev,
1120                                  const struct pci_device_id *id)
1121{
1122        return comedi_pci_auto_config(dev, &amplc_pci224_driver,
1123                                      id->driver_data);
1124}
1125
1126static const struct pci_device_id amplc_pci224_pci_table[] = {
1127        { PCI_VDEVICE(AMPLICON, 0x0007), pci224_model },
1128        { PCI_VDEVICE(AMPLICON, 0x0008), pci234_model },
1129        { 0 }
1130};
1131MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1132
1133static struct pci_driver amplc_pci224_pci_driver = {
1134        .name           = "amplc_pci224",
1135        .id_table       = amplc_pci224_pci_table,
1136        .probe          = amplc_pci224_pci_probe,
1137        .remove         = comedi_pci_auto_unconfig,
1138};
1139module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1140
1141MODULE_AUTHOR("Comedi http://www.comedi.org");
1142MODULE_DESCRIPTION("Comedi driver for Amplicon PCI224 and PCI234 AO boards");
1143MODULE_LICENSE("GPL");
1144