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