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/*
  21Driver: amplc_pci224
  22Description: Amplicon PCI224, PCI234
  23Author: Ian Abbott <abbotti@mev.co.uk>
  24Devices: [Amplicon] PCI224 (amplc_pci224 or pci224),
  25  PCI234 (amplc_pci224 or pci234)
  26Updated: Wed, 22 Oct 2008 12:25:08 +0100
  27Status: works, but see caveats
  28
  29Supports:
  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
  47Configuration options - PCI224:
  48  [0] - PCI bus of device (optional).
  49  [1] - PCI slot of device (optional).
  50          If bus/slot is not specified, the first available PCI device
  51          will be used.
  52  [2] - Select available ranges according to jumper LK1.  All channels
  53        are set to the same range:
  54        0=Jumper position 1-2 (factory default), 4 software-selectable
  55          internal voltage references, giving 4 bipolar and 4 unipolar
  56          ranges:
  57            [-10V,+10V], [-5V,+5V], [-2.5V,+2.5V], [-1.25V,+1.25V],
  58            [0,+10V], [0,+5V], [0,+2.5V], [0,1.25V].
  59        1=Jumper position 2-3, 1 external voltage reference, giving
  60          1 bipolar and 1 unipolar range:
  61            [-Vext,+Vext], [0,+Vext].
  62
  63Configuration options - PCI234:
  64  [0] - PCI bus of device (optional).
  65  [1] - PCI slot of device (optional).
  66          If bus/slot is not specified, the first available PCI device
  67          will be used.
  68  [2] - Select internal or external voltage reference according to
  69        jumper LK1.  This affects all channels:
  70        0=Jumper position 1-2 (factory default), Vref=5V internal.
  71        1=Jumper position 2-3, Vref=Vext external.
  72  [3] - Select channel 0 range according to jumper LK2:
  73        0=Jumper position 2-3 (factory default), range [-2*Vref,+2*Vref]
  74          (10V bipolar when options[2]=0).
  75        1=Jumper position 1-2, range [-Vref,+Vref]
  76          (5V bipolar when options[2]=0).
  77  [4] - Select channel 1 range according to jumper LK3: cf. options[3].
  78  [5] - Select channel 2 range according to jumper LK4: cf. options[3].
  79  [6] - Select channel 3 range according to jumper LK5: cf. options[3].
  80
  81Passing a zero for an option is the same as leaving it unspecified.
  82
  83Caveats:
  84
  85  1) All channels on the PCI224 share the same range.  Any change to the
  86     range as a result of insn_write or a streaming command will affect
  87     the output voltages of all channels, including those not specified
  88     by the instruction or command.
  89
  90  2) For the analog output command,  the first scan may be triggered
  91     falsely at the start of acquisition.  This occurs when the DAC scan
  92     trigger source is switched from 'none' to 'timer' (scan_begin_src =
  93     TRIG_TIMER) or 'external' (scan_begin_src == TRIG_EXT) at the start
  94     of acquisition and the trigger source is at logic level 1 at the
  95     time of the switch.  This is very likely for TRIG_TIMER.  For
  96     TRIG_EXT, it depends on the state of the external line and whether
  97     the CR_INVERT flag has been set.  The remaining scans are triggered
  98     correctly.
  99*/
 100
 101#include <linux/module.h>
 102#include <linux/pci.h>
 103#include <linux/interrupt.h>
 104#include <linux/slab.h>
 105
 106#include "../comedidev.h"
 107
 108#include "comedi_fc.h"
 109#include "8253.h"
 110
 111#define DRIVER_NAME     "amplc_pci224"
 112
 113/*
 114 * PCI IDs.
 115 */
 116#define PCI_DEVICE_ID_AMPLICON_PCI224 0x0007
 117#define PCI_DEVICE_ID_AMPLICON_PCI234 0x0008
 118#define PCI_DEVICE_ID_INVALID 0xffff
 119
 120/*
 121 * PCI224/234 i/o space 1 (PCIBAR2) registers.
 122 */
 123#define PCI224_IO1_SIZE 0x20    /* Size of i/o space 1 (8-bit registers) */
 124#define PCI224_Z2_CT0   0x14    /* 82C54 counter/timer 0 */
 125#define PCI224_Z2_CT1   0x15    /* 82C54 counter/timer 1 */
 126#define PCI224_Z2_CT2   0x16    /* 82C54 counter/timer 2 */
 127#define PCI224_Z2_CTC   0x17    /* 82C54 counter/timer control word */
 128#define PCI224_ZCLK_SCE 0x1A    /* Group Z Clock Configuration Register */
 129#define PCI224_ZGAT_SCE 0x1D    /* Group Z Gate Configuration Register */
 130#define PCI224_INT_SCE  0x1E    /* ISR Interrupt source mask register */
 131                                /* /Interrupt status */
 132
 133/*
 134 * PCI224/234 i/o space 2 (PCIBAR3) 16-bit registers.
 135 */
 136#define PCI224_IO2_SIZE 0x10    /* Size of i/o space 2 (16-bit registers). */
 137#define PCI224_DACDATA  0x00    /* (w-o) DAC FIFO data. */
 138#define PCI224_SOFTTRIG 0x00    /* (r-o) DAC software scan trigger. */
 139#define PCI224_DACCON   0x02    /* (r/w) DAC status/configuration. */
 140#define PCI224_FIFOSIZ  0x04    /* (w-o) FIFO size for wraparound mode. */
 141#define PCI224_DACCEN   0x06    /* (w-o) DAC channel enable register. */
 142
 143/*
 144 * DACCON values.
 145 */
 146/* (r/w) Scan trigger. */
 147#define PCI224_DACCON_TRIG_MASK         (7 << 0)
 148#define PCI224_DACCON_TRIG_NONE         (0 << 0)        /* none */
 149#define PCI224_DACCON_TRIG_SW           (1 << 0)        /* software trig */
 150#define PCI224_DACCON_TRIG_EXTP         (2 << 0)        /* ext +ve edge */
 151#define PCI224_DACCON_TRIG_EXTN         (3 << 0)        /* ext -ve edge */
 152#define PCI224_DACCON_TRIG_Z2CT0        (4 << 0)        /* Z2 CT0 out */
 153#define PCI224_DACCON_TRIG_Z2CT1        (5 << 0)        /* Z2 CT1 out */
 154#define PCI224_DACCON_TRIG_Z2CT2        (6 << 0)        /* Z2 CT2 out */
 155/* (r/w) Polarity (PCI224 only, PCI234 always bipolar!). */
 156#define PCI224_DACCON_POLAR_MASK        (1 << 3)
 157#define PCI224_DACCON_POLAR_UNI         (0 << 3)        /* range [0,Vref] */
 158#define PCI224_DACCON_POLAR_BI          (1 << 3)        /* range [-Vref,Vref] */
 159/* (r/w) Internal Vref (PCI224 only, when LK1 in position 1-2). */
 160#define PCI224_DACCON_VREF_MASK         (3 << 4)
 161#define PCI224_DACCON_VREF_1_25         (0 << 4)        /* Vref = 1.25V */
 162#define PCI224_DACCON_VREF_2_5          (1 << 4)        /* Vref = 2.5V */
 163#define PCI224_DACCON_VREF_5            (2 << 4)        /* Vref = 5V */
 164#define PCI224_DACCON_VREF_10           (3 << 4)        /* Vref = 10V */
 165/* (r/w) Wraparound mode enable (to play back stored waveform). */
 166#define PCI224_DACCON_FIFOWRAP          (1 << 7)
 167/* (r/w) FIFO enable.  It MUST be set! */
 168#define PCI224_DACCON_FIFOENAB          (1 << 8)
 169/* (r/w) FIFO interrupt trigger level (most values are not very useful). */
 170#define PCI224_DACCON_FIFOINTR_MASK     (7 << 9)
 171#define PCI224_DACCON_FIFOINTR_EMPTY    (0 << 9)        /* when empty */
 172#define PCI224_DACCON_FIFOINTR_NEMPTY   (1 << 9)        /* when not empty */
 173#define PCI224_DACCON_FIFOINTR_NHALF    (2 << 9)        /* when not half full */
 174#define PCI224_DACCON_FIFOINTR_HALF     (3 << 9)        /* when half full */
 175#define PCI224_DACCON_FIFOINTR_NFULL    (4 << 9)        /* when not full */
 176#define PCI224_DACCON_FIFOINTR_FULL     (5 << 9)        /* when full */
 177/* (r-o) FIFO fill level. */
 178#define PCI224_DACCON_FIFOFL_MASK       (7 << 12)
 179#define PCI224_DACCON_FIFOFL_EMPTY      (1 << 12)       /* 0 */
 180#define PCI224_DACCON_FIFOFL_ONETOHALF  (0 << 12)       /* [1,2048] */
 181#define PCI224_DACCON_FIFOFL_HALFTOFULL (4 << 12)       /* [2049,4095] */
 182#define PCI224_DACCON_FIFOFL_FULL       (6 << 12)       /* 4096 */
 183/* (r-o) DAC busy flag. */
 184#define PCI224_DACCON_BUSY              (1 << 15)
 185/* (w-o) FIFO reset. */
 186#define PCI224_DACCON_FIFORESET         (1 << 12)
 187/* (w-o) Global reset (not sure what it does). */
 188#define PCI224_DACCON_GLOBALRESET       (1 << 13)
 189
 190/*
 191 * DAC FIFO size.
 192 */
 193#define PCI224_FIFO_SIZE        4096
 194
 195/*
 196 * DAC FIFO guaranteed minimum room available, depending on reported fill level.
 197 * The maximum room available depends on the reported fill level and how much
 198 * has been written!
 199 */
 200#define PCI224_FIFO_ROOM_EMPTY          PCI224_FIFO_SIZE
 201#define PCI224_FIFO_ROOM_ONETOHALF      (PCI224_FIFO_SIZE / 2)
 202#define PCI224_FIFO_ROOM_HALFTOFULL     1
 203#define PCI224_FIFO_ROOM_FULL           0
 204
 205/*
 206 * Counter/timer clock input configuration sources.
 207 */
 208#define CLK_CLK         0       /* reserved (channel-specific clock) */
 209#define CLK_10MHZ       1       /* internal 10 MHz clock */
 210#define CLK_1MHZ        2       /* internal 1 MHz clock */
 211#define CLK_100KHZ      3       /* internal 100 kHz clock */
 212#define CLK_10KHZ       4       /* internal 10 kHz clock */
 213#define CLK_1KHZ        5       /* internal 1 kHz clock */
 214#define CLK_OUTNM1      6       /* output of channel-1 modulo total */
 215#define CLK_EXT         7       /* external clock */
 216/* Macro to construct clock input configuration register value. */
 217#define CLK_CONFIG(chan, src)   ((((chan) & 3) << 3) | ((src) & 7))
 218/* Timebases in ns. */
 219#define TIMEBASE_10MHZ          100
 220#define TIMEBASE_1MHZ           1000
 221#define TIMEBASE_100KHZ         10000
 222#define TIMEBASE_10KHZ          100000
 223#define TIMEBASE_1KHZ           1000000
 224
 225/*
 226 * Counter/timer gate input configuration sources.
 227 */
 228#define GAT_VCC         0       /* VCC (i.e. enabled) */
 229#define GAT_GND         1       /* GND (i.e. disabled) */
 230#define GAT_EXT         2       /* reserved (external gate input) */
 231#define GAT_NOUTNM2     3       /* inverted output of channel-2 modulo total */
 232/* Macro to construct gate input configuration register value. */
 233#define GAT_CONFIG(chan, src)   ((((chan) & 3) << 3) | ((src) & 7))
 234
 235/*
 236 * Summary of CLK_OUTNM1 and GAT_NOUTNM2 connections for PCI224 and PCI234:
 237 *
 238 *              Channel's       Channel's
 239 *              clock input     gate input
 240 * Channel      CLK_OUTNM1      GAT_NOUTNM2
 241 * -------      ----------      -----------
 242 * Z2-CT0       Z2-CT2-OUT      /Z2-CT1-OUT
 243 * Z2-CT1       Z2-CT0-OUT      /Z2-CT2-OUT
 244 * Z2-CT2       Z2-CT1-OUT      /Z2-CT0-OUT
 245 */
 246
 247/*
 248 * Interrupt enable/status bits
 249 */
 250#define PCI224_INTR_EXT         0x01    /* rising edge on external input */
 251#define PCI224_INTR_DAC         0x04    /* DAC (FIFO) interrupt */
 252#define PCI224_INTR_Z2CT1       0x20    /* rising edge on Z2-CT1 output */
 253
 254#define PCI224_INTR_EDGE_BITS   (PCI224_INTR_EXT | PCI224_INTR_Z2CT1)
 255#define PCI224_INTR_LEVEL_BITS  PCI224_INTR_DACFIFO
 256
 257/*
 258 * Handy macros.
 259 */
 260
 261/* Combine old and new bits. */
 262#define COMBINE(old, new, mask) (((old) & ~(mask)) | ((new) & (mask)))
 263
 264/* Current CPU.  XXX should this be hard_smp_processor_id()? */
 265#define THISCPU         smp_processor_id()
 266
 267/* State bits for use with atomic bit operations. */
 268#define AO_CMD_STARTED  0
 269
 270/*
 271 * Range tables.
 272 */
 273
 274/* The software selectable internal ranges for PCI224 (option[2] == 0). */
 275static const struct comedi_lrange range_pci224_internal = {
 276        8,
 277        {
 278         BIP_RANGE(10),
 279         BIP_RANGE(5),
 280         BIP_RANGE(2.5),
 281         BIP_RANGE(1.25),
 282         UNI_RANGE(10),
 283         UNI_RANGE(5),
 284         UNI_RANGE(2.5),
 285         UNI_RANGE(1.25),
 286         }
 287};
 288
 289static const unsigned short hwrange_pci224_internal[8] = {
 290        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_10,
 291        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_5,
 292        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_2_5,
 293        PCI224_DACCON_POLAR_BI | PCI224_DACCON_VREF_1_25,
 294        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_10,
 295        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_5,
 296        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_2_5,
 297        PCI224_DACCON_POLAR_UNI | PCI224_DACCON_VREF_1_25,
 298};
 299
 300/* The software selectable external ranges for PCI224 (option[2] == 1). */
 301static const struct comedi_lrange range_pci224_external = {
 302        2,
 303        {
 304         RANGE_ext(-1, 1),      /* bipolar [-Vref,+Vref] */
 305         RANGE_ext(0, 1),       /* unipolar [0,+Vref] */
 306         }
 307};
 308
 309static const unsigned short hwrange_pci224_external[2] = {
 310        PCI224_DACCON_POLAR_BI,
 311        PCI224_DACCON_POLAR_UNI,
 312};
 313
 314/* The hardware selectable Vref*2 external range for PCI234
 315 * (option[2] == 1, option[3+n] == 0). */
 316static const struct comedi_lrange range_pci234_ext2 = {
 317        1,
 318        {
 319         RANGE_ext(-2, 2),
 320         }
 321};
 322
 323/* The hardware selectable Vref external range for PCI234
 324 * (option[2] == 1, option[3+n] == 1). */
 325static const struct comedi_lrange range_pci234_ext = {
 326        1,
 327        {
 328         RANGE_ext(-1, 1),
 329         }
 330};
 331
 332/* This serves for all the PCI234 ranges. */
 333static const unsigned short hwrange_pci234[1] = {
 334        PCI224_DACCON_POLAR_BI, /* bipolar - hardware ignores it! */
 335};
 336
 337/*
 338 * Board descriptions.
 339 */
 340
 341enum pci224_model { any_model, pci224_model, pci234_model };
 342
 343struct pci224_board {
 344        const char *name;
 345        unsigned short devid;
 346        enum pci224_model model;
 347        unsigned int ao_chans;
 348        unsigned int ao_bits;
 349};
 350
 351static const struct pci224_board pci224_boards[] = {
 352        {
 353         .name = "pci224",
 354         .devid = PCI_DEVICE_ID_AMPLICON_PCI224,
 355         .model = pci224_model,
 356         .ao_chans = 16,
 357         .ao_bits = 12,
 358         },
 359        {
 360         .name = "pci234",
 361         .devid = PCI_DEVICE_ID_AMPLICON_PCI234,
 362         .model = pci234_model,
 363         .ao_chans = 4,
 364         .ao_bits = 16,
 365         },
 366        {
 367         .name = DRIVER_NAME,
 368         .devid = PCI_DEVICE_ID_INVALID,
 369         .model = any_model,    /* wildcard */
 370         },
 371};
 372
 373/* this structure is for data unique to this hardware driver.  If
 374   several hardware drivers keep similar information in this structure,
 375   feel free to suggest moving the variable to the struct comedi_device struct.  */
 376struct pci224_private {
 377        const unsigned short *hwrange;
 378        unsigned long iobase1;
 379        unsigned long state;
 380        spinlock_t ao_spinlock;
 381        unsigned int *ao_readback;
 382        short *ao_scan_vals;
 383        unsigned char *ao_scan_order;
 384        int intr_cpuid;
 385        short intr_running;
 386        unsigned short daccon;
 387        unsigned int cached_div1;
 388        unsigned int cached_div2;
 389        unsigned int ao_stop_count;
 390        short ao_stop_continuous;
 391        unsigned short ao_enab; /* max 16 channels so 'short' will do */
 392        unsigned char intsce;
 393};
 394
 395/*
 396 * Called from the 'insn_write' function to perform a single write.
 397 */
 398static void
 399pci224_ao_set_data(struct comedi_device *dev, int chan, int range,
 400                   unsigned int data)
 401{
 402        const struct pci224_board *thisboard = comedi_board(dev);
 403        struct pci224_private *devpriv = dev->private;
 404        unsigned short mangled;
 405
 406        /* Store unmangled data for readback. */
 407        devpriv->ao_readback[chan] = data;
 408        /* Enable the channel. */
 409        outw(1 << chan, dev->iobase + PCI224_DACCEN);
 410        /* Set range and reset FIFO. */
 411        devpriv->daccon = COMBINE(devpriv->daccon, devpriv->hwrange[range],
 412                                  (PCI224_DACCON_POLAR_MASK |
 413                                   PCI224_DACCON_VREF_MASK));
 414        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 415             dev->iobase + PCI224_DACCON);
 416        /*
 417         * Mangle the data.  The hardware expects:
 418         * - bipolar: 16-bit 2's complement
 419         * - unipolar: 16-bit unsigned
 420         */
 421        mangled = (unsigned short)data << (16 - thisboard->ao_bits);
 422        if ((devpriv->daccon & PCI224_DACCON_POLAR_MASK) ==
 423            PCI224_DACCON_POLAR_BI) {
 424                mangled ^= 0x8000;
 425        }
 426        /* Write mangled data to the FIFO. */
 427        outw(mangled, dev->iobase + PCI224_DACDATA);
 428        /* Trigger the conversion. */
 429        inw(dev->iobase + PCI224_SOFTTRIG);
 430}
 431
 432/*
 433 * 'insn_write' function for AO subdevice.
 434 */
 435static int
 436pci224_ao_insn_write(struct comedi_device *dev, struct comedi_subdevice *s,
 437                     struct comedi_insn *insn, unsigned int *data)
 438{
 439        int i;
 440        int chan, range;
 441
 442        /* Unpack channel and range. */
 443        chan = CR_CHAN(insn->chanspec);
 444        range = CR_RANGE(insn->chanspec);
 445
 446        /* Writing a list of values to an AO channel is probably not
 447         * very useful, but that's how the interface is defined. */
 448        for (i = 0; i < insn->n; i++)
 449                pci224_ao_set_data(dev, chan, range, data[i]);
 450
 451        return i;
 452}
 453
 454/*
 455 * 'insn_read' function for AO subdevice.
 456 *
 457 * N.B. The value read will not be valid if the DAC channel has
 458 * never been written successfully since the device was attached
 459 * or since the channel has been used by an AO streaming write
 460 * command.
 461 */
 462static int
 463pci224_ao_insn_read(struct comedi_device *dev, struct comedi_subdevice *s,
 464                    struct comedi_insn *insn, unsigned int *data)
 465{
 466        struct pci224_private *devpriv = dev->private;
 467        int i;
 468        int chan;
 469
 470        chan = CR_CHAN(insn->chanspec);
 471
 472        for (i = 0; i < insn->n; i++)
 473                data[i] = devpriv->ao_readback[chan];
 474
 475
 476        return i;
 477}
 478
 479/*
 480 * Just a wrapper for the inline function 'i8253_cascade_ns_to_timer'.
 481 */
 482static void
 483pci224_cascade_ns_to_timer(int osc_base, unsigned int *d1, unsigned int *d2,
 484                           unsigned int *nanosec, int round_mode)
 485{
 486        i8253_cascade_ns_to_timer(osc_base, d1, d2, nanosec, round_mode);
 487}
 488
 489/*
 490 * Kills a command running on the AO subdevice.
 491 */
 492static void pci224_ao_stop(struct comedi_device *dev,
 493                           struct comedi_subdevice *s)
 494{
 495        struct pci224_private *devpriv = dev->private;
 496        unsigned long flags;
 497
 498        if (!test_and_clear_bit(AO_CMD_STARTED, &devpriv->state))
 499                return;
 500
 501
 502        spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 503        /* Kill the interrupts. */
 504        devpriv->intsce = 0;
 505        outb(0, devpriv->iobase1 + PCI224_INT_SCE);
 506        /*
 507         * Interrupt routine may or may not be running.  We may or may not
 508         * have been called from the interrupt routine (directly or
 509         * indirectly via a comedi_events() callback routine).  It's highly
 510         * unlikely that we've been called from some other interrupt routine
 511         * but who knows what strange things coders get up to!
 512         *
 513         * If the interrupt routine is currently running, wait for it to
 514         * finish, unless we appear to have been called via the interrupt
 515         * routine.
 516         */
 517        while (devpriv->intr_running && devpriv->intr_cpuid != THISCPU) {
 518                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 519                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 520        }
 521        spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 522        /* Reconfigure DAC for insn_write usage. */
 523        outw(0, dev->iobase + PCI224_DACCEN);   /* Disable channels. */
 524        devpriv->daccon = COMBINE(devpriv->daccon,
 525                                  PCI224_DACCON_TRIG_SW |
 526                                  PCI224_DACCON_FIFOINTR_EMPTY,
 527                                  PCI224_DACCON_TRIG_MASK |
 528                                  PCI224_DACCON_FIFOINTR_MASK);
 529        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 530             dev->iobase + PCI224_DACCON);
 531}
 532
 533/*
 534 * Handles start of acquisition for the AO subdevice.
 535 */
 536static void pci224_ao_start(struct comedi_device *dev,
 537                            struct comedi_subdevice *s)
 538{
 539        struct pci224_private *devpriv = dev->private;
 540        struct comedi_cmd *cmd = &s->async->cmd;
 541        unsigned long flags;
 542
 543        set_bit(AO_CMD_STARTED, &devpriv->state);
 544        if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
 545                /* An empty acquisition! */
 546                pci224_ao_stop(dev, s);
 547                s->async->events |= COMEDI_CB_EOA;
 548                comedi_event(dev, s);
 549        } else {
 550                /* Enable interrupts. */
 551                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
 552                if (cmd->stop_src == TRIG_EXT)
 553                        devpriv->intsce = PCI224_INTR_EXT | PCI224_INTR_DAC;
 554                else
 555                        devpriv->intsce = PCI224_INTR_DAC;
 556
 557                outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
 558                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
 559        }
 560}
 561
 562/*
 563 * Handles interrupts from the DAC FIFO.
 564 */
 565static void pci224_ao_handle_fifo(struct comedi_device *dev,
 566                                  struct comedi_subdevice *s)
 567{
 568        struct pci224_private *devpriv = dev->private;
 569        struct comedi_cmd *cmd = &s->async->cmd;
 570        unsigned int num_scans;
 571        unsigned int room;
 572        unsigned short dacstat;
 573        unsigned int i, n;
 574        unsigned int bytes_per_scan;
 575
 576        if (cmd->chanlist_len) {
 577                bytes_per_scan = cmd->chanlist_len * sizeof(short);
 578        } else {
 579                /* Shouldn't get here! */
 580                bytes_per_scan = sizeof(short);
 581        }
 582        /* Determine number of scans available in buffer. */
 583        num_scans = comedi_buf_read_n_available(s->async) / bytes_per_scan;
 584        if (!devpriv->ao_stop_continuous) {
 585                /* Fixed number of scans. */
 586                if (num_scans > devpriv->ao_stop_count)
 587                        num_scans = devpriv->ao_stop_count;
 588
 589        }
 590
 591        /* Determine how much room is in the FIFO (in samples). */
 592        dacstat = inw(dev->iobase + PCI224_DACCON);
 593        switch (dacstat & PCI224_DACCON_FIFOFL_MASK) {
 594        case PCI224_DACCON_FIFOFL_EMPTY:
 595                room = PCI224_FIFO_ROOM_EMPTY;
 596                if (!devpriv->ao_stop_continuous && devpriv->ao_stop_count == 0) {
 597                        /* FIFO empty at end of counted acquisition. */
 598                        pci224_ao_stop(dev, s);
 599                        s->async->events |= COMEDI_CB_EOA;
 600                        comedi_event(dev, s);
 601                        return;
 602                }
 603                break;
 604        case PCI224_DACCON_FIFOFL_ONETOHALF:
 605                room = PCI224_FIFO_ROOM_ONETOHALF;
 606                break;
 607        case PCI224_DACCON_FIFOFL_HALFTOFULL:
 608                room = PCI224_FIFO_ROOM_HALFTOFULL;
 609                break;
 610        default:
 611                room = PCI224_FIFO_ROOM_FULL;
 612                break;
 613        }
 614        if (room >= PCI224_FIFO_ROOM_ONETOHALF) {
 615                /* FIFO is less than half-full. */
 616                if (num_scans == 0) {
 617                        /* Nothing left to put in the FIFO. */
 618                        pci224_ao_stop(dev, s);
 619                        s->async->events |= COMEDI_CB_OVERFLOW;
 620                        dev_err(dev->class_dev, "AO buffer underrun\n");
 621                }
 622        }
 623        /* Determine how many new scans can be put in the FIFO. */
 624        if (cmd->chanlist_len)
 625                room /= cmd->chanlist_len;
 626
 627        /* Determine how many scans to process. */
 628        if (num_scans > room)
 629                num_scans = room;
 630
 631        /* Process scans. */
 632        for (n = 0; n < num_scans; n++) {
 633                cfc_read_array_from_buffer(s, &devpriv->ao_scan_vals[0],
 634                                           bytes_per_scan);
 635                for (i = 0; i < cmd->chanlist_len; i++) {
 636                        outw(devpriv->ao_scan_vals[devpriv->ao_scan_order[i]],
 637                             dev->iobase + PCI224_DACDATA);
 638                }
 639        }
 640        if (!devpriv->ao_stop_continuous) {
 641                devpriv->ao_stop_count -= num_scans;
 642                if (devpriv->ao_stop_count == 0) {
 643                        /*
 644                         * Change FIFO interrupt trigger level to wait
 645                         * until FIFO is empty.
 646                         */
 647                        devpriv->daccon = COMBINE(devpriv->daccon,
 648                                                  PCI224_DACCON_FIFOINTR_EMPTY,
 649                                                  PCI224_DACCON_FIFOINTR_MASK);
 650                        outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 651                }
 652        }
 653        if ((devpriv->daccon & PCI224_DACCON_TRIG_MASK) ==
 654            PCI224_DACCON_TRIG_NONE) {
 655                unsigned short trig;
 656
 657                /*
 658                 * This is the initial DAC FIFO interrupt at the
 659                 * start of the acquisition.  The DAC's scan trigger
 660                 * has been set to 'none' up until now.
 661                 *
 662                 * Now that data has been written to the FIFO, the
 663                 * DAC's scan trigger source can be set to the
 664                 * correct value.
 665                 *
 666                 * BUG: The first scan will be triggered immediately
 667                 * if the scan trigger source is at logic level 1.
 668                 */
 669                if (cmd->scan_begin_src == TRIG_TIMER) {
 670                        trig = PCI224_DACCON_TRIG_Z2CT0;
 671                } else {
 672                        /* cmd->scan_begin_src == TRIG_EXT */
 673                        if (cmd->scan_begin_arg & CR_INVERT)
 674                                trig = PCI224_DACCON_TRIG_EXTN;
 675                        else
 676                                trig = PCI224_DACCON_TRIG_EXTP;
 677
 678                }
 679                devpriv->daccon = COMBINE(devpriv->daccon, trig,
 680                                          PCI224_DACCON_TRIG_MASK);
 681                outw(devpriv->daccon, dev->iobase + PCI224_DACCON);
 682        }
 683        if (s->async->events)
 684                comedi_event(dev, s);
 685
 686}
 687
 688/*
 689 * Internal trigger function to start acquisition on AO subdevice.
 690 */
 691static int
 692pci224_ao_inttrig_start(struct comedi_device *dev, struct comedi_subdevice *s,
 693                        unsigned int trignum)
 694{
 695        if (trignum != 0)
 696                return -EINVAL;
 697
 698        s->async->inttrig = NULL;
 699        pci224_ao_start(dev, s);
 700
 701        return 1;
 702}
 703
 704#define MAX_SCAN_PERIOD         0xFFFFFFFFU
 705#define MIN_SCAN_PERIOD         2500
 706#define CONVERT_PERIOD          625
 707
 708/*
 709 * 'do_cmdtest' function for AO subdevice.
 710 */
 711static int
 712pci224_ao_cmdtest(struct comedi_device *dev, struct comedi_subdevice *s,
 713                  struct comedi_cmd *cmd)
 714{
 715        struct pci224_private *devpriv = dev->private;
 716        int err = 0;
 717        unsigned int tmp;
 718
 719        /* Step 1 : check if triggers are trivially valid */
 720
 721        err |= cfc_check_trigger_src(&cmd->start_src, TRIG_INT | TRIG_EXT);
 722        err |= cfc_check_trigger_src(&cmd->scan_begin_src,
 723                                        TRIG_EXT | TRIG_TIMER);
 724        err |= cfc_check_trigger_src(&cmd->convert_src, TRIG_NOW);
 725        err |= cfc_check_trigger_src(&cmd->scan_end_src, TRIG_COUNT);
 726        err |= cfc_check_trigger_src(&cmd->stop_src,
 727                                        TRIG_COUNT | TRIG_EXT | TRIG_NONE);
 728
 729        if (err)
 730                return 1;
 731
 732        /* Step 2a : make sure trigger sources are unique */
 733
 734        err |= cfc_check_trigger_is_unique(cmd->start_src);
 735        err |= cfc_check_trigger_is_unique(cmd->scan_begin_src);
 736        err |= cfc_check_trigger_is_unique(cmd->stop_src);
 737
 738        /* Step 2b : and mutually compatible */
 739
 740        /*
 741         * There's only one external trigger signal (which makes these
 742         * tests easier).  Only one thing can use it.
 743         */
 744        tmp = 0;
 745        if (cmd->start_src & TRIG_EXT)
 746                tmp++;
 747        if (cmd->scan_begin_src & TRIG_EXT)
 748                tmp++;
 749        if (cmd->stop_src & TRIG_EXT)
 750                tmp++;
 751        if (tmp > 1)
 752                err |= -EINVAL;
 753
 754        if (err)
 755                return 2;
 756
 757        /* Step 3: check if arguments are trivially valid */
 758
 759        switch (cmd->start_src) {
 760        case TRIG_INT:
 761                err |= cfc_check_trigger_arg_is(&cmd->start_arg, 0);
 762                break;
 763        case TRIG_EXT:
 764                /* Force to external trigger 0. */
 765                if ((cmd->start_arg & ~CR_FLAGS_MASK) != 0) {
 766                        cmd->start_arg = COMBINE(cmd->start_arg, 0,
 767                                                 ~CR_FLAGS_MASK);
 768                        err |= -EINVAL;
 769                }
 770                /* The only flag allowed is CR_EDGE, which is ignored. */
 771                if ((cmd->start_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
 772                        cmd->start_arg = COMBINE(cmd->start_arg, 0,
 773                                                 CR_FLAGS_MASK & ~CR_EDGE);
 774                        err |= -EINVAL;
 775                }
 776                break;
 777        }
 778
 779        switch (cmd->scan_begin_src) {
 780        case TRIG_TIMER:
 781                err |= cfc_check_trigger_arg_max(&cmd->scan_begin_arg,
 782                                                 MAX_SCAN_PERIOD);
 783
 784                tmp = cmd->chanlist_len * CONVERT_PERIOD;
 785                if (tmp < MIN_SCAN_PERIOD)
 786                        tmp = MIN_SCAN_PERIOD;
 787                err |= cfc_check_trigger_arg_min(&cmd->scan_begin_arg, tmp);
 788                break;
 789        case TRIG_EXT:
 790                /* Force to external trigger 0. */
 791                if ((cmd->scan_begin_arg & ~CR_FLAGS_MASK) != 0) {
 792                        cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 793                                                      ~CR_FLAGS_MASK);
 794                        err |= -EINVAL;
 795                }
 796                /* Only allow flags CR_EDGE and CR_INVERT.  Ignore CR_EDGE. */
 797                if ((cmd->scan_begin_arg & CR_FLAGS_MASK &
 798                     ~(CR_EDGE | CR_INVERT)) != 0) {
 799                        cmd->scan_begin_arg = COMBINE(cmd->scan_begin_arg, 0,
 800                                                      CR_FLAGS_MASK &
 801                                                      ~(CR_EDGE | CR_INVERT));
 802                        err |= -EINVAL;
 803                }
 804                break;
 805        }
 806
 807        err |= cfc_check_trigger_arg_is(&cmd->convert_arg, 0);
 808        err |= cfc_check_trigger_arg_is(&cmd->scan_end_arg, cmd->chanlist_len);
 809
 810        switch (cmd->stop_src) {
 811        case TRIG_COUNT:
 812                /* Any count allowed. */
 813                break;
 814        case TRIG_EXT:
 815                /* Force to external trigger 0. */
 816                if ((cmd->stop_arg & ~CR_FLAGS_MASK) != 0) {
 817                        cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
 818                                                ~CR_FLAGS_MASK);
 819                        err |= -EINVAL;
 820                }
 821                /* The only flag allowed is CR_EDGE, which is ignored. */
 822                if ((cmd->stop_arg & CR_FLAGS_MASK & ~CR_EDGE) != 0) {
 823                        cmd->stop_arg = COMBINE(cmd->stop_arg, 0,
 824                                                CR_FLAGS_MASK & ~CR_EDGE);
 825                }
 826                break;
 827        case TRIG_NONE:
 828                err |= cfc_check_trigger_arg_is(&cmd->stop_arg, 0);
 829                break;
 830        }
 831
 832        if (err)
 833                return 3;
 834
 835        /* Step 4: fix up any arguments. */
 836
 837        if (cmd->scan_begin_src == TRIG_TIMER) {
 838                unsigned int div1, div2, round;
 839                int round_mode = cmd->flags & TRIG_ROUND_MASK;
 840
 841                tmp = cmd->scan_begin_arg;
 842                /* Check whether to use a single timer. */
 843                switch (round_mode) {
 844                case TRIG_ROUND_NEAREST:
 845                default:
 846                        round = TIMEBASE_10MHZ / 2;
 847                        break;
 848                case TRIG_ROUND_DOWN:
 849                        round = 0;
 850                        break;
 851                case TRIG_ROUND_UP:
 852                        round = TIMEBASE_10MHZ - 1;
 853                        break;
 854                }
 855                /* Be careful to avoid overflow! */
 856                div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
 857                div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
 858                    TIMEBASE_10MHZ;
 859                if (div2 <= 0x10000) {
 860                        /* A single timer will suffice. */
 861                        if (div2 < 2)
 862                                div2 = 2;
 863                        cmd->scan_begin_arg = div2 * TIMEBASE_10MHZ;
 864                        if (cmd->scan_begin_arg < div2 ||
 865                            cmd->scan_begin_arg < TIMEBASE_10MHZ) {
 866                                /* Overflow! */
 867                                cmd->scan_begin_arg = MAX_SCAN_PERIOD;
 868                        }
 869                } else {
 870                        /* Use two timers. */
 871                        div1 = devpriv->cached_div1;
 872                        div2 = devpriv->cached_div2;
 873                        pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
 874                                                   &cmd->scan_begin_arg,
 875                                                   round_mode);
 876                        devpriv->cached_div1 = div1;
 877                        devpriv->cached_div2 = div2;
 878                }
 879                if (tmp != cmd->scan_begin_arg)
 880                        err++;
 881
 882        }
 883
 884        if (err)
 885                return 4;
 886
 887        /* Step 5: check channel list. */
 888
 889        if (cmd->chanlist && (cmd->chanlist_len > 0)) {
 890                unsigned int range;
 891                enum { range_err = 1, dupchan_err = 2, };
 892                unsigned errors;
 893                unsigned int n;
 894                unsigned int ch;
 895
 896                /*
 897                 * Check all channels have the same range index.  Don't care
 898                 * about analogue reference, as we can't configure it.
 899                 *
 900                 * Check the list has no duplicate channels.
 901                 */
 902                range = CR_RANGE(cmd->chanlist[0]);
 903                errors = 0;
 904                tmp = 0;
 905                for (n = 0; n < cmd->chanlist_len; n++) {
 906                        ch = CR_CHAN(cmd->chanlist[n]);
 907                        if (tmp & (1U << ch))
 908                                errors |= dupchan_err;
 909
 910                        tmp |= (1U << ch);
 911                        if (CR_RANGE(cmd->chanlist[n]) != range)
 912                                errors |= range_err;
 913
 914                }
 915                if (errors) {
 916                        if (errors & dupchan_err) {
 917                                DPRINTK("comedi%d: " DRIVER_NAME
 918                                        ": ao_cmdtest: "
 919                                        "entries in chanlist must contain no "
 920                                        "duplicate channels\n", dev->minor);
 921                        }
 922                        if (errors & range_err) {
 923                                DPRINTK("comedi%d: " DRIVER_NAME
 924                                        ": ao_cmdtest: "
 925                                        "entries in chanlist must all have "
 926                                        "the same range index\n", dev->minor);
 927                        }
 928                        err++;
 929                }
 930        }
 931
 932        if (err)
 933                return 5;
 934
 935        return 0;
 936}
 937
 938/*
 939 * 'do_cmd' function for AO subdevice.
 940 */
 941static int pci224_ao_cmd(struct comedi_device *dev, struct comedi_subdevice *s)
 942{
 943        struct pci224_private *devpriv = dev->private;
 944        struct comedi_cmd *cmd = &s->async->cmd;
 945        int range;
 946        unsigned int i, j;
 947        unsigned int ch;
 948        unsigned int rank;
 949        unsigned long flags;
 950
 951        /* Cannot handle null/empty chanlist. */
 952        if (cmd->chanlist == NULL || cmd->chanlist_len == 0)
 953                return -EINVAL;
 954
 955
 956        /* Determine which channels are enabled and their load order.  */
 957        devpriv->ao_enab = 0;
 958
 959        for (i = 0; i < cmd->chanlist_len; i++) {
 960                ch = CR_CHAN(cmd->chanlist[i]);
 961                devpriv->ao_enab |= 1U << ch;
 962                rank = 0;
 963                for (j = 0; j < cmd->chanlist_len; j++) {
 964                        if (CR_CHAN(cmd->chanlist[j]) < ch)
 965                                rank++;
 966
 967                }
 968                devpriv->ao_scan_order[rank] = i;
 969        }
 970
 971        /* Set enabled channels. */
 972        outw(devpriv->ao_enab, dev->iobase + PCI224_DACCEN);
 973
 974        /* Determine range and polarity.  All channels the same.  */
 975        range = CR_RANGE(cmd->chanlist[0]);
 976
 977        /*
 978         * Set DAC range and polarity.
 979         * Set DAC scan trigger source to 'none'.
 980         * Set DAC FIFO interrupt trigger level to 'not half full'.
 981         * Reset DAC FIFO.
 982         *
 983         * N.B. DAC FIFO interrupts are currently disabled.
 984         */
 985        devpriv->daccon = COMBINE(devpriv->daccon,
 986                                  (devpriv->
 987                                   hwrange[range] | PCI224_DACCON_TRIG_NONE |
 988                                   PCI224_DACCON_FIFOINTR_NHALF),
 989                                  (PCI224_DACCON_POLAR_MASK |
 990                                   PCI224_DACCON_VREF_MASK |
 991                                   PCI224_DACCON_TRIG_MASK |
 992                                   PCI224_DACCON_FIFOINTR_MASK));
 993        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
 994             dev->iobase + PCI224_DACCON);
 995
 996        if (cmd->scan_begin_src == TRIG_TIMER) {
 997                unsigned int div1, div2, round;
 998                unsigned int ns = cmd->scan_begin_arg;
 999                int round_mode = cmd->flags & TRIG_ROUND_MASK;
1000
1001                /* Check whether to use a single timer. */
1002                switch (round_mode) {
1003                case TRIG_ROUND_NEAREST:
1004                default:
1005                        round = TIMEBASE_10MHZ / 2;
1006                        break;
1007                case TRIG_ROUND_DOWN:
1008                        round = 0;
1009                        break;
1010                case TRIG_ROUND_UP:
1011                        round = TIMEBASE_10MHZ - 1;
1012                        break;
1013                }
1014                /* Be careful to avoid overflow! */
1015                div2 = cmd->scan_begin_arg / TIMEBASE_10MHZ;
1016                div2 += (round + cmd->scan_begin_arg % TIMEBASE_10MHZ) /
1017                    TIMEBASE_10MHZ;
1018                if (div2 <= 0x10000) {
1019                        /* A single timer will suffice. */
1020                        if (div2 < 2)
1021                                div2 = 2;
1022                        div2 &= 0xffff;
1023                        div1 = 1;       /* Flag that single timer to be used. */
1024                } else {
1025                        /* Use two timers. */
1026                        div1 = devpriv->cached_div1;
1027                        div2 = devpriv->cached_div2;
1028                        pci224_cascade_ns_to_timer(TIMEBASE_10MHZ, &div1, &div2,
1029                                                   &ns, round_mode);
1030                }
1031
1032                /*
1033                 * The output of timer Z2-0 will be used as the scan trigger
1034                 * source.
1035                 */
1036                /* Make sure Z2-0 is gated on.  */
1037                outb(GAT_CONFIG(0, GAT_VCC),
1038                     devpriv->iobase1 + PCI224_ZGAT_SCE);
1039                if (div1 == 1) {
1040                        /* Not cascading.  Z2-0 needs 10 MHz clock. */
1041                        outb(CLK_CONFIG(0, CLK_10MHZ),
1042                             devpriv->iobase1 + PCI224_ZCLK_SCE);
1043                } else {
1044                        /* Cascading with Z2-2. */
1045                        /* Make sure Z2-2 is gated on.  */
1046                        outb(GAT_CONFIG(2, GAT_VCC),
1047                             devpriv->iobase1 + PCI224_ZGAT_SCE);
1048                        /* Z2-2 needs 10 MHz clock. */
1049                        outb(CLK_CONFIG(2, CLK_10MHZ),
1050                             devpriv->iobase1 + PCI224_ZCLK_SCE);
1051                        /* Load Z2-2 mode (2) and counter (div1). */
1052                        i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0,
1053                                   2, div1, 2);
1054                        /* Z2-0 is clocked from Z2-2's output. */
1055                        outb(CLK_CONFIG(0, CLK_OUTNM1),
1056                             devpriv->iobase1 + PCI224_ZCLK_SCE);
1057                }
1058                /* Load Z2-0 mode (2) and counter (div2). */
1059                i8254_load(devpriv->iobase1 + PCI224_Z2_CT0, 0, 0, div2, 2);
1060        }
1061
1062        /*
1063         * Sort out end of acquisition.
1064         */
1065        switch (cmd->stop_src) {
1066        case TRIG_COUNT:
1067                /* Fixed number of scans.  */
1068                devpriv->ao_stop_continuous = 0;
1069                devpriv->ao_stop_count = cmd->stop_arg;
1070                break;
1071        default:
1072                /* Continuous scans. */
1073                devpriv->ao_stop_continuous = 1;
1074                devpriv->ao_stop_count = 0;
1075                break;
1076        }
1077
1078        /*
1079         * Sort out start of acquisition.
1080         */
1081        switch (cmd->start_src) {
1082        case TRIG_INT:
1083                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1084                s->async->inttrig = &pci224_ao_inttrig_start;
1085                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1086                break;
1087        case TRIG_EXT:
1088                /* Enable external interrupt trigger to start acquisition. */
1089                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1090                devpriv->intsce |= PCI224_INTR_EXT;
1091                outb(devpriv->intsce, devpriv->iobase1 + PCI224_INT_SCE);
1092                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1093                break;
1094        }
1095
1096        return 0;
1097}
1098
1099/*
1100 * 'cancel' function for AO subdevice.
1101 */
1102static int pci224_ao_cancel(struct comedi_device *dev,
1103                            struct comedi_subdevice *s)
1104{
1105        pci224_ao_stop(dev, s);
1106        return 0;
1107}
1108
1109/*
1110 * 'munge' data for AO command.
1111 */
1112static void
1113pci224_ao_munge(struct comedi_device *dev, struct comedi_subdevice *s,
1114                void *data, unsigned int num_bytes, unsigned int chan_index)
1115{
1116        const struct pci224_board *thisboard = comedi_board(dev);
1117        struct pci224_private *devpriv = dev->private;
1118        struct comedi_async *async = s->async;
1119        short *array = data;
1120        unsigned int length = num_bytes / sizeof(*array);
1121        unsigned int offset;
1122        unsigned int shift;
1123        unsigned int i;
1124
1125        /* The hardware expects 16-bit numbers. */
1126        shift = 16 - thisboard->ao_bits;
1127        /* Channels will be all bipolar or all unipolar. */
1128        if ((devpriv->hwrange[CR_RANGE(async->cmd.chanlist[0])] &
1129             PCI224_DACCON_POLAR_MASK) == PCI224_DACCON_POLAR_UNI) {
1130                /* Unipolar */
1131                offset = 0;
1132        } else {
1133                /* Bipolar */
1134                offset = 32768;
1135        }
1136        /* Munge the data. */
1137        for (i = 0; i < length; i++)
1138                array[i] = (array[i] << shift) - offset;
1139
1140}
1141
1142/*
1143 * Interrupt handler.
1144 */
1145static irqreturn_t pci224_interrupt(int irq, void *d)
1146{
1147        struct comedi_device *dev = d;
1148        struct pci224_private *devpriv = dev->private;
1149        struct comedi_subdevice *s = &dev->subdevices[0];
1150        struct comedi_cmd *cmd;
1151        unsigned char intstat, valid_intstat;
1152        unsigned char curenab;
1153        int retval = 0;
1154        unsigned long flags;
1155
1156        intstat = inb(devpriv->iobase1 + PCI224_INT_SCE) & 0x3F;
1157        if (intstat) {
1158                retval = 1;
1159                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1160                valid_intstat = devpriv->intsce & intstat;
1161                /* Temporarily disable interrupt sources. */
1162                curenab = devpriv->intsce & ~intstat;
1163                outb(curenab, devpriv->iobase1 + PCI224_INT_SCE);
1164                devpriv->intr_running = 1;
1165                devpriv->intr_cpuid = THISCPU;
1166                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1167                if (valid_intstat != 0) {
1168                        cmd = &s->async->cmd;
1169                        if (valid_intstat & PCI224_INTR_EXT) {
1170                                devpriv->intsce &= ~PCI224_INTR_EXT;
1171                                if (cmd->start_src == TRIG_EXT)
1172                                        pci224_ao_start(dev, s);
1173                                else if (cmd->stop_src == TRIG_EXT)
1174                                        pci224_ao_stop(dev, s);
1175
1176                        }
1177                        if (valid_intstat & PCI224_INTR_DAC)
1178                                pci224_ao_handle_fifo(dev, s);
1179
1180                }
1181                /* Reenable interrupt sources. */
1182                spin_lock_irqsave(&devpriv->ao_spinlock, flags);
1183                if (curenab != devpriv->intsce) {
1184                        outb(devpriv->intsce,
1185                             devpriv->iobase1 + PCI224_INT_SCE);
1186                }
1187                devpriv->intr_running = 0;
1188                spin_unlock_irqrestore(&devpriv->ao_spinlock, flags);
1189        }
1190        return IRQ_RETVAL(retval);
1191}
1192
1193/*
1194 * This function looks for a board matching the supplied PCI device.
1195 */
1196static const struct pci224_board
1197*pci224_find_pci_board(struct pci_dev *pci_dev)
1198{
1199        int i;
1200
1201        for (i = 0; i < ARRAY_SIZE(pci224_boards); i++)
1202                if (pci_dev->device == pci224_boards[i].devid)
1203                        return &pci224_boards[i];
1204        return NULL;
1205}
1206
1207/*
1208 * This function looks for a PCI device matching the requested board name,
1209 * bus and slot.
1210 */
1211static struct pci_dev *pci224_find_pci_dev(struct comedi_device *dev,
1212                                           struct comedi_devconfig *it)
1213{
1214        const struct pci224_board *thisboard = comedi_board(dev);
1215        struct pci_dev *pci_dev = NULL;
1216        int bus = it->options[0];
1217        int slot = it->options[1];
1218
1219        for_each_pci_dev(pci_dev) {
1220                if (bus || slot) {
1221                        if (bus != pci_dev->bus->number ||
1222                            slot != PCI_SLOT(pci_dev->devfn))
1223                                continue;
1224                }
1225                if (pci_dev->vendor != PCI_VENDOR_ID_AMPLICON)
1226                        continue;
1227
1228                if (thisboard->model == any_model) {
1229                        /* Match any supported model. */
1230                        const struct pci224_board *board_ptr;
1231
1232                        board_ptr = pci224_find_pci_board(pci_dev);
1233                        if (board_ptr == NULL)
1234                                continue;
1235                        /* Change board_ptr to matched board. */
1236                        dev->board_ptr = board_ptr;
1237                } else {
1238                        /* Match specific model name. */
1239                        if (thisboard->devid != pci_dev->device)
1240                                continue;
1241                }
1242                return pci_dev;
1243        }
1244        dev_err(dev->class_dev,
1245                "No supported board found! (req. bus %d, slot %d)\n",
1246                bus, slot);
1247        return NULL;
1248}
1249
1250static void pci224_report_attach(struct comedi_device *dev, unsigned int irq)
1251{
1252        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1253        char tmpbuf[30];
1254
1255        if (irq)
1256                snprintf(tmpbuf, sizeof(tmpbuf), "irq %u%s", irq,
1257                         (dev->irq ? "" : " UNAVAILABLE"));
1258        else
1259                snprintf(tmpbuf, sizeof(tmpbuf), "no irq");
1260        dev_info(dev->class_dev, "%s (pci %s) (%s) attached\n",
1261                 dev->board_name, pci_name(pcidev), tmpbuf);
1262}
1263
1264/*
1265 * Common part of attach and auto_attach.
1266 */
1267static int pci224_attach_common(struct comedi_device *dev,
1268                                struct pci_dev *pci_dev, int *options)
1269{
1270        const struct pci224_board *thisboard = comedi_board(dev);
1271        struct pci224_private *devpriv = dev->private;
1272        struct comedi_subdevice *s;
1273        unsigned int irq;
1274        unsigned n;
1275        int ret;
1276
1277        comedi_set_hw_dev(dev, &pci_dev->dev);
1278
1279        ret = comedi_pci_enable(dev);
1280        if (ret)
1281                return ret;
1282
1283        spin_lock_init(&devpriv->ao_spinlock);
1284
1285        devpriv->iobase1 = pci_resource_start(pci_dev, 2);
1286        dev->iobase = pci_resource_start(pci_dev, 3);
1287        irq = pci_dev->irq;
1288
1289        /* Allocate readback buffer for AO channels. */
1290        devpriv->ao_readback = kmalloc(sizeof(devpriv->ao_readback[0]) *
1291                                       thisboard->ao_chans, GFP_KERNEL);
1292        if (!devpriv->ao_readback)
1293                return -ENOMEM;
1294
1295
1296        /* Allocate buffer to hold values for AO channel scan. */
1297        devpriv->ao_scan_vals = kmalloc(sizeof(devpriv->ao_scan_vals[0]) *
1298                                        thisboard->ao_chans, GFP_KERNEL);
1299        if (!devpriv->ao_scan_vals)
1300                return -ENOMEM;
1301
1302
1303        /* Allocate buffer to hold AO channel scan order. */
1304        devpriv->ao_scan_order = kmalloc(sizeof(devpriv->ao_scan_order[0]) *
1305                                         thisboard->ao_chans, GFP_KERNEL);
1306        if (!devpriv->ao_scan_order)
1307                return -ENOMEM;
1308
1309
1310        /* Disable interrupt sources. */
1311        devpriv->intsce = 0;
1312        outb(0, devpriv->iobase1 + PCI224_INT_SCE);
1313
1314        /* Initialize the DAC hardware. */
1315        outw(PCI224_DACCON_GLOBALRESET, dev->iobase + PCI224_DACCON);
1316        outw(0, dev->iobase + PCI224_DACCEN);
1317        outw(0, dev->iobase + PCI224_FIFOSIZ);
1318        devpriv->daccon = (PCI224_DACCON_TRIG_SW | PCI224_DACCON_POLAR_BI |
1319                           PCI224_DACCON_FIFOENAB |
1320                           PCI224_DACCON_FIFOINTR_EMPTY);
1321        outw(devpriv->daccon | PCI224_DACCON_FIFORESET,
1322             dev->iobase + PCI224_DACCON);
1323
1324        ret = comedi_alloc_subdevices(dev, 1);
1325        if (ret)
1326                return ret;
1327
1328        s = &dev->subdevices[0];
1329        /* Analog output subdevice. */
1330        s->type = COMEDI_SUBD_AO;
1331        s->subdev_flags = SDF_WRITABLE | SDF_GROUND | SDF_CMD_WRITE;
1332        s->n_chan = thisboard->ao_chans;
1333        s->maxdata = (1 << thisboard->ao_bits) - 1;
1334        s->insn_write = &pci224_ao_insn_write;
1335        s->insn_read = &pci224_ao_insn_read;
1336        s->len_chanlist = s->n_chan;
1337
1338        dev->write_subdev = s;
1339        s->do_cmd = &pci224_ao_cmd;
1340        s->do_cmdtest = &pci224_ao_cmdtest;
1341        s->cancel = &pci224_ao_cancel;
1342        s->munge = &pci224_ao_munge;
1343
1344        /* Sort out channel range options. */
1345        if (thisboard->model == pci234_model) {
1346                /* PCI234 range options. */
1347                const struct comedi_lrange **range_table_list;
1348
1349                s->range_table_list = range_table_list =
1350                    kmalloc(sizeof(struct comedi_lrange *) * s->n_chan,
1351                            GFP_KERNEL);
1352                if (!s->range_table_list)
1353                        return -ENOMEM;
1354
1355                if (options) {
1356                        for (n = 2; n < 3 + s->n_chan; n++) {
1357                                if (options[n] < 0 || options[n] > 1) {
1358                                        dev_warn(dev->class_dev, DRIVER_NAME
1359                                                 ": warning! bad options[%u]=%d\n",
1360                                                 n, options[n]);
1361                                }
1362                        }
1363                }
1364                for (n = 0; n < s->n_chan; n++) {
1365                        if (n < COMEDI_NDEVCONFOPTS - 3 && options &&
1366                            options[3 + n] == 1) {
1367                                if (options[2] == 1)
1368                                        range_table_list[n] = &range_pci234_ext;
1369                                else
1370                                        range_table_list[n] = &range_bipolar5;
1371
1372                        } else {
1373                                if (options && options[2] == 1) {
1374                                        range_table_list[n] =
1375                                            &range_pci234_ext2;
1376                                } else {
1377                                        range_table_list[n] = &range_bipolar10;
1378                                }
1379                        }
1380                }
1381                devpriv->hwrange = hwrange_pci234;
1382        } else {
1383                /* PCI224 range options. */
1384                if (options && options[2] == 1) {
1385                        s->range_table = &range_pci224_external;
1386                        devpriv->hwrange = hwrange_pci224_external;
1387                } else {
1388                        if (options && options[2] != 0) {
1389                                dev_warn(dev->class_dev, DRIVER_NAME
1390                                         ": warning! bad options[2]=%d\n",
1391                                         options[2]);
1392                        }
1393                        s->range_table = &range_pci224_internal;
1394                        devpriv->hwrange = hwrange_pci224_internal;
1395                }
1396        }
1397
1398        dev->board_name = thisboard->name;
1399
1400        if (irq) {
1401                ret = request_irq(irq, pci224_interrupt, IRQF_SHARED,
1402                                  DRIVER_NAME, dev);
1403                if (ret < 0) {
1404                        dev_err(dev->class_dev,
1405                                "error! unable to allocate irq %u\n", irq);
1406                        return ret;
1407                } else {
1408                        dev->irq = irq;
1409                }
1410        }
1411
1412        pci224_report_attach(dev, irq);
1413        return 1;
1414}
1415
1416static int pci224_attach(struct comedi_device *dev, struct comedi_devconfig *it)
1417{
1418        struct pci224_private *devpriv;
1419        struct pci_dev *pci_dev;
1420
1421        dev_info(dev->class_dev, DRIVER_NAME ": attach\n");
1422
1423        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1424        if (!devpriv)
1425                return -ENOMEM;
1426
1427        pci_dev = pci224_find_pci_dev(dev, it);
1428        if (!pci_dev)
1429                return -EIO;
1430
1431        return pci224_attach_common(dev, pci_dev, it->options);
1432}
1433
1434static int
1435pci224_auto_attach(struct comedi_device *dev, unsigned long context_unused)
1436{
1437        struct pci_dev *pci_dev = comedi_to_pci_dev(dev);
1438        struct pci224_private *devpriv;
1439
1440        dev_info(dev->class_dev, DRIVER_NAME ": attach pci %s\n",
1441                 pci_name(pci_dev));
1442
1443        devpriv = comedi_alloc_devpriv(dev, sizeof(*devpriv));
1444        if (!devpriv)
1445                return -ENOMEM;
1446
1447        dev->board_ptr = pci224_find_pci_board(pci_dev);
1448        if (dev->board_ptr == NULL) {
1449                dev_err(dev->class_dev,
1450                        DRIVER_NAME ": BUG! cannot determine board type!\n");
1451                return -EINVAL;
1452        }
1453        /*
1454         * Need to 'get' the PCI device to match the 'put' in pci224_detach().
1455         * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
1456         * support for manual attachment of PCI devices via pci224_attach()
1457         * has been removed.
1458         */
1459        pci_dev_get(pci_dev);
1460        return pci224_attach_common(dev, pci_dev, NULL);
1461}
1462
1463static void pci224_detach(struct comedi_device *dev)
1464{
1465        struct pci224_private *devpriv = dev->private;
1466        struct pci_dev *pcidev = comedi_to_pci_dev(dev);
1467
1468        if (dev->irq)
1469                free_irq(dev->irq, dev);
1470        if (dev->subdevices) {
1471                struct comedi_subdevice *s;
1472
1473                s = &dev->subdevices[0];
1474                /* AO subdevice */
1475                kfree(s->range_table_list);
1476        }
1477        if (devpriv) {
1478                kfree(devpriv->ao_readback);
1479                kfree(devpriv->ao_scan_vals);
1480                kfree(devpriv->ao_scan_order);
1481        }
1482        comedi_pci_disable(dev);
1483        if (pcidev)
1484                pci_dev_put(pcidev);
1485}
1486
1487static struct comedi_driver amplc_pci224_driver = {
1488        .driver_name    = "amplc_pci224",
1489        .module         = THIS_MODULE,
1490        .attach         = pci224_attach,
1491        .detach         = pci224_detach,
1492        .auto_attach    = pci224_auto_attach,
1493        .board_name     = &pci224_boards[0].name,
1494        .offset         = sizeof(struct pci224_board),
1495        .num_names      = ARRAY_SIZE(pci224_boards),
1496};
1497
1498static int amplc_pci224_pci_probe(struct pci_dev *dev,
1499                                  const struct pci_device_id *id)
1500{
1501        return comedi_pci_auto_config(dev, &amplc_pci224_driver,
1502                                      id->driver_data);
1503}
1504
1505static DEFINE_PCI_DEVICE_TABLE(amplc_pci224_pci_table) = {
1506        { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI224) },
1507        { PCI_DEVICE(PCI_VENDOR_ID_AMPLICON, PCI_DEVICE_ID_AMPLICON_PCI234) },
1508        { 0 }
1509};
1510MODULE_DEVICE_TABLE(pci, amplc_pci224_pci_table);
1511
1512static struct pci_driver amplc_pci224_pci_driver = {
1513        .name           = "amplc_pci224",
1514        .id_table       = amplc_pci224_pci_table,
1515        .probe          = amplc_pci224_pci_probe,
1516        .remove         = comedi_pci_auto_unconfig,
1517};
1518module_comedi_pci_driver(amplc_pci224_driver, amplc_pci224_pci_driver);
1519
1520MODULE_AUTHOR("Comedi http://www.comedi.org");
1521MODULE_DESCRIPTION("Comedi low-level driver");
1522MODULE_LICENSE("GPL");
1523